aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLarry Finger <Larry.Finger@lwfinger.net>2014-03-28 22:37:38 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-04-05 17:51:22 -0400
commit5e93f35209578fcabfa855e427354195e54b491f (patch)
tree81acd3faa55eb71c1969497a78f272c7a59e263a
parent8e0c0832348c7fda1c85d67697cfe4adf077344c (diff)
staging: r8723au: Add source files for new driver - part 1
The Realtek USB device RTL8723AU is found in Lenovo Yoga 13 tablets. A driver for it has been available in a GitHub repo for several months. This commit contains the first part of the source files. The source is arbitrarily split to avoid E-mail files that are too large. Jes Sorensen at RedHat has made many improvements to the vendor code, and he has been doing the testing. I do not have access to this device. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Cc: Jes Sorensen <Jes.Sorensen@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/staging/rtl8723au/core/rtw_ap.c2087
-rw-r--r--drivers/staging/rtl8723au/core/rtw_cmd.c1874
-rw-r--r--drivers/staging/rtl8723au/core/rtw_efuse.c718
-rw-r--r--drivers/staging/rtl8723au/core/rtw_ieee80211.c1861
-rw-r--r--drivers/staging/rtl8723au/core/rtw_io.c266
-rw-r--r--drivers/staging/rtl8723au/core/rtw_ioctl_set.c601
-rw-r--r--drivers/staging/rtl8723au/core/rtw_led.c1899
-rw-r--r--drivers/staging/rtl8723au/core/rtw_mlme.c2499
-rw-r--r--drivers/staging/rtl8723au/core/rtw_mlme_ext.c9988
-rw-r--r--drivers/staging/rtl8723au/core/rtw_p2p.c3963
-rw-r--r--drivers/staging/rtl8723au/core/rtw_pwrctrl.c686
-rw-r--r--drivers/staging/rtl8723au/core/rtw_recv.c2471
-rw-r--r--drivers/staging/rtl8723au/core/rtw_security.c1653
-rw-r--r--drivers/staging/rtl8723au/core/rtw_sreset.c253
-rw-r--r--drivers/staging/rtl8723au/core/rtw_sta_mgt.c509
-rw-r--r--drivers/staging/rtl8723au/core/rtw_wlan_util.c1760
-rw-r--r--drivers/staging/rtl8723au/core/rtw_xmit.c2463
17 files changed, 35551 insertions, 0 deletions
diff --git a/drivers/staging/rtl8723au/core/rtw_ap.c b/drivers/staging/rtl8723au/core/rtw_ap.c
new file mode 100644
index 000000000000..3d936eb937ef
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_ap.c
@@ -0,0 +1,2087 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _RTW_AP_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <linux/ieee80211.h>
20#include <wifi.h>
21
22#ifdef CONFIG_8723AU_AP_MODE
23
24extern unsigned char RTW_WPA_OUI23A[];
25extern unsigned char WMM_OUI23A[];
26extern unsigned char WPS_OUI23A[];
27extern unsigned char P2P_OUI23A[];
28extern unsigned char WFD_OUI23A[];
29
30void init_mlme_ap_info23a(struct rtw_adapter *padapter)
31{
32 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
33 struct sta_priv *pstapriv = &padapter->stapriv;
34 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
35
36 spin_lock_init(&pmlmepriv->bcn_update_lock);
37
38 /* for ACL */
39 _rtw_init_queue23a(&pacl_list->acl_node_q);
40
41 start_ap_mode23a(padapter);
42}
43
44void free_mlme_ap_info23a(struct rtw_adapter *padapter)
45{
46 struct sta_info *psta = NULL;
47 struct sta_priv *pstapriv = &padapter->stapriv;
48 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
49 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
50 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
51
52 pmlmepriv->update_bcn = false;
53 pmlmeext->bstart_bss = false;
54
55 rtw_sta_flush23a(padapter);
56
57 pmlmeinfo->state = _HW_STATE_NOLINK_;
58
59 /* free_assoc_sta_resources */
60 rtw_free_all_stainfo23a(padapter);
61
62 /* free bc/mc sta_info */
63 psta = rtw_get_bcmc_stainfo23a(padapter);
64 spin_lock_bh(&pstapriv->sta_hash_lock);
65 rtw_free_stainfo23a(padapter, psta);
66 spin_unlock_bh(&pstapriv->sta_hash_lock);
67}
68
69static void update_BCNTIM(struct rtw_adapter *padapter)
70{
71 struct sta_priv *pstapriv = &padapter->stapriv;
72 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
73 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
74 struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network;
75 unsigned char *pie = pnetwork_mlmeext->IEs;
76 u8 *p, *dst_ie, *premainder_ie = NULL, *pbackup_remainder_ie = NULL;
77 u16 tim_bitmap_le;
78 uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;
79
80 tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap);
81
82 p = rtw_get_ie23a(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_);
83 if (p != NULL && tim_ielen>0) {
84 tim_ielen += 2;
85
86 premainder_ie = p+tim_ielen;
87
88 tim_ie_offset = (int)(p -pie);
89
90 remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen;
91
92 /* append TIM IE from dst_ie offset */
93 dst_ie = p;
94 } else {
95 tim_ielen = 0;
96
97 /* calulate head_len */
98 offset = _FIXED_IE_LENGTH_;
99
100 /* get ssid_ie len */
101 p = rtw_get_ie23a(pie + _BEACON_IE_OFFSET_, _SSID_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));
102 if (p != NULL)
103 offset += tmp_len+2;
104
105 /* get supported rates len */
106 p = rtw_get_ie23a(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));
107 if (p != NULL)
108 offset += tmp_len+2;
109
110 /* DS Parameter Set IE, len = 3 */
111 offset += 3;
112
113 premainder_ie = pie + offset;
114
115 remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen;
116
117 /* append TIM IE from offset */
118 dst_ie = pie + offset;
119 }
120
121 if (remainder_ielen > 0) {
122 pbackup_remainder_ie = kmalloc(remainder_ielen, GFP_ATOMIC);
123 if (pbackup_remainder_ie && premainder_ie)
124 memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
125 }
126
127 *dst_ie++= _TIM_IE_;
128
129 if ((pstapriv->tim_bitmap&0xff00) && (pstapriv->tim_bitmap&0x00fc))
130 tim_ielen = 5;
131 else
132 tim_ielen = 4;
133
134 *dst_ie++= tim_ielen;
135
136 *dst_ie++= 0;/* DTIM count */
137 *dst_ie++= 1;/* DTIM peroid */
138
139 if (pstapriv->tim_bitmap & BIT(0))/* for bc/mc frames */
140 *dst_ie++ = BIT(0);/* bitmap ctrl */
141 else
142 *dst_ie++ = 0;
143
144 if (tim_ielen == 4) {
145 *dst_ie++ = *(u8*)&tim_bitmap_le;
146 } else if (tim_ielen == 5) {
147 memcpy(dst_ie, &tim_bitmap_le, 2);
148 dst_ie+= 2;
149 }
150
151 /* copy remainder IE */
152 if (pbackup_remainder_ie) {
153 memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
154
155 kfree(pbackup_remainder_ie);
156 }
157
158 offset = (uint)(dst_ie - pie);
159 pnetwork_mlmeext->IELength = offset + remainder_ielen;
160
161 set_tx_beacon_cmd23a(padapter);
162}
163
164static u8 chk_sta_is_alive(struct sta_info *psta)
165{
166 u8 ret = false;
167
168 if ((psta->sta_stats.last_rx_data_pkts +
169 psta->sta_stats.last_rx_ctrl_pkts) !=
170 (psta->sta_stats.rx_data_pkts + psta->sta_stats.rx_ctrl_pkts))
171 ret = true;
172
173 sta_update_last_rx_pkts(psta);
174
175 return ret;
176}
177
178void expire_timeout_chk23a(struct rtw_adapter *padapter)
179{
180 struct list_head *phead, *plist, *ptmp;
181 u8 updated = 0;
182 struct sta_info *psta;
183 struct sta_priv *pstapriv = &padapter->stapriv;
184 u8 chk_alive_num = 0;
185 char chk_alive_list[NUM_STA];
186 int i;
187
188 spin_lock_bh(&pstapriv->auth_list_lock);
189
190 phead = &pstapriv->auth_list;
191
192 /* check auth_queue */
193 list_for_each_safe(plist, ptmp, phead) {
194 psta = container_of(plist, struct sta_info, auth_list);
195
196 if (psta->expire_to>0) {
197 psta->expire_to--;
198 if (psta->expire_to == 0) {
199 list_del_init(&psta->auth_list);
200 pstapriv->auth_list_cnt--;
201
202 DBG_8723A("auth expire %pM\n", psta->hwaddr);
203
204 spin_unlock_bh(&pstapriv->auth_list_lock);
205
206 spin_lock_bh(&pstapriv->sta_hash_lock);
207 rtw_free_stainfo23a(padapter, psta);
208 spin_unlock_bh(&pstapriv->sta_hash_lock);
209
210 spin_lock_bh(&pstapriv->auth_list_lock);
211 }
212 }
213
214 }
215
216 spin_unlock_bh(&pstapriv->auth_list_lock);
217
218 spin_lock_bh(&pstapriv->asoc_list_lock);
219
220 phead = &pstapriv->asoc_list;
221
222 /* check asoc_queue */
223 list_for_each_safe(plist, ptmp, phead) {
224 psta = container_of(plist, struct sta_info, asoc_list);
225
226 if (chk_sta_is_alive(psta) || !psta->expire_to) {
227 psta->expire_to = pstapriv->expire_to;
228 psta->keep_alive_trycnt = 0;
229 } else {
230 psta->expire_to--;
231 }
232
233 if (psta->expire_to <= 0)
234 {
235 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
236
237 if (padapter->registrypriv.wifi_spec == 1)
238 {
239 psta->expire_to = pstapriv->expire_to;
240 continue;
241 }
242
243 if (psta->state & WIFI_SLEEP_STATE) {
244 if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
245 /* to check if alive by another methods if staion is at ps mode. */
246 psta->expire_to = pstapriv->expire_to;
247 psta->state |= WIFI_STA_ALIVE_CHK_STATE;
248
249 /* to update bcn with tim_bitmap for this station */
250 pstapriv->tim_bitmap |= CHKBIT(psta->aid);
251 update_beacon23a(padapter, _TIM_IE_, NULL, false);
252
253 if (!pmlmeext->active_keep_alive_check)
254 continue;
255 }
256 }
257
258 if (pmlmeext->active_keep_alive_check) {
259 int stainfo_offset;
260
261 stainfo_offset = rtw_stainfo_offset23a(pstapriv, psta);
262 if (stainfo_offset_valid(stainfo_offset)) {
263 chk_alive_list[chk_alive_num++] = stainfo_offset;
264 }
265
266 continue;
267 }
268
269 list_del_init(&psta->asoc_list);
270 pstapriv->asoc_list_cnt--;
271
272 DBG_8723A("asoc expire "MAC_FMT", state = 0x%x\n", MAC_ARG(psta->hwaddr), psta->state);
273 updated = ap_free_sta23a(padapter, psta, false, WLAN_REASON_DEAUTH_LEAVING);
274 } else {
275 /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */
276 if (psta->sleepq_len > (NR_XMITFRAME/pstapriv->asoc_list_cnt)
277 && padapter->xmitpriv.free_xmitframe_cnt < ((NR_XMITFRAME/pstapriv->asoc_list_cnt)/2)
278 ) {
279 DBG_8723A("%s sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", __func__,
280 MAC_ARG(psta->hwaddr),
281 psta->sleepq_len,
282 padapter->xmitpriv.free_xmitframe_cnt,
283 pstapriv->asoc_list_cnt);
284 wakeup_sta_to_xmit23a(padapter, psta);
285 }
286 }
287 }
288
289 spin_unlock_bh(&pstapriv->asoc_list_lock);
290
291 if (chk_alive_num) {
292
293 u8 backup_oper_channel = 0;
294 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
295 /* switch to correct channel of current network before issue keep-alive frames */
296 if (rtw_get_oper_ch23a(padapter) != pmlmeext->cur_channel) {
297 backup_oper_channel = rtw_get_oper_ch23a(padapter);
298 SelectChannel23a(padapter, pmlmeext->cur_channel);
299 }
300
301 /* issue null data to check sta alive*/
302 for (i = 0; i < chk_alive_num; i++) {
303
304 int ret = _FAIL;
305
306 psta = rtw_get_stainfo23a_by_offset23a(pstapriv, chk_alive_list[i]);
307 if (!(psta->state &_FW_LINKED))
308 continue;
309
310 if (psta->state & WIFI_SLEEP_STATE)
311 ret = issue_nulldata23a(padapter, psta->hwaddr, 0, 1, 50);
312 else
313 ret = issue_nulldata23a(padapter, psta->hwaddr, 0, 3, 50);
314
315 psta->keep_alive_trycnt++;
316 if (ret == _SUCCESS)
317 {
318 DBG_8723A("asoc check, sta(" MAC_FMT ") is alive\n", MAC_ARG(psta->hwaddr));
319 psta->expire_to = pstapriv->expire_to;
320 psta->keep_alive_trycnt = 0;
321 continue;
322 }
323 else if (psta->keep_alive_trycnt <= 3)
324 {
325 DBG_8723A("ack check for asoc expire, keep_alive_trycnt =%d\n", psta->keep_alive_trycnt);
326 psta->expire_to = 1;
327 continue;
328 }
329
330 psta->keep_alive_trycnt = 0;
331
332 DBG_8723A("asoc expire "MAC_FMT", state = 0x%x\n", MAC_ARG(psta->hwaddr), psta->state);
333 spin_lock_bh(&pstapriv->asoc_list_lock);
334 if (!list_empty(&psta->asoc_list)) {
335 list_del_init(&psta->asoc_list);
336 pstapriv->asoc_list_cnt--;
337 updated = ap_free_sta23a(padapter, psta, false, WLAN_REASON_DEAUTH_LEAVING);
338 }
339 spin_unlock_bh(&pstapriv->asoc_list_lock);
340
341 }
342
343 if (backup_oper_channel>0) /* back to the original operation channel */
344 SelectChannel23a(padapter, backup_oper_channel);
345}
346
347 associated_clients_update23a(padapter, updated);
348}
349
350void add_RATid23a(struct rtw_adapter *padapter, struct sta_info *psta, u8 rssi_level)
351{
352 int i;
353 u8 rf_type;
354 u32 init_rate = 0;
355 unsigned char sta_band = 0, raid, shortGIrate = false;
356 unsigned char limit;
357 unsigned int tx_ra_bitmap = 0;
358 struct ht_priv *psta_ht = NULL;
359 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
360 struct wlan_bssid_ex *pcur_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
361
362 if (psta)
363 psta_ht = &psta->htpriv;
364 else
365 return;
366
367 if (!(psta->state & _FW_LINKED))
368 return;
369
370 /* b/g mode ra_bitmap */
371 for (i = 0; i<sizeof(psta->bssrateset); i++)
372 {
373 if (psta->bssrateset[i])
374 tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value23a(psta->bssrateset[i]&0x7f);
375 }
376 /* n mode ra_bitmap */
377 if (psta_ht->ht_option)
378 {
379 rtw23a_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
380 if (rf_type == RF_2T2R)
381 limit = 16;/* 2R */
382 else
383 limit = 8;/* 1R */
384
385 for (i = 0; i<limit; i++) {
386 if (psta_ht->ht_cap.mcs.rx_mask[i/8] & BIT(i%8))
387 tx_ra_bitmap |= CHKBIT(i+12);
388 }
389
390 /* max short GI rate */
391 shortGIrate = psta_ht->sgi;
392 }
393
394 if (pcur_network->Configuration.DSConfig > 14) {
395 /* 5G band */
396 if (tx_ra_bitmap & 0xffff000)
397 sta_band |= WIRELESS_11_5N | WIRELESS_11A;
398 else
399 sta_band |= WIRELESS_11A;
400 } else {
401 if (tx_ra_bitmap & 0xffff000)
402 sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B;
403 else if (tx_ra_bitmap & 0xff0)
404 sta_band |= WIRELESS_11G |WIRELESS_11B;
405 else
406 sta_band |= WIRELESS_11B;
407 }
408
409 psta->wireless_mode = sta_band;
410
411 raid = networktype_to_raid23a(sta_band);
412 init_rate = get_highest_rate_idx23a(tx_ra_bitmap&0x0fffffff)&0x3f;
413
414 if (psta->aid < NUM_STA)
415 {
416 u8 arg = 0;
417
418 arg = psta->mac_id&0x1f;
419
420 arg |= BIT(7);/* support entry 2~31 */
421
422 if (shortGIrate == true)
423 arg |= BIT(5);
424
425 tx_ra_bitmap |= ((raid<<28)&0xf0000000);
426
427 DBG_8723A("%s => mac_id:%d , raid:%d , bitmap = 0x%x, arg = "
428 "0x%x\n",
429 __func__, psta->mac_id, raid, tx_ra_bitmap, arg);
430
431 /* bitmap[0:27] = tx_rate_bitmap */
432 /* bitmap[28:31]= Rate Adaptive id */
433 /* arg[0:4] = macid */
434 /* arg[5] = Short GI */
435 rtw_hal_add_ra_tid23a(padapter, tx_ra_bitmap, arg, rssi_level);
436
437 if (shortGIrate == true)
438 init_rate |= BIT(6);
439
440 /* set ra_id, init_rate */
441 psta->raid = raid;
442 psta->init_rate = init_rate;
443
444 }
445 else
446 {
447 DBG_8723A("station aid %d exceed the max number\n", psta->aid);
448 }
449}
450
451static void update_bmc_sta(struct rtw_adapter *padapter)
452{
453 u32 init_rate = 0;
454 unsigned char network_type, raid;
455 int i, supportRateNum = 0;
456 unsigned int tx_ra_bitmap = 0;
457 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
458 struct wlan_bssid_ex *pcur_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
459 struct sta_info *psta = rtw_get_bcmc_stainfo23a(padapter);
460
461 if (psta)
462 {
463 psta->aid = 0;/* default set to 0 */
464 psta->mac_id = psta->aid + 1;
465
466 psta->qos_option = 0;
467 psta->htpriv.ht_option = false;
468
469 psta->ieee8021x_blocked = 0;
470
471 memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
472
473 /* prepare for add_RATid23a */
474 supportRateNum = rtw_get_rateset_len23a((u8*)&pcur_network->SupportedRates);
475 network_type = rtw_check_network_type23a((u8*)&pcur_network->SupportedRates, supportRateNum, 1);
476
477 memcpy(psta->bssrateset, &pcur_network->SupportedRates, supportRateNum);
478 psta->bssratelen = supportRateNum;
479
480 /* b/g mode ra_bitmap */
481 for (i = 0; i<supportRateNum; i++)
482 {
483 if (psta->bssrateset[i])
484 tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value23a(psta->bssrateset[i]&0x7f);
485 }
486
487 if (pcur_network->Configuration.DSConfig > 14) {
488 /* force to A mode. 5G doesn't support CCK rates */
489 network_type = WIRELESS_11A;
490 tx_ra_bitmap = 0x150; /* 6, 12, 24 Mbps */
491 } else {
492 /* force to b mode */
493 network_type = WIRELESS_11B;
494 tx_ra_bitmap = 0xf;
495 }
496
497 raid = networktype_to_raid23a(network_type);
498 init_rate = get_highest_rate_idx23a(tx_ra_bitmap&0x0fffffff)&0x3f;
499
500 /* ap mode */
501 rtw_hal_set_odm_var23a(padapter, HAL_ODM_STA_INFO, psta, true);
502
503 {
504 u8 arg = 0;
505
506 arg = psta->mac_id&0x1f;
507
508 arg |= BIT(7);
509
510 tx_ra_bitmap |= ((raid<<28)&0xf0000000);
511
512 DBG_8723A("update_bmc_sta, mask = 0x%x, arg = 0x%x\n", tx_ra_bitmap, arg);
513
514 /* bitmap[0:27] = tx_rate_bitmap */
515 /* bitmap[28:31]= Rate Adaptive id */
516 /* arg[0:4] = macid */
517 /* arg[5] = Short GI */
518 rtw_hal_add_ra_tid23a(padapter, tx_ra_bitmap, arg, 0);
519
520 }
521
522 /* set ra_id, init_rate */
523 psta->raid = raid;
524 psta->init_rate = init_rate;
525
526 rtw_stassoc_hw_rpt23a(padapter, psta);
527
528 spin_lock_bh(&psta->lock);
529 psta->state = _FW_LINKED;
530 spin_unlock_bh(&psta->lock);
531
532 }
533 else
534 {
535 DBG_8723A("add_RATid23a_bmc_sta error!\n");
536 }
537}
538
539/* notes: */
540/* AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode */
541/* MAC_ID = AID+1 for sta in ap/adhoc mode */
542/* MAC_ID = 1 for bc/mc for sta/ap/adhoc */
543/* MAC_ID = 0 for bssid for sta/ap/adhoc */
544/* CAM_ID = 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
545
546void update_sta_info23a_apmode23a(struct rtw_adapter *padapter, struct sta_info *psta)
547{
548 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
549 struct security_priv *psecuritypriv = &padapter->securitypriv;
550 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
551 struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
552 struct ht_priv *phtpriv_sta = &psta->htpriv;
553 /* set intf_tag to if1 */
554
555 psta->mac_id = psta->aid+1;
556 DBG_8723A("%s\n", __func__);
557
558 /* ap mode */
559 rtw_hal_set_odm_var23a(padapter, HAL_ODM_STA_INFO, psta, true);
560
561 if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
562 psta->ieee8021x_blocked = true;
563 else
564 psta->ieee8021x_blocked = false;
565
566 /* update sta's cap */
567
568 /* ERP */
569 VCS_update23a(padapter, psta);
570 /* HT related cap */
571 if (phtpriv_sta->ht_option)
572 {
573 /* check if sta supports rx ampdu */
574 phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable;
575
576 /* check if sta support s Short GI */
577 if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40))
578 phtpriv_sta->sgi = true;
579
580 /* bwmode */
581 if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40)) {
582 /* phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_40; */
583 phtpriv_sta->bwmode = pmlmeext->cur_bwmode;
584 phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
585
586 }
587
588 psta->qos_option = true;
589
590 }
591 else
592 {
593 phtpriv_sta->ampdu_enable = false;
594
595 phtpriv_sta->sgi = false;
596 phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20;
597 phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
598 }
599
600 /* Rx AMPDU */
601 send_delba23a(padapter, 0, psta->hwaddr);/* recipient */
602
603 /* TX AMPDU */
604 send_delba23a(padapter, 1, psta->hwaddr);/* originator */
605 phtpriv_sta->agg_enable_bitmap = 0x0;/* reset */
606 phtpriv_sta->candidate_tid_bitmap = 0x0;/* reset */
607
608 /* todo: init other variables */
609
610 memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
611
612 spin_lock_bh(&psta->lock);
613 psta->state |= _FW_LINKED;
614 spin_unlock_bh(&psta->lock);
615}
616
617static void update_hw_ht_param(struct rtw_adapter *padapter)
618{
619 unsigned char max_AMPDU_len;
620 unsigned char min_MPDU_spacing;
621 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
622 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
623
624 DBG_8723A("%s\n", __func__);
625
626 /* handle A-MPDU parameter field */
627 /*
628 AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
629 AMPDU_para [4:2]:Min MPDU Start Spacing
630 */
631 max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
632
633 min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
634
635 rtw_hal_set_hwreg23a(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
636
637 rtw_hal_set_hwreg23a(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
638
639 /* Config SM Power Save setting */
640 pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;
641 if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
642 DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
643}
644
645static void start_bss_network(struct rtw_adapter *padapter, u8 *pbuf)
646{
647 u8 *p;
648 u8 val8, cur_channel, cur_bwmode, cur_ch_offset;
649 u16 bcn_interval;
650 u32 acparm;
651 int ie_len;
652 struct registry_priv *pregpriv = &padapter->registrypriv;
653 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
654 struct security_priv* psecuritypriv = &padapter->securitypriv;
655 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
656 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
657 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
658 struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network;
659 struct HT_info_element *pht_info = NULL;
660#ifdef CONFIG_8723AU_P2P
661 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
662#endif /* CONFIG_8723AU_P2P */
663
664 bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;
665 cur_channel = pnetwork->Configuration.DSConfig;
666 cur_bwmode = HT_CHANNEL_WIDTH_20;;
667 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
668
669 /* check if there is wps ie, */
670 /* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */
671 /* and at first time the security ie (RSN/WPA IE) will not include in beacon. */
672 if (NULL == rtw_get_wps_ie23a(pnetwork->IEs+_FIXED_IE_LENGTH_, pnetwork->IELength-_FIXED_IE_LENGTH_, NULL, NULL))
673 pmlmeext->bstart_bss = true;
674
675 /* todo: update wmm, ht cap */
676 /* pmlmeinfo->WMM_enable; */
677 /* pmlmeinfo->HT_enable; */
678 if (pmlmepriv->qospriv.qos_option)
679 pmlmeinfo->WMM_enable = true;
680 if (pmlmepriv->htpriv.ht_option) {
681 pmlmeinfo->WMM_enable = true;
682 pmlmeinfo->HT_enable = true;
683
684 update_hw_ht_param(padapter);
685 }
686
687 if (pmlmepriv->cur_network.join_res != true) {
688 /* setting only at first time */
689 /* WEP Key will be set before this function, do not clear CAM. */
690 if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) && (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_))
691 flush_all_cam_entry23a(padapter); /* clear CAM */
692 }
693
694 /* set MSR to AP_Mode */
695 Set_MSR23a(padapter, _HW_STATE_AP_);
696
697 /* Set BSSID REG */
698 rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, pnetwork->MacAddress);
699
700 /* Set EDCA param reg */
701 acparm = 0x002F3217; /* VO */
702 rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
703 acparm = 0x005E4317; /* VI */
704 rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
705 acparm = 0x005ea42b;
706 rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
707 acparm = 0x0000A444; /* BK */
708 rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
709
710 /* Set Security */
711 val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf;
712 rtw_hal_set_hwreg23a(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
713
714 /* Beacon Control related register */
715 rtw_hal_set_hwreg23a(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval));
716
717 UpdateBrateTbl23a(padapter, pnetwork->SupportedRates);
718 rtw_hal_set_hwreg23a(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
719
720 if (!pmlmepriv->cur_network.join_res) {
721 /* setting only at first time */
722
723 /* disable dynamic functions, such as high power, DIG */
724
725 /* turn on all dynamic functions */
726 Switch_DM_Func23a(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
727 }
728 /* set channel, bwmode */
729 p = rtw_get_ie23a((pnetwork->IEs + sizeof(struct ndis_802_11_fixed_ies)),
730 _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength -
731 sizeof(struct ndis_802_11_fixed_ies)));
732 if (p && ie_len) {
733 pht_info = (struct HT_info_element *)(p+2);
734
735 if ((pregpriv->cbw40_enable) && (pht_info->infos[0] & BIT(2))) {
736 /* switch to the 40M Hz mode */
737 cur_bwmode = HT_CHANNEL_WIDTH_40;
738 switch (pht_info->infos[0] & 0x3) {
739 case 1:
740 /* pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; */
741 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
742 break;
743 case 3:
744 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
745 break;
746 default:
747 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
748 break;
749 }
750 }
751 }
752 /* TODO: need to judge the phy parameters on concurrent mode for single phy */
753 set_channel_bwmode23a(padapter, cur_channel, cur_ch_offset, cur_bwmode);
754
755 DBG_8723A("CH =%d, BW =%d, offset =%d\n", cur_channel, cur_bwmode,
756 cur_ch_offset);
757
758 pmlmeext->cur_channel = cur_channel;
759 pmlmeext->cur_bwmode = cur_bwmode;
760 pmlmeext->cur_ch_offset = cur_ch_offset;
761 pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type;
762
763 /* update cur_wireless_mode */
764 update_wireless_mode23a(padapter);
765
766 /* udpate capability after cur_wireless_mode updated */
767 update_capinfo23a(padapter, rtw_get_capability23a((struct wlan_bssid_ex *)pnetwork));
768
769 /* let pnetwork_mlmeext == pnetwork_mlme. */
770 memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);
771
772#ifdef CONFIG_8723AU_P2P
773 memcpy(pwdinfo->p2p_group_ssid, pnetwork->Ssid.ssid,
774 pnetwork->Ssid.ssid_len);
775 pwdinfo->p2p_group_ssid_len = pnetwork->Ssid.ssid_len;
776#endif /* CONFIG_8723AU_P2P */
777
778 if (pmlmeext->bstart_bss) {
779 update_beacon23a(padapter, _TIM_IE_, NULL, false);
780
781 /* issue beacon frame */
782 if (send_beacon23a(padapter) == _FAIL)
783 DBG_8723A("issue_beacon23a, fail!\n");
784 }
785
786 /* update bc/mc sta_info */
787 update_bmc_sta(padapter);
788}
789
790int rtw_check_beacon_data23a(struct rtw_adapter *padapter, u8 *pbuf, int len)
791{
792 int ret = _SUCCESS;
793 u8 *p;
794 u8 *pHT_caps_ie = NULL;
795 u8 *pHT_info_ie = NULL;
796 struct sta_info *psta = NULL;
797 u16 cap, ht_cap = false;
798 uint ie_len = 0;
799 int group_cipher, pairwise_cipher;
800 u8 channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX];
801 int supportRateNum = 0;
802 u8 OUI1[] = {0x00, 0x50, 0xf2, 0x01};
803 u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
804 struct registry_priv *pregistrypriv = &padapter->registrypriv;
805 struct security_priv *psecuritypriv = &padapter->securitypriv;
806 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
807 struct wlan_bssid_ex *pbss_network = &pmlmepriv->cur_network.network;
808 u8 *ie = pbss_network->IEs;
809
810 /* SSID */
811 /* Supported rates */
812 /* DS Params */
813 /* WLAN_EID_COUNTRY */
814 /* ERP Information element */
815 /* Extended supported rates */
816 /* WPA/WPA2 */
817 /* Wi-Fi Wireless Multimedia Extensions */
818 /* ht_capab, ht_oper */
819 /* WPS IE */
820
821 DBG_8723A("%s, len =%d\n", __func__, len);
822
823 if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
824 return _FAIL;
825
826 if (len>MAX_IE_SZ)
827 return _FAIL;
828
829 pbss_network->IELength = len;
830
831 memset(ie, 0, MAX_IE_SZ);
832
833 memcpy(ie, pbuf, pbss_network->IELength);
834
835 if (pbss_network->InfrastructureMode!= Ndis802_11APMode)
836 return _FAIL;
837
838 pbss_network->Rssi = 0;
839
840 memcpy(pbss_network->MacAddress, myid(&padapter->eeprompriv), ETH_ALEN);
841
842 /* beacon interval */
843 /* ie + 8; 8: TimeStamp, 2: Beacon Interval 2:Capability */
844 p = rtw_get_beacon_interval23a_from_ie(ie);
845 pbss_network->Configuration.BeaconPeriod = RTW_GET_LE16(p);
846
847 /* capability */
848 cap = RTW_GET_LE16(ie);
849
850 /* SSID */
851 p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len,
852 (pbss_network->IELength -_BEACON_IE_OFFSET_));
853 if (p && ie_len > 0) {
854 memset(&pbss_network->Ssid, 0, sizeof(struct cfg80211_ssid));
855 memcpy(pbss_network->Ssid.ssid, (p + 2), ie_len);
856 pbss_network->Ssid.ssid_len = ie_len;
857 }
858
859 /* chnnel */
860 channel = 0;
861 pbss_network->Configuration.Length = 0;
862 p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len,
863 (pbss_network->IELength - _BEACON_IE_OFFSET_));
864 if (p && ie_len > 0)
865 channel = *(p + 2);
866
867 pbss_network->Configuration.DSConfig = channel;
868
869 memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);
870 /* get supported rates */
871 p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len,
872 (pbss_network->IELength - _BEACON_IE_OFFSET_));
873 if (p) {
874 memcpy(supportRate, p+2, ie_len);
875 supportRateNum = ie_len;
876 }
877
878 /* get ext_supported rates */
879 p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_,
880 &ie_len, pbss_network->IELength - _BEACON_IE_OFFSET_);
881 if (p) {
882 memcpy(supportRate+supportRateNum, p+2, ie_len);
883 supportRateNum += ie_len;
884 }
885
886 network_type = rtw_check_network_type23a(supportRate,
887 supportRateNum, channel);
888
889 rtw_set_supported_rate23a(pbss_network->SupportedRates, network_type);
890
891 /* parsing ERP_IE */
892 p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len,
893 (pbss_network->IELength - _BEACON_IE_OFFSET_));
894 if (p && ie_len > 0)
895 ERP_IE_handler23a(padapter, (struct ndis_802_11_var_ies *)p);
896
897 /* update privacy/security */
898 if (cap & BIT(4))
899 pbss_network->Privacy = 1;
900 else
901 pbss_network->Privacy = 0;
902
903 psecuritypriv->wpa_psk = 0;
904
905 /* wpa2 */
906 group_cipher = 0; pairwise_cipher = 0;
907 psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
908 psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
909 p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len,
910 (pbss_network->IELength - _BEACON_IE_OFFSET_));
911 if (p && ie_len > 0) {
912 if (rtw_parse_wpa2_ie23a(p, ie_len+2, &group_cipher,
913 &pairwise_cipher, NULL) == _SUCCESS) {
914 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
915
916 psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */
917 psecuritypriv->wpa_psk |= BIT(1);
918
919 psecuritypriv->wpa2_group_cipher = group_cipher;
920 psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher;
921 }
922 }
923
924 /* wpa */
925 ie_len = 0;
926 group_cipher = 0;
927 pairwise_cipher = 0;
928 psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
929 psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
930 for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2)) {
931 p = rtw_get_ie23a(p, _SSN_IE_1_, &ie_len,
932 (pbss_network->IELength - _BEACON_IE_OFFSET_ -
933 (ie_len + 2)));
934 if ((p) && (!memcmp(p+2, OUI1, 4))) {
935 if (rtw_parse_wpa_ie23a(p, ie_len+2, &group_cipher,
936 &pairwise_cipher, NULL) == _SUCCESS) {
937 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
938
939 /* psk, todo:802.1x */
940 psecuritypriv->dot8021xalg = 1;
941
942 psecuritypriv->wpa_psk |= BIT(0);
943
944 psecuritypriv->wpa_group_cipher = group_cipher;
945 psecuritypriv->wpa_pairwise_cipher = pairwise_cipher;
946 }
947 break;
948 }
949
950 if ((p == NULL) || (ie_len == 0))
951 break;
952 }
953
954 /* wmm */
955 ie_len = 0;
956 pmlmepriv->qospriv.qos_option = 0;
957 if (pregistrypriv->wmm_enable) {
958 for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2)) {
959 p = rtw_get_ie23a(p, _VENDOR_SPECIFIC_IE_, &ie_len,
960 (pbss_network->IELength -
961 _BEACON_IE_OFFSET_ - (ie_len + 2)));
962 if ((p) && !memcmp(p+2, WMM_PARA_IE, 6)) {
963 pmlmepriv->qospriv.qos_option = 1;
964
965 *(p+8) |= BIT(7);/* QoS Info, support U-APSD */
966
967 /* disable all ACM bits since the WMM admission
968 * control is not supported
969 */
970 *(p + 10) &= ~BIT(4); /* BE */
971 *(p + 14) &= ~BIT(4); /* BK */
972 *(p + 18) &= ~BIT(4); /* VI */
973 *(p + 22) &= ~BIT(4); /* VO */
974 break;
975 }
976 if ((p == NULL) || (ie_len == 0))
977 break;
978 }
979 }
980 /* parsing HT_CAP_IE */
981 p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len,
982 (pbss_network->IELength - _BEACON_IE_OFFSET_));
983 if (p && ie_len > 0) {
984 u8 rf_type;
985
986 struct ieee80211_ht_cap *pht_cap = (struct ieee80211_ht_cap *)(p+2);
987
988 pHT_caps_ie = p;
989
990 ht_cap = true;
991 network_type |= WIRELESS_11_24N;
992
993 rtw23a_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
994
995 if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) ||
996 (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP))
997 pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY & (0x07<<2));
998 else
999 pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY&0x00);
1000
1001 /* set Max Rx AMPDU size to 64K */
1002 pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_FACTOR & 0x03);
1003
1004 if (rf_type == RF_1T1R) {
1005 pht_cap->mcs.rx_mask[0] = 0xff;
1006 pht_cap->mcs.rx_mask[1] = 0x0;
1007 }
1008
1009 memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len);
1010 }
1011
1012 /* parsing HT_INFO_IE */
1013 p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len,
1014 (pbss_network->IELength - _BEACON_IE_OFFSET_));
1015 if (p && ie_len > 0)
1016 pHT_info_ie = p;
1017
1018 switch (network_type) {
1019 case WIRELESS_11B:
1020 pbss_network->NetworkTypeInUse = Ndis802_11DS;
1021 break;
1022 case WIRELESS_11G:
1023 case WIRELESS_11BG:
1024 case WIRELESS_11G_24N:
1025 case WIRELESS_11BG_24N:
1026 pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
1027 break;
1028 case WIRELESS_11A:
1029 pbss_network->NetworkTypeInUse = Ndis802_11OFDM5;
1030 break;
1031 default :
1032 pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
1033 break;
1034 }
1035
1036 pmlmepriv->cur_network.network_type = network_type;
1037
1038 pmlmepriv->htpriv.ht_option = false;
1039
1040 /* ht_cap */
1041 if (pregistrypriv->ht_enable && ht_cap) {
1042 pmlmepriv->htpriv.ht_option = true;
1043 pmlmepriv->qospriv.qos_option = 1;
1044
1045 if (pregistrypriv->ampdu_enable == 1)
1046 pmlmepriv->htpriv.ampdu_enable = true;
1047
1048 HT_caps_handler23a(padapter, (struct ndis_802_11_var_ies *)pHT_caps_ie);
1049
1050 HT_info_handler23a(padapter, (struct ndis_802_11_var_ies *)pHT_info_ie);
1051 }
1052
1053 pbss_network->Length = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pbss_network);
1054
1055 /* issue beacon to start bss network */
1056 start_bss_network(padapter, (u8*)pbss_network);
1057
1058 /* alloc sta_info for ap itself */
1059 psta = rtw_get_stainfo23a(&padapter->stapriv, pbss_network->MacAddress);
1060 if (!psta) {
1061 psta = rtw_alloc_stainfo23a(&padapter->stapriv, pbss_network->MacAddress);
1062 if (!psta)
1063 return _FAIL;
1064 }
1065 /* fix bug of flush_cam_entry at STOP AP mode */
1066 psta->state |= WIFI_AP_STATE;
1067 rtw_indicate_connect23a(padapter);
1068
1069 /* for check if already set beacon */
1070 pmlmepriv->cur_network.join_res = true;
1071
1072 return ret;
1073}
1074
1075void rtw_set_macaddr_acl23a(struct rtw_adapter *padapter, int mode)
1076{
1077 struct sta_priv *pstapriv = &padapter->stapriv;
1078 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1079
1080 DBG_8723A("%s, mode =%d\n", __func__, mode);
1081
1082 pacl_list->mode = mode;
1083}
1084
1085int rtw_acl_add_sta23a(struct rtw_adapter *padapter, u8 *addr)
1086{
1087 struct list_head *plist, *phead;
1088 u8 added = false;
1089 int i, ret = 0;
1090 struct rtw_wlan_acl_node *paclnode;
1091 struct sta_priv *pstapriv = &padapter->stapriv;
1092 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1093 struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q;
1094
1095 DBG_8723A("%s(acl_num =%d) =" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr));
1096
1097 if ((NUM_ACL-1) < pacl_list->num)
1098 return -1;
1099
1100 spin_lock_bh(&pacl_node_q->lock);
1101
1102 phead = get_list_head(pacl_node_q);
1103
1104 list_for_each(plist, phead) {
1105 paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
1106
1107 if (!memcmp(paclnode->addr, addr, ETH_ALEN)) {
1108 if (paclnode->valid == true) {
1109 added = true;
1110 DBG_8723A("%s, sta has been added\n", __func__);
1111 break;
1112 }
1113 }
1114 }
1115
1116 spin_unlock_bh(&pacl_node_q->lock);
1117
1118 if (added)
1119 return ret;
1120
1121 spin_lock_bh(&pacl_node_q->lock);
1122
1123 for (i = 0; i < NUM_ACL; i++) {
1124 paclnode = &pacl_list->aclnode[i];
1125
1126 if (!paclnode->valid) {
1127 INIT_LIST_HEAD(&paclnode->list);
1128
1129 memcpy(paclnode->addr, addr, ETH_ALEN);
1130
1131 paclnode->valid = true;
1132
1133 list_add_tail(&paclnode->list, get_list_head(pacl_node_q));
1134
1135 pacl_list->num++;
1136
1137 break;
1138 }
1139 }
1140
1141 DBG_8723A("%s, acl_num =%d\n", __func__, pacl_list->num);
1142
1143 spin_unlock_bh(&pacl_node_q->lock);
1144 return ret;
1145}
1146
1147int rtw_acl_remove_sta23a(struct rtw_adapter *padapter, u8 *addr)
1148{
1149 struct list_head *plist, *phead, *ptmp;
1150 struct rtw_wlan_acl_node *paclnode;
1151 struct sta_priv *pstapriv = &padapter->stapriv;
1152 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1153 struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q;
1154 int ret = 0;
1155
1156 DBG_8723A("%s(acl_num =%d) = %pM\n", __func__, pacl_list->num, addr);
1157
1158 spin_lock_bh(&pacl_node_q->lock);
1159
1160 phead = get_list_head(pacl_node_q);
1161
1162 list_for_each_safe(plist, ptmp, phead) {
1163 paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
1164
1165 if (!memcmp(paclnode->addr, addr, ETH_ALEN)) {
1166 if (paclnode->valid) {
1167 paclnode->valid = false;
1168
1169 list_del_init(&paclnode->list);
1170
1171 pacl_list->num--;
1172 }
1173 }
1174 }
1175
1176 spin_unlock_bh(&pacl_node_q->lock);
1177
1178 DBG_8723A("%s, acl_num =%d\n", __func__, pacl_list->num);
1179
1180 return ret;
1181}
1182
1183static void update_bcn_fixed_ie(struct rtw_adapter *padapter)
1184{
1185 DBG_8723A("%s\n", __func__);
1186}
1187
1188static void update_bcn_erpinfo_ie(struct rtw_adapter *padapter)
1189{
1190 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1191 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1192 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1193 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
1194 unsigned char *p, *ie = pnetwork->IEs;
1195 u32 len = 0;
1196
1197 DBG_8723A("%s, ERP_enable =%d\n", __func__, pmlmeinfo->ERP_enable);
1198
1199 if (!pmlmeinfo->ERP_enable)
1200 return;
1201
1202 /* parsing ERP_IE */
1203 p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
1204 if (p && len>0)
1205 {
1206 struct ndis_802_11_var_ies * pIE = (struct ndis_802_11_var_ies *)p;
1207
1208 if (pmlmepriv->num_sta_non_erp == 1)
1209 pIE->data[0] |= WLAN_ERP_NON_ERP_PRESENT |
1210 WLAN_ERP_USE_PROTECTION;
1211 else
1212 pIE->data[0] &= ~(WLAN_ERP_NON_ERP_PRESENT |
1213 WLAN_ERP_USE_PROTECTION);
1214
1215 if (pmlmepriv->num_sta_no_short_preamble > 0)
1216 pIE->data[0] |= WLAN_ERP_BARKER_PREAMBLE;
1217 else
1218 pIE->data[0] &= ~(WLAN_ERP_BARKER_PREAMBLE);
1219
1220 ERP_IE_handler23a(padapter, pIE);
1221 }
1222}
1223
1224static void update_bcn_htcap_ie(struct rtw_adapter *padapter)
1225{
1226 DBG_8723A("%s\n", __func__);
1227}
1228
1229static void update_bcn_htinfo_ie(struct rtw_adapter *padapter)
1230{
1231 DBG_8723A("%s\n", __func__);
1232}
1233
1234static void update_bcn_rsn_ie(struct rtw_adapter *padapter)
1235{
1236 DBG_8723A("%s\n", __func__);
1237}
1238
1239static void update_bcn_wpa_ie(struct rtw_adapter *padapter)
1240{
1241 DBG_8723A("%s\n", __func__);
1242}
1243
1244static void update_bcn_wmm_ie(struct rtw_adapter *padapter)
1245{
1246 DBG_8723A("%s\n", __func__);
1247}
1248
1249static void update_bcn_wps_ie(struct rtw_adapter *padapter)
1250{
1251 u8 *pwps_ie = NULL, *pwps_ie_src, *premainder_ie, *pbackup_remainder_ie = NULL;
1252 uint wps_ielen = 0, wps_offset, remainder_ielen;
1253 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1254 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1255 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1256 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
1257 unsigned char *ie = pnetwork->IEs;
1258 u32 ielen = pnetwork->IELength;
1259
1260 DBG_8723A("%s\n", __func__);
1261
1262 pwps_ie = rtw_get_wps_ie23a(ie+_FIXED_IE_LENGTH_, ielen-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
1263
1264 if (pwps_ie == NULL || wps_ielen == 0)
1265 return;
1266
1267 wps_offset = (uint)(pwps_ie-ie);
1268
1269 premainder_ie = pwps_ie + wps_ielen;
1270
1271 remainder_ielen = ielen - wps_offset - wps_ielen;
1272
1273 if (remainder_ielen > 0) {
1274 pbackup_remainder_ie = kmalloc(remainder_ielen, GFP_ATOMIC);
1275 if (pbackup_remainder_ie)
1276 memcpy(pbackup_remainder_ie, premainder_ie,
1277 remainder_ielen);
1278 }
1279
1280 pwps_ie_src = pmlmepriv->wps_beacon_ie;
1281 if (pwps_ie_src == NULL)
1282 return;
1283
1284 wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */
1285 if ((wps_offset+wps_ielen+2+remainder_ielen)<= MAX_IE_SZ)
1286 {
1287 memcpy(pwps_ie, pwps_ie_src, wps_ielen+2);
1288 pwps_ie += (wps_ielen+2);
1289
1290 if (pbackup_remainder_ie)
1291 memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);
1292
1293 /* update IELength */
1294 pnetwork->IELength = wps_offset + (wps_ielen+2) + remainder_ielen;
1295 }
1296
1297 if (pbackup_remainder_ie)
1298 kfree(pbackup_remainder_ie);
1299}
1300
1301static void update_bcn_p2p_ie(struct rtw_adapter *padapter)
1302{
1303}
1304
1305static void update_bcn_vendor_spec_ie(struct rtw_adapter *padapter, u8*oui)
1306{
1307 DBG_8723A("%s\n", __func__);
1308
1309 if (!memcmp(RTW_WPA_OUI23A, oui, 4))
1310 {
1311 update_bcn_wpa_ie(padapter);
1312 }
1313 else if (!memcmp(WMM_OUI23A, oui, 4))
1314 {
1315 update_bcn_wmm_ie(padapter);
1316 }
1317 else if (!memcmp(WPS_OUI23A, oui, 4))
1318 {
1319 update_bcn_wps_ie(padapter);
1320 }
1321 else if (!memcmp(P2P_OUI23A, oui, 4))
1322 {
1323 update_bcn_p2p_ie(padapter);
1324 }
1325 else
1326 {
1327 DBG_8723A("unknown OUI type!\n");
1328 }
1329}
1330
1331void update_beacon23a(struct rtw_adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
1332{
1333 struct mlme_priv *pmlmepriv;
1334 struct mlme_ext_priv *pmlmeext;
1335 /* struct mlme_ext_info *pmlmeinfo; */
1336
1337 /* DBG_8723A("%s\n", __func__); */
1338
1339 if (!padapter)
1340 return;
1341
1342 pmlmepriv = &padapter->mlmepriv;
1343 pmlmeext = &padapter->mlmeextpriv;
1344 /* pmlmeinfo = &pmlmeext->mlmext_info; */
1345
1346 if (false == pmlmeext->bstart_bss)
1347 return;
1348
1349 spin_lock_bh(&pmlmepriv->bcn_update_lock);
1350
1351 switch (ie_id)
1352 {
1353 case 0xFF:
1354
1355 update_bcn_fixed_ie(padapter);/* 8: TimeStamp, 2: Beacon Interval 2:Capability */
1356
1357 break;
1358
1359 case _TIM_IE_:
1360
1361 update_BCNTIM(padapter);
1362
1363 break;
1364
1365 case _ERPINFO_IE_:
1366
1367 update_bcn_erpinfo_ie(padapter);
1368
1369 break;
1370
1371 case _HT_CAPABILITY_IE_:
1372
1373 update_bcn_htcap_ie(padapter);
1374
1375 break;
1376
1377 case _RSN_IE_2_:
1378
1379 update_bcn_rsn_ie(padapter);
1380
1381 break;
1382
1383 case _HT_ADD_INFO_IE_:
1384
1385 update_bcn_htinfo_ie(padapter);
1386
1387 break;
1388
1389 case _VENDOR_SPECIFIC_IE_:
1390
1391 update_bcn_vendor_spec_ie(padapter, oui);
1392
1393 break;
1394
1395 default:
1396 break;
1397 }
1398
1399 pmlmepriv->update_bcn = true;
1400
1401 spin_unlock_bh(&pmlmepriv->bcn_update_lock);
1402
1403 if (tx)
1404 set_tx_beacon_cmd23a(padapter);
1405}
1406
1407/*
1408op_mode
1409Set to 0 (HT pure) under the followign conditions
1410 - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
1411 - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
1412Set to 1 (HT non-member protection) if there may be non-HT STAs
1413 in both the primary and the secondary channel
1414Set to 2 if only HT STAs are associated in BSS,
1415 however and at least one 20 MHz HT STA is associated
1416Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
1417 (currently non-GF HT station is considered as non-HT STA also)
1418*/
1419static int rtw_ht_operation_update(struct rtw_adapter *padapter)
1420{
1421 u16 cur_op_mode, new_op_mode;
1422 int op_mode_changes = 0;
1423 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1424 struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
1425
1426 if (pmlmepriv->htpriv.ht_option == true)
1427 return 0;
1428
1429 /* if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed) */
1430 /* return 0; */
1431
1432 DBG_8723A("%s current operation mode = 0x%X\n",
1433 __func__, pmlmepriv->ht_op_mode);
1434
1435 if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)
1436 && pmlmepriv->num_sta_ht_no_gf) {
1437 pmlmepriv->ht_op_mode |=
1438 HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
1439 op_mode_changes++;
1440 } else if ((pmlmepriv->ht_op_mode &
1441 HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
1442 pmlmepriv->num_sta_ht_no_gf == 0) {
1443 pmlmepriv->ht_op_mode &=
1444 ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
1445 op_mode_changes++;
1446 }
1447
1448 if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
1449 (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) {
1450 pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
1451 op_mode_changes++;
1452 } else if ((pmlmepriv->ht_op_mode &
1453 HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
1454 (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) {
1455 pmlmepriv->ht_op_mode &=
1456 ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
1457 op_mode_changes++;
1458 }
1459
1460 /* Note: currently we switch to the MIXED op mode if HT non-greenfield
1461 * station is associated. Probably it's a theoretical case, since
1462 * it looks like all known HT STAs support greenfield.
1463 */
1464 new_op_mode = 0;
1465 if (pmlmepriv->num_sta_no_ht ||
1466 (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))
1467 new_op_mode = OP_MODE_MIXED;
1468 else if ((phtpriv_ap->ht_cap.cap_info & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
1469 && pmlmepriv->num_sta_ht_20mhz)
1470 new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
1471 else if (pmlmepriv->olbc_ht)
1472 new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;
1473 else
1474 new_op_mode = OP_MODE_PURE;
1475
1476 cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
1477 if (cur_op_mode != new_op_mode) {
1478 pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
1479 pmlmepriv->ht_op_mode |= new_op_mode;
1480 op_mode_changes++;
1481 }
1482
1483 DBG_8723A("%s new operation mode = 0x%X changes =%d\n",
1484 __func__, pmlmepriv->ht_op_mode, op_mode_changes);
1485
1486 return op_mode_changes;
1487}
1488
1489void associated_clients_update23a(struct rtw_adapter *padapter, u8 updated)
1490{
1491 /* update associcated stations cap. */
1492 if (updated == true)
1493 {
1494 struct list_head *phead, *plist, *ptmp;
1495 struct sta_info *psta;
1496 struct sta_priv *pstapriv = &padapter->stapriv;
1497
1498 spin_lock_bh(&pstapriv->asoc_list_lock);
1499
1500 phead = &pstapriv->asoc_list;
1501
1502 list_for_each_safe(plist, ptmp, phead) {
1503 psta = container_of(plist, struct sta_info, asoc_list);
1504
1505 VCS_update23a(padapter, psta);
1506 }
1507
1508 spin_unlock_bh(&pstapriv->asoc_list_lock);
1509 }
1510}
1511
1512/* called > TSR LEVEL for USB or SDIO Interface*/
1513void bss_cap_update_on_sta_join23a(struct rtw_adapter *padapter, struct sta_info *psta)
1514{
1515 u8 beacon_updated = false;
1516 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1517 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1518
1519 if (!(psta->flags & WLAN_STA_SHORT_PREAMBLE))
1520 {
1521 if (!psta->no_short_preamble_set)
1522 {
1523 psta->no_short_preamble_set = 1;
1524
1525 pmlmepriv->num_sta_no_short_preamble++;
1526
1527 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
1528 (pmlmepriv->num_sta_no_short_preamble == 1))
1529 {
1530 beacon_updated = true;
1531 update_beacon23a(padapter, 0xFF, NULL, true);
1532 }
1533
1534 }
1535 }
1536 else
1537 {
1538 if (psta->no_short_preamble_set)
1539 {
1540 psta->no_short_preamble_set = 0;
1541
1542 pmlmepriv->num_sta_no_short_preamble--;
1543
1544 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
1545 (pmlmepriv->num_sta_no_short_preamble == 0))
1546 {
1547 beacon_updated = true;
1548 update_beacon23a(padapter, 0xFF, NULL, true);
1549 }
1550
1551 }
1552 }
1553
1554 if (psta->flags & WLAN_STA_NONERP)
1555 {
1556 if (!psta->nonerp_set)
1557 {
1558 psta->nonerp_set = 1;
1559
1560 pmlmepriv->num_sta_non_erp++;
1561
1562 if (pmlmepriv->num_sta_non_erp == 1)
1563 {
1564 beacon_updated = true;
1565 update_beacon23a(padapter, _ERPINFO_IE_, NULL, true);
1566 }
1567 }
1568
1569 }
1570 else
1571 {
1572 if (psta->nonerp_set)
1573 {
1574 psta->nonerp_set = 0;
1575
1576 pmlmepriv->num_sta_non_erp--;
1577
1578 if (pmlmepriv->num_sta_non_erp == 0)
1579 {
1580 beacon_updated = true;
1581 update_beacon23a(padapter, _ERPINFO_IE_, NULL, true);
1582 }
1583 }
1584
1585 }
1586
1587 if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME))
1588 {
1589 if (!psta->no_short_slot_time_set)
1590 {
1591 psta->no_short_slot_time_set = 1;
1592
1593 pmlmepriv->num_sta_no_short_slot_time++;
1594
1595 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
1596 (pmlmepriv->num_sta_no_short_slot_time == 1))
1597 {
1598 beacon_updated = true;
1599 update_beacon23a(padapter, 0xFF, NULL, true);
1600 }
1601
1602 }
1603 }
1604 else
1605 {
1606 if (psta->no_short_slot_time_set)
1607 {
1608 psta->no_short_slot_time_set = 0;
1609
1610 pmlmepriv->num_sta_no_short_slot_time--;
1611
1612 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
1613 (pmlmepriv->num_sta_no_short_slot_time == 0))
1614 {
1615 beacon_updated = true;
1616 update_beacon23a(padapter, 0xFF, NULL, true);
1617 }
1618 }
1619 }
1620
1621 if (psta->flags & WLAN_STA_HT)
1622 {
1623 u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info);
1624
1625 DBG_8723A("HT: STA " MAC_FMT " HT Capabilities "
1626 "Info: 0x%04x\n", MAC_ARG(psta->hwaddr), ht_capab);
1627
1628 if (psta->no_ht_set) {
1629 psta->no_ht_set = 0;
1630 pmlmepriv->num_sta_no_ht--;
1631 }
1632
1633 if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) {
1634 if (!psta->no_ht_gf_set) {
1635 psta->no_ht_gf_set = 1;
1636 pmlmepriv->num_sta_ht_no_gf++;
1637 }
1638 DBG_8723A("%s STA " MAC_FMT " - no "
1639 "greenfield, num of non-gf stations %d\n",
1640 __func__, MAC_ARG(psta->hwaddr),
1641 pmlmepriv->num_sta_ht_no_gf);
1642 }
1643
1644 if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH_20_40) == 0) {
1645 if (!psta->ht_20mhz_set) {
1646 psta->ht_20mhz_set = 1;
1647 pmlmepriv->num_sta_ht_20mhz++;
1648 }
1649 DBG_8723A("%s STA " MAC_FMT " - 20 MHz HT, "
1650 "num of 20MHz HT STAs %d\n",
1651 __func__, MAC_ARG(psta->hwaddr),
1652 pmlmepriv->num_sta_ht_20mhz);
1653 }
1654
1655 }
1656 else
1657 {
1658 if (!psta->no_ht_set) {
1659 psta->no_ht_set = 1;
1660 pmlmepriv->num_sta_no_ht++;
1661 }
1662 if (pmlmepriv->htpriv.ht_option == true) {
1663 DBG_8723A("%s STA " MAC_FMT
1664 " - no HT, num of non-HT stations %d\n",
1665 __func__, MAC_ARG(psta->hwaddr),
1666 pmlmepriv->num_sta_no_ht);
1667 }
1668 }
1669
1670 if (rtw_ht_operation_update(padapter) > 0)
1671 {
1672 update_beacon23a(padapter, _HT_CAPABILITY_IE_, NULL, false);
1673 update_beacon23a(padapter, _HT_ADD_INFO_IE_, NULL, true);
1674 }
1675
1676 /* update associcated stations cap. */
1677 associated_clients_update23a(padapter, beacon_updated);
1678
1679 DBG_8723A("%s, updated =%d\n", __func__, beacon_updated);
1680}
1681
1682u8 bss_cap_update_on_sta_leave23a(struct rtw_adapter *padapter, struct sta_info *psta)
1683{
1684 u8 beacon_updated = false;
1685 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1686 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1687
1688 if (!psta)
1689 return beacon_updated;
1690
1691 if (psta->no_short_preamble_set) {
1692 psta->no_short_preamble_set = 0;
1693 pmlmepriv->num_sta_no_short_preamble--;
1694 if (pmlmeext->cur_wireless_mode > WIRELESS_11B
1695 && pmlmepriv->num_sta_no_short_preamble == 0)
1696 {
1697 beacon_updated = true;
1698 update_beacon23a(padapter, 0xFF, NULL, true);
1699 }
1700 }
1701
1702 if (psta->nonerp_set) {
1703 psta->nonerp_set = 0;
1704 pmlmepriv->num_sta_non_erp--;
1705 if (pmlmepriv->num_sta_non_erp == 0)
1706 {
1707 beacon_updated = true;
1708 update_beacon23a(padapter, _ERPINFO_IE_, NULL, true);
1709 }
1710 }
1711
1712 if (psta->no_short_slot_time_set) {
1713 psta->no_short_slot_time_set = 0;
1714 pmlmepriv->num_sta_no_short_slot_time--;
1715 if (pmlmeext->cur_wireless_mode > WIRELESS_11B
1716 && pmlmepriv->num_sta_no_short_slot_time == 0)
1717 {
1718 beacon_updated = true;
1719 update_beacon23a(padapter, 0xFF, NULL, true);
1720 }
1721 }
1722
1723 if (psta->no_ht_gf_set) {
1724 psta->no_ht_gf_set = 0;
1725 pmlmepriv->num_sta_ht_no_gf--;
1726 }
1727
1728 if (psta->no_ht_set) {
1729 psta->no_ht_set = 0;
1730 pmlmepriv->num_sta_no_ht--;
1731 }
1732
1733 if (psta->ht_20mhz_set) {
1734 psta->ht_20mhz_set = 0;
1735 pmlmepriv->num_sta_ht_20mhz--;
1736 }
1737
1738 if (rtw_ht_operation_update(padapter) > 0)
1739 {
1740 update_beacon23a(padapter, _HT_CAPABILITY_IE_, NULL, false);
1741 update_beacon23a(padapter, _HT_ADD_INFO_IE_, NULL, true);
1742 }
1743
1744 /* update associcated stations cap. */
1745
1746 DBG_8723A("%s, updated =%d\n", __func__, beacon_updated);
1747
1748 return beacon_updated;
1749}
1750
1751u8 ap_free_sta23a(struct rtw_adapter *padapter, struct sta_info *psta, bool active, u16 reason)
1752{
1753 struct sta_priv *pstapriv = &padapter->stapriv;
1754 u8 beacon_updated = false;
1755
1756 if (!psta)
1757 return beacon_updated;
1758
1759 if (active == true)
1760 {
1761 /* tear down Rx AMPDU */
1762 send_delba23a(padapter, 0, psta->hwaddr);/* recipient */
1763
1764 /* tear down TX AMPDU */
1765 send_delba23a(padapter, 1, psta->hwaddr);/* originator */
1766
1767 issue_deauth23a(padapter, psta->hwaddr, reason);
1768 }
1769
1770 psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
1771 psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
1772
1773 /* report_del_sta_event23a(padapter, psta->hwaddr, reason); */
1774
1775 /* clear cam entry / key */
1776 /* clear_cam_entry23a(padapter, (psta->mac_id + 3)); */
1777 rtw_clearstakey_cmd23a(padapter, (u8*)psta, (u8)(psta->mac_id + 3), true);
1778
1779 spin_lock_bh(&psta->lock);
1780 psta->state &= ~_FW_LINKED;
1781 spin_unlock_bh(&psta->lock);
1782
1783 rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason);
1784
1785 report_del_sta_event23a(padapter, psta->hwaddr, reason);
1786
1787 beacon_updated = bss_cap_update_on_sta_leave23a(padapter, psta);
1788
1789 spin_lock_bh(&pstapriv->sta_hash_lock);
1790 rtw_free_stainfo23a(padapter, psta);
1791 spin_unlock_bh(&pstapriv->sta_hash_lock);
1792
1793 return beacon_updated;
1794}
1795
1796int rtw_ap_inform_ch_switch23a (struct rtw_adapter *padapter, u8 new_ch, u8 ch_offset)
1797{
1798 struct list_head *phead, *plist;
1799 int ret = 0;
1800 struct sta_info *psta = NULL;
1801 struct sta_priv *pstapriv = &padapter->stapriv;
1802 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1803 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1804 u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1805
1806 if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1807 return ret;
1808
1809 DBG_8723A(FUNC_NDEV_FMT" with ch:%u, offset:%u\n",
1810 FUNC_NDEV_ARG(padapter->pnetdev), new_ch, ch_offset);
1811
1812 spin_lock_bh(&pstapriv->asoc_list_lock);
1813 phead = &pstapriv->asoc_list;
1814
1815 list_for_each(plist, phead) {
1816 psta = container_of(plist, struct sta_info, asoc_list);
1817
1818 issue_action_spct_ch_switch23a (padapter, psta->hwaddr, new_ch, ch_offset);
1819 psta->expire_to = ((pstapriv->expire_to * 2) > 5) ? 5 : (pstapriv->expire_to * 2);
1820 }
1821 spin_unlock_bh(&pstapriv->asoc_list_lock);
1822
1823 issue_action_spct_ch_switch23a (padapter, bc_addr, new_ch, ch_offset);
1824
1825 return ret;
1826}
1827
1828int rtw_sta_flush23a(struct rtw_adapter *padapter)
1829{
1830 struct list_head *phead, *plist, *ptmp;
1831 int ret = 0;
1832 struct sta_info *psta;
1833 struct sta_priv *pstapriv = &padapter->stapriv;
1834 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1835 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1836 u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1837 u8 chk_alive_num = 0;
1838 char chk_alive_list[NUM_STA];
1839 int i;
1840
1841 DBG_8723A(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
1842
1843 if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1844 return ret;
1845
1846 spin_lock_bh(&pstapriv->asoc_list_lock);
1847 phead = &pstapriv->asoc_list;
1848
1849 list_for_each_safe(plist, ptmp, phead) {
1850 int stainfo_offset;
1851
1852 psta = container_of(plist, struct sta_info, asoc_list);
1853
1854 /* Remove sta from asoc_list */
1855 list_del_init(&psta->asoc_list);
1856 pstapriv->asoc_list_cnt--;
1857
1858 /* Keep sta for ap_free_sta23a() beyond this asoc_list loop */
1859 stainfo_offset = rtw_stainfo_offset23a(pstapriv, psta);
1860 if (stainfo_offset_valid(stainfo_offset)) {
1861 chk_alive_list[chk_alive_num++] = stainfo_offset;
1862 }
1863 }
1864 spin_unlock_bh(&pstapriv->asoc_list_lock);
1865
1866 /* For each sta in chk_alive_list, call ap_free_sta23a */
1867 for (i = 0; i < chk_alive_num; i++) {
1868 psta = rtw_get_stainfo23a_by_offset23a(pstapriv, chk_alive_list[i]);
1869 ap_free_sta23a(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
1870 }
1871
1872 issue_deauth23a(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING);
1873
1874 associated_clients_update23a(padapter, true);
1875
1876 return ret;
1877}
1878
1879/* called > TSR LEVEL for USB or SDIO Interface*/
1880void sta_info_update23a(struct rtw_adapter *padapter, struct sta_info *psta)
1881{
1882 int flags = psta->flags;
1883 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1884
1885 /* update wmm cap. */
1886 if (WLAN_STA_WME&flags)
1887 psta->qos_option = 1;
1888 else
1889 psta->qos_option = 0;
1890
1891 if (pmlmepriv->qospriv.qos_option == 0)
1892 psta->qos_option = 0;
1893
1894 /* update 802.11n ht cap. */
1895 if (WLAN_STA_HT&flags)
1896 {
1897 psta->htpriv.ht_option = true;
1898 psta->qos_option = 1;
1899 }
1900 else
1901 {
1902 psta->htpriv.ht_option = false;
1903 }
1904
1905 if (pmlmepriv->htpriv.ht_option == false)
1906 psta->htpriv.ht_option = false;
1907
1908 update_sta_info23a_apmode23a(padapter, psta);
1909}
1910
1911/* called >= TSR LEVEL for USB or SDIO Interface*/
1912void ap_sta_info_defer_update23a(struct rtw_adapter *padapter, struct sta_info *psta)
1913{
1914 if (psta->state & _FW_LINKED)
1915 {
1916 /* add ratid */
1917 add_RATid23a(padapter, psta, 0);/* DM_RATR_STA_INIT */
1918 }
1919}
1920
1921/* restore hw setting from sw data structures */
1922void rtw_ap_restore_network(struct rtw_adapter *padapter)
1923{
1924 struct mlme_priv *mlmepriv = &padapter->mlmepriv;
1925 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1926 struct sta_priv * pstapriv = &padapter->stapriv;
1927 struct sta_info *psta;
1928 struct security_priv *psecuritypriv = &padapter->securitypriv;
1929 struct list_head *phead, *plist, *ptmp;
1930 u8 chk_alive_num = 0;
1931 char chk_alive_list[NUM_STA];
1932 int i;
1933
1934 rtw_setopmode_cmd23a(padapter, Ndis802_11APMode);
1935
1936 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
1937
1938 start_bss_network(padapter, (u8*)&mlmepriv->cur_network.network);
1939
1940 if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
1941 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))
1942 {
1943 /* restore group key, WEP keys is restored in ips_leave23a() */
1944 rtw_set_key23a(padapter, psecuritypriv, psecuritypriv->dot118021XGrpKeyid, 0);
1945 }
1946
1947 /* per sta pairwise key and settings */
1948 if ((padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_) &&
1949 (padapter->securitypriv.dot11PrivacyAlgrthm != _AES_)) {
1950 return;
1951 }
1952
1953 spin_lock_bh(&pstapriv->asoc_list_lock);
1954
1955 phead = &pstapriv->asoc_list;
1956
1957 list_for_each_safe(plist, ptmp, phead) {
1958 int stainfo_offset;
1959
1960 psta = container_of(plist, struct sta_info, asoc_list);
1961
1962 stainfo_offset = rtw_stainfo_offset23a(pstapriv, psta);
1963 if (stainfo_offset_valid(stainfo_offset)) {
1964 chk_alive_list[chk_alive_num++] = stainfo_offset;
1965 }
1966 }
1967
1968 spin_unlock_bh(&pstapriv->asoc_list_lock);
1969
1970 for (i = 0; i < chk_alive_num; i++) {
1971 psta = rtw_get_stainfo23a_by_offset23a(pstapriv, chk_alive_list[i]);
1972
1973 if (psta == NULL) {
1974 DBG_8723A(FUNC_ADPT_FMT" sta_info is null\n", FUNC_ADPT_ARG(padapter));
1975 }
1976 else if (psta->state &_FW_LINKED)
1977 {
1978 Update_RA_Entry23a(padapter, psta);
1979 /* pairwise key */
1980 rtw_setstakey_cmd23a(padapter, (unsigned char *)psta, true);
1981 }
1982 }
1983}
1984
1985void start_ap_mode23a(struct rtw_adapter *padapter)
1986{
1987 int i;
1988 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1989 struct sta_priv *pstapriv = &padapter->stapriv;
1990 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1991 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1992
1993 pmlmepriv->update_bcn = false;
1994
1995 /* init_mlme_ap_info23a(padapter); */
1996 pmlmeext->bstart_bss = false;
1997
1998 pmlmepriv->num_sta_non_erp = 0;
1999
2000 pmlmepriv->num_sta_no_short_slot_time = 0;
2001
2002 pmlmepriv->num_sta_no_short_preamble = 0;
2003
2004 pmlmepriv->num_sta_ht_no_gf = 0;
2005 pmlmepriv->num_sta_no_ht = 0;
2006 pmlmepriv->num_sta_ht_20mhz = 0;
2007
2008 pmlmepriv->olbc = false;
2009
2010 pmlmepriv->olbc_ht = false;
2011
2012 pmlmepriv->ht_op_mode = 0;
2013
2014 for (i = 0; i<NUM_STA; i++)
2015 pstapriv->sta_aid[i] = NULL;
2016
2017 pmlmepriv->wps_beacon_ie = NULL;
2018 pmlmepriv->wps_probe_resp_ie = NULL;
2019 pmlmepriv->wps_assoc_resp_ie = NULL;
2020
2021 pmlmepriv->p2p_beacon_ie = NULL;
2022 pmlmepriv->p2p_probe_resp_ie = NULL;
2023
2024 /* for ACL */
2025 INIT_LIST_HEAD(&pacl_list->acl_node_q.queue);
2026 pacl_list->num = 0;
2027 pacl_list->mode = 0;
2028 for (i = 0; i < NUM_ACL; i++) {
2029 INIT_LIST_HEAD(&pacl_list->aclnode[i].list);
2030 pacl_list->aclnode[i].valid = false;
2031 }
2032}
2033
2034void stop_ap_mode23a(struct rtw_adapter *padapter)
2035{
2036 struct list_head *phead, *plist, *ptmp;
2037 struct rtw_wlan_acl_node *paclnode;
2038 struct sta_info *psta = NULL;
2039 struct sta_priv *pstapriv = &padapter->stapriv;
2040 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2041 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2042 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
2043 struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q;
2044
2045 pmlmepriv->update_bcn = false;
2046 pmlmeext->bstart_bss = false;
2047
2048 /* reset and init security priv , this can refine with rtw_reset_securitypriv23a */
2049 memset((unsigned char *)&padapter->securitypriv, 0, sizeof (struct security_priv));
2050 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
2051 padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
2052
2053 /* for ACL */
2054 spin_lock_bh(&pacl_node_q->lock);
2055 phead = get_list_head(pacl_node_q);
2056
2057 list_for_each_safe(plist, ptmp, phead) {
2058 paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
2059
2060 if (paclnode->valid == true) {
2061 paclnode->valid = false;
2062
2063 list_del_init(&paclnode->list);
2064
2065 pacl_list->num--;
2066 }
2067 }
2068 spin_unlock_bh(&pacl_node_q->lock);
2069
2070 DBG_8723A("%s, free acl_node_queue, num =%d\n", __func__, pacl_list->num);
2071
2072 rtw_sta_flush23a(padapter);
2073
2074 /* free_assoc_sta_resources */
2075 rtw_free_all_stainfo23a(padapter);
2076
2077 psta = rtw_get_bcmc_stainfo23a(padapter);
2078 spin_lock_bh(&pstapriv->sta_hash_lock);
2079 rtw_free_stainfo23a(padapter, psta);
2080 spin_unlock_bh(&pstapriv->sta_hash_lock);
2081
2082 rtw_init_bcmc_stainfo23a(padapter);
2083
2084 rtw23a_free_mlme_priv_ie_data(pmlmepriv);
2085}
2086
2087#endif /* CONFIG_8723AU_AP_MODE */
diff --git a/drivers/staging/rtl8723au/core/rtw_cmd.c b/drivers/staging/rtl8723au/core/rtw_cmd.c
new file mode 100644
index 000000000000..dbc6401c6e13
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_cmd.c
@@ -0,0 +1,1874 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _RTW_CMD_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <recv_osdep.h>
20#include <cmd_osdep.h>
21#include <mlme_osdep.h>
22
23#ifdef CONFIG_8723AU_BT_COEXIST
24#include <rtl8723a_hal.h>
25#endif /* CONFIG_8723AU_BT_COEXIST */
26
27static struct cmd_hdl wlancmds[] = {
28 GEN_DRV_CMD_HANDLER(0, NULL) /*0*/
29 GEN_DRV_CMD_HANDLER(0, NULL)
30 GEN_DRV_CMD_HANDLER(0, NULL)
31 GEN_DRV_CMD_HANDLER(0, NULL)
32 GEN_DRV_CMD_HANDLER(0, NULL)
33 GEN_DRV_CMD_HANDLER(0, NULL)
34 GEN_MLME_EXT_HANDLER(0, NULL)
35 GEN_MLME_EXT_HANDLER(0, NULL)
36 GEN_MLME_EXT_HANDLER(0, NULL)
37 GEN_MLME_EXT_HANDLER(0, NULL)
38 GEN_MLME_EXT_HANDLER(0, NULL) /*10*/
39 GEN_MLME_EXT_HANDLER(0, NULL)
40 GEN_MLME_EXT_HANDLER(0, NULL)
41 GEN_MLME_EXT_HANDLER(0, NULL)
42 GEN_MLME_EXT_HANDLER(sizeof (struct wlan_bssid_ex), join_cmd_hdl23a) /*14*/
43 GEN_MLME_EXT_HANDLER(sizeof (struct disconnect_parm), disconnect_hdl23a)
44 GEN_MLME_EXT_HANDLER(sizeof (struct wlan_bssid_ex), createbss_hdl23a)
45 GEN_MLME_EXT_HANDLER(sizeof (struct setopmode_parm), setopmode_hdl23a)
46 GEN_MLME_EXT_HANDLER(sizeof (struct sitesurvey_parm), sitesurvey_cmd_hdl23a) /*18*/
47 GEN_MLME_EXT_HANDLER(sizeof (struct setauth_parm), setauth_hdl23a)
48 GEN_MLME_EXT_HANDLER(sizeof (struct setkey_parm), setkey_hdl23a) /*20*/
49 GEN_MLME_EXT_HANDLER(sizeof (struct set_stakey_parm), set_stakey_hdl23a)
50 GEN_MLME_EXT_HANDLER(sizeof (struct set_assocsta_parm), NULL)
51 GEN_MLME_EXT_HANDLER(sizeof (struct del_assocsta_parm), NULL)
52 GEN_MLME_EXT_HANDLER(sizeof (struct setstapwrstate_parm), NULL)
53 GEN_MLME_EXT_HANDLER(sizeof (struct setbasicrate_parm), NULL)
54 GEN_MLME_EXT_HANDLER(sizeof (struct getbasicrate_parm), NULL)
55 GEN_MLME_EXT_HANDLER(sizeof (struct setdatarate_parm), NULL)
56 GEN_MLME_EXT_HANDLER(sizeof (struct getdatarate_parm), NULL)
57 GEN_MLME_EXT_HANDLER(sizeof (struct setphyinfo_parm), NULL)
58 GEN_MLME_EXT_HANDLER(sizeof (struct getphyinfo_parm), NULL) /*30*/
59 GEN_MLME_EXT_HANDLER(sizeof (struct setphy_parm), NULL)
60 GEN_MLME_EXT_HANDLER(sizeof (struct getphy_parm), NULL)
61 GEN_MLME_EXT_HANDLER(0, NULL)
62 GEN_MLME_EXT_HANDLER(0, NULL)
63 GEN_MLME_EXT_HANDLER(0, NULL)
64 GEN_MLME_EXT_HANDLER(0, NULL)
65 GEN_MLME_EXT_HANDLER(0, NULL)
66 GEN_MLME_EXT_HANDLER(0, NULL)
67 GEN_MLME_EXT_HANDLER(0, NULL)
68 GEN_MLME_EXT_HANDLER(0, NULL) /*40*/
69 GEN_MLME_EXT_HANDLER(0, NULL)
70 GEN_MLME_EXT_HANDLER(0, NULL)
71 GEN_MLME_EXT_HANDLER(0, NULL)
72 GEN_MLME_EXT_HANDLER(0, NULL)
73 GEN_MLME_EXT_HANDLER(sizeof(struct addBaReq_parm), add_ba_hdl23a)
74 GEN_MLME_EXT_HANDLER(sizeof(struct set_ch_parm), set_ch_hdl23a) /* 46 */
75 GEN_MLME_EXT_HANDLER(0, NULL)
76 GEN_MLME_EXT_HANDLER(0, NULL)
77 GEN_MLME_EXT_HANDLER(0, NULL)
78 GEN_MLME_EXT_HANDLER(0, NULL) /*50*/
79 GEN_MLME_EXT_HANDLER(0, NULL)
80 GEN_MLME_EXT_HANDLER(0, NULL)
81 GEN_MLME_EXT_HANDLER(0, NULL)
82 GEN_MLME_EXT_HANDLER(0, NULL)
83 GEN_MLME_EXT_HANDLER(sizeof(struct Tx_Beacon_param), tx_beacon_hdl23a) /*55*/
84
85 GEN_MLME_EXT_HANDLER(0, mlme_evt_hdl23a) /*56*/
86 GEN_MLME_EXT_HANDLER(0, rtw_drvextra_cmd_hdl23a) /*57*/
87
88 GEN_MLME_EXT_HANDLER(0, h2c_msg_hdl23a) /*58*/
89 GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelPlan_param), set_chplan_hdl23a) /*59*/
90 GEN_MLME_EXT_HANDLER(sizeof(struct LedBlink_param), led_blink_hdl23a) /*60*/
91
92 GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelSwitch_param), set_csa_hdl23a) /*61*/
93 GEN_MLME_EXT_HANDLER(sizeof(struct TDLSoption_param), tdls_hdl23a) /*62*/
94};
95
96struct _cmd_callback rtw_cmd_callback[] = {
97 {GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/
98 {GEN_CMD_CODE(_Write_MACREG), NULL},
99 {GEN_CMD_CODE(_Read_BBREG), &rtw_getbbrfreg_cmdrsp_callback23a},
100 {GEN_CMD_CODE(_Write_BBREG), NULL},
101 {GEN_CMD_CODE(_Read_RFREG), &rtw_getbbrfreg_cmdrsp_callback23a},
102 {GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/
103 {GEN_CMD_CODE(_Read_EEPROM), NULL},
104 {GEN_CMD_CODE(_Write_EEPROM), NULL},
105 {GEN_CMD_CODE(_Read_EFUSE), NULL},
106 {GEN_CMD_CODE(_Write_EFUSE), NULL},
107
108 {GEN_CMD_CODE(_Read_CAM), NULL}, /*10*/
109 {GEN_CMD_CODE(_Write_CAM), NULL},
110 {GEN_CMD_CODE(_setBCNITV), NULL},
111 {GEN_CMD_CODE(_setMBIDCFG), NULL},
112 {GEN_CMD_CODE(_JoinBss), &rtw_joinbss_cmd23a_callback}, /*14*/
113 {GEN_CMD_CODE(_DisConnect), &rtw_disassoc_cmd23a_callback}, /*15*/
114 {GEN_CMD_CODE(_CreateBss), &rtw_createbss_cmd23a_callback},
115 {GEN_CMD_CODE(_SetOpMode), NULL},
116 {GEN_CMD_CODE(_SiteSurvey), &rtw_survey_cmd_callback23a}, /*18*/
117 {GEN_CMD_CODE(_SetAuth), NULL},
118
119 {GEN_CMD_CODE(_SetKey), NULL}, /*20*/
120 {GEN_CMD_CODE(_SetStaKey), &rtw_setstaKey_cmdrsp_callback23a},
121 {GEN_CMD_CODE(_SetAssocSta), &rtw_setassocsta_cmdrsp_callback23a},
122 {GEN_CMD_CODE(_DelAssocSta), NULL},
123 {GEN_CMD_CODE(_SetStaPwrState), NULL},
124 {GEN_CMD_CODE(_SetBasicRate), NULL}, /*25*/
125 {GEN_CMD_CODE(_GetBasicRate), NULL},
126 {GEN_CMD_CODE(_SetDataRate), NULL},
127 {GEN_CMD_CODE(_GetDataRate), NULL},
128 {GEN_CMD_CODE(_SetPhyInfo), NULL},
129
130 {GEN_CMD_CODE(_GetPhyInfo), NULL}, /*30*/
131 {GEN_CMD_CODE(_SetPhy), NULL},
132 {GEN_CMD_CODE(_GetPhy), NULL},
133 {GEN_CMD_CODE(_readRssi), NULL},
134 {GEN_CMD_CODE(_readGain), NULL},
135 {GEN_CMD_CODE(_SetAtim), NULL}, /*35*/
136 {GEN_CMD_CODE(_SetPwrMode), NULL},
137 {GEN_CMD_CODE(_JoinbssRpt), NULL},
138 {GEN_CMD_CODE(_SetRaTable), NULL},
139 {GEN_CMD_CODE(_GetRaTable), NULL},
140
141 {GEN_CMD_CODE(_GetCCXReport), NULL}, /*40*/
142 {GEN_CMD_CODE(_GetDTMReport), NULL},
143 {GEN_CMD_CODE(_GetTXRateStatistics), NULL},
144 {GEN_CMD_CODE(_SetUsbSuspend), NULL},
145 {GEN_CMD_CODE(_SetH2cLbk), NULL},
146 {GEN_CMD_CODE(_AddBAReq), NULL}, /*45*/
147 {GEN_CMD_CODE(_SetChannel), NULL}, /*46*/
148 {GEN_CMD_CODE(_SetTxPower), NULL},
149 {GEN_CMD_CODE(_SwitchAntenna), NULL},
150 {GEN_CMD_CODE(_SetCrystalCap), NULL},
151 {GEN_CMD_CODE(_SetSingleCarrierTx), NULL}, /*50*/
152
153 {GEN_CMD_CODE(_SetSingleToneTx), NULL}, /*51*/
154 {GEN_CMD_CODE(_SetCarrierSuppressionTx), NULL},
155 {GEN_CMD_CODE(_SetContinuousTx), NULL},
156 {GEN_CMD_CODE(_SwitchBandwidth), NULL}, /*54*/
157 {GEN_CMD_CODE(_TX_Beacon), NULL},/*55*/
158
159 {GEN_CMD_CODE(_Set_MLME_EVT), NULL},/*56*/
160 {GEN_CMD_CODE(_Set_Drv_Extra), NULL},/*57*/
161 {GEN_CMD_CODE(_Set_H2C_MSG), NULL},/*58*/
162 {GEN_CMD_CODE(_SetChannelPlan), NULL},/*59*/
163 {GEN_CMD_CODE(_LedBlink), NULL},/*60*/
164
165 {GEN_CMD_CODE(_SetChannelSwitch), NULL},/*61*/
166 {GEN_CMD_CODE(_TDLS), NULL},/*62*/
167};
168
169/*
170Caller and the rtw_cmd_thread23a can protect cmd_q by spin_lock.
171No irqsave is necessary.
172*/
173
174int rtw_init_cmd_priv23a(struct cmd_priv *pcmdpriv)
175{
176 int res = _SUCCESS;
177
178 sema_init(&pcmdpriv->cmd_queue_sema, 0);
179 sema_init(&pcmdpriv->terminate_cmdthread_sema, 0);
180
181 _rtw_init_queue23a(&pcmdpriv->cmd_queue);
182
183 pcmdpriv->cmd_seq = 1;
184
185 pcmdpriv->cmd_allocated_buf = kzalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ,
186 GFP_KERNEL);
187
188 if (pcmdpriv->cmd_allocated_buf == NULL) {
189 res = _FAIL;
190 goto exit;
191 }
192
193 pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ -
194 ((unsigned long)(pcmdpriv->cmd_allocated_buf) &
195 (CMDBUFF_ALIGN_SZ - 1));
196
197 pcmdpriv->rsp_allocated_buf = kzalloc(MAX_RSPSZ + 4, GFP_KERNEL);
198
199 if (!pcmdpriv->rsp_allocated_buf) {
200 res = _FAIL;
201 goto exit;
202 }
203
204 pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 -
205 ((unsigned long)(pcmdpriv->rsp_allocated_buf) & 3);
206
207 pcmdpriv->cmd_issued_cnt = 0;
208 pcmdpriv->cmd_done_cnt = 0;
209 pcmdpriv->rsp_cnt = 0;
210
211exit:
212
213 return res;
214}
215
216/* forward definition */
217
218static void c2h_wk_callback(struct work_struct *work);
219int _rtw_init_evt_priv23a(struct evt_priv *pevtpriv)
220{
221 int res = _SUCCESS;
222
223 /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
224 atomic_set(&pevtpriv->event_seq, 0);
225 pevtpriv->evt_done_cnt = 0;
226
227 INIT_WORK(&pevtpriv->c2h_wk, c2h_wk_callback);
228 pevtpriv->c2h_wk_alive = false;
229 pevtpriv->c2h_queue = rtw_cbuf_alloc23a(C2H_QUEUE_MAX_LEN + 1);
230
231 return res;
232}
233
234void _rtw_free_evt_priv23a (struct evt_priv *pevtpriv)
235{
236 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
237 ("+_rtw_free_evt_priv23a\n"));
238 cancel_work_sync(&pevtpriv->c2h_wk);
239 while(pevtpriv->c2h_wk_alive)
240 msleep(10);
241
242 while (!rtw_cbuf_empty23a(pevtpriv->c2h_queue)) {
243 void *c2h;
244 if ((c2h = rtw_cbuf_pop23a(pevtpriv->c2h_queue)) != NULL &&
245 c2h != (void *)pevtpriv) {
246 kfree(c2h);
247 }
248 }
249
250 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
251 ("-_rtw_free_evt_priv23a\n"));
252}
253
254void _rtw_free_cmd_priv23a(struct cmd_priv *pcmdpriv)
255{
256 if (pcmdpriv) {
257 kfree(pcmdpriv->cmd_allocated_buf);
258 kfree(pcmdpriv->rsp_allocated_buf);
259 }
260}
261
262/*
263Calling Context:
264rtw_enqueue_cmd23a can only be called between kernel thread,
265since only spin_lock is used.
266
267ISR/Call-Back functions can't call this sub-function.
268*/
269
270int _rtw_enqueue_cmd23a(struct rtw_queue *queue, struct cmd_obj *obj)
271{
272 unsigned long irqL;
273
274 if (obj == NULL)
275 goto exit;
276
277 spin_lock_irqsave(&queue->lock, irqL);
278
279 list_add_tail(&obj->list, &queue->queue);
280
281 spin_unlock_irqrestore(&queue->lock, irqL);
282
283exit:
284
285 return _SUCCESS;
286}
287
288u32 rtw_init_evt_priv23a(struct evt_priv *pevtpriv)
289{
290 int res;
291
292 res = _rtw_init_evt_priv23a(pevtpriv);
293
294 return res;
295}
296
297void rtw_free_evt_priv23a(struct evt_priv *pevtpriv)
298{
299 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
300 ("rtw_free_evt_priv23a\n"));
301 _rtw_free_evt_priv23a(pevtpriv);
302}
303
304void rtw_free_cmd_priv23a(struct cmd_priv *pcmdpriv)
305{
306 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
307 ("rtw_free_cmd_priv23a\n"));
308 _rtw_free_cmd_priv23a(pcmdpriv);
309}
310
311static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
312{
313 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
314 /* set to true to allow enqueuing cmd when hw_init_completed is false */
315 u8 bAllow = false;
316
317 /* To decide allow or not */
318 if (pcmdpriv->padapter->pwrctrlpriv.bHWPwrPindetect &&
319 !pcmdpriv->padapter->registrypriv.usbss_enable) {
320 if (cmd_obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
321 pdrvextra_cmd_parm =
322 (struct drvextra_cmd_parm *)cmd_obj->parmbuf;
323 if (pdrvextra_cmd_parm->ec_id ==
324 POWER_SAVING_CTRL_WK_CID)
325 bAllow = true;
326 }
327 }
328
329 if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan))
330 bAllow = true;
331
332 if ((pcmdpriv->padapter->hw_init_completed == false &&
333 bAllow == false) || pcmdpriv->cmdthd_running == false)
334 return _FAIL;
335 return _SUCCESS;
336}
337
338u32 rtw_enqueue_cmd23a(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
339{
340 int res = _FAIL;
341 struct rtw_adapter *padapter = pcmdpriv->padapter;
342
343 if (!cmd_obj)
344 goto exit;
345
346 cmd_obj->padapter = padapter;
347
348 res = rtw_cmd_filter(pcmdpriv, cmd_obj);
349 if (res == _FAIL) {
350 rtw_free_cmd_obj23a(cmd_obj);
351 goto exit;
352 }
353
354 res = _rtw_enqueue_cmd23a(&pcmdpriv->cmd_queue, cmd_obj);
355
356 if (res == _SUCCESS)
357 up(&pcmdpriv->cmd_queue_sema);
358
359exit:
360 return res;
361}
362
363static struct cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv)
364{
365 struct cmd_obj *obj;
366 struct rtw_queue *queue = &pcmdpriv->cmd_queue;
367 unsigned long irqL;
368
369 spin_lock_irqsave(&queue->lock, irqL);
370 if (list_empty(&queue->queue))
371 obj = NULL;
372 else {
373 obj = container_of((&queue->queue)->next, struct cmd_obj, list);
374 list_del_init(&obj->list);
375 }
376
377 spin_unlock_irqrestore(&queue->lock, irqL);
378
379 return obj;
380}
381
382void rtw_cmd_clr_isr23a(struct cmd_priv *pcmdpriv)
383{
384 pcmdpriv->cmd_done_cnt++;
385}
386
387void rtw_free_cmd_obj23a(struct cmd_obj *pcmd)
388{
389
390 if (pcmd->cmdcode != _JoinBss_CMD_ &&
391 pcmd->cmdcode != _CreateBss_CMD_) {
392 /* free parmbuf in cmd_obj */
393 kfree(pcmd->parmbuf);
394 }
395
396 if (pcmd->rsp) {
397 if (pcmd->rspsz != 0) {
398 /* free rsp in cmd_obj */
399 kfree(pcmd->rsp);
400 }
401 }
402
403 kfree(pcmd);
404}
405
406int rtw_cmd_thread23a(void *context)
407{
408 u8 ret;
409 struct cmd_obj *pcmd;
410 u8 *pcmdbuf, *prspbuf;
411 u8 (*cmd_hdl)(struct rtw_adapter *padapter, u8* pbuf);
412 void (*pcmd_callback)(struct rtw_adapter *dev, struct cmd_obj *pcmd);
413 struct rtw_adapter *padapter = (struct rtw_adapter *)context;
414 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
415
416 allow_signal(SIGTERM);
417
418 pcmdbuf = pcmdpriv->cmd_buf;
419 prspbuf = pcmdpriv->rsp_buf;
420
421 pcmdpriv->cmdthd_running = true;
422 up(&pcmdpriv->terminate_cmdthread_sema);
423
424 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
425 ("start r871x rtw_cmd_thread23a !!!!\n"));
426
427 while(1) {
428 if (down_interruptible(&pcmdpriv->cmd_queue_sema))
429 break;
430_next:
431 if ((padapter->bDriverStopped == true) ||
432 (padapter->bSurpriseRemoved == true)) {
433 DBG_8723A("%s: DriverStopped(%d) SurpriseRemoved(%d) "
434 "break at line %d\n", __func__,
435 padapter->bDriverStopped,
436 padapter->bSurpriseRemoved, __LINE__);
437 break;
438 }
439
440 if (!(pcmd = rtw_dequeue_cmd(pcmdpriv)))
441 continue;
442
443 if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) {
444 pcmd->res = H2C_DROPPED;
445 goto post_process;
446 }
447
448 pcmdpriv->cmd_issued_cnt++;
449
450 pcmd->cmdsz = _RND4(pcmd->cmdsz);/* _RND4 */
451
452 memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
453
454 if (pcmd->cmdcode < (sizeof(wlancmds)/sizeof(struct cmd_hdl))) {
455 cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
456
457 if (cmd_hdl) {
458 ret = cmd_hdl(pcmd->padapter, pcmdbuf);
459 pcmd->res = ret;
460 }
461
462 pcmdpriv->cmd_seq++;
463 } else
464 pcmd->res = H2C_PARAMETERS_ERROR;
465
466 cmd_hdl = NULL;
467
468post_process:
469 /* call callback function for post-processed */
470 if (pcmd->cmdcode < (sizeof(rtw_cmd_callback) /
471 sizeof(struct _cmd_callback))) {
472 pcmd_callback =
473 rtw_cmd_callback[pcmd->cmdcode].callback;
474 if (!pcmd_callback) {
475 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
476 ("mlme_cmd_hdl(): pcmd_callback = "
477 "0x%p, cmdcode = 0x%x\n",
478 pcmd_callback, pcmd->cmdcode));
479 rtw_free_cmd_obj23a(pcmd);
480 } else {
481 /* todo: !!! fill rsp_buf to pcmd->rsp
482 if (pcmd->rsp!= NULL) */
483 /* need conider that free cmd_obj in
484 rtw_cmd_callback */
485 pcmd_callback(pcmd->padapter, pcmd);
486 }
487 } else {
488 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
489 ("%s: cmdcode = 0x%x callback not defined!\n",
490 __func__, pcmd->cmdcode));
491 rtw_free_cmd_obj23a(pcmd);
492 }
493
494 if (signal_pending (current))
495 flush_signals(current);
496
497 goto _next;
498
499 }
500 pcmdpriv->cmdthd_running = false;
501
502 /* free all cmd_obj resources */
503 do {
504 pcmd = rtw_dequeue_cmd(pcmdpriv);
505 if (!pcmd)
506 break;
507
508 rtw_free_cmd_obj23a(pcmd);
509 } while(1);
510
511 up(&pcmdpriv->terminate_cmdthread_sema);
512
513 complete_and_exit(NULL, 0);
514}
515
516u8 rtw_sitesurvey_cmd23a(struct rtw_adapter *padapter,
517 struct cfg80211_ssid *ssid, int ssid_num,
518 struct rtw_ieee80211_channel *ch, int ch_num)
519{
520 u8 res = _FAIL;
521 struct cmd_obj *ph2c;
522 struct sitesurvey_parm *psurveyPara;
523 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
524 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
525
526 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
527 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_SCAN, 1);
528
529#ifdef CONFIG_8723AU_P2P
530 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
531 p2p_ps_wk_cmd23a(padapter, P2P_PS_SCAN, 1);
532 }
533#endif /* CONFIG_8723AU_P2P */
534
535 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
536 if (!ph2c)
537 return _FAIL;
538
539 psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC);
540 if (!psurveyPara) {
541 kfree(ph2c);
542 return _FAIL;
543 }
544
545 rtw_free_network_queue23a(padapter, false);
546
547 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
548 ("%s: flush network queue\n", __func__));
549
550 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara,
551 GEN_CMD_CODE(_SiteSurvey));
552
553 /* psurveyPara->bsslimit = 48; */
554 psurveyPara->scan_mode = pmlmepriv->scan_mode;
555
556 /* prepare ssid list */
557 if (ssid) {
558 int i;
559 for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {
560 if (ssid[i].ssid_len) {
561 memcpy(&psurveyPara->ssid[i], &ssid[i],
562 sizeof(struct cfg80211_ssid));
563 psurveyPara->ssid_num++;
564 if (0)
565 DBG_8723A(FUNC_ADPT_FMT" ssid:(%s, %d)\n",
566 FUNC_ADPT_ARG(padapter),
567 psurveyPara->ssid[i].ssid,
568 psurveyPara->ssid[i].ssid_len);
569 }
570 }
571 }
572
573 /* prepare channel list */
574 if (ch) {
575 int i;
576 for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
577 if (ch[i].hw_value &&
578 !(ch[i].flags & IEEE80211_CHAN_DISABLED)) {
579 memcpy(&psurveyPara->ch[i], &ch[i],
580 sizeof(struct rtw_ieee80211_channel));
581 psurveyPara->ch_num++;
582 if (0)
583 DBG_8723A(FUNC_ADPT_FMT" ch:%u\n",
584 FUNC_ADPT_ARG(padapter),
585 psurveyPara->ch[i].hw_value);
586 }
587 }
588 }
589
590 set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
591
592 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
593
594 if (res == _SUCCESS) {
595 mod_timer(&pmlmepriv->scan_to_timer, jiffies +
596 msecs_to_jiffies(SCANNING_TIMEOUT));
597
598 rtw_led_control(padapter, LED_CTL_SITE_SURVEY);
599
600 pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
601 } else
602 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
603
604 return res;
605}
606
607void rtw_getbbrfreg_cmdrsp_callback23a(struct rtw_adapter *padapter,
608 struct cmd_obj *pcmd)
609{
610 kfree(pcmd->parmbuf);
611 kfree(pcmd);
612}
613
614u8 rtw_createbss_cmd23a(struct rtw_adapter *padapter)
615{
616 struct cmd_obj *pcmd;
617 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
618 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
619 struct wlan_bssid_ex *pdev_network;
620 u8 res = _SUCCESS;
621
622 pdev_network = &padapter->registrypriv.dev_network;
623
624 rtw_led_control(padapter, LED_CTL_START_TO_LINK);
625
626 if (pmlmepriv->assoc_ssid.ssid_len == 0) {
627 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
628 (" createbss for Any SSid:%s\n",
629 pmlmepriv->assoc_ssid.ssid));
630 } else {
631 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
632 (" createbss for SSid:%s\n",
633 pmlmepriv->assoc_ssid.ssid));
634 }
635
636 pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
637 if (!pcmd) {
638 res = _FAIL;
639 goto exit;
640 }
641
642 INIT_LIST_HEAD(&pcmd->list);
643 pcmd->cmdcode = _CreateBss_CMD_;
644 pcmd->parmbuf = (unsigned char *)pdev_network;
645 pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex*)pdev_network);
646 pcmd->rsp = NULL;
647 pcmd->rspsz = 0;
648
649 pdev_network->Length = pcmd->cmdsz;
650
651 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
652
653exit:
654
655 return res;
656}
657
658u8 rtw_joinbss_cmd23a(struct rtw_adapter *padapter,
659 struct wlan_network * pnetwork)
660{
661 u8 *auth, res = _SUCCESS;
662 uint t_len = 0;
663 struct wlan_bssid_ex *psecnetwork;
664 struct cmd_obj *pcmd;
665 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
666 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
667 struct qos_priv *pqospriv = &pmlmepriv->qospriv;
668 struct security_priv *psecuritypriv = &padapter->securitypriv;
669 struct registry_priv *pregistrypriv = &padapter->registrypriv;
670 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
671 enum ndis_802_11_net_infra ndis_network_mode;
672 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
673 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
674
675 ndis_network_mode = pnetwork->network.InfrastructureMode;
676
677 rtw_led_control(padapter, LED_CTL_START_TO_LINK);
678
679 if (pmlmepriv->assoc_ssid.ssid_len == 0) {
680 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
681 ("+Join cmd: Any SSid\n"));
682 } else {
683 RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_,
684 ("+Join cmd: SSid =[%s]\n",
685 pmlmepriv->assoc_ssid.ssid));
686 }
687
688 pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
689 if (!pcmd) {
690 res = _FAIL;
691 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
692 ("rtw_joinbss_cmd23a: memory allocate for cmd_obj "
693 "fail!!!\n"));
694 goto exit;
695 }
696 /* for IEs is fix buf size */
697 t_len = sizeof(struct wlan_bssid_ex);
698
699 /* for hidden ap to set fw_state here */
700 if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE)) {
701 switch (ndis_network_mode) {
702 case Ndis802_11IBSS:
703 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
704 break;
705 case Ndis802_11Infrastructure:
706 set_fwstate(pmlmepriv, WIFI_STATION_STATE);
707 break;
708 case Ndis802_11APMode:
709 case Ndis802_11AutoUnknown:
710 case Ndis802_11InfrastructureMax:
711 break;
712 }
713 }
714
715 psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss;
716 if (!psecnetwork) {
717 if (pcmd)
718 kfree(pcmd);
719
720 res = _FAIL;
721
722 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
723 ("rtw_joinbss_cmd23a :psecnetwork == NULL!!!\n"));
724
725 goto exit;
726 }
727
728 memset(psecnetwork, 0, t_len);
729
730 memcpy(psecnetwork, &pnetwork->network,
731 get_wlan_bssid_ex_sz(&pnetwork->network));
732
733 auth = &psecuritypriv->authenticator_ie[0];
734 psecuritypriv->authenticator_ie[0] =
735 (unsigned char)psecnetwork->IELength;
736
737 if ((psecnetwork->IELength-12) < (256-1)) {
738 memcpy(&psecuritypriv->authenticator_ie[1],
739 &psecnetwork->IEs[12], psecnetwork->IELength - 12);
740 } else {
741 memcpy(&psecuritypriv->authenticator_ie[1],
742 &psecnetwork->IEs[12], 256 - 1);
743 }
744
745 psecnetwork->IELength = 0;
746 /* Added by Albert 2009/02/18 */
747 /* If the the driver wants to use the bssid to create the
748 * connection. If not, we have to copy the connecting AP's
749 * MAC address to it so that the driver just has the bssid
750 * information for PMKIDList searching. */
751
752 if (pmlmepriv->assoc_by_bssid == false)
753 ether_addr_copy(&pmlmepriv->assoc_bssid[0],
754 &pnetwork->network.MacAddress[0]);
755
756 psecnetwork->IELength =
757 rtw_restruct_sec_ie23a(padapter, &pnetwork->network.IEs[0],
758 &psecnetwork->IEs[0],
759 pnetwork->network.IELength);
760
761 pqospriv->qos_option = 0;
762
763 if (pregistrypriv->wmm_enable) {
764 u32 tmp_len;
765
766 tmp_len = rtw_restruct_wmm_ie23a(padapter,
767 &pnetwork->network.IEs[0],
768 &psecnetwork->IEs[0],
769 pnetwork->network.IELength,
770 psecnetwork->IELength);
771
772 if (psecnetwork->IELength != tmp_len) {
773 psecnetwork->IELength = tmp_len;
774 /* There is WMM IE in this corresp. beacon */
775 pqospriv->qos_option = 1;
776 } else {
777 /* There is no WMM IE in this corresp. beacon */
778 pqospriv->qos_option = 0;
779 }
780 }
781
782 phtpriv->ht_option = false;
783 if (pregistrypriv->ht_enable) {
784 /* Added by Albert 2010/06/23 */
785 /* For the WEP mode, we will use the bg mode to do
786 the connection to avoid some IOT issue. */
787 /* Especially for Realtek 8192u SoftAP. */
788 if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
789 (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
790 (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
791 /* rtw_restructure_ht_ie23a */
792 rtw_restructure_ht_ie23a(padapter,
793 &pnetwork->network.IEs[0],
794 &psecnetwork->IEs[0],
795 pnetwork->network.IELength,
796 &psecnetwork->IELength);
797 }
798 }
799
800 pmlmeinfo->assoc_AP_vendor =
801 check_assoc_AP23a(pnetwork->network.IEs,
802 pnetwork->network.IELength);
803
804 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA)
805 padapter->pwrctrlpriv.smart_ps = 0;
806 else
807 padapter->pwrctrlpriv.smart_ps =
808 padapter->registrypriv.smart_ps;
809
810 DBG_8723A("%s: smart_ps =%d\n", __func__,
811 padapter->pwrctrlpriv.smart_ps);
812
813 /* get cmdsz before endian conversion */
814 pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);
815
816 INIT_LIST_HEAD(&pcmd->list);
817 pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */
818 pcmd->parmbuf = (unsigned char *)psecnetwork;
819 pcmd->rsp = NULL;
820 pcmd->rspsz = 0;
821
822 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
823exit:
824
825 return res;
826}
827
828u8 rtw_disassoc_cmd23a(struct rtw_adapter*padapter, u32 deauth_timeout_ms,
829 bool enqueue)
830{
831 struct cmd_obj *cmdobj = NULL;
832 struct disconnect_parm *param = NULL;
833 struct cmd_priv *cmdpriv = &padapter->cmdpriv;
834 u8 res = _SUCCESS;
835
836 RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_,
837 ("+rtw_disassoc_cmd23a\n"));
838
839 /* prepare cmd parameter */
840 param = kzalloc(sizeof(*param), GFP_ATOMIC);
841 if (param == NULL) {
842 res = _FAIL;
843 goto exit;
844 }
845 param->deauth_timeout_ms = deauth_timeout_ms;
846
847 if (enqueue) {
848 /* need enqueue, prepare cmd_obj and enqueue */
849 cmdobj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
850 if (!cmdobj) {
851 res = _FAIL;
852 kfree(param);
853 goto exit;
854 }
855 init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
856 res = rtw_enqueue_cmd23a(cmdpriv, cmdobj);
857 } else {
858 /* no need to enqueue, do the cmd hdl directly and
859 free cmd parameter */
860 if (H2C_SUCCESS != disconnect_hdl23a(padapter, (u8 *)param))
861 res = _FAIL;
862 kfree(param);
863 }
864
865exit:
866 return res;
867}
868
869u8 rtw_setopmode_cmd23a(struct rtw_adapter *padapter,
870 enum ndis_802_11_net_infra networktype)
871{
872 struct cmd_obj *ph2c;
873 struct setopmode_parm *psetop;
874 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
875 u8 res = _SUCCESS;
876
877 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
878 if (!ph2c) {
879 res = false;
880 goto exit;
881 }
882 psetop = kzalloc(sizeof(struct setopmode_parm), GFP_KERNEL);
883
884 if (!psetop) {
885 kfree(ph2c);
886 res = false;
887 goto exit;
888 }
889
890 init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
891 psetop->mode = (u8)networktype;
892
893 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
894exit:
895 return res;
896}
897
898u8 rtw_setstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 unicast_key)
899{
900 struct cmd_obj *ph2c;
901 struct set_stakey_parm *psetstakey_para;
902 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
903 struct set_stakey_rsp *psetstakey_rsp = NULL;
904 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
905 struct security_priv *psecuritypriv = &padapter->securitypriv;
906 struct sta_info *sta = (struct sta_info*)psta;
907 u8 res = _SUCCESS;
908
909 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
910 if (!ph2c) {
911 res = _FAIL;
912 goto exit;
913 }
914
915 psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
916 if (!psetstakey_para) {
917 kfree(ph2c);
918 res = _FAIL;
919 goto exit;
920 }
921
922 psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_KERNEL);
923 if (!psetstakey_rsp) {
924 kfree(ph2c);
925 kfree(psetstakey_para);
926 res = _FAIL;
927 goto exit;
928 }
929
930 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
931 ph2c->rsp = (u8 *) psetstakey_rsp;
932 ph2c->rspsz = sizeof(struct set_stakey_rsp);
933
934 ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
935
936 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
937 psetstakey_para->algorithm =
938 (unsigned char)psecuritypriv->dot11PrivacyAlgrthm;
939 } else {
940 GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm,
941 false);
942 }
943
944 if (unicast_key == true) {
945 memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);
946 } else {
947 int idx = psecuritypriv->dot118021XGrpKeyid;
948 memcpy(&psetstakey_para->key,
949 &psecuritypriv->dot118021XGrpKey[idx].skey, 16);
950 }
951
952 /* jeff: set this becasue at least sw key is ready */
953 padapter->securitypriv.busetkipkey = true;
954
955 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
956
957exit:
958
959 return res;
960}
961
962u8 rtw_clearstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 entry,
963 u8 enqueue)
964{
965 struct cmd_obj *ph2c;
966 struct set_stakey_parm *psetstakey_para;
967 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
968 struct set_stakey_rsp *psetstakey_rsp = NULL;
969 struct sta_info *sta = (struct sta_info *)psta;
970 u8 res = _SUCCESS;
971
972 if (!enqueue) {
973 clear_cam_entry23a(padapter, entry);
974 } else {
975 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
976 if (!ph2c) {
977 res = _FAIL;
978 goto exit;
979 }
980
981 psetstakey_para = kzalloc(sizeof(struct set_stakey_parm),
982 GFP_KERNEL);
983 if (!psetstakey_para) {
984 kfree(ph2c);
985 res = _FAIL;
986 goto exit;
987 }
988
989 psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp),
990 GFP_KERNEL);
991 if (!psetstakey_rsp) {
992 kfree(ph2c);
993 kfree(psetstakey_para);
994 res = _FAIL;
995 goto exit;
996 }
997
998 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para,
999 _SetStaKey_CMD_);
1000 ph2c->rsp = (u8 *) psetstakey_rsp;
1001 ph2c->rspsz = sizeof(struct set_stakey_rsp);
1002
1003 ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
1004
1005 psetstakey_para->algorithm = _NO_PRIVACY_;
1006
1007 psetstakey_para->id = entry;
1008
1009 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1010 }
1011exit:
1012 return res;
1013}
1014
1015u8 rtw_addbareq_cmd23a(struct rtw_adapter*padapter, u8 tid, u8 *addr)
1016{
1017 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1018 struct cmd_obj *ph2c;
1019 struct addBaReq_parm *paddbareq_parm;
1020 u8 res = _SUCCESS;
1021
1022 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1023 if (!ph2c) {
1024 res = _FAIL;
1025 goto exit;
1026 }
1027
1028 paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_ATOMIC);
1029 if (!paddbareq_parm) {
1030 kfree(ph2c);
1031 res = _FAIL;
1032 goto exit;
1033 }
1034
1035 paddbareq_parm->tid = tid;
1036 ether_addr_copy(paddbareq_parm->addr, addr);
1037
1038 init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm,
1039 GEN_CMD_CODE(_AddBAReq));
1040
1041 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1042exit:
1043 return res;
1044}
1045
1046u8 rtw_dynamic_chk_wk_cmd23a(struct rtw_adapter*padapter)
1047{
1048 struct cmd_obj *ph2c;
1049 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1050 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1051 u8 res = _SUCCESS;
1052
1053 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1054 if (!ph2c) {
1055 res = _FAIL;
1056 goto exit;
1057 }
1058
1059 pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
1060 if (!pdrvextra_cmd_parm) {
1061 kfree(ph2c);
1062 res = _FAIL;
1063 goto exit;
1064 }
1065
1066 pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
1067 pdrvextra_cmd_parm->type_size = 0;
1068 pdrvextra_cmd_parm->pbuf = (u8 *)padapter;
1069
1070 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
1071 GEN_CMD_CODE(_Set_Drv_Extra));
1072
1073 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1074exit:
1075
1076 return res;
1077}
1078
1079/*
1080 * This is only ever called from on_action_spct23a_ch_switch () which isn't
1081 * called from anywhere itself
1082 */
1083u8 rtw_set_ch_cmd23a(struct rtw_adapter*padapter, u8 ch, u8 bw, u8 ch_offset,
1084 u8 enqueue)
1085{
1086 struct cmd_obj *pcmdobj;
1087 struct set_ch_parm *set_ch_parm;
1088 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1089
1090 u8 res = _SUCCESS;
1091
1092 DBG_8723A(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
1093 FUNC_NDEV_ARG(padapter->pnetdev), ch, bw, ch_offset);
1094
1095 /* check input parameter */
1096
1097 /* prepare cmd parameter */
1098 set_ch_parm = kzalloc(sizeof(*set_ch_parm), GFP_KERNEL);
1099 if (!set_ch_parm) {
1100 res = _FAIL;
1101 goto exit;
1102 }
1103 set_ch_parm->ch = ch;
1104 set_ch_parm->bw = bw;
1105 set_ch_parm->ch_offset = ch_offset;
1106
1107 if (enqueue) {
1108 /* need enqueue, prepare cmd_obj and enqueue */
1109 pcmdobj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1110 if (!pcmdobj) {
1111 kfree(set_ch_parm);
1112 res = _FAIL;
1113 goto exit;
1114 }
1115
1116 init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm,
1117 GEN_CMD_CODE(_SetChannel));
1118 res = rtw_enqueue_cmd23a(pcmdpriv, pcmdobj);
1119 } else {
1120 /* no need to enqueue, do the cmd hdl directly and
1121 free cmd parameter */
1122 if (H2C_SUCCESS != set_ch_hdl23a(padapter, (u8 *)set_ch_parm))
1123 res = _FAIL;
1124
1125 kfree(set_ch_parm);
1126 }
1127
1128 /* do something based on res... */
1129exit:
1130
1131 DBG_8723A(FUNC_NDEV_FMT" res:%u\n", FUNC_NDEV_ARG(padapter->pnetdev),
1132 res);
1133
1134 return res;
1135}
1136
1137static void traffic_status_watchdog(struct rtw_adapter *padapter)
1138{
1139 u8 bEnterPS;
1140 u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false;
1141 u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false;
1142 u8 bHigherBusyTxTraffic = false;
1143 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1144
1145 /* */
1146 /* Determine if our traffic is busy now */
1147 /* */
1148 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1149#ifdef CONFIG_8723AU_BT_COEXIST
1150 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 50 ||
1151 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 50)
1152#else /* !CONFIG_8723AU_BT_COEXIST */
1153 /* if we raise bBusyTraffic in last watchdog, using
1154 lower threshold. */
1155 if (pmlmepriv->LinkDetectInfo.bBusyTraffic)
1156 BusyThreshold = 75;
1157 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold ||
1158 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold)
1159#endif /* !CONFIG_8723AU_BT_COEXIST */
1160 {
1161 bBusyTraffic = true;
1162
1163 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod >
1164 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
1165 bRxBusyTraffic = true;
1166 else
1167 bTxBusyTraffic = true;
1168 }
1169
1170 /* Higher Tx/Rx data. */
1171 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
1172 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
1173 bHigherBusyTraffic = true;
1174
1175 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod >
1176 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
1177 bHigherBusyRxTraffic = true;
1178 else
1179 bHigherBusyTxTraffic = true;
1180 }
1181
1182#ifdef CONFIG_8723AU_BT_COEXIST
1183 if (BT_1Ant(padapter) == false)
1184#endif
1185 {
1186 /* check traffic for powersaving. */
1187 if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod +
1188 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
1189 (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2))
1190 bEnterPS = false;
1191 else
1192 bEnterPS = true;
1193
1194 /* LeisurePS only work in infra mode. */
1195 if (bEnterPS)
1196 LPS_Enter23a(padapter);
1197 else
1198 LPS_Leave23a(padapter);
1199 }
1200 } else
1201 LPS_Leave23a(padapter);
1202
1203 pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
1204 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
1205 pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
1206 pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
1207 pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
1208 pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
1209 pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
1210 pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
1211 pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
1212}
1213
1214void dynamic_chk_wk_hdl(struct rtw_adapter *padapter, u8 *pbuf, int sz)
1215{
1216 struct mlme_priv *pmlmepriv;
1217
1218 padapter = (struct rtw_adapter *)pbuf;
1219 pmlmepriv = &padapter->mlmepriv;
1220
1221#ifdef CONFIG_8723AU_AP_MODE
1222 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
1223 expire_timeout_chk23a(padapter);
1224#endif
1225
1226 rtw_hal_sreset_xmit_status_check23a(padapter);
1227
1228 linked_status_chk23a(padapter);
1229 traffic_status_watchdog(padapter);
1230
1231 rtw_hal_dm_watchdog23a(padapter);
1232
1233#ifdef CONFIG_8723AU_BT_COEXIST
1234 /* */
1235 /* BT-Coexist */
1236 /* */
1237 BT_CoexistMechanism(padapter);
1238#endif
1239}
1240
1241void lps_ctrl_wk_hdl(struct rtw_adapter *padapter, u8 lps_ctrl_type)
1242{
1243 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
1244 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1245 u8 mstatus;
1246
1247 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
1248 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true))
1249 return;
1250
1251 switch (lps_ctrl_type)
1252 {
1253 case LPS_CTRL_SCAN:
1254#ifdef CONFIG_8723AU_BT_COEXIST
1255 BT_WifiScanNotify(padapter, true);
1256 if (BT_1Ant(padapter) == false)
1257#endif
1258 {
1259 if (check_fwstate(pmlmepriv, _FW_LINKED))
1260 LPS_Leave23a(padapter);
1261 }
1262 break;
1263 case LPS_CTRL_JOINBSS:
1264 LPS_Leave23a(padapter);
1265 break;
1266 case LPS_CTRL_CONNECT:
1267 mstatus = 1;/* connect */
1268 /* Reset LPS Setting */
1269 padapter->pwrctrlpriv.LpsIdleCount = 0;
1270 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_JOINBSSRPT,
1271 (u8 *)&mstatus);
1272#ifdef CONFIG_8723AU_BT_COEXIST
1273 BT_WifiMediaStatusNotify(padapter, mstatus);
1274#endif
1275 break;
1276 case LPS_CTRL_DISCONNECT:
1277 mstatus = 0;/* disconnect */
1278#ifdef CONFIG_8723AU_BT_COEXIST
1279 BT_WifiMediaStatusNotify(padapter, mstatus);
1280 if (BT_1Ant(padapter) == false)
1281#endif
1282 {
1283 LPS_Leave23a(padapter);
1284 }
1285 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_JOINBSSRPT,
1286 (u8 *)&mstatus);
1287 break;
1288 case LPS_CTRL_SPECIAL_PACKET:
1289 pwrpriv->DelayLPSLastTimeStamp = jiffies;
1290#ifdef CONFIG_8723AU_BT_COEXIST
1291 BT_SpecialPacketNotify(padapter);
1292 if (BT_1Ant(padapter) == false)
1293#endif
1294 {
1295 LPS_Leave23a(padapter);
1296 }
1297 break;
1298 case LPS_CTRL_LEAVE:
1299#ifdef CONFIG_8723AU_BT_COEXIST
1300 BT_LpsLeave(padapter);
1301 if (BT_1Ant(padapter) == false)
1302#endif
1303 {
1304 LPS_Leave23a(padapter);
1305 }
1306 break;
1307
1308 default:
1309 break;
1310 }
1311}
1312
1313u8 rtw_lps_ctrl_wk_cmd23a(struct rtw_adapter *padapter,
1314 u8 lps_ctrl_type, u8 enqueue)
1315{
1316 struct cmd_obj *ph2c;
1317 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1318 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1319 u8 res = _SUCCESS;
1320
1321 if (enqueue) {
1322 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1323 if (!ph2c) {
1324 res = _FAIL;
1325 goto exit;
1326 }
1327
1328 pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1329 GFP_ATOMIC);
1330 if (!pdrvextra_cmd_parm) {
1331 kfree(ph2c);
1332 res = _FAIL;
1333 goto exit;
1334 }
1335
1336 pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
1337 pdrvextra_cmd_parm->type_size = lps_ctrl_type;
1338 pdrvextra_cmd_parm->pbuf = NULL;
1339
1340 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
1341 GEN_CMD_CODE(_Set_Drv_Extra));
1342
1343 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1344 } else
1345 lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
1346exit:
1347
1348 return res;
1349}
1350
1351static void power_saving_wk_hdl(struct rtw_adapter *padapter, u8 *pbuf, int sz)
1352{
1353 rtw_ps_processor23a(padapter);
1354}
1355
1356#ifdef CONFIG_8723AU_P2P
1357u8 p2p_protocol_wk_cmd23a(struct rtw_adapter*padapter, int intCmdType)
1358{
1359 struct cmd_obj *ph2c;
1360 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1361 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1362 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1363 u8 res = _SUCCESS;
1364
1365 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1366 {
1367 return res;
1368 }
1369
1370 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1371 if (!ph2c) {
1372 res = _FAIL;
1373 goto exit;
1374 }
1375
1376 pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1377 GFP_ATOMIC);
1378 if (!pdrvextra_cmd_parm) {
1379 kfree(ph2c);
1380 res = _FAIL;
1381 goto exit;
1382 }
1383
1384 pdrvextra_cmd_parm->ec_id = P2P_PROTO_WK_CID;
1385 pdrvextra_cmd_parm->type_size = intCmdType; /* As the command tppe. */
1386 pdrvextra_cmd_parm->pbuf = NULL; /* Must be NULL here */
1387
1388 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
1389 GEN_CMD_CODE(_Set_Drv_Extra));
1390
1391 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1392exit:
1393
1394 return res;
1395}
1396#endif /* CONFIG_8723AU_P2P */
1397
1398u8 rtw_ps_cmd23a(struct rtw_adapter*padapter)
1399{
1400 struct cmd_obj *ppscmd;
1401 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1402 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1403
1404 u8 res = _SUCCESS;
1405
1406 ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1407 if (!ppscmd) {
1408 res = _FAIL;
1409 goto exit;
1410 }
1411
1412 pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1413 GFP_ATOMIC);
1414 if (!pdrvextra_cmd_parm) {
1415 kfree(ppscmd);
1416 res = _FAIL;
1417 goto exit;
1418 }
1419
1420 pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
1421 pdrvextra_cmd_parm->pbuf = NULL;
1422 init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm,
1423 GEN_CMD_CODE(_Set_Drv_Extra));
1424
1425 res = rtw_enqueue_cmd23a(pcmdpriv, ppscmd);
1426exit:
1427
1428 return res;
1429}
1430
1431#ifdef CONFIG_8723AU_AP_MODE
1432
1433static void rtw_chk_hi_queue_hdl(struct rtw_adapter *padapter)
1434{
1435 int cnt = 0;
1436 struct sta_info *psta_bmc;
1437 struct sta_priv *pstapriv = &padapter->stapriv;
1438
1439 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
1440 if (!psta_bmc)
1441 return;
1442
1443 if (psta_bmc->sleepq_len == 0) {
1444 u8 val = 0;
1445
1446 rtw23a_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
1447
1448 while(val == false) {
1449 msleep(100);
1450
1451 cnt++;
1452
1453 if (cnt>10)
1454 break;
1455
1456 rtw23a_hal_get_hwreg(padapter,
1457 HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
1458 }
1459
1460 if (cnt <= 10) {
1461 pstapriv->tim_bitmap &= ~BIT(0);
1462 pstapriv->sta_dz_bitmap &= ~BIT(0);
1463
1464 update_beacon23a(padapter, _TIM_IE_, NULL, false);
1465 } else /* re check again */
1466 rtw_chk_hi_queue_cmd23a(padapter);
1467 }
1468}
1469
1470u8 rtw_chk_hi_queue_cmd23a(struct rtw_adapter*padapter)
1471{
1472 struct cmd_obj *ph2c;
1473 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1474 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1475 u8 res = _SUCCESS;
1476
1477 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1478 if (!ph2c) {
1479 res = _FAIL;
1480 goto exit;
1481 }
1482
1483 pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1484 GFP_ATOMIC);
1485 if (!pdrvextra_cmd_parm) {
1486 kfree(ph2c);
1487 res = _FAIL;
1488 goto exit;
1489 }
1490
1491 pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
1492 pdrvextra_cmd_parm->type_size = 0;
1493 pdrvextra_cmd_parm->pbuf = NULL;
1494
1495 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
1496 GEN_CMD_CODE(_Set_Drv_Extra));
1497
1498 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1499exit:
1500
1501 return res;
1502}
1503#endif
1504
1505u8 rtw_c2h_wk_cmd23a(struct rtw_adapter *padapter, u8 *c2h_evt)
1506{
1507 struct cmd_obj *ph2c;
1508 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1509 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1510 u8 res = _SUCCESS;
1511
1512 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1513 if (!ph2c) {
1514 res = _FAIL;
1515 goto exit;
1516 }
1517
1518 pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1519 GFP_ATOMIC);
1520 if (!pdrvextra_cmd_parm) {
1521 kfree(ph2c);
1522 res = _FAIL;
1523 goto exit;
1524 }
1525
1526 pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
1527 pdrvextra_cmd_parm->type_size = c2h_evt?16:0;
1528 pdrvextra_cmd_parm->pbuf = c2h_evt;
1529
1530 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
1531 GEN_CMD_CODE(_Set_Drv_Extra));
1532
1533 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1534
1535exit:
1536
1537 return res;
1538}
1539
1540s32 c2h_evt_hdl(struct rtw_adapter *adapter, struct c2h_evt_hdr *c2h_evt,
1541 c2h_id_filter filter)
1542{
1543 s32 ret = _FAIL;
1544 u8 buf[16];
1545
1546 if (!c2h_evt) {
1547 /* No c2h event in cmd_obj, read c2h event before handling*/
1548 if (c2h_evt_read23a(adapter, buf) == _SUCCESS) {
1549 c2h_evt = (struct c2h_evt_hdr *)buf;
1550
1551 if (filter && filter(c2h_evt->id) == false)
1552 goto exit;
1553
1554 ret = rtw_hal_c2h_handler23a(adapter, c2h_evt);
1555 }
1556 } else {
1557
1558 if (filter && filter(c2h_evt->id) == false)
1559 goto exit;
1560
1561 ret = rtw_hal_c2h_handler23a(adapter, c2h_evt);
1562 }
1563exit:
1564 return ret;
1565}
1566
1567static void c2h_wk_callback(struct work_struct *work)
1568{
1569 struct evt_priv *evtpriv;
1570 struct rtw_adapter *adapter;
1571 struct c2h_evt_hdr *c2h_evt;
1572 c2h_id_filter ccx_id_filter;
1573
1574 evtpriv = container_of(work, struct evt_priv, c2h_wk);
1575 adapter = container_of(evtpriv, struct rtw_adapter, evtpriv);
1576 ccx_id_filter = rtw_hal_c2h_id_filter_ccx23a(adapter);
1577
1578 evtpriv->c2h_wk_alive = true;
1579
1580 while (!rtw_cbuf_empty23a(evtpriv->c2h_queue)) {
1581 c2h_evt = (struct c2h_evt_hdr *)
1582 rtw_cbuf_pop23a(evtpriv->c2h_queue);
1583 if (c2h_evt) {
1584 /* This C2H event is read, clear it */
1585 c2h_evt_clear23a(adapter);
1586 } else if ((c2h_evt = (struct c2h_evt_hdr *)
1587 kmalloc(16, GFP_ATOMIC))) {
1588 /* This C2H event is not read, read & clear now */
1589 if (c2h_evt_read23a(adapter, (u8*)c2h_evt) != _SUCCESS)
1590 continue;
1591 }
1592
1593 /* Special pointer to trigger c2h_evt_clear23a only */
1594 if ((void *)c2h_evt == (void *)evtpriv)
1595 continue;
1596
1597 if (!c2h_evt_exist(c2h_evt)) {
1598 kfree(c2h_evt);
1599 continue;
1600 }
1601
1602 if (ccx_id_filter(c2h_evt->id) == true) {
1603 /* Handle CCX report here */
1604 rtw_hal_c2h_handler23a(adapter, c2h_evt);
1605 kfree(c2h_evt);
1606 } else {
1607 /* Enqueue into cmd_thread for others */
1608 rtw_c2h_wk_cmd23a(adapter, (u8 *)c2h_evt);
1609 }
1610 }
1611
1612 evtpriv->c2h_wk_alive = false;
1613}
1614
1615u8 rtw_drvextra_cmd_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
1616{
1617 struct drvextra_cmd_parm *pdrvextra_cmd;
1618
1619 if (!pbuf)
1620 return H2C_PARAMETERS_ERROR;
1621
1622 pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
1623
1624 switch (pdrvextra_cmd->ec_id)
1625 {
1626 case DYNAMIC_CHK_WK_CID:
1627 dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf,
1628 pdrvextra_cmd->type_size);
1629 break;
1630 case POWER_SAVING_CTRL_WK_CID:
1631 power_saving_wk_hdl(padapter, pdrvextra_cmd->pbuf,
1632 pdrvextra_cmd->type_size);
1633 break;
1634 case LPS_CTRL_WK_CID:
1635 lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size);
1636 break;
1637#ifdef CONFIG_8723AU_P2P
1638 case P2P_PS_WK_CID:
1639 p2p_ps_wk_hdl23a(padapter, pdrvextra_cmd->type_size);
1640 break;
1641#endif /* CONFIG_8723AU_P2P */
1642 case P2P_PROTO_WK_CID:
1643 /* Commented by Albert 2011/07/01 */
1644 /* I used the type_size as the type command */
1645 p2p_protocol_wk_hdl23a(padapter, pdrvextra_cmd->type_size);
1646 break;
1647#ifdef CONFIG_8723AU_AP_MODE
1648 case CHECK_HIQ_WK_CID:
1649 rtw_chk_hi_queue_hdl(padapter);
1650 break;
1651#endif /* CONFIG_8723AU_AP_MODE */
1652 case C2H_WK_CID:
1653 c2h_evt_hdl(padapter,
1654 (struct c2h_evt_hdr *)pdrvextra_cmd->pbuf, NULL);
1655 break;
1656
1657 default:
1658 break;
1659 }
1660
1661 if (pdrvextra_cmd->pbuf && (pdrvextra_cmd->type_size > 0)) {
1662 kfree(pdrvextra_cmd->pbuf);
1663 pdrvextra_cmd->pbuf = NULL;
1664 }
1665
1666 return H2C_SUCCESS;
1667}
1668
1669void rtw_survey_cmd_callback23a(struct rtw_adapter *padapter,
1670 struct cmd_obj *pcmd)
1671{
1672 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1673
1674 if (pcmd->res == H2C_DROPPED) {
1675 /* TODO: cancel timer and do timeout handler directly... */
1676 /* need to make timeout handlerOS independent */
1677 mod_timer(&pmlmepriv->scan_to_timer,
1678 jiffies + msecs_to_jiffies(1));
1679 } else if (pcmd->res != H2C_SUCCESS) {
1680 mod_timer(&pmlmepriv->scan_to_timer,
1681 jiffies + msecs_to_jiffies(1));
1682 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1683 ("\n ********Error: MgntActrtw_set_802_11_bssid23a_"
1684 "LIST_SCAN Fail ************\n\n."));
1685 }
1686
1687 /* free cmd */
1688 rtw_free_cmd_obj23a(pcmd);
1689}
1690
1691void rtw_disassoc_cmd23a_callback(struct rtw_adapter *padapter,
1692 struct cmd_obj *pcmd)
1693{
1694 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1695
1696 if (pcmd->res != H2C_SUCCESS) {
1697 spin_lock_bh(&pmlmepriv->lock);
1698 set_fwstate(pmlmepriv, _FW_LINKED);
1699 spin_unlock_bh(&pmlmepriv->lock);
1700 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1701 ("\n ***Error: disconnect_cmd_callback Fail ***\n."));
1702 return;
1703 }
1704
1705 /* free cmd */
1706 rtw_free_cmd_obj23a(pcmd);
1707}
1708
1709void rtw_joinbss_cmd23a_callback(struct rtw_adapter *padapter,
1710 struct cmd_obj *pcmd)
1711{
1712 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1713
1714 if (pcmd->res == H2C_DROPPED) {
1715 /* TODO: cancel timer and do timeout handler directly... */
1716 /* need to make timeout handlerOS independent */
1717 mod_timer(&pmlmepriv->assoc_timer,
1718 jiffies + msecs_to_jiffies(1));
1719 } else if (pcmd->res != H2C_SUCCESS) {
1720 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1721 ("********Error:rtw_select_and_join_from_scanned_"
1722 "queue Wait Sema Fail ************\n"));
1723 mod_timer(&pmlmepriv->assoc_timer,
1724 jiffies + msecs_to_jiffies(1));
1725 }
1726
1727 rtw_free_cmd_obj23a(pcmd);
1728}
1729
1730void rtw_createbss_cmd23a_callback(struct rtw_adapter *padapter,
1731 struct cmd_obj *pcmd)
1732{
1733 struct sta_info *psta;
1734 struct wlan_network *pwlan;
1735 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1736 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
1737 struct wlan_network *tgt_network = &pmlmepriv->cur_network;
1738
1739 if (pcmd->res != H2C_SUCCESS) {
1740 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1741 ("\n ********Error: rtw_createbss_cmd23a_callback "
1742 "Fail ************\n\n."));
1743 mod_timer(&pmlmepriv->assoc_timer,
1744 jiffies + msecs_to_jiffies(1));
1745 }
1746
1747 del_timer_sync(&pmlmepriv->assoc_timer);
1748
1749 spin_lock_bh(&pmlmepriv->lock);
1750
1751 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1752 psta = rtw_get_stainfo23a(&padapter->stapriv,
1753 pnetwork->MacAddress);
1754 if (!psta) {
1755 psta = rtw_alloc_stainfo23a(&padapter->stapriv,
1756 pnetwork->MacAddress);
1757 if (!psta) {
1758 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1759 ("\nCan't alloc sta_info when "
1760 "createbss_cmd_callback\n"));
1761 goto createbss_cmd_fail ;
1762 }
1763 }
1764
1765 rtw_indicate_connect23a(padapter);
1766 } else {
1767 pwlan = rtw_alloc_network(pmlmepriv);
1768 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1769 if (!pwlan) {
1770 pwlan = rtw_get_oldest_wlan_network23a(&pmlmepriv->scanned_queue);
1771 if (!pwlan) {
1772 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1773 ("\n Error: can't get pwlan in "
1774 "rtw23a_joinbss_event_cb\n"));
1775 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1776 goto createbss_cmd_fail;
1777 }
1778 pwlan->last_scanned = jiffies;
1779 } else {
1780 list_add_tail(&pwlan->list,
1781 &pmlmepriv->scanned_queue.queue);
1782 }
1783
1784 pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
1785 memcpy(&pwlan->network, pnetwork, pnetwork->Length);
1786 /* pwlan->fixed = true; */
1787
1788 /* list_add_tail(&pwlan->list,
1789 &pmlmepriv->scanned_queue.queue); */
1790
1791 /* copy pdev_network information to
1792 pmlmepriv->cur_network */
1793 memcpy(&tgt_network->network, pnetwork,
1794 get_wlan_bssid_ex_sz(pnetwork));
1795
1796 /* reset DSConfig */
1797
1798 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1799
1800 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1801 /* we will set _FW_LINKED when there is one more sat to
1802 join us (rtw_stassoc_event_callback23a) */
1803 }
1804
1805createbss_cmd_fail:
1806
1807 spin_unlock_bh(&pmlmepriv->lock);
1808
1809 rtw_free_cmd_obj23a(pcmd);
1810}
1811
1812void rtw_setstaKey_cmdrsp_callback23a(struct rtw_adapter *padapter,
1813 struct cmd_obj *pcmd)
1814{
1815 struct sta_priv *pstapriv;
1816 struct set_stakey_rsp *psetstakey_rsp;
1817 struct sta_info *psta;
1818
1819 pstapriv = &padapter->stapriv;
1820 psetstakey_rsp = (struct set_stakey_rsp*) (pcmd->rsp);
1821 psta = rtw_get_stainfo23a(pstapriv, psetstakey_rsp->addr);
1822
1823 if (!psta) {
1824 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1825 ("\nERROR: rtw_setstaKey_cmdrsp_callback23a => "
1826 "can't get sta_info\n\n"));
1827 goto exit;
1828 }
1829
1830exit:
1831
1832 rtw_free_cmd_obj23a(pcmd);
1833}
1834
1835void rtw_setassocsta_cmdrsp_callback23a(struct rtw_adapter *padapter,
1836 struct cmd_obj *pcmd)
1837{
1838 struct sta_priv *pstapriv = &padapter->stapriv;
1839 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1840 struct set_assocsta_parm* passocsta_parm;
1841 struct set_assocsta_rsp* passocsta_rsp;
1842 struct sta_info *psta;
1843
1844 passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
1845 passocsta_rsp = (struct set_assocsta_rsp*) (pcmd->rsp);
1846 psta = rtw_get_stainfo23a(pstapriv, passocsta_parm->addr);
1847
1848 if (psta == NULL) {
1849 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1850 ("\nERROR: setassocsta_cmdrsp_callbac => can't "
1851 "get sta_info\n\n"));
1852 goto exit;
1853 }
1854
1855 psta->aid = psta->mac_id = passocsta_rsp->cam_id;
1856
1857 spin_lock_bh(&pmlmepriv->lock);
1858
1859 if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) &&
1860 (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true))
1861 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1862
1863 set_fwstate(pmlmepriv, _FW_LINKED);
1864 spin_unlock_bh(&pmlmepriv->lock);
1865
1866exit:
1867 rtw_free_cmd_obj23a(pcmd);
1868}
1869
1870void rtw_getrttbl_cmd_cmdrsp_callback(struct rtw_adapter *padapter,
1871 struct cmd_obj *pcmd)
1872{
1873 rtw_free_cmd_obj23a(pcmd);
1874}
diff --git a/drivers/staging/rtl8723au/core/rtw_efuse.c b/drivers/staging/rtl8723au/core/rtw_efuse.c
new file mode 100644
index 000000000000..94221ee45bd2
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_efuse.c
@@ -0,0 +1,718 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _RTW_EFUSE_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19
20#include <rtw_efuse.h>
21
22/*------------------------Define local variable------------------------------*/
23
24/* */
25#define REG_EFUSE_CTRL 0x0030
26#define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */
27/* */
28
29/*-----------------------------------------------------------------------------
30 * Function: Efuse_PowerSwitch23a
31 *
32 * Overview: When we want to enable write operation, we should change to
33 * pwr on state. When we stop write, we should switch to 500k mode
34 * and disable LDO 2.5V.
35 *
36 * Input: NONE
37 *
38 * Output: NONE
39 *
40 * Return: NONE
41 *
42 * Revised History:
43 * When Who Remark
44 * 11/17/2008 MHC Create Version 0.
45 *
46 *---------------------------------------------------------------------------*/
47void
48Efuse_PowerSwitch23a(
49 struct rtw_adapter * pAdapter,
50 u8 bWrite,
51 u8 PwrState)
52{
53 pAdapter->HalFunc.EfusePowerSwitch(pAdapter, bWrite, PwrState);
54}
55
56/*-----------------------------------------------------------------------------
57 * Function: efuse_GetCurrentSize23a
58 *
59 * Overview: Get current efuse size!!!
60 *
61 * Input: NONE
62 *
63 * Output: NONE
64 *
65 * Return: NONE
66 *
67 * Revised History:
68 * When Who Remark
69 * 11/16/2008 MHC Create Version 0.
70 *
71 *---------------------------------------------------------------------------*/
72u16
73Efuse_GetCurrentSize23a(struct rtw_adapter *pAdapter, u8 efuseType)
74{
75 u16 ret = 0;
76
77 ret = pAdapter->HalFunc.EfuseGetCurrentSize(pAdapter, efuseType);
78
79 return ret;
80}
81
82/* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */
83u8
84Efuse_CalculateWordCnts23a(u8 word_en)
85{
86 u8 word_cnts = 0;
87 if (!(word_en & BIT(0))) word_cnts++; /* 0 : write enable */
88 if (!(word_en & BIT(1))) word_cnts++;
89 if (!(word_en & BIT(2))) word_cnts++;
90 if (!(word_en & BIT(3))) word_cnts++;
91 return word_cnts;
92}
93
94/* */
95/* Description: */
96/* Execute E-Fuse read byte operation. */
97/* Refered from SD1 Richard. */
98/* */
99/* Assumption: */
100/* 1. Boot from E-Fuse and successfully auto-load. */
101/* 2. PASSIVE_LEVEL (USB interface) */
102/* */
103/* Created by Roger, 2008.10.21. */
104/* */
105void
106ReadEFuseByte23a(struct rtw_adapter *Adapter, u16 _offset, u8 *pbuf)
107{
108 u32 value32;
109 u8 readbyte;
110 u16 retry;
111 /* u32 start = rtw_get_current_time(); */
112
113 /* Write Address */
114 rtw_write8(Adapter, EFUSE_CTRL+1, (_offset & 0xff));
115 readbyte = rtw_read8(Adapter, EFUSE_CTRL+2);
116 rtw_write8(Adapter, EFUSE_CTRL+2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
117
118 /* Write bit 32 0 */
119 readbyte = rtw_read8(Adapter, EFUSE_CTRL+3);
120 rtw_write8(Adapter, EFUSE_CTRL+3, (readbyte & 0x7f));
121
122 /* Check bit 32 read-ready */
123 retry = 0;
124 value32 = rtw_read32(Adapter, EFUSE_CTRL);
125 /* while(!(((value32 >> 24) & 0xff) & 0x80) && (retry<10)) */
126 while(!(((value32 >> 24) & 0xff) & 0x80) && (retry<10000))
127 {
128 value32 = rtw_read32(Adapter, EFUSE_CTRL);
129 retry++;
130 }
131
132 /* 20100205 Joseph: Add delay suggested by SD1 Victor. */
133 /* This fix the problem that Efuse read error in high temperature condition. */
134 /* Designer says that there shall be some delay after ready bit is set, or the */
135 /* result will always stay on last data we read. */
136 udelay(50);
137 value32 = rtw_read32(Adapter, EFUSE_CTRL);
138
139 *pbuf = (u8)(value32 & 0xff);
140 /* DBG_8723A("ReadEFuseByte23a _offset:%08u, in %d ms\n", _offset , rtw_get_passing_time_ms23a(start)); */
141}
142
143/* */
144/* Description: */
145/* 1. Execute E-Fuse read byte operation according as map offset and */
146/* save to E-Fuse table. */
147/* 2. Refered from SD1 Richard. */
148/* */
149/* Assumption: */
150/* 1. Boot from E-Fuse and successfully auto-load. */
151/* 2. PASSIVE_LEVEL (USB interface) */
152/* */
153/* Created by Roger, 2008.10.21. */
154/* */
155/* 2008/12/12 MH 1. Reorganize code flow and reserve bytes. and add description. */
156/* 2. Add efuse utilization collect. */
157/* 2008/12/22 MH Read Efuse must check if we write section 1 data again!!! Sec1 */
158/* write addr must be after sec5. */
159/* */
160
161void
162efuse_ReadEFuse(struct rtw_adapter *Adapter, u8 efuseType,
163 u16 _offset, u16 _size_byte, u8 *pbuf);
164void
165efuse_ReadEFuse(struct rtw_adapter *Adapter, u8 efuseType,
166 u16 _offset, u16 _size_byte, u8 *pbuf)
167{
168 Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset,
169 _size_byte, pbuf);
170}
171
172void
173EFUSE_GetEfuseDefinition23a(struct rtw_adapter *pAdapter, u8 efuseType,
174 u8 type, void *pOut)
175{
176 pAdapter->HalFunc.EFUSEGetEfuseDefinition(pAdapter, efuseType,
177 type, pOut);
178}
179
180/*-----------------------------------------------------------------------------
181 * Function: EFUSE_Read1Byte23a
182 *
183 * Overview: Copy from WMAC fot EFUSE read 1 byte.
184 *
185 * Input: NONE
186 *
187 * Output: NONE
188 *
189 * Return: NONE
190 *
191 * Revised History:
192 * When Who Remark
193 * 09/23/2008 MHC Copy from WMAC.
194 *
195 *---------------------------------------------------------------------------*/
196u8
197EFUSE_Read1Byte23a(struct rtw_adapter *Adapter, u16 Address)
198{
199 u8 data;
200 u8 Bytetemp = {0x00};
201 u8 temp = {0x00};
202 u32 k = 0;
203 u16 contentLen = 0;
204
205 EFUSE_GetEfuseDefinition23a(Adapter, EFUSE_WIFI,
206 TYPE_EFUSE_REAL_CONTENT_LEN,
207 (void *)&contentLen);
208
209 if (Address < contentLen) /* E-fuse 512Byte */
210 {
211 /* Write E-fuse Register address bit0~7 */
212 temp = Address & 0xFF;
213 rtw_write8(Adapter, EFUSE_CTRL+1, temp);
214 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+2);
215 /* Write E-fuse Register address bit8~9 */
216 temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
217 rtw_write8(Adapter, EFUSE_CTRL+2, temp);
218
219 /* Write 0x30[31]= 0 */
220 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
221 temp = Bytetemp & 0x7F;
222 rtw_write8(Adapter, EFUSE_CTRL+3, temp);
223
224 /* Wait Write-ready (0x30[31]= 1) */
225 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
226 while(!(Bytetemp & 0x80))
227 {
228 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
229 k++;
230 if (k == 1000)
231 {
232 k = 0;
233 break;
234 }
235 }
236 data = rtw_read8(Adapter, EFUSE_CTRL);
237 return data;
238 }
239 else
240 return 0xFF;
241}/* EFUSE_Read1Byte23a */
242
243/*-----------------------------------------------------------------------------
244 * Function: EFUSE_Write1Byte
245 *
246 * Overview: Copy from WMAC fot EFUSE write 1 byte.
247 *
248 * Input: NONE
249 *
250 * Output: NONE
251 *
252 * Return: NONE
253 *
254 * Revised History:
255 * When Who Remark
256 * 09/23/2008 MHC Copy from WMAC.
257 *
258 *---------------------------------------------------------------------------*/
259
260void
261EFUSE_Write1Byte(
262 struct rtw_adapter * Adapter,
263 u16 Address,
264 u8 Value);
265void
266EFUSE_Write1Byte(
267 struct rtw_adapter * Adapter,
268 u16 Address,
269 u8 Value)
270{
271 u8 Bytetemp = {0x00};
272 u8 temp = {0x00};
273 u32 k = 0;
274 u16 contentLen = 0;
275
276 /* RT_TRACE(COMP_EFUSE, DBG_LOUD, ("Addr =%x Data =%x\n", Address, Value)); */
277 EFUSE_GetEfuseDefinition23a(Adapter, EFUSE_WIFI,
278 TYPE_EFUSE_REAL_CONTENT_LEN,
279 (void *)&contentLen);
280
281 if (Address < contentLen) /* E-fuse 512Byte */
282 {
283 rtw_write8(Adapter, EFUSE_CTRL, Value);
284
285 /* Write E-fuse Register address bit0~7 */
286 temp = Address & 0xFF;
287 rtw_write8(Adapter, EFUSE_CTRL+1, temp);
288 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+2);
289
290 /* Write E-fuse Register address bit8~9 */
291 temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
292 rtw_write8(Adapter, EFUSE_CTRL+2, temp);
293
294 /* Write 0x30[31]= 1 */
295 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
296 temp = Bytetemp | 0x80;
297 rtw_write8(Adapter, EFUSE_CTRL+3, temp);
298
299 /* Wait Write-ready (0x30[31]= 0) */
300 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
301 while(Bytetemp & 0x80)
302 {
303 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
304 k++;
305 if (k == 100)
306 {
307 k = 0;
308 break;
309 }
310 }
311 }
312}/* EFUSE_Write1Byte */
313
314/* 11/16/2008 MH Read one byte from real Efuse. */
315u8
316efuse_OneByteRead23a(struct rtw_adapter *pAdapter, u16 addr, u8 *data)
317{
318 u8 tmpidx = 0;
319 u8 bResult;
320
321 /* -----------------e-fuse reg ctrl --------------------------------- */
322 /* address */
323 rtw_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
324 rtw_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) &0x03)) |
325 (rtw_read8(pAdapter, EFUSE_CTRL+2)&0xFC));
326
327 rtw_write8(pAdapter, EFUSE_CTRL+3, 0x72);/* read cmd */
328
329 while(!(0x80 &rtw_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx<100))
330 tmpidx++;
331 if (tmpidx < 100) {
332 *data = rtw_read8(pAdapter, EFUSE_CTRL);
333 bResult = true;
334 } else {
335 *data = 0xff;
336 bResult = false;
337 }
338 return bResult;
339}
340
341/* 11/16/2008 MH Write one byte to reald Efuse. */
342u8
343efuse_OneByteWrite23a(struct rtw_adapter *pAdapter, u16 addr, u8 data)
344{
345 u8 tmpidx = 0;
346 u8 bResult;
347
348 /* RT_TRACE(COMP_EFUSE, DBG_LOUD, ("Addr = %x Data =%x\n", addr, data)); */
349
350 /* return 0; */
351
352 /* -----------------e-fuse reg ctrl --------------------------------- */
353 /* address */
354 rtw_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
355 rtw_write8(pAdapter, EFUSE_CTRL+2,
356 (rtw_read8(pAdapter, EFUSE_CTRL+2)&0xFC)|(u8)((addr>>8)&0x03));
357 rtw_write8(pAdapter, EFUSE_CTRL, data);/* data */
358
359 rtw_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */
360
361 while((0x80 & rtw_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx<100)) {
362 tmpidx++;
363 }
364
365 if (tmpidx<100)
366 {
367 bResult = true;
368 }
369 else
370 {
371 bResult = false;
372 }
373
374 return bResult;
375}
376
377int
378Efuse_PgPacketRead23a(struct rtw_adapter *pAdapter, u8 offset, u8 *data)
379{
380 int ret = 0;
381
382 ret = pAdapter->HalFunc.Efuse_PgPacketRead23a(pAdapter, offset, data);
383
384 return ret;
385}
386
387int
388Efuse_PgPacketWrite23a(struct rtw_adapter *pAdapter, u8 offset,
389 u8 word_en, u8 *data)
390{
391 int ret;
392
393 ret = pAdapter->HalFunc.Efuse_PgPacketWrite23a(pAdapter, offset,
394 word_en, data);
395
396 return ret;
397}
398
399/*-----------------------------------------------------------------------------
400 * Function: efuse_WordEnableDataRead23a
401 *
402 * Overview: Read allowed word in current efuse section data.
403 *
404 * Input: NONE
405 *
406 * Output: NONE
407 *
408 * Return: NONE
409 *
410 * Revised History:
411 * When Who Remark
412 * 11/16/2008 MHC Create Version 0.
413 * 11/21/2008 MHC Fix Write bug when we only enable late word.
414 *
415 *---------------------------------------------------------------------------*/
416void
417efuse_WordEnableDataRead23a(u8 word_en,
418 u8 *sourdata,
419 u8 *targetdata)
420{
421 if (!(word_en&BIT(0)))
422 {
423 targetdata[0] = sourdata[0];
424 targetdata[1] = sourdata[1];
425 }
426 if (!(word_en&BIT(1)))
427 {
428 targetdata[2] = sourdata[2];
429 targetdata[3] = sourdata[3];
430 }
431 if (!(word_en&BIT(2)))
432 {
433 targetdata[4] = sourdata[4];
434 targetdata[5] = sourdata[5];
435 }
436 if (!(word_en&BIT(3)))
437 {
438 targetdata[6] = sourdata[6];
439 targetdata[7] = sourdata[7];
440 }
441}
442
443u8
444Efuse_WordEnableDataWrite23a(struct rtw_adapter *pAdapter, u16 efuse_addr,
445 u8 word_en, u8 *data)
446{
447 u8 ret = 0;
448
449 ret = pAdapter->HalFunc.Efuse_WordEnableDataWrite23a(pAdapter, efuse_addr,
450 word_en, data);
451
452 return ret;
453}
454
455static u8 efuse_read8(struct rtw_adapter *padapter, u16 address, u8 *value)
456{
457 return efuse_OneByteRead23a(padapter, address, value);
458}
459
460static u8 efuse_write8(struct rtw_adapter *padapter, u16 address, u8 *value)
461{
462 return efuse_OneByteWrite23a(padapter, address, *value);
463}
464
465/*
466 * read/wirte raw efuse data
467 */
468u8 rtw_efuse_access23a(struct rtw_adapter *padapter, u8 bWrite, u16 start_addr,
469 u16 cnts, u8 *data)
470{
471 int i = 0;
472 u16 real_content_len = 0, max_available_size = 0;
473 u8 res = _FAIL ;
474 u8 (*rw8)(struct rtw_adapter *, u16, u8*);
475
476 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
477 TYPE_EFUSE_REAL_CONTENT_LEN,
478 (void *)&real_content_len);
479 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
480 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
481 (void *)&max_available_size);
482
483 if (start_addr > real_content_len)
484 return _FAIL;
485
486 if (true == bWrite) {
487 if ((start_addr + cnts) > max_available_size)
488 return _FAIL;
489 rw8 = &efuse_write8;
490 } else
491 rw8 = &efuse_read8;
492
493 Efuse_PowerSwitch23a(padapter, bWrite, true);
494
495 /* e-fuse one byte read / write */
496 for (i = 0; i < cnts; i++) {
497 if (start_addr >= real_content_len) {
498 res = _FAIL;
499 break;
500 }
501
502 res = rw8(padapter, start_addr++, data++);
503 if (_FAIL == res) break;
504 }
505
506 Efuse_PowerSwitch23a(padapter, bWrite, false);
507
508 return res;
509}
510/* */
511u16 efuse_GetMaxSize23a(struct rtw_adapter *padapter)
512{
513 u16 max_size;
514 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
515 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
516 (void *)&max_size);
517 return max_size;
518}
519/* */
520u8 efuse_GetCurrentSize23a(struct rtw_adapter *padapter, u16 *size)
521{
522 Efuse_PowerSwitch23a(padapter, false, true);
523 *size = Efuse_GetCurrentSize23a(padapter, EFUSE_WIFI);
524 Efuse_PowerSwitch23a(padapter, false, false);
525
526 return _SUCCESS;
527}
528/* */
529u8 rtw_efuse_map_read23a(struct rtw_adapter *padapter, u16 addr, u16 cnts, u8 *data)
530{
531 u16 mapLen = 0;
532
533 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
534 TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
535
536 if ((addr + cnts) > mapLen)
537 return _FAIL;
538
539 Efuse_PowerSwitch23a(padapter, false, true);
540
541 efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data);
542
543 Efuse_PowerSwitch23a(padapter, false, false);
544
545 return _SUCCESS;
546}
547
548u8 rtw_BT_efuse_map_read23a(struct rtw_adapter *padapter, u16 addr, u16 cnts, u8 *data)
549{
550 u16 mapLen = 0;
551
552 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
553 TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
554
555 if ((addr + cnts) > mapLen)
556 return _FAIL;
557
558 Efuse_PowerSwitch23a(padapter, false, true);
559
560 efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data);
561
562 Efuse_PowerSwitch23a(padapter, false, false);
563
564 return _SUCCESS;
565}
566
567/*-----------------------------------------------------------------------------
568 * Function: Efuse_ReadAllMap
569 *
570 * Overview: Read All Efuse content
571 *
572 * Input: NONE
573 *
574 * Output: NONE
575 *
576 * Return: NONE
577 *
578 * Revised History:
579 * When Who Remark
580 * 11/11/2008 MHC Create Version 0.
581 *
582 *---------------------------------------------------------------------------*/
583void
584Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, u8 *Efuse);
585void
586Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, u8 *Efuse)
587{
588 u16 mapLen = 0;
589
590 Efuse_PowerSwitch23a(pAdapter, false, true);
591
592 EFUSE_GetEfuseDefinition23a(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN,
593 (void *)&mapLen);
594
595 efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse);
596
597 Efuse_PowerSwitch23a(pAdapter, false, false);
598}
599
600/*-----------------------------------------------------------------------------
601 * Function: efuse_ShadowRead1Byte
602 * efuse_ShadowRead2Byte
603 * efuse_ShadowRead4Byte
604 *
605 * Overview: Read from efuse init map by one/two/four bytes !!!!!
606 *
607 * Input: NONE
608 *
609 * Output: NONE
610 *
611 * Return: NONE
612 *
613 * Revised History:
614 * When Who Remark
615 * 11/12/2008 MHC Create Version 0.
616 *
617 *---------------------------------------------------------------------------*/
618static void
619efuse_ShadowRead1Byte(
620 struct rtw_adapter * pAdapter,
621 u16 Offset,
622 u8 *Value)
623{
624 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
625
626 *Value = pEEPROM->efuse_eeprom_data[Offset];
627} /* EFUSE_ShadowRead23a1Byte */
628
629/* Read Two Bytes */
630static void
631efuse_ShadowRead2Byte(
632 struct rtw_adapter * pAdapter,
633 u16 Offset,
634 u16 *Value)
635{
636 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
637
638 *Value = pEEPROM->efuse_eeprom_data[Offset];
639 *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
640} /* EFUSE_ShadowRead23a2Byte */
641
642/* Read Four Bytes */
643static void
644efuse_ShadowRead4Byte(
645 struct rtw_adapter * pAdapter,
646 u16 Offset,
647 u32 *Value)
648{
649 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
650
651 *Value = pEEPROM->efuse_eeprom_data[Offset];
652 *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
653 *Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16;
654 *Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24;
655} /* efuse_ShadowRead4Byte */
656
657/*-----------------------------------------------------------------------------
658 * Function: EFUSE_ShadowMapUpdate23a
659 *
660 * Overview: Transfer current EFUSE content to shadow init and modify map.
661 *
662 * Input: NONE
663 *
664 * Output: NONE
665 *
666 * Return: NONE
667 *
668 * Revised History:
669 * When Who Remark
670 * 11/13/2008 MHC Create Version 0.
671 *
672 *---------------------------------------------------------------------------*/
673void EFUSE_ShadowMapUpdate23a(struct rtw_adapter *pAdapter, u8 efuseType)
674{
675 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
676 u16 mapLen = 0;
677
678 EFUSE_GetEfuseDefinition23a(pAdapter, efuseType,
679 TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
680
681 if (pEEPROM->bautoload_fail_flag == true)
682 memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
683 else
684 Efuse_ReadAllMap(pAdapter, efuseType,
685 pEEPROM->efuse_eeprom_data);
686
687}/* EFUSE_ShadowMapUpdate23a */
688
689/*-----------------------------------------------------------------------------
690 * Function: EFUSE_ShadowRead23a
691 *
692 * Overview: Read from efuse init map !!!!!
693 *
694 * Input: NONE
695 *
696 * Output: NONE
697 *
698 * Return: NONE
699 *
700 * Revised History:
701 * When Who Remark
702 * 11/12/2008 MHC Create Version 0.
703 *
704 *---------------------------------------------------------------------------*/
705void
706EFUSE_ShadowRead23a(
707 struct rtw_adapter * pAdapter,
708 u8 Type,
709 u16 Offset,
710 u32 *Value )
711{
712 if (Type == 1)
713 efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value);
714 else if (Type == 2)
715 efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
716 else if (Type == 4)
717 efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);
718} /* EFUSE_ShadowRead23a */
diff --git a/drivers/staging/rtl8723au/core/rtw_ieee80211.c b/drivers/staging/rtl8723au/core/rtw_ieee80211.c
new file mode 100644
index 000000000000..8287f447cbdd
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_ieee80211.c
@@ -0,0 +1,1861 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _IEEE80211_C
16
17#include <drv_types.h>
18#include <linux/ieee80211.h>
19#include <ieee80211.h>
20#include <wifi.h>
21#include <osdep_service.h>
22#include <wlan_bssdef.h>
23
24u8 RTW_WPA_OUI23A_TYPE[] = { 0x00, 0x50, 0xf2, 1 };
25u16 RTW_WPA_VERSION23A = 1;
26u8 WPA_AUTH_KEY_MGMT_NONE23A[] = { 0x00, 0x50, 0xf2, 0 };
27u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X23A[] = { 0x00, 0x50, 0xf2, 1 };
28u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[] = { 0x00, 0x50, 0xf2, 2 };
29u8 WPA_CIPHER_SUITE_NONE23A[] = { 0x00, 0x50, 0xf2, 0 };
30u8 WPA_CIPHER_SUITE_WEP4023A[] = { 0x00, 0x50, 0xf2, 1 };
31u8 WPA_CIPHER_SUITE_TKIP23A[] = { 0x00, 0x50, 0xf2, 2 };
32u8 WPA_CIPHER_SUITE_WRAP23A[] = { 0x00, 0x50, 0xf2, 3 };
33u8 WPA_CIPHER_SUITE_CCMP23A[] = { 0x00, 0x50, 0xf2, 4 };
34u8 WPA_CIPHER_SUITE_WEP10423A[] = { 0x00, 0x50, 0xf2, 5 };
35
36u16 RSN_VERSION_BSD23A = 1;
37u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X23A[] = { 0x00, 0x0f, 0xac, 1 };
38u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[] = { 0x00, 0x0f, 0xac, 2 };
39u8 RSN_CIPHER_SUITE_NONE23A[] = { 0x00, 0x0f, 0xac, 0 };
40u8 RSN_CIPHER_SUITE_WEP4023A[] = { 0x00, 0x0f, 0xac, 1 };
41u8 RSN_CIPHER_SUITE_TKIP23A[] = { 0x00, 0x0f, 0xac, 2 };
42u8 RSN_CIPHER_SUITE_WRAP23A[] = { 0x00, 0x0f, 0xac, 3 };
43u8 RSN_CIPHER_SUITE_CCMP23A[] = { 0x00, 0x0f, 0xac, 4 };
44u8 RSN_CIPHER_SUITE_WEP10423A[] = { 0x00, 0x0f, 0xac, 5 };
45/* */
46/* for adhoc-master to generate ie and provide supported-rate to fw */
47/* */
48
49static u8 WIFI_CCKRATES[] =
50{(IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK),
51 (IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK),
52 (IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK),
53 (IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK)};
54
55static u8 WIFI_OFDMRATES[] =
56{(IEEE80211_OFDM_RATE_6MB),
57 (IEEE80211_OFDM_RATE_9MB),
58 (IEEE80211_OFDM_RATE_12MB),
59 (IEEE80211_OFDM_RATE_18MB),
60 (IEEE80211_OFDM_RATE_24MB),
61 IEEE80211_OFDM_RATE_36MB,
62 IEEE80211_OFDM_RATE_48MB,
63 IEEE80211_OFDM_RATE_54MB};
64
65int rtw_get_bit_value_from_ieee_value23a(u8 val)
66{
67 unsigned char dot11_rate_table[]=
68 {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 0};
69
70 int i = 0;
71 while (dot11_rate_table[i] != 0) {
72 if (dot11_rate_table[i] == val)
73 return BIT(i);
74 i++;
75 }
76 return 0;
77}
78
79uint rtw_is_cckrates_included23a(u8 *rate)
80{
81 u32 i = 0;
82
83 while (rate[i] != 0) {
84 if ((((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) ||
85 (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22))
86 return true;
87 i++;
88 }
89
90 return false;
91}
92
93uint rtw_is_cckratesonly_included23a(u8 *rate)
94{
95 u32 i = 0;
96
97 while (rate[i] != 0) {
98 if ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
99 (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22))
100 return false;
101
102 i++;
103 }
104
105 return true;
106}
107
108int rtw_check_network_type23a(unsigned char *rate, int ratelen, int channel)
109{
110 if (channel > 14) {
111 if ((rtw_is_cckrates_included23a(rate)) == true)
112 return WIRELESS_INVALID;
113 else
114 return WIRELESS_11A;
115 } else { /* could be pure B, pure G, or B/G */
116 if ((rtw_is_cckratesonly_included23a(rate)) == true)
117 return WIRELESS_11B;
118 else if ((rtw_is_cckrates_included23a(rate)) == true)
119 return WIRELESS_11BG;
120 else
121 return WIRELESS_11G;
122 }
123}
124
125u8 *rtw_set_fixed_ie23a(unsigned char *pbuf, unsigned int len,
126 unsigned char *source, unsigned int *frlen)
127{
128 memcpy((void *)pbuf, (void *)source, len);
129 *frlen = *frlen + len;
130 return pbuf + len;
131}
132
133/* rtw_set_ie23a will update frame length */
134u8 *rtw_set_ie23a(u8 *pbuf, int index, uint len, u8 *source, uint *frlen)
135{
136
137 *pbuf = (u8)index;
138
139 *(pbuf + 1) = (u8)len;
140
141 if (len > 0)
142 memcpy((void *)(pbuf + 2), (void *)source, len);
143
144 *frlen = *frlen + (len + 2);
145
146
147 return pbuf + len + 2;
148}
149
150inline u8 *rtw_set_ie23a_ch_switch (u8 *buf, u32 *buf_len, u8 ch_switch_mode,
151 u8 new_ch, u8 ch_switch_cnt)
152{
153 u8 ie_data[3];
154
155 ie_data[0] = ch_switch_mode;
156 ie_data[1] = new_ch;
157 ie_data[2] = ch_switch_cnt;
158 return rtw_set_ie23a(buf, WLAN_EID_CHANNEL_SWITCH, 3, ie_data, buf_len);
159}
160
161inline u8 secondary_ch_offset_to_hal_ch_offset23a(u8 ch_offset)
162{
163 if (ch_offset == SCN)
164 return HAL_PRIME_CHNL_OFFSET_DONT_CARE;
165 else if (ch_offset == SCA)
166 return HAL_PRIME_CHNL_OFFSET_UPPER;
167 else if (ch_offset == SCB)
168 return HAL_PRIME_CHNL_OFFSET_LOWER;
169
170 return HAL_PRIME_CHNL_OFFSET_DONT_CARE;
171}
172
173inline u8 hal_ch_offset_to_secondary_ch_offset23a(u8 ch_offset)
174{
175 if (ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
176 return SCN;
177 else if (ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
178 return SCB;
179 else if (ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
180 return SCA;
181
182 return SCN;
183}
184
185inline u8 *rtw_set_ie23a_secondary_ch_offset(u8 *buf, u32 *buf_len,
186 u8 secondary_ch_offset)
187{
188 return rtw_set_ie23a(buf, WLAN_EID_SECONDARY_CHANNEL_OFFSET,
189 1, &secondary_ch_offset, buf_len);
190}
191
192inline u8 *rtw_set_ie23a_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl,
193 u8 flags, u16 reason, u16 precedence)
194{
195 u8 ie_data[6];
196
197 ie_data[0] = ttl;
198 ie_data[1] = flags;
199 RTW_PUT_LE16((u8*)&ie_data[2], reason);
200 RTW_PUT_LE16((u8*)&ie_data[4], precedence);
201
202 return rtw_set_ie23a(buf, 0x118, 6, ie_data, buf_len);
203}
204
205/*----------------------------------------------------------------------------
206index: the information element id index, limit is the limit for search
207-----------------------------------------------------------------------------*/
208u8 *rtw_get_ie23a(u8 *pbuf, int index, int *len, int limit)
209{
210 int tmp, i;
211 u8 *p;
212
213 if (limit < 1) {
214
215 return NULL;
216 }
217
218 p = pbuf;
219 i = 0;
220 *len = 0;
221 while (1) {
222 if (*p == index) {
223 *len = *(p + 1);
224 return p;
225 } else {
226 tmp = *(p + 1);
227 p += (tmp + 2);
228 i += (tmp + 2);
229 }
230 if (i >= limit)
231 break;
232 }
233
234 return NULL;
235}
236
237/**
238 * rtw_get_ie23a_ex - Search specific IE from a series of IEs
239 * @in_ie: Address of IEs to search
240 * @in_len: Length limit from in_ie
241 * @eid: Element ID to match
242 * @oui: OUI to match
243 * @oui_len: OUI length
244 * @ie: If not NULL and the specific IE is found, the IE will be copied
245 * to the buf starting from the specific IE
246 * @ielen: If not NULL and the specific IE is found, will set to the length
247 * of the entire IE
248 *
249 * Returns: The address of the specific IE found, or NULL
250 */
251u8 *rtw_get_ie23a_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len,
252 u8 *ie, uint *ielen)
253{
254 uint cnt;
255 u8 *target_ie = NULL;
256
257 if (ielen)
258 *ielen = 0;
259
260 if (!in_ie || in_len <= 0)
261 return target_ie;
262
263 cnt = 0;
264
265 while (cnt < in_len) {
266 if (eid == in_ie[cnt] &&
267 (!oui || !memcmp(&in_ie[cnt+2], oui, oui_len))) {
268 target_ie = &in_ie[cnt];
269
270 if (ie)
271 memcpy(ie, &in_ie[cnt], in_ie[cnt+1]+2);
272
273 if (ielen)
274 *ielen = in_ie[cnt+1]+2;
275 break;
276 } else {
277 cnt += in_ie[cnt + 1] + 2; /* goto next */
278 }
279 }
280
281 return target_ie;
282}
283
284/**
285 * rtw_ies_remove_ie23a - Find matching IEs and remove
286 * @ies: Address of IEs to search
287 * @ies_len: Pointer of length of ies, will update to new length
288 * @offset: The offset to start scarch
289 * @eid: Element ID to match
290 * @oui: OUI to match
291 * @oui_len: OUI length
292 *
293 * Returns: _SUCCESS: ies is updated, _FAIL: not updated
294 */
295int rtw_ies_remove_ie23a(u8 *ies, uint *ies_len, uint offset, u8 eid,
296 u8 *oui, u8 oui_len)
297{
298 int ret = _FAIL;
299 u8 *target_ie;
300 u32 target_ielen;
301 u8 *start;
302 uint search_len;
303
304 if (!ies || !ies_len || *ies_len <= offset)
305 goto exit;
306
307 start = ies + offset;
308 search_len = *ies_len - offset;
309
310 while (1) {
311 target_ie = rtw_get_ie23a_ex(start, search_len, eid, oui, oui_len,
312 NULL, &target_ielen);
313 if (target_ie && target_ielen) {
314 u8 buf[MAX_IE_SZ] = {0};
315 u8 *remain_ies = target_ie + target_ielen;
316 uint remain_len = search_len - (remain_ies - start);
317
318 memcpy(buf, remain_ies, remain_len);
319 memcpy(target_ie, buf, remain_len);
320 *ies_len = *ies_len - target_ielen;
321 ret = _SUCCESS;
322
323 start = target_ie;
324 search_len = remain_len;
325 } else {
326 break;
327 }
328 }
329exit:
330 return ret;
331}
332
333void rtw_set_supported_rate23a(u8* SupportedRates, uint mode)
334{
335
336
337 memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
338
339 switch (mode)
340 {
341 case WIRELESS_11B:
342 memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
343 break;
344
345 case WIRELESS_11G:
346 case WIRELESS_11A:
347 case WIRELESS_11_5N:
348 case WIRELESS_11A_5N:/* Todo: no basic rate for ofdm ? */
349 memcpy(SupportedRates, WIFI_OFDMRATES,
350 IEEE80211_NUM_OFDM_RATESLEN);
351 break;
352
353 case WIRELESS_11BG:
354 case WIRELESS_11G_24N:
355 case WIRELESS_11_24N:
356 case WIRELESS_11BG_24N:
357 memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
358 memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES,
359 IEEE80211_NUM_OFDM_RATESLEN);
360 break;
361 }
362
363}
364
365uint rtw_get_rateset_len23a(u8 *rateset)
366{
367 uint i = 0;
368
369 while(1) {
370 if ((rateset[i]) == 0)
371 break;
372
373 if (i > 12)
374 break;
375
376 i++;
377 }
378
379 return i;
380}
381
382int rtw_generate_ie23a(struct registry_priv *pregistrypriv)
383{
384 u8 wireless_mode;
385 int sz = 0, rateLen;
386 struct wlan_bssid_ex* pdev_network = &pregistrypriv->dev_network;
387 u8* ie = pdev_network->IEs;
388
389
390
391 /* timestamp will be inserted by hardware */
392 sz += 8;
393 ie += sz;
394
395 /* beacon interval : 2bytes */
396 /* BCN_INTERVAL; */
397 *(u16*)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);
398 sz += 2;
399 ie += 2;
400
401 /* capability info */
402 *(u16*)ie = 0;
403
404 *(u16*)ie |= cpu_to_le16(cap_IBSS);
405
406 if (pregistrypriv->preamble == PREAMBLE_SHORT)
407 *(u16*)ie |= cpu_to_le16(cap_ShortPremble);
408
409 if (pdev_network->Privacy)
410 *(u16*)ie |= cpu_to_le16(cap_Privacy);
411
412 sz += 2;
413 ie += 2;
414
415 /* SSID */
416 ie = rtw_set_ie23a(ie, _SSID_IE_, pdev_network->Ssid.ssid_len,
417 pdev_network->Ssid.ssid, &sz);
418
419 /* supported rates */
420 if (pregistrypriv->wireless_mode == WIRELESS_11ABGN) {
421 if (pdev_network->Configuration.DSConfig > 14)
422 wireless_mode = WIRELESS_11A_5N;
423 else
424 wireless_mode = WIRELESS_11BG_24N;
425 } else {
426 wireless_mode = pregistrypriv->wireless_mode;
427 }
428
429 rtw_set_supported_rate23a(pdev_network->SupportedRates, wireless_mode) ;
430
431 rateLen = rtw_get_rateset_len23a(pdev_network->SupportedRates);
432
433 if (rateLen > 8) {
434 ie = rtw_set_ie23a(ie, _SUPPORTEDRATES_IE_, 8,
435 pdev_network->SupportedRates, &sz);
436 /* ie = rtw_set_ie23a(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */
437 } else {
438 ie = rtw_set_ie23a(ie, _SUPPORTEDRATES_IE_, rateLen,
439 pdev_network->SupportedRates, &sz);
440 }
441
442 /* DS parameter set */
443 ie = rtw_set_ie23a(ie, _DSSET_IE_, 1,
444 (u8 *)&pdev_network->Configuration.DSConfig, &sz);
445
446 /* IBSS Parameter Set */
447
448 ie = rtw_set_ie23a(ie, _IBSS_PARA_IE_, 2,
449 (u8 *)&pdev_network->Configuration.ATIMWindow, &sz);
450
451 if (rateLen > 8) {
452 ie = rtw_set_ie23a(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8),
453 (pdev_network->SupportedRates + 8), &sz);
454 }
455
456
457
458 /* return _SUCCESS; */
459
460 return sz;
461}
462
463unsigned char *rtw_get_wpa_ie23a(unsigned char *pie, int *wpa_ie_len, int limit)
464{
465 int len;
466 u16 val16;
467 unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01};
468 u8 *pbuf = pie;
469 int limit_new = limit;
470
471 while(1) {
472 pbuf = rtw_get_ie23a(pbuf, _WPA_IE_ID_, &len, limit_new);
473
474 if (pbuf) {
475 /* check if oui matches... */
476 if (memcmp((pbuf + 2), wpa_oui_type,
477 sizeof(wpa_oui_type))) {
478 goto check_next_ie;
479 }
480
481 /* check version... */
482 memcpy((u8 *)&val16, (pbuf + 6), sizeof(val16));
483
484 val16 = le16_to_cpu(val16);
485 if (val16 != 0x0001)
486 goto check_next_ie;
487
488 *wpa_ie_len = *(pbuf + 1);
489
490 return pbuf;
491 } else {
492 *wpa_ie_len = 0;
493 return NULL;
494 }
495
496check_next_ie:
497
498 limit_new = limit - (pbuf - pie) - 2 - len;
499
500 if (limit_new <= 0)
501 break;
502
503 pbuf += (2 + len);
504 }
505
506 *wpa_ie_len = 0;
507
508 return NULL;
509}
510
511unsigned char *rtw_get_wpa2_ie23a(unsigned char *pie, int *rsn_ie_len, int limit)
512{
513 return rtw_get_ie23a(pie, _WPA2_IE_ID_, rsn_ie_len, limit);
514}
515
516int rtw_get_wpa_cipher_suite23a(u8 *s)
517{
518 if (!memcmp(s, WPA_CIPHER_SUITE_NONE23A, WPA_SELECTOR_LEN))
519 return WPA_CIPHER_NONE;
520 if (!memcmp(s, WPA_CIPHER_SUITE_WEP4023A, WPA_SELECTOR_LEN))
521 return WPA_CIPHER_WEP40;
522 if (!memcmp(s, WPA_CIPHER_SUITE_TKIP23A, WPA_SELECTOR_LEN))
523 return WPA_CIPHER_TKIP;
524 if (!memcmp(s, WPA_CIPHER_SUITE_CCMP23A, WPA_SELECTOR_LEN))
525 return WPA_CIPHER_CCMP;
526 if (!memcmp(s, WPA_CIPHER_SUITE_WEP10423A, WPA_SELECTOR_LEN))
527 return WPA_CIPHER_WEP104;
528
529 return 0;
530}
531
532int rtw_get_wpa2_cipher_suite23a(u8 *s)
533{
534 if (!memcmp(s, RSN_CIPHER_SUITE_NONE23A, RSN_SELECTOR_LEN))
535 return WPA_CIPHER_NONE;
536 if (!memcmp(s, RSN_CIPHER_SUITE_WEP4023A, RSN_SELECTOR_LEN))
537 return WPA_CIPHER_WEP40;
538 if (!memcmp(s, RSN_CIPHER_SUITE_TKIP23A, RSN_SELECTOR_LEN))
539 return WPA_CIPHER_TKIP;
540 if (!memcmp(s, RSN_CIPHER_SUITE_CCMP23A, RSN_SELECTOR_LEN))
541 return WPA_CIPHER_CCMP;
542 if (!memcmp(s, RSN_CIPHER_SUITE_WEP10423A, RSN_SELECTOR_LEN))
543 return WPA_CIPHER_WEP104;
544
545 return 0;
546}
547
548int rtw_parse_wpa_ie23a(u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
549{
550 int i, ret = _SUCCESS;
551 int left, count;
552 u8 *pos;
553 u8 SUITE_1X[4] = {0x00, 0x50, 0xf2, 1};
554
555 if (wpa_ie_len <= 0) {
556 /* No WPA IE - fail silently */
557 return _FAIL;
558 }
559
560 if ((*wpa_ie != _WPA_IE_ID_) || (*(wpa_ie+1) != (u8)(wpa_ie_len - 2)) ||
561 memcmp(wpa_ie + 2, RTW_WPA_OUI23A_TYPE, WPA_SELECTOR_LEN)) {
562 return _FAIL;
563 }
564
565 pos = wpa_ie;
566
567 pos += 8;
568 left = wpa_ie_len - 8;
569
570 /* group_cipher */
571 if (left >= WPA_SELECTOR_LEN) {
572
573 *group_cipher = rtw_get_wpa_cipher_suite23a(pos);
574
575 pos += WPA_SELECTOR_LEN;
576 left -= WPA_SELECTOR_LEN;
577 } else if (left > 0) {
578 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
579 ("%s: ie length mismatch, %u too much",
580 __func__, left));
581
582 return _FAIL;
583 }
584
585 /* pairwise_cipher */
586 if (left >= 2) {
587 /* count = le16_to_cpu(*(u16*)pos); */
588 count = RTW_GET_LE16(pos);
589 pos += 2;
590 left -= 2;
591
592 if (count == 0 || left < count * WPA_SELECTOR_LEN) {
593 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
594 ("%s: ie count botch (pairwise), "
595 "count %u left %u", __func__,
596 count, left));
597 return _FAIL;
598 }
599
600 for (i = 0; i < count; i++) {
601 *pairwise_cipher |= rtw_get_wpa_cipher_suite23a(pos);
602
603 pos += WPA_SELECTOR_LEN;
604 left -= WPA_SELECTOR_LEN;
605 }
606 } else if (left == 1) {
607 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
608 ("%s: ie too short (for key mgmt)", __func__));
609 return _FAIL;
610 }
611
612 if (is_8021x) {
613 if (left >= 6) {
614 pos += 2;
615 if (!memcmp(pos, SUITE_1X, 4)) {
616 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
617 ("%s : there has 802.1x auth\n",
618 __func__));
619 *is_8021x = 1;
620 }
621 }
622 }
623
624 return ret;
625}
626
627int rtw_parse_wpa2_ie23a(u8* rsn_ie, int rsn_ie_len, int *group_cipher,
628 int *pairwise_cipher, int *is_8021x)
629{
630 int i, ret = _SUCCESS;
631 int left, count;
632 u8 *pos;
633 u8 SUITE_1X[4] = {0x00, 0x0f, 0xac, 0x01};
634
635 if (rsn_ie_len <= 0) {
636 /* No RSN IE - fail silently */
637 return _FAIL;
638 }
639
640 if ((*rsn_ie!= _WPA2_IE_ID_) || (*(rsn_ie+1) != (u8)(rsn_ie_len - 2))) {
641 return _FAIL;
642 }
643
644 pos = rsn_ie;
645 pos += 4;
646 left = rsn_ie_len - 4;
647
648 /* group_cipher */
649 if (left >= RSN_SELECTOR_LEN) {
650 *group_cipher = rtw_get_wpa2_cipher_suite23a(pos);
651
652 pos += RSN_SELECTOR_LEN;
653 left -= RSN_SELECTOR_LEN;
654 } else if (left > 0) {
655 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
656 ("%s: ie length mismatch, %u too much",
657 __func__, left));
658 return _FAIL;
659 }
660
661 /* pairwise_cipher */
662 if (left >= 2) {
663 /* count = le16_to_cpu(*(u16*)pos); */
664 count = RTW_GET_LE16(pos);
665 pos += 2;
666 left -= 2;
667
668 if (count == 0 || left < count * RSN_SELECTOR_LEN) {
669 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
670 ("%s: ie count botch (pairwise), "
671 "count %u left %u",
672 __func__, count, left));
673 return _FAIL;
674 }
675
676 for (i = 0; i < count; i++) {
677 *pairwise_cipher |= rtw_get_wpa2_cipher_suite23a(pos);
678
679 pos += RSN_SELECTOR_LEN;
680 left -= RSN_SELECTOR_LEN;
681 }
682 } else if (left == 1) {
683 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
684 ("%s: ie too short (for key mgmt)", __func__));
685
686 return _FAIL;
687 }
688
689 if (is_8021x) {
690 if (left >= 6) {
691 pos += 2;
692 if (!memcmp(pos, SUITE_1X, 4)) {
693 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
694 ("%s (): there has 802.1x auth\n",
695 __func__));
696 *is_8021x = 1;
697 }
698 }
699 }
700
701 return ret;
702}
703
704int rtw_get_sec_ie23a(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len,
705 u8 *wpa_ie, u16 *wpa_len)
706{
707 u8 authmode, sec_idx, i;
708 u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
709 uint cnt;
710
711
712
713 /* Search required WPA or WPA2 IE and copy to sec_ie[ ] */
714
715 cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_);
716
717 sec_idx = 0;
718
719 while(cnt < in_len) {
720 authmode = in_ie[cnt];
721
722 if ((authmode == _WPA_IE_ID_) &&
723 !memcmp(&in_ie[cnt+2], &wpa_oui[0], 4)) {
724 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
725 ("\n rtw_get_wpa_ie23a: sec_idx =%d "
726 "in_ie[cnt+1]+2 =%d\n",
727 sec_idx, in_ie[cnt + 1] + 2));
728
729 if (wpa_ie) {
730 memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt+1]+2);
731
732 for (i = 0; i < (in_ie[cnt + 1] + 2); i = i + 8) {
733 RT_TRACE(_module_rtl871x_mlme_c_,
734 _drv_info_,
735 ("\n %2x,%2x,%2x,%2x,%2x,%2x,"
736 "%2x,%2x\n", wpa_ie[i],
737 wpa_ie[i + 1], wpa_ie[i + 2],
738 wpa_ie[i + 3], wpa_ie[i + 4],
739 wpa_ie[i + 5], wpa_ie[i + 6],
740 wpa_ie[i + 7]));
741 }
742 }
743
744 *wpa_len = in_ie[cnt + 1] + 2;
745 cnt += in_ie[cnt + 1] + 2; /* get next */
746 } else {
747 if (authmode == _WPA2_IE_ID_) {
748 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
749 ("\n get_rsn_ie: sec_idx =%d in_ie"
750 "[cnt+1]+2 =%d\n", sec_idx,
751 in_ie[cnt + 1] + 2));
752
753 if (rsn_ie) {
754 memcpy(rsn_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
755
756 for (i = 0; i < (in_ie[cnt + 1] + 2); i = i + 8) {
757 RT_TRACE(_module_rtl871x_mlme_c_,
758 _drv_info_,
759 ("\n %2x,%2x,%2x,%2x,%2x,%2x,"
760 "%2x,%2x\n", rsn_ie[i],
761 rsn_ie[i + 1], rsn_ie[i + 2],
762 rsn_ie[i + 3], rsn_ie[i + 4],
763 rsn_ie[i + 5], rsn_ie[i + 6],
764 rsn_ie[i + 7]));
765 }
766 }
767
768 *rsn_len = in_ie[cnt + 1] + 2;
769 cnt += in_ie[cnt + 1] + 2; /* get next */
770 } else {
771 cnt += in_ie[cnt + 1] + 2; /* get next */
772 }
773 }
774 }
775
776
777
778 return *rsn_len + *wpa_len;
779}
780
781u8 rtw_is_wps_ie23a(u8 *ie_ptr, uint *wps_ielen)
782{
783 u8 match = false;
784 u8 eid, wps_oui[4]= {0x0, 0x50, 0xf2, 0x04};
785
786 if (!ie_ptr)
787 return match;
788
789 eid = ie_ptr[0];
790
791 if ((eid == _WPA_IE_ID_) && !memcmp(&ie_ptr[2], wps_oui, 4)) {
792 /* DBG_8723A("==> found WPS_IE.....\n"); */
793 *wps_ielen = ie_ptr[1] + 2;
794 match = true;
795 }
796 return match;
797}
798
799/**
800 * rtw_get_wps_ie23a - Search WPS IE from a series of IEs
801 * @in_ie: Address of IEs to search
802 * @in_len: Length limit from in_ie
803 * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the
804 * buf starting from wps_ie
805 * @wps_ielen: If not NULL and WPS IE is found, will set to the length of
806 * the entire WPS IE
807 *
808 * Returns: The address of the WPS IE found, or NULL
809 */
810u8 *rtw_get_wps_ie23a(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen)
811{
812 uint cnt;
813 u8 *wpsie_ptr = NULL;
814 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
815
816 if (wps_ielen)
817 *wps_ielen = 0;
818
819 if (!in_ie || in_len <= 0)
820 return wpsie_ptr;
821
822 cnt = 0;
823
824 while (cnt < in_len) {
825 eid = in_ie[cnt];
826
827 if ((eid == _WPA_IE_ID_) && !memcmp(&in_ie[cnt+2], wps_oui, 4)) {
828 wpsie_ptr = &in_ie[cnt];
829
830 if (wps_ie)
831 memcpy(wps_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
832
833 if (wps_ielen)
834 *wps_ielen = in_ie[cnt + 1] + 2;
835
836 cnt += in_ie[cnt + 1] + 2;
837
838 break;
839 } else {
840 cnt += in_ie[cnt + 1] + 2; /* goto next */
841 }
842 }
843
844 return wpsie_ptr;
845}
846
847/**
848 * rtw_get_wps_attr23a - Search a specific WPS attribute from a given WPS IE
849 * @wps_ie: Address of WPS IE to search
850 * @wps_ielen: Length limit from wps_ie
851 * @target_attr_id: The attribute ID of WPS attribute to search
852 * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute
853 * will be copied to the buf starting from buf_attr
854 * @len_attr: If not NULL and the WPS attribute is found, will set to the
855 * length of the entire WPS attribute
856 *
857 * Returns: the address of the specific WPS attribute found, or NULL
858 */
859u8 *rtw_get_wps_attr23a(u8 *wps_ie, uint wps_ielen, u16 target_attr_id,
860 u8 *buf_attr, u32 *len_attr)
861{
862 u8 *attr_ptr = NULL;
863 u8 * target_attr_ptr = NULL;
864 u8 wps_oui[4] = {0x00, 0x50, 0xF2, 0x04};
865
866 if (len_attr)
867 *len_attr = 0;
868
869 if ((wps_ie[0] != _VENDOR_SPECIFIC_IE_) ||
870 memcmp(wps_ie + 2, wps_oui, 4)) {
871 return attr_ptr;
872 }
873
874 /* 6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */
875 attr_ptr = wps_ie + 6; /* goto first attr */
876
877 while (attr_ptr - wps_ie < wps_ielen) {
878 /* 4 = 2(Attribute ID) + 2(Length) */
879 u16 attr_id = RTW_GET_BE16(attr_ptr);
880 u16 attr_data_len = RTW_GET_BE16(attr_ptr + 2);
881 u16 attr_len = attr_data_len + 4;
882
883 /* DBG_8723A("%s attr_ptr:%p, id:%u, length:%u\n", __func__, attr_ptr, attr_id, attr_data_len); */
884 if (attr_id == target_attr_id) {
885 target_attr_ptr = attr_ptr;
886
887 if (buf_attr)
888 memcpy(buf_attr, attr_ptr, attr_len);
889
890 if (len_attr)
891 *len_attr = attr_len;
892
893 break;
894 } else {
895 attr_ptr += attr_len; /* goto next */
896 }
897 }
898
899 return target_attr_ptr;
900}
901
902/**
903 * rtw_get_wps_attr_content23a - Search a specific WPS attribute content
904 * from a given WPS IE
905 * @wps_ie: Address of WPS IE to search
906 * @wps_ielen: Length limit from wps_ie
907 * @target_attr_id: The attribute ID of WPS attribute to search
908 * @buf_content: If not NULL and the WPS attribute is found, WPS attribute
909 * content will be copied to the buf starting from buf_content
910 * @len_content: If not NULL and the WPS attribute is found, will set to the
911 * length of the WPS attribute content
912 *
913 * Returns: the address of the specific WPS attribute content found, or NULL
914 */
915u8 *rtw_get_wps_attr_content23a(u8 *wps_ie, uint wps_ielen, u16 target_attr_id,
916 u8 *buf_content, uint *len_content)
917{
918 u8 *attr_ptr;
919 u32 attr_len;
920
921 if (len_content)
922 *len_content = 0;
923
924 attr_ptr = rtw_get_wps_attr23a(wps_ie, wps_ielen, target_attr_id,
925 NULL, &attr_len);
926
927 if (attr_ptr && attr_len) {
928 if (buf_content)
929 memcpy(buf_content, attr_ptr + 4, attr_len - 4);
930
931 if (len_content)
932 *len_content = attr_len - 4;
933
934 return attr_ptr + 4;
935 }
936
937 return NULL;
938}
939
940static int
941rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen,
942 struct rtw_ieee802_11_elems *elems,
943 int show_errors)
944{
945 unsigned int oui;
946
947 /* first 3 bytes in vendor specific information element are the IEEE
948 * OUI of the vendor. The following byte is used a vendor specific
949 * sub-type. */
950 if (elen < 4) {
951 if (show_errors) {
952 DBG_8723A("short vendor specific "
953 "information element ignored (len =%lu)\n",
954 (unsigned long) elen);
955 }
956 return -1;
957 }
958
959 oui = RTW_GET_BE24(pos);
960 switch (oui) {
961 case WLAN_OUI_MICROSOFT:
962 /* Microsoft/Wi-Fi information elements are further typed and
963 * subtyped */
964 switch (pos[3]) {
965 case 1:
966 /* Microsoft OUI (00:50:F2) with OUI Type 1:
967 * real WPA information element */
968 elems->wpa_ie = pos;
969 elems->wpa_ie_len = elen;
970 break;
971 case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */
972 if (elen < 5) {
973 DBG_8723A("short WME "
974 "information element ignored "
975 "(len =%lu)\n",
976 (unsigned long) elen);
977 return -1;
978 }
979 switch (pos[4]) {
980 case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
981 case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
982 elems->wme = pos;
983 elems->wme_len = elen;
984 break;
985 case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
986 elems->wme_tspec = pos;
987 elems->wme_tspec_len = elen;
988 break;
989 default:
990 DBG_8723A("unknown WME "
991 "information element ignored "
992 "(subtype =%d len =%lu)\n",
993 pos[4], (unsigned long) elen);
994 return -1;
995 }
996 break;
997 case 4:
998 /* Wi-Fi Protected Setup (WPS) IE */
999 elems->wps_ie = pos;
1000 elems->wps_ie_len = elen;
1001 break;
1002 default:
1003 DBG_8723A("Unknown Microsoft "
1004 "information element ignored "
1005 "(type =%d len =%lu)\n",
1006 pos[3], (unsigned long) elen);
1007 return -1;
1008 }
1009 break;
1010
1011 case OUI_BROADCOM:
1012 switch (pos[3]) {
1013 case VENDOR_HT_CAPAB_OUI_TYPE:
1014 elems->vendor_ht_cap = pos;
1015 elems->vendor_ht_cap_len = elen;
1016 break;
1017 default:
1018 DBG_8723A("Unknown Broadcom "
1019 "information element ignored "
1020 "(type =%d len =%lu)\n",
1021 pos[3], (unsigned long) elen);
1022 return -1;
1023 }
1024 break;
1025
1026 default:
1027 DBG_8723A("unknown vendor specific information "
1028 "element ignored (vendor OUI %02x:%02x:%02x "
1029 "len =%lu)\n",
1030 pos[0], pos[1], pos[2], (unsigned long) elen);
1031 return -1;
1032 }
1033
1034 return 0;
1035}
1036
1037/**
1038 * ieee802_11_parse_elems - Parse information elements in management frames
1039 * @start: Pointer to the start of IEs
1040 * @len: Length of IE buffer in octets
1041 * @elems: Data structure for parsed elements
1042 * @show_errors: Whether to show parsing errors in debug log
1043 * Returns: Parsing result
1044 */
1045enum parse_res rtw_ieee802_11_parse_elems23a(u8 *start, uint len,
1046 struct rtw_ieee802_11_elems *elems,
1047 int show_errors)
1048{
1049 uint left = len;
1050 u8 *pos = start;
1051 int unknown = 0;
1052
1053 memset(elems, 0, sizeof(*elems));
1054
1055 while (left >= 2) {
1056 u8 id, elen;
1057
1058 id = *pos++;
1059 elen = *pos++;
1060 left -= 2;
1061
1062 if (elen > left) {
1063 if (show_errors) {
1064 DBG_8723A("IEEE 802.11 element "
1065 "parse failed (id =%d elen =%d "
1066 "left =%lu)\n",
1067 id, elen, (unsigned long) left);
1068 }
1069 return ParseFailed;
1070 }
1071
1072 switch (id) {
1073 case WLAN_EID_SSID:
1074 elems->ssid = pos;
1075 elems->ssid_len = elen;
1076 break;
1077 case WLAN_EID_SUPP_RATES:
1078 elems->supp_rates = pos;
1079 elems->supp_rates_len = elen;
1080 break;
1081 case WLAN_EID_FH_PARAMS:
1082 elems->fh_params = pos;
1083 elems->fh_params_len = elen;
1084 break;
1085 case WLAN_EID_DS_PARAMS:
1086 elems->ds_params = pos;
1087 elems->ds_params_len = elen;
1088 break;
1089 case WLAN_EID_CF_PARAMS:
1090 elems->cf_params = pos;
1091 elems->cf_params_len = elen;
1092 break;
1093 case WLAN_EID_TIM:
1094 elems->tim = pos;
1095 elems->tim_len = elen;
1096 break;
1097 case WLAN_EID_IBSS_PARAMS:
1098 elems->ibss_params = pos;
1099 elems->ibss_params_len = elen;
1100 break;
1101 case WLAN_EID_CHALLENGE:
1102 elems->challenge = pos;
1103 elems->challenge_len = elen;
1104 break;
1105 case WLAN_EID_ERP_INFO:
1106 elems->erp_info = pos;
1107 elems->erp_info_len = elen;
1108 break;
1109 case WLAN_EID_EXT_SUPP_RATES:
1110 elems->ext_supp_rates = pos;
1111 elems->ext_supp_rates_len = elen;
1112 break;
1113 case WLAN_EID_VENDOR_SPECIFIC:
1114 if (rtw_ieee802_11_parse_vendor_specific(pos, elen,
1115 elems,
1116 show_errors))
1117 unknown++;
1118 break;
1119 case WLAN_EID_RSN:
1120 elems->rsn_ie = pos;
1121 elems->rsn_ie_len = elen;
1122 break;
1123 case WLAN_EID_PWR_CAPABILITY:
1124 elems->power_cap = pos;
1125 elems->power_cap_len = elen;
1126 break;
1127 case WLAN_EID_SUPPORTED_CHANNELS:
1128 elems->supp_channels = pos;
1129 elems->supp_channels_len = elen;
1130 break;
1131 case WLAN_EID_MOBILITY_DOMAIN:
1132 elems->mdie = pos;
1133 elems->mdie_len = elen;
1134 break;
1135 case WLAN_EID_FAST_BSS_TRANSITION:
1136 elems->ftie = pos;
1137 elems->ftie_len = elen;
1138 break;
1139 case WLAN_EID_TIMEOUT_INTERVAL:
1140 elems->timeout_int = pos;
1141 elems->timeout_int_len = elen;
1142 break;
1143 case WLAN_EID_HT_CAPABILITY:
1144 elems->ht_capabilities = pos;
1145 elems->ht_capabilities_len = elen;
1146 break;
1147 case WLAN_EID_HT_OPERATION:
1148 elems->ht_operation = pos;
1149 elems->ht_operation_len = elen;
1150 break;
1151 default:
1152 unknown++;
1153 if (!show_errors)
1154 break;
1155 DBG_8723A("IEEE 802.11 element parse "
1156 "ignored unknown element (id =%d elen =%d)\n",
1157 id, elen);
1158 break;
1159 }
1160
1161 left -= elen;
1162 pos += elen;
1163 }
1164
1165 if (left)
1166 return ParseFailed;
1167
1168 return unknown ? ParseUnknown : ParseOK;
1169}
1170
1171static u8 key_char2num(u8 ch)
1172{
1173 if ((ch >= '0') && (ch <= '9'))
1174 return ch - '0';
1175 else if ((ch >= 'a') && (ch <= 'f'))
1176 return ch - 'a' + 10;
1177 else if ((ch >= 'A') && (ch <= 'F'))
1178 return ch - 'A' + 10;
1179 else
1180 return 0xff;
1181}
1182
1183u8 str_2char2num23a(u8 hch, u8 lch)
1184{
1185 return (key_char2num(hch) * 10) + key_char2num(lch);
1186}
1187
1188u8 key_2char2num23a(u8 hch, u8 lch)
1189{
1190 return (key_char2num(hch) << 4) | key_char2num(lch);
1191}
1192
1193void rtw_macaddr_cfg23a(u8 *mac_addr)
1194{
1195 u8 mac[ETH_ALEN];
1196 if (!mac_addr)
1197 return;
1198
1199 memcpy(mac, mac_addr, ETH_ALEN);
1200
1201 if (is_broadcast_ether_addr(mac) || is_zero_ether_addr(mac)) {
1202 mac[0] = 0x00;
1203 mac[1] = 0xe0;
1204 mac[2] = 0x4c;
1205 mac[3] = 0x87;
1206 mac[4] = 0x00;
1207 mac[5] = 0x00;
1208 /* use default mac addresss */
1209 memcpy(mac_addr, mac, ETH_ALEN);
1210 DBG_8723A("MAC Address from efuse error, assign default "
1211 "one !!!\n");
1212 }
1213 DBG_8723A("rtw_macaddr_cfg23a MAC Address = "MAC_FMT"\n",
1214 MAC_ARG(mac_addr));
1215}
1216
1217void dump_ies23a(u8 *buf, u32 buf_len) {
1218 u8* pos = (u8*)buf;
1219 u8 id, len;
1220
1221 while (pos-buf <= buf_len) {
1222 id = *pos;
1223 len = *(pos + 1);
1224
1225 DBG_8723A("%s ID:%u, LEN:%u\n", __func__, id, len);
1226#ifdef CONFIG_8723AU_P2P
1227 dump_p2p_ie23a(pos, len);
1228#endif
1229 dump_wps_ie23a(pos, len);
1230
1231 pos += (2 + len);
1232 }
1233}
1234
1235void dump_wps_ie23a(u8 *ie, u32 ie_len) {
1236 u8* pos = (u8*)ie;
1237 u16 id;
1238 u16 len;
1239
1240 u8 *wps_ie;
1241 uint wps_ielen;
1242
1243 wps_ie = rtw_get_wps_ie23a(ie, ie_len, NULL, &wps_ielen);
1244 if (wps_ie != ie || wps_ielen == 0)
1245 return;
1246
1247 pos+= 6;
1248 while (pos-ie < ie_len) {
1249 id = RTW_GET_BE16(pos);
1250 len = RTW_GET_BE16(pos + 2);
1251
1252 DBG_8723A("%s ID:0x%04x, LEN:%u\n", __func__, id, len);
1253
1254 pos += (4 + len);
1255 }
1256}
1257
1258#ifdef CONFIG_8723AU_P2P
1259void dump_p2p_ie23a(u8 *ie, u32 ie_len) {
1260 u8* pos = (u8*)ie;
1261 u8 id;
1262 u16 len;
1263
1264 u8 *p2p_ie;
1265 uint p2p_ielen;
1266
1267 p2p_ie = rtw_get_p2p_ie23a(ie, ie_len, NULL, &p2p_ielen);
1268 if (p2p_ie != ie || p2p_ielen == 0)
1269 return;
1270
1271 pos += 6;
1272 while (pos-ie < ie_len) {
1273 id = *pos;
1274 len = RTW_GET_LE16(pos+1);
1275
1276 DBG_8723A("%s ID:%u, LEN:%u\n", __func__, id, len);
1277
1278 pos+= (3+len);
1279 }
1280}
1281
1282/**
1283 * rtw_get_p2p_ie23a - Search P2P IE from a series of IEs
1284 * @in_ie: Address of IEs to search
1285 * @in_len: Length limit from in_ie
1286 * @p2p_ie: If not NULL and P2P IE is found, P2P IE will be copied to the
1287 * buf starting from p2p_ie
1288 * @p2p_ielen: If not NULL and P2P IE is found, will set to the length of
1289 * the entire P2P IE
1290 *
1291 * Returns: The address of the P2P IE found, or NULL
1292 */
1293u8 *rtw_get_p2p_ie23a(u8 *in_ie, int in_len, u8 *p2p_ie, uint *p2p_ielen)
1294{
1295 uint cnt = 0;
1296 u8 *p2p_ie_ptr;
1297 u8 eid, p2p_oui[4]={0x50, 0x6F, 0x9A, 0x09};
1298
1299 if (p2p_ielen)
1300 *p2p_ielen = 0;
1301
1302 while (cnt<in_len) {
1303 eid = in_ie[cnt];
1304 if ((in_len < 0) || (cnt > MAX_IE_SZ)) {
1305 dump_stack();
1306 return NULL;
1307 }
1308 if ((eid == _VENDOR_SPECIFIC_IE_) &&
1309 !memcmp(&in_ie[cnt + 2], p2p_oui, 4)) {
1310 p2p_ie_ptr = in_ie + cnt;
1311
1312 if (p2p_ie != NULL) {
1313 memcpy(p2p_ie, &in_ie[cnt],
1314 in_ie[cnt + 1] + 2);
1315 }
1316
1317 if (p2p_ielen != NULL) {
1318 *p2p_ielen = in_ie[cnt + 1] + 2;
1319 }
1320
1321 return p2p_ie_ptr;
1322
1323 break;
1324 } else {
1325 cnt += in_ie[cnt + 1] + 2; /* goto next */
1326 }
1327 }
1328
1329 return NULL;
1330}
1331
1332/**
1333 * rtw_get_p2p_attr23a - Search a specific P2P attribute from a given P2P IE
1334 * @p2p_ie: Address of P2P IE to search
1335 * @p2p_ielen: Length limit from p2p_ie
1336 * @target_attr_id: The attribute ID of P2P attribute to search
1337 * @buf_attr: If not NULL and the P2P attribute is found, P2P attribute will
1338 * be copied to the buf starting from buf_attr
1339 * @len_attr: If not NULL and the P2P attribute is found, will set to the
1340 * length of the entire P2P attribute
1341 *
1342 * Returns: the address of the specific WPS attribute found, or NULL
1343 */
1344u8 *rtw_get_p2p_attr23a(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id,
1345 u8 *buf_attr, u32 *len_attr)
1346{
1347 u8 *attr_ptr = NULL;
1348 u8 *target_attr_ptr = NULL;
1349 u8 p2p_oui[4]={0x50, 0x6F, 0x9A, 0x09};
1350
1351 if (len_attr)
1352 *len_attr = 0;
1353
1354 if (!p2p_ie || (p2p_ie[0] != _VENDOR_SPECIFIC_IE_) ||
1355 memcmp(p2p_ie + 2, p2p_oui, 4)) {
1356 return attr_ptr;
1357 }
1358
1359 /* 6 = 1(Element ID) + 1(Length) + 3 (OUI) + 1(OUI Type) */
1360 attr_ptr = p2p_ie + 6; /* goto first attr */
1361
1362 while (attr_ptr - p2p_ie < p2p_ielen) {
1363 /* 3 = 1(Attribute ID) + 2(Length) */
1364 u8 attr_id = *attr_ptr;
1365 u16 attr_data_len = RTW_GET_LE16(attr_ptr + 1);
1366 u16 attr_len = attr_data_len + 3;
1367
1368 /* DBG_8723A("%s attr_ptr:%p, id:%u, length:%u\n", __func__, attr_ptr, attr_id, attr_data_len); */
1369 if (attr_id == target_attr_id) {
1370 target_attr_ptr = attr_ptr;
1371
1372 if (buf_attr)
1373 memcpy(buf_attr, attr_ptr, attr_len);
1374
1375 if (len_attr)
1376 *len_attr = attr_len;
1377
1378 break;
1379 } else {
1380 attr_ptr += attr_len; /* goto next */
1381 }
1382 }
1383
1384 return target_attr_ptr;
1385}
1386
1387/**
1388 * rtw_get_p2p_attr23a_content - Search a specific P2P attribute content from
1389 * a given P2P IE
1390 * @p2p_ie: Address of P2P IE to search
1391 * @p2p_ielen: Length limit from p2p_ie
1392 * @target_attr_id: The attribute ID of P2P attribute to search
1393 * @buf_content: If not NULL and the P2P attribute is found, P2P attribute
1394 * content will be copied to the buf starting from buf_content
1395 * @len_content: If not NULL and the P2P attribute is found, will set to the
1396 * length of the P2P attribute content
1397 *
1398 * Returns: the address of the specific P2P attribute content found, or NULL
1399 */
1400u8 *rtw_get_p2p_attr23a_content(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id,
1401 u8 *buf_content, uint *len_content)
1402{
1403 u8 *attr_ptr;
1404 u32 attr_len;
1405
1406 if (len_content)
1407 *len_content = 0;
1408
1409 attr_ptr = rtw_get_p2p_attr23a(p2p_ie, p2p_ielen, target_attr_id,
1410 NULL, &attr_len);
1411
1412 if (attr_ptr && attr_len) {
1413 if (buf_content)
1414 memcpy(buf_content, attr_ptr + 3, attr_len - 3);
1415
1416 if (len_content)
1417 *len_content = attr_len - 3;
1418
1419 return attr_ptr+3;
1420 }
1421
1422 return NULL;
1423}
1424
1425u32 rtw_set_p2p_attr_content23a(u8 *pbuf, u8 attr_id, u16 attr_len, u8 *pdata_attr)
1426{
1427 u32 a_len;
1428
1429 *pbuf = attr_id;
1430
1431 /* u16*)(pbuf + 1) = cpu_to_le16(attr_len); */
1432 RTW_PUT_LE16(pbuf + 1, attr_len);
1433
1434 if (pdata_attr)
1435 memcpy(pbuf + 3, pdata_attr, attr_len);
1436
1437 a_len = attr_len + 3;
1438
1439 return a_len;
1440}
1441
1442static uint rtw_p2p_attr_remove(u8 *ie, uint ielen_ori, u8 attr_id)
1443{
1444 u8 *target_attr;
1445 u32 target_attr_len;
1446 uint ielen = ielen_ori;
1447
1448 while(1) {
1449 target_attr = rtw_get_p2p_attr23a(ie, ielen, attr_id, NULL,
1450 &target_attr_len);
1451 if (target_attr && target_attr_len) {
1452 u8 *next_attr = target_attr+target_attr_len;
1453 uint remain_len = ielen-(next_attr-ie);
1454 /* dump_ies23a(ie, ielen); */
1455
1456 memset(target_attr, 0, target_attr_len);
1457 memcpy(target_attr, next_attr, remain_len);
1458 memset(target_attr+remain_len, 0, target_attr_len);
1459 *(ie + 1) -= target_attr_len;
1460 ielen -= target_attr_len;
1461 } else {
1462 /* if (index>0) */
1463 /* dump_ies23a(ie, ielen); */
1464 break;
1465 }
1466 }
1467
1468 return ielen;
1469}
1470
1471void rtw_wlan_bssid_ex_remove_p2p_attr23a(struct wlan_bssid_ex *bss_ex, u8 attr_id)
1472{
1473 u8 *p2p_ie;
1474 uint p2p_ielen, p2p_ielen_ori;
1475
1476 if ((p2p_ie = rtw_get_p2p_ie23a(bss_ex->IEs + _FIXED_IE_LENGTH_,
1477 bss_ex->IELength - _FIXED_IE_LENGTH_,
1478 NULL, &p2p_ielen_ori))) {
1479 p2p_ielen = rtw_p2p_attr_remove(p2p_ie, p2p_ielen_ori, attr_id);
1480 if (p2p_ielen != p2p_ielen_ori) {
1481 u8 *next_ie_ori = p2p_ie+p2p_ielen_ori;
1482 u8 *next_ie = p2p_ie+p2p_ielen;
1483 uint remain_len;
1484 remain_len = bss_ex->IELength-(next_ie_ori-bss_ex->IEs);
1485
1486 memcpy(next_ie, next_ie_ori, remain_len);
1487 memset(next_ie+remain_len, 0, p2p_ielen_ori-p2p_ielen);
1488 bss_ex->IELength -= p2p_ielen_ori-p2p_ielen;
1489 }
1490 }
1491}
1492
1493#endif /* CONFIG_8723AU_P2P */
1494
1495#ifdef CONFIG_8723AU_P2P
1496int rtw_get_wfd_ie(u8 *in_ie, int in_len, u8 *wfd_ie, uint *wfd_ielen)
1497{
1498 int match;
1499 uint cnt = 0;
1500 u8 eid, wfd_oui[4] = {0x50, 0x6F, 0x9A, 0x0A};
1501
1502 match = false;
1503
1504 if (in_len < 0) {
1505 return match;
1506 }
1507
1508 while (cnt < in_len)
1509 {
1510 eid = in_ie[cnt];
1511
1512 if ((eid == _VENDOR_SPECIFIC_IE_) &&
1513 !memcmp(&in_ie[cnt+2], wfd_oui, 4)) {
1514 if (wfd_ie != NULL) {
1515 memcpy(wfd_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
1516
1517 } else {
1518 if (wfd_ielen != NULL) {
1519 *wfd_ielen = 0;
1520 }
1521 }
1522
1523 if (wfd_ielen != NULL) {
1524 *wfd_ielen = in_ie[cnt + 1] + 2;
1525 }
1526
1527 cnt += in_ie[cnt + 1] + 2;
1528
1529 match = true;
1530 break;
1531 } else {
1532 cnt += in_ie[cnt + 1] +2; /* goto next */
1533 }
1534 }
1535
1536 if (match == true) {
1537 match = cnt;
1538 }
1539
1540 return match;
1541}
1542
1543/* attr_content: The output buffer, contains the "body field" of
1544 WFD attribute. */
1545/* attr_contentlen: The data length of the "body field" of WFD
1546 attribute. */
1547int rtw_get_wfd_attr_content(u8 *wfd_ie, uint wfd_ielen, u8 target_attr_id,
1548 u8 *attr_content, uint *attr_contentlen)
1549{
1550 int match;
1551 uint cnt = 0;
1552 u8 attr_id, wfd_oui[4] = {0x50, 0x6F, 0x9A, 0x0A};
1553
1554 match = false;
1555
1556 if ((wfd_ie[0] != _VENDOR_SPECIFIC_IE_) ||
1557 memcmp(wfd_ie + 2, wfd_oui, 4)) {
1558 return match;
1559 }
1560
1561 /* 1 (WFD IE) + 1 (Length) + 3 (OUI) + 1 (OUI Type) */
1562 cnt = 6;
1563 while (cnt < wfd_ielen) {
1564 u16 attrlen = RTW_GET_BE16(wfd_ie + cnt + 1);
1565
1566 attr_id = wfd_ie[cnt];
1567 if (attr_id == target_attr_id) {
1568 /* 3 -> 1 byte for attribute ID field, 2
1569 bytes for length field */
1570 if (attr_content)
1571 memcpy(attr_content, &wfd_ie[cnt + 3], attrlen);
1572
1573 if (attr_contentlen)
1574 *attr_contentlen = attrlen;
1575
1576 cnt += attrlen + 3;
1577
1578 match = true;
1579 break;
1580 } else {
1581 cnt += attrlen + 3; /* goto next */
1582 }
1583 }
1584
1585 return match;
1586}
1587#endif /* CONFIG_8723AU_P2P */
1588
1589/* Baron adds to avoid FreeBSD warning */
1590int ieee80211_is_empty_essid23a(const char *essid, int essid_len)
1591{
1592 /* Single white space is for Linksys APs */
1593 if (essid_len == 1 && essid[0] == ' ')
1594 return 1;
1595
1596 /* Otherwise, if the entire essid is 0, we assume it is hidden */
1597 while (essid_len) {
1598 essid_len--;
1599 if (essid[essid_len] != '\0')
1600 return 0;
1601 }
1602
1603 return 1;
1604}
1605
1606static int rtw_get_cipher_info(struct wlan_network *pnetwork)
1607{
1608 u32 wpa_ielen;
1609 unsigned char *pbuf;
1610 int group_cipher = 0, pairwise_cipher = 0, is8021x = 0;
1611 int ret = _FAIL;
1612 int r;
1613 pbuf = rtw_get_wpa_ie23a(&pnetwork->network.IEs[12], &wpa_ielen,
1614 pnetwork->network.IELength - 12);
1615
1616 if (pbuf && (wpa_ielen > 0)) {
1617 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1618 ("rtw_get_cipher_info: wpa_ielen: %d", wpa_ielen));
1619 r = rtw_parse_wpa_ie23a(pbuf, wpa_ielen + 2, &group_cipher,
1620 &pairwise_cipher, &is8021x);
1621 if (r == _SUCCESS) {
1622 pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
1623 pnetwork->BcnInfo.group_cipher = group_cipher;
1624 pnetwork->BcnInfo.is_8021x = is8021x;
1625 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1626 ("%s: pnetwork->pairwise_cipher: %d, is_"
1627 "8021x is %d", __func__,
1628 pnetwork->BcnInfo.pairwise_cipher,
1629 pnetwork->BcnInfo.is_8021x));
1630 ret = _SUCCESS;
1631 }
1632 } else {
1633 pbuf = rtw_get_wpa2_ie23a(&pnetwork->network.IEs[12], &wpa_ielen,
1634 pnetwork->network.IELength - 12);
1635
1636 if (pbuf && (wpa_ielen > 0)) {
1637 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1638 ("get RSN IE\n"));
1639 r = rtw_parse_wpa2_ie23a(pbuf, wpa_ielen + 2,
1640 &group_cipher, &pairwise_cipher,
1641 &is8021x);
1642 if (r == _SUCCESS) {
1643 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1644 ("get RSN IE OK!!!\n"));
1645 pnetwork->BcnInfo.pairwise_cipher =
1646 pairwise_cipher;
1647 pnetwork->BcnInfo.group_cipher = group_cipher;
1648 pnetwork->BcnInfo.is_8021x = is8021x;
1649 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1650 ("%s: pnetwork->pairwise_cipher: %d,"
1651 "pnetwork->group_cipher is %d, "
1652 "is_8021x is %d", __func__,
1653 pnetwork->BcnInfo.pairwise_cipher,
1654 pnetwork->BcnInfo.group_cipher,
1655 pnetwork->BcnInfo.is_8021x));
1656 ret = _SUCCESS;
1657 }
1658 }
1659 }
1660
1661 return ret;
1662}
1663
1664void rtw_get_bcn_info23a(struct wlan_network *pnetwork)
1665{
1666 unsigned short cap = 0;
1667 u8 bencrypt = 0;
1668 /* u8 wpa_ie[255], rsn_ie[255]; */
1669 u16 wpa_len = 0, rsn_len = 0;
1670 struct HT_info_element *pht_info = NULL;
1671 struct ieee80211_ht_cap *pht_cap = NULL;
1672 unsigned int len;
1673 unsigned char *p;
1674
1675 memcpy(&cap, rtw_get_capability23a_from_ie(pnetwork->network.IEs), 2);
1676 cap = le16_to_cpu(cap);
1677 if (cap & WLAN_CAPABILITY_PRIVACY) {
1678 bencrypt = 1;
1679 pnetwork->network.Privacy = 1;
1680 } else {
1681 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
1682 }
1683 rtw_get_sec_ie23a(pnetwork->network.IEs, pnetwork->network.IELength,
1684 NULL, &rsn_len, NULL, &wpa_len);
1685 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1686 ("rtw_get_bcn_info23a: ssid =%s\n", pnetwork->network.Ssid.ssid));
1687 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1688 ("rtw_get_bcn_info23a: wpa_len =%d rsn_len =%d\n",
1689 wpa_len, rsn_len));
1690 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1691 ("rtw_get_bcn_info23a: ssid =%s\n", pnetwork->network.Ssid.ssid));
1692 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1693 ("rtw_get_bcn_info23a: wpa_len =%d rsn_len =%d\n",
1694 wpa_len, rsn_len));
1695
1696 if (rsn_len > 0) {
1697 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2;
1698 } else if (wpa_len > 0) {
1699 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA;
1700 } else {
1701 if (bencrypt)
1702 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP;
1703 }
1704 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1705 ("rtw_get_bcn_info23a: pnetwork->encryp_protocol is %x\n",
1706 pnetwork->BcnInfo.encryp_protocol));
1707 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1708 ("rtw_get_bcn_info23a: pnetwork->encryp_protocol is %x\n",
1709 pnetwork->BcnInfo.encryp_protocol));
1710 rtw_get_cipher_info(pnetwork);
1711
1712 /* get bwmode and ch_offset */
1713 /* parsing HT_CAP_IE */
1714 p = rtw_get_ie23a(pnetwork->network.IEs + _FIXED_IE_LENGTH_,
1715 _HT_CAPABILITY_IE_, &len,
1716 pnetwork->network.IELength - _FIXED_IE_LENGTH_);
1717 if (p && len > 0) {
1718 pht_cap = (struct ieee80211_ht_cap *)(p + 2);
1719 pnetwork->BcnInfo.ht_cap_info = pht_cap->cap_info;
1720 } else {
1721 pnetwork->BcnInfo.ht_cap_info = 0;
1722 }
1723 /* parsing HT_INFO_IE */
1724 p = rtw_get_ie23a(pnetwork->network.IEs + _FIXED_IE_LENGTH_,
1725 _HT_ADD_INFO_IE_, &len,
1726 pnetwork->network.IELength - _FIXED_IE_LENGTH_);
1727 if (p && len > 0) {
1728 pht_info = (struct HT_info_element *)(p + 2);
1729 pnetwork->BcnInfo.ht_info_infos_0 = pht_info->infos[0];
1730 } else {
1731 pnetwork->BcnInfo.ht_info_infos_0 = 0;
1732 }
1733}
1734
1735/* show MCS rate, unit: 100Kbps */
1736u16 rtw_mcs_rate23a(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40,
1737 unsigned char * MCS_rate)
1738{
1739 u16 max_rate = 0;
1740
1741 if (rf_type == RF_1T1R) {
1742 if (MCS_rate[0] & BIT(7))
1743 max_rate = (bw_40MHz) ? ((short_GI_40)?1500:1350):
1744 ((short_GI_20)?722:650);
1745 else if (MCS_rate[0] & BIT(6))
1746 max_rate = (bw_40MHz) ? ((short_GI_40)?1350:1215):
1747 ((short_GI_20)?650:585);
1748 else if (MCS_rate[0] & BIT(5))
1749 max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):
1750 ((short_GI_20)?578:520);
1751 else if (MCS_rate[0] & BIT(4))
1752 max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):
1753 ((short_GI_20)?433:390);
1754 else if (MCS_rate[0] & BIT(3))
1755 max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):
1756 ((short_GI_20)?289:260);
1757 else if (MCS_rate[0] & BIT(2))
1758 max_rate = (bw_40MHz) ? ((short_GI_40)?450:405):
1759 ((short_GI_20)?217:195);
1760 else if (MCS_rate[0] & BIT(1))
1761 max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):
1762 ((short_GI_20)?144:130);
1763 else if (MCS_rate[0] & BIT(0))
1764 max_rate = (bw_40MHz) ? ((short_GI_40)?150:135):
1765 ((short_GI_20)?72:65);
1766 } else {
1767 if (MCS_rate[1]) {
1768 if (MCS_rate[1] & BIT(7))
1769 max_rate = (bw_40MHz) ? ((short_GI_40)?3000:2700):((short_GI_20)?1444:1300);
1770 else if (MCS_rate[1] & BIT(6))
1771 max_rate = (bw_40MHz) ? ((short_GI_40)?2700:2430):((short_GI_20)?1300:1170);
1772 else if (MCS_rate[1] & BIT(5))
1773 max_rate = (bw_40MHz) ? ((short_GI_40)?2400:2160):((short_GI_20)?1156:1040);
1774 else if (MCS_rate[1] & BIT(4))
1775 max_rate = (bw_40MHz) ? ((short_GI_40)?1800:1620):((short_GI_20)?867:780);
1776 else if (MCS_rate[1] & BIT(3))
1777 max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520);
1778 else if (MCS_rate[1] & BIT(2))
1779 max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390);
1780 else if (MCS_rate[1] & BIT(1))
1781 max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260);
1782 else if (MCS_rate[1] & BIT(0))
1783 max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130);
1784 } else {
1785 if (MCS_rate[0] & BIT(7))
1786 max_rate = (bw_40MHz) ? ((short_GI_40)?1500:1350):((short_GI_20)?722:650);
1787 else if (MCS_rate[0] & BIT(6))
1788 max_rate = (bw_40MHz) ? ((short_GI_40)?1350:1215):((short_GI_20)?650:585);
1789 else if (MCS_rate[0] & BIT(5))
1790 max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520);
1791 else if (MCS_rate[0] & BIT(4))
1792 max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390);
1793 else if (MCS_rate[0] & BIT(3))
1794 max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260);
1795 else if (MCS_rate[0] & BIT(2))
1796 max_rate = (bw_40MHz) ? ((short_GI_40)?450:405):((short_GI_20)?217:195);
1797 else if (MCS_rate[0] & BIT(1))
1798 max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130);
1799 else if (MCS_rate[0] & BIT(0))
1800 max_rate = (bw_40MHz) ? ((short_GI_40)?150:135):((short_GI_20)?72:65);
1801 }
1802 }
1803 return max_rate;
1804}
1805
1806int rtw_action_frame_parse23a(const u8 *frame, u32 frame_len, u8* category,
1807 u8 *action)
1808{
1809 const u8 *frame_body = frame + sizeof(struct ieee80211_hdr_3addr);
1810 u16 fc;
1811 u8 c, a = 0;
1812
1813 fc = le16_to_cpu(((struct ieee80211_hdr_3addr *)frame)->frame_control);
1814
1815 if ((fc & (IEEE80211_FCTL_FTYPE|IEEE80211_FCTL_STYPE)) !=
1816 (IEEE80211_FTYPE_MGMT|IEEE80211_STYPE_ACTION)) {
1817 return false;
1818 }
1819
1820 c = frame_body[0];
1821
1822 switch (c) {
1823 case WLAN_CATEGORY_VENDOR_SPECIFIC: /* vendor-specific */
1824 break;
1825 default:
1826 a = frame_body[1];
1827 }
1828
1829 if (category)
1830 *category = c;
1831 if (action)
1832 *action = a;
1833
1834 return true;
1835}
1836
1837static const char *_action_public_str23a[] = {
1838 "ACT_PUB_BSSCOEXIST",
1839 "ACT_PUB_DSE_ENABLE",
1840 "ACT_PUB_DSE_DEENABLE",
1841 "ACT_PUB_DSE_REG_LOCATION",
1842 "ACT_PUB_EXT_CHL_SWITCH",
1843 "ACT_PUB_DSE_MSR_REQ",
1844 "ACT_PUB_DSE_MSR_RPRT",
1845 "ACT_PUB_MP",
1846 "ACT_PUB_DSE_PWR_CONSTRAINT",
1847 "ACT_PUB_VENDOR",
1848 "ACT_PUB_GAS_INITIAL_REQ",
1849 "ACT_PUB_GAS_INITIAL_RSP",
1850 "ACT_PUB_GAS_COMEBACK_REQ",
1851 "ACT_PUB_GAS_COMEBACK_RSP",
1852 "ACT_PUB_TDLS_DISCOVERY_RSP",
1853 "ACT_PUB_LOCATION_TRACK",
1854 "ACT_PUB_RSVD",
1855};
1856
1857const char *action_public_str23a(u8 action)
1858{
1859 action = (action >= ACT_PUBLIC_MAX) ? ACT_PUBLIC_MAX : action;
1860 return _action_public_str23a[action];
1861}
diff --git a/drivers/staging/rtl8723au/core/rtw_io.c b/drivers/staging/rtl8723au/core/rtw_io.c
new file mode 100644
index 000000000000..1cae8d7659b9
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_io.c
@@ -0,0 +1,266 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15/*
16
17The purpose of rtw_io.c
18
19a. provides the API
20
21b. provides the protocol engine
22
23c. provides the software interface between caller and the hardware interface
24
25Compiler Flag Option:
26
271. For USB:
28 a. USE_ASYNC_IRP: Both sync/async operations are provided.
29
30Only sync read/rtw_write_mem operations are provided.
31
32jackson@realtek.com.tw
33
34*/
35
36#define _RTW_IO_C_
37#include <osdep_service.h>
38#include <drv_types.h>
39#include <rtw_io.h>
40#include <osdep_intf.h>
41
42#include <usb_ops.h>
43
44u8 _rtw_read823a(struct rtw_adapter *adapter, u32 addr)
45{
46 u8 r_val;
47 struct io_priv *pio_priv = &adapter->iopriv;
48 struct intf_hdl *pintfhdl = &pio_priv->intf;
49
50 r_val = pintfhdl->io_ops._read8(pintfhdl, addr);
51
52 return r_val;
53}
54
55u16 _rtw_read1623a(struct rtw_adapter *adapter, u32 addr)
56{
57 u16 r_val;
58 struct io_priv *pio_priv = &adapter->iopriv;
59 struct intf_hdl *pintfhdl = &pio_priv->intf;
60
61 r_val = pintfhdl->io_ops._read16(pintfhdl, addr);
62
63 return le16_to_cpu(r_val);
64}
65
66u32 _rtw_read3223a(struct rtw_adapter *adapter, u32 addr)
67{
68 u32 r_val;
69 struct io_priv *pio_priv = &adapter->iopriv;
70 struct intf_hdl *pintfhdl = &pio_priv->intf;
71
72 r_val = pintfhdl->io_ops._read32(pintfhdl, addr);
73
74 return le32_to_cpu(r_val);
75}
76
77int _rtw_write823a(struct rtw_adapter *adapter, u32 addr, u8 val)
78{
79 struct io_priv *pio_priv = &adapter->iopriv;
80 struct intf_hdl *pintfhdl = &pio_priv->intf;
81 int ret;
82
83 ret = pintfhdl->io_ops._write8(pintfhdl, addr, val);
84
85 return RTW_STATUS_CODE23a(ret);
86}
87
88int _rtw_write1623a(struct rtw_adapter *adapter, u32 addr, u16 val)
89{
90 struct io_priv *pio_priv = &adapter->iopriv;
91 struct intf_hdl *pintfhdl = &pio_priv->intf;
92 int ret;
93
94 val = cpu_to_le16(val);
95 ret = pintfhdl->io_ops._write16(pintfhdl, addr, val);
96
97 return RTW_STATUS_CODE23a(ret);
98}
99int _rtw_write3223a(struct rtw_adapter *adapter, u32 addr, u32 val)
100{
101 struct io_priv *pio_priv = &adapter->iopriv;
102 struct intf_hdl *pintfhdl = &pio_priv->intf;
103 int ret;
104
105 val = cpu_to_le32(val);
106 ret = pintfhdl->io_ops._write32(pintfhdl, addr, val);
107
108 return RTW_STATUS_CODE23a(ret);
109}
110
111int _rtw_writeN23a(struct rtw_adapter *adapter, u32 addr , u32 length , u8 *pdata)
112{
113 struct io_priv *pio_priv = &adapter->iopriv;
114 struct intf_hdl *pintfhdl = (struct intf_hdl*)&pio_priv->intf;
115 int ret;
116
117 ret = pintfhdl->io_ops._writeN(pintfhdl, addr, length, pdata);
118
119 return RTW_STATUS_CODE23a(ret);
120}
121int _rtw_write823a_async23a(struct rtw_adapter *adapter, u32 addr, u8 val)
122{
123 struct io_priv *pio_priv = &adapter->iopriv;
124 struct intf_hdl *pintfhdl = &pio_priv->intf;
125 int ret;
126
127 ret = pintfhdl->io_ops._write8_async(pintfhdl, addr, val);
128
129 return RTW_STATUS_CODE23a(ret);
130}
131int _rtw_write1623a_async(struct rtw_adapter *adapter, u32 addr, u16 val)
132{
133 struct io_priv *pio_priv = &adapter->iopriv;
134 struct intf_hdl *pintfhdl = &pio_priv->intf;
135 int ret;
136
137 val = cpu_to_le16(val);
138 ret = pintfhdl->io_ops._write16_async(pintfhdl, addr, val);
139
140 return RTW_STATUS_CODE23a(ret);
141}
142int _rtw_write3223a_async23a(struct rtw_adapter *adapter, u32 addr, u32 val)
143{
144 struct io_priv *pio_priv = &adapter->iopriv;
145 struct intf_hdl *pintfhdl = &pio_priv->intf;
146 int ret;
147
148 val = cpu_to_le32(val);
149 ret = pintfhdl->io_ops._write32_async(pintfhdl, addr, val);
150
151 return RTW_STATUS_CODE23a(ret);
152}
153
154void _rtw_read_mem23a(struct rtw_adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
155{
156 struct io_priv *pio_priv = &adapter->iopriv;
157 struct intf_hdl *pintfhdl = &pio_priv->intf;
158
159 if ((adapter->bDriverStopped == true) ||
160 (adapter->bSurpriseRemoved == true)) {
161 RT_TRACE(_module_rtl871x_io_c_, _drv_info_,
162 ("rtw_read_mem:bDriverStopped(%d) OR "
163 "bSurpriseRemoved(%d)", adapter->bDriverStopped,
164 adapter->bSurpriseRemoved));
165 return;
166 }
167
168 pintfhdl->io_ops._read_mem(pintfhdl, addr, cnt, pmem);
169}
170
171void _rtw_write_mem23a(struct rtw_adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
172{
173 struct io_priv *pio_priv = &adapter->iopriv;
174 struct intf_hdl *pintfhdl = &pio_priv->intf;
175
176 pintfhdl->io_ops._write_mem(pintfhdl, addr, cnt, pmem);
177}
178
179void _rtw_read_port23a(struct rtw_adapter *adapter, u32 addr, u32 cnt,
180 struct recv_buf *rbuf)
181{
182 struct io_priv *pio_priv = &adapter->iopriv;
183 struct intf_hdl *pintfhdl = &pio_priv->intf;
184
185 if ((adapter->bDriverStopped == true) ||
186 (adapter->bSurpriseRemoved == true)) {
187 RT_TRACE(_module_rtl871x_io_c_, _drv_info_,
188 ("rtw_read_port:bDriverStopped(%d) OR "
189 "bSurpriseRemoved(%d)", adapter->bDriverStopped,
190 adapter->bSurpriseRemoved));
191 return;
192 }
193
194 pintfhdl->io_ops._read_port(pintfhdl, addr, cnt, rbuf);
195}
196
197void _rtw_read_port23a_cancel(struct rtw_adapter *adapter)
198{
199 void (*_read_port_cancel)(struct intf_hdl *pintfhdl);
200 struct io_priv *pio_priv = &adapter->iopriv;
201 struct intf_hdl *pintfhdl = &pio_priv->intf;
202
203 _read_port_cancel = pintfhdl->io_ops._read_port_cancel;
204
205 if (_read_port_cancel)
206 _read_port_cancel(pintfhdl);
207}
208
209u32 _rtw_write_port23a(struct rtw_adapter *adapter, u32 addr, u32 cnt,
210 struct xmit_buf *xbuf)
211{
212 struct io_priv *pio_priv = &adapter->iopriv;
213 struct intf_hdl *pintfhdl = &pio_priv->intf;
214 u32 ret = _SUCCESS;
215
216 ret = pintfhdl->io_ops._write_port(pintfhdl, addr, cnt, xbuf);
217
218 return ret;
219}
220
221u32 _rtw_write_port23a_and_wait23a(struct rtw_adapter *adapter, u32 addr, u32 cnt,
222 struct xmit_buf *pxmitbuf, int timeout_ms)
223{
224 int ret = _SUCCESS;
225 struct submit_ctx sctx;
226
227 rtw_sctx_init23a(&sctx, timeout_ms);
228 pxmitbuf->sctx = &sctx;
229
230 ret = _rtw_write_port23a(adapter, addr, cnt, pxmitbuf);
231
232 if (ret == _SUCCESS)
233 ret = rtw_sctx_wait23a(&sctx);
234
235 return ret;
236}
237
238void _rtw_write_port23a_cancel(struct rtw_adapter *adapter)
239{
240 void (*_write_port_cancel)(struct intf_hdl *pintfhdl);
241 struct io_priv *pio_priv = &adapter->iopriv;
242 struct intf_hdl *pintfhdl = &pio_priv->intf;
243
244 _write_port_cancel = pintfhdl->io_ops._write_port_cancel;
245
246 if (_write_port_cancel)
247 _write_port_cancel(pintfhdl);
248}
249
250int rtw_init_io_priv23a(struct rtw_adapter *padapter,
251 void (*set_intf_ops)(struct _io_ops *pops))
252{
253 struct io_priv *piopriv = &padapter->iopriv;
254 struct intf_hdl *pintf = &piopriv->intf;
255
256 if (set_intf_ops == NULL)
257 return _FAIL;
258
259 piopriv->padapter = padapter;
260 pintf->padapter = padapter;
261 pintf->pintf_dev = adapter_to_dvobj(padapter);
262
263 set_intf_ops(&pintf->io_ops);
264
265 return _SUCCESS;
266}
diff --git a/drivers/staging/rtl8723au/core/rtw_ioctl_set.c b/drivers/staging/rtl8723au/core/rtw_ioctl_set.c
new file mode 100644
index 000000000000..30d7185e5637
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_ioctl_set.c
@@ -0,0 +1,601 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _RTW_IOCTL_SET_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <rtw_ioctl_set.h>
20#include <hal_intf.h>
21
22#include <usb_osintf.h>
23#include <usb_ops.h>
24#include <linux/ieee80211.h>
25
26u8 rtw_do_join23a(struct rtw_adapter *padapter)
27{
28 struct list_head *plist, *phead;
29 u8* pibss = NULL;
30 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
31 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
32 u8 ret = _SUCCESS;
33
34 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
35 phead = get_list_head(queue);
36 plist = phead->next;
37
38 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
39 ("\n rtw_do_join23a: phead = %p; plist = %p\n\n\n",
40 phead, plist));
41
42 pmlmepriv->cur_network.join_res = -2;
43
44 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
45
46 pmlmepriv->to_join = true;
47
48 if (_rtw_queue_empty23a(queue) == true) {
49 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
50 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
51
52 /* when set_ssid/set_bssid for rtw_do_join23a(), but
53 scanning queue is empty */
54 /* we try to issue sitesurvey firstly */
55
56 if (pmlmepriv->LinkDetectInfo.bBusyTraffic == false ||
57 rtw_to_roaming(padapter) > 0) {
58 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
59 ("rtw_do_join23a(): site survey if scanned_queue "
60 "is empty\n."));
61 /* submit site_survey23a_cmd */
62 ret = rtw_sitesurvey_cmd23a(padapter,
63 &pmlmepriv->assoc_ssid, 1,
64 NULL, 0);
65 if (ret != _SUCCESS) {
66 pmlmepriv->to_join = false;
67 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
68 ("rtw_do_join23a(): site survey return "
69 "error\n."));
70 }
71 } else {
72 pmlmepriv->to_join = false;
73 ret = _FAIL;
74 }
75
76 goto exit;
77 } else {
78 int select_ret;
79 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
80 select_ret = rtw_select_and_join_from_scanned_queue23a(pmlmepriv);
81 if (select_ret == _SUCCESS) {
82 pmlmepriv->to_join = false;
83 mod_timer(&pmlmepriv->assoc_timer,
84 jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
85 } else {
86 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
87 struct wlan_bssid_ex *pdev_network;
88 /* submit createbss_cmd to change to a
89 ADHOC_MASTER */
90
91 /* pmlmepriv->lock has been acquired by
92 caller... */
93 pdev_network =
94 &padapter->registrypriv.dev_network;
95
96 pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
97
98 pibss = padapter->registrypriv.dev_network.MacAddress;
99
100 memcpy(&pdev_network->Ssid,
101 &pmlmepriv->assoc_ssid,
102 sizeof(struct cfg80211_ssid));
103
104 rtw_update_registrypriv_dev_network23a(padapter);
105
106 rtw_generate_random_ibss23a(pibss);
107
108 if (rtw_createbss_cmd23a(padapter) != _SUCCESS) {
109 RT_TRACE(_module_rtl871x_ioctl_set_c_,
110 _drv_err_,
111 ("***Error =>do_goin: rtw_creat"
112 "ebss_cmd status FAIL***\n"));
113 ret = false;
114 goto exit;
115 }
116
117 pmlmepriv->to_join = false;
118
119 RT_TRACE(_module_rtl871x_ioctl_set_c_,
120 _drv_info_,
121 ("***Error => rtw_select_and_join_from"
122 "_scanned_queue FAIL under STA_Mode"
123 "***\n "));
124 } else {
125 /* can't associate ; reset under-linking */
126 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
127
128 /* when set_ssid/set_bssid for rtw_do_join23a(),
129 but there are no desired bss in scanning
130 queue */
131 /* we try to issue sitesurvey firstly */
132 if (pmlmepriv->LinkDetectInfo.bBusyTraffic ==
133 false || rtw_to_roaming(padapter) > 0) {
134 /* DBG_8723A("rtw_do_join23a() when no "
135 "desired bss in scanning queue\n");
136 */
137 ret = rtw_sitesurvey_cmd23a(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
138 if (ret != _SUCCESS) {
139 pmlmepriv->to_join = false;
140 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("do_join(): site survey return error\n."));
141 }
142 } else {
143 ret = _FAIL;
144 pmlmepriv->to_join = false;
145 }
146 }
147 }
148 }
149
150exit:
151
152 return ret;
153}
154
155u8 rtw_set_802_11_ssid23a(struct rtw_adapter* padapter, struct cfg80211_ssid *ssid)
156{
157 u8 status = _SUCCESS;
158 u32 cur_time = 0;
159
160 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
161 struct wlan_network *pnetwork = &pmlmepriv->cur_network;
162
163
164
165 DBG_8723A_LEVEL(_drv_always_, "set ssid [%s] fw_state = 0x%08x\n",
166 ssid->ssid, get_fwstate(pmlmepriv));
167
168 if (padapter->hw_init_completed == false) {
169 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
170 ("set_ssid: hw_init_completed == false =>exit!!!\n"));
171 status = _FAIL;
172 goto exit;
173 }
174
175 spin_lock_bh(&pmlmepriv->lock);
176
177 DBG_8723A("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
178 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
179 goto handle_tkip_countermeasure;
180 } else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) {
181 goto release_mlme_lock;
182 }
183
184 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true)
185 {
186 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
187 ("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
188
189 if ((pmlmepriv->assoc_ssid.ssid_len == ssid->ssid_len) &&
190 !memcmp(&pmlmepriv->assoc_ssid.ssid, ssid->ssid,
191 ssid->ssid_len)) {
192 if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == false))
193 {
194 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
195 ("Set SSID is the same ssid, fw_state = 0x%08x\n",
196 get_fwstate(pmlmepriv)));
197
198 if (rtw_is_same_ibss23a(padapter, pnetwork) == false)
199 {
200 /* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */
201 rtw_disassoc_cmd23a(padapter, 0, true);
202
203 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
204 rtw_indicate_disconnect23a(padapter);
205
206 rtw_free_assoc_resources23a(padapter, 1);
207
208 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
209 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
210 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
211 }
212 } else {
213 goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
214 }
215 } else {
216 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_JOINBSS, 1);
217 }
218 } else {
219 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
220 ("Set SSID not the same ssid\n"));
221 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
222 ("set_ssid =[%s] len = 0x%x\n", ssid->ssid,
223 (unsigned int)ssid->ssid_len));
224 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
225 ("assoc_ssid =[%s] len = 0x%x\n",
226 pmlmepriv->assoc_ssid.ssid,
227 (unsigned int)pmlmepriv->assoc_ssid.ssid_len));
228
229 rtw_disassoc_cmd23a(padapter, 0, true);
230
231 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
232 rtw_indicate_disconnect23a(padapter);
233
234 rtw_free_assoc_resources23a(padapter, 1);
235
236 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
237 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
238 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
239 }
240 }
241 }
242
243handle_tkip_countermeasure:
244
245 if (padapter->securitypriv.btkip_countermeasure == true) {
246 cur_time = jiffies;
247
248 if ((cur_time - padapter->securitypriv.btkip_countermeasure_time) > 60 * HZ)
249 {
250 padapter->securitypriv.btkip_countermeasure = false;
251 padapter->securitypriv.btkip_countermeasure_time = 0;
252 }
253 else
254 {
255 status = _FAIL;
256 goto release_mlme_lock;
257 }
258 }
259
260 memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct cfg80211_ssid));
261 pmlmepriv->assoc_by_bssid = false;
262
263 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
264 pmlmepriv->to_join = true;
265 }
266 else {
267 status = rtw_do_join23a(padapter);
268 }
269
270release_mlme_lock:
271 spin_unlock_bh(&pmlmepriv->lock);
272
273exit:
274 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
275 ("-rtw_set_802_11_ssid23a: status =%d\n", status));
276
277
278
279 return status;
280}
281
282u8 rtw_set_802_11_infrastructure_mode23a(struct rtw_adapter* padapter,
283 enum ndis_802_11_net_infra networktype)
284{
285 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
286 struct wlan_network *cur_network = &pmlmepriv->cur_network;
287 enum ndis_802_11_net_infra* pold_state = &cur_network->network.InfrastructureMode;
288
289
290
291 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_,
292 ("+rtw_set_802_11_infrastructure_mode23a: old =%d new =%d fw_state = 0x%08x\n",
293 *pold_state, networktype, get_fwstate(pmlmepriv)));
294
295 if (*pold_state != networktype)
296 {
297 spin_lock_bh(&pmlmepriv->lock);
298
299 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, (" change mode!"));
300 /* DBG_8723A("change mode, old_mode =%d, new_mode =%d, fw_state = 0x%x\n", *pold_state, networktype, get_fwstate(pmlmepriv)); */
301
302 if (*pold_state == Ndis802_11APMode)
303 {
304 /* change to other mode from Ndis802_11APMode */
305 cur_network->join_res = -1;
306
307#ifdef CONFIG_8723AU_AP_MODE
308 stop_ap_mode23a(padapter);
309#endif
310 }
311
312 if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) ||(*pold_state == Ndis802_11IBSS))
313 rtw_disassoc_cmd23a(padapter, 0, true);
314
315 if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) ||
316 (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true))
317 rtw_free_assoc_resources23a(padapter, 1);
318
319 if ((*pold_state == Ndis802_11Infrastructure) ||(*pold_state == Ndis802_11IBSS))
320 {
321 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
322 {
323 rtw_indicate_disconnect23a(padapter); /* will clr Linked_state; before this function, we must have chked whether issue dis-assoc_cmd or not */
324 }
325 }
326
327 *pold_state = networktype;
328
329 _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
330
331 switch (networktype)
332 {
333 case Ndis802_11IBSS:
334 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
335 break;
336
337 case Ndis802_11Infrastructure:
338 set_fwstate(pmlmepriv, WIFI_STATION_STATE);
339 break;
340
341 case Ndis802_11APMode:
342 set_fwstate(pmlmepriv, WIFI_AP_STATE);
343#ifdef CONFIG_8723AU_AP_MODE
344 start_ap_mode23a(padapter);
345 /* rtw_indicate_connect23a(padapter); */
346#endif
347
348 break;
349
350 case Ndis802_11AutoUnknown:
351 case Ndis802_11InfrastructureMax:
352 break;
353 }
354
355 /* SecClearAllKeys(adapter); */
356
357 /* RT_TRACE(COMP_OID_SET, DBG_LOUD, ("set_infrastructure: fw_state:%x after changing mode\n", */
358 /* get_fwstate(pmlmepriv))); */
359
360 spin_unlock_bh(&pmlmepriv->lock);
361 }
362
363
364
365 return true;
366}
367
368u8 rtw_set_802_11_bssid23a_list_scan(struct rtw_adapter *padapter,
369 struct cfg80211_ssid *pssid, int ssid_max_num)
370{
371 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
372 u8 res = true;
373
374 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
375 ("+rtw_set_802_11_bssid23a_list_scan(), fw_state =%x\n",
376 get_fwstate(pmlmepriv)));
377
378 if (!padapter) {
379 res = false;
380 goto exit;
381 }
382 if (padapter->hw_init_completed == false) {
383 res = false;
384 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
385 ("\n === rtw_set_802_11_bssid23a_list_scan:"
386 "hw_init_completed == false ===\n"));
387 goto exit;
388 }
389
390 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ||
391 (pmlmepriv->LinkDetectInfo.bBusyTraffic == true)) {
392 /* Scan or linking is in progress, do nothing. */
393 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
394 ("rtw_set_802_11_bssid23a_list_scan fail since fw_state "
395 "= %x\n", get_fwstate(pmlmepriv)));
396 res = true;
397
398 if (check_fwstate(pmlmepriv,
399 (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) {
400 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
401 ("\n###_FW_UNDER_SURVEY|_FW_UNDER_LINKING\n"));
402 } else {
403 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
404 ("\n###pmlmepriv->sitesurveyctrl.traffic_"
405 "busy == true\n"));
406 }
407 } else {
408 if (rtw_is_scan_deny(padapter)) {
409 DBG_8723A(FUNC_ADPT_FMT": scan deny\n",
410 FUNC_ADPT_ARG(padapter));
411 return _SUCCESS;
412 }
413
414 spin_lock_bh(&pmlmepriv->lock);
415
416 res = rtw_sitesurvey_cmd23a(padapter, pssid, ssid_max_num,
417 NULL, 0);
418
419 spin_unlock_bh(&pmlmepriv->lock);
420 }
421exit:
422 return res;
423}
424
425u8 rtw_set_802_11_authentication_mode23a(struct rtw_adapter* padapter,
426 enum ndis_802_11_auth_mode authmode)
427{
428 struct security_priv *psecuritypriv = &padapter->securitypriv;
429 int res;
430 u8 ret;
431
432 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
433 ("set_802_11_auth.mode(): mode =%x\n", authmode));
434
435 psecuritypriv->ndisauthtype = authmode;
436
437 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
438 ("rtw_set_802_11_authentication_mode23a:"
439 "psecuritypriv->ndisauthtype =%d",
440 psecuritypriv->ndisauthtype));
441
442 if (psecuritypriv->ndisauthtype > 3)
443 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
444
445 res = rtw_set_auth23a(padapter, psecuritypriv);
446
447 if (res == _SUCCESS)
448 ret = true;
449 else
450 ret = false;
451
452 return ret;
453}
454
455u8 rtw_set_802_11_add_wep23a(struct rtw_adapter* padapter,
456 struct ndis_802_11_wep *wep)
457{
458 u8 bdefaultkey;
459 u8 btransmitkey;
460 int keyid, res;
461 struct security_priv *psecuritypriv = &padapter->securitypriv;
462 u8 ret = _SUCCESS;
463
464 bdefaultkey = (wep->KeyIndex & 0x40000000) > 0 ? false : true;
465 btransmitkey = (wep->KeyIndex & 0x80000000) > 0 ? true : false;
466 keyid = wep->KeyIndex & 0x3fffffff;
467
468 if (keyid >= 4) {
469 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
470 ("MgntActrtw_set_802_11_add_wep23a:keyid>4 =>fail\n"));
471 ret = false;
472 goto exit;
473 }
474
475 switch (wep->KeyLength)
476 {
477 case 5:
478 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
479 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
480 ("MgntActrtw_set_802_11_add_wep23a:wep->KeyLength = 5\n"));
481 break;
482 case 13:
483 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
484 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
485 ("MgntActrtw_set_802_11_add_wep23a:wep->KeyLength = 13\n"));
486 break;
487 default:
488 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
489 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
490 ("MgntActrtw_set_802_11_add_wep23a:wep->KeyLength!= 5 "
491 "or 13\n"));
492 break;
493 }
494
495 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
496 ("rtw_set_802_11_add_wep23a:befor memcpy, wep->KeyLength = 0x%x "
497 "wep->KeyIndex = 0x%x keyid =%x\n",
498 wep->KeyLength, wep->KeyIndex, keyid));
499
500 memcpy(&psecuritypriv->dot11DefKey[keyid].skey[0],
501 &wep->KeyMaterial, wep->KeyLength);
502
503 psecuritypriv->dot11DefKeylen[keyid] = wep->KeyLength;
504
505 psecuritypriv->dot11PrivacyKeyIndex = keyid;
506
507 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
508 ("rtw_set_802_11_add_wep23a:security key material : %x %x %x %x "
509 "%x %x %x %x %x %x %x %x %x\n",
510 psecuritypriv->dot11DefKey[keyid].skey[0],
511 psecuritypriv->dot11DefKey[keyid].skey[1],
512 psecuritypriv->dot11DefKey[keyid].skey[2],
513 psecuritypriv->dot11DefKey[keyid].skey[3],
514 psecuritypriv->dot11DefKey[keyid].skey[4],
515 psecuritypriv->dot11DefKey[keyid].skey[5],
516 psecuritypriv->dot11DefKey[keyid].skey[6],
517 psecuritypriv->dot11DefKey[keyid].skey[7],
518 psecuritypriv->dot11DefKey[keyid].skey[8],
519 psecuritypriv->dot11DefKey[keyid].skey[9],
520 psecuritypriv->dot11DefKey[keyid].skey[10],
521 psecuritypriv->dot11DefKey[keyid].skey[11],
522 psecuritypriv->dot11DefKey[keyid].skey[12]));
523
524 res = rtw_set_key23a(padapter, psecuritypriv, keyid, 1);
525
526 if (res == _FAIL)
527 ret = false;
528exit:
529
530 return ret;
531}
532
533/*
534* rtw_get_cur_max_rate23a -
535* @adapter: pointer to _adapter structure
536*
537* Return 0 or 100Kbps
538*/
539u16 rtw_get_cur_max_rate23a(struct rtw_adapter *adapter)
540{
541 int i = 0;
542 u8 *p;
543 u16 rate = 0, max_rate = 0;
544 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
545 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
546 struct registry_priv *pregistrypriv = &adapter->registrypriv;
547 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
548 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
549 struct ieee80211_ht_cap *pht_capie;
550 u8 rf_type = 0;
551 u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0;
552 u16 mcs_rate = 0;
553 u32 ht_ielen = 0;
554
555 if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
556 !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
557 return 0;
558
559 if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N|WIRELESS_11_5N)) {
560 p = rtw_get_ie23a(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
561 &ht_ielen, pcur_bss->IELength - 12);
562 if (p && ht_ielen > 0) {
563 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
564
565 memcpy(&mcs_rate, &pht_capie->mcs, 2);
566
567 /* bw_40MHz = (pht_capie->cap_info&
568 IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1:0; */
569 /* cur_bwmod is updated by beacon, pmlmeinfo is
570 updated by association response */
571 bw_40MHz = (pmlmeext->cur_bwmode &&
572 (HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH &
573 pmlmeinfo->HT_info.infos[0])) ? 1:0;
574
575 /* short_GI = (pht_capie->cap_info & (IEEE80211_HT_CAP
576 _SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; */
577 short_GI_20 = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info&IEEE80211_HT_CAP_SGI_20) ? 1:0;
578 short_GI_40 = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info&IEEE80211_HT_CAP_SGI_40) ? 1:0;
579
580 rtw23a_hal_get_hwreg(adapter, HW_VAR_RF_TYPE,
581 (u8 *)(&rf_type));
582 max_rate = rtw_mcs_rate23a(rf_type, bw_40MHz &
583 pregistrypriv->cbw40_enable,
584 short_GI_20, short_GI_40,
585 pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate
586 );
587 }
588 } else {
589 while ((pcur_bss->SupportedRates[i] != 0) &&
590 (pcur_bss->SupportedRates[i] != 0xFF)) {
591 rate = pcur_bss->SupportedRates[i] & 0x7F;
592 if (rate>max_rate)
593 max_rate = rate;
594 i++;
595 }
596
597 max_rate = max_rate * 10 / 2;
598 }
599
600 return max_rate;
601}
diff --git a/drivers/staging/rtl8723au/core/rtw_led.c b/drivers/staging/rtl8723au/core/rtw_led.c
new file mode 100644
index 000000000000..68532a3b2c14
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_led.c
@@ -0,0 +1,1899 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15
16#include <drv_types.h>
17#include <rtl8723a_led.h>
18
19/* */
20/* Description: */
21/* Callback function of LED BlinkTimer, */
22/* it just schedules to corresponding BlinkWorkItem/led_blink_hdl23a */
23/* */
24static void BlinkTimerCallback(unsigned long data)
25{
26 struct led_8723a *pLed = (struct led_8723a *)data;
27 struct rtw_adapter *padapter = pLed->padapter;
28
29 /* DBG_8723A("%s\n", __func__); */
30
31 if ((padapter->bSurpriseRemoved == true) || (padapter->bDriverStopped == true))
32 {
33 /* DBG_8723A("%s bSurpriseRemoved:%d, bDriverStopped:%d\n", __func__, padapter->bSurpriseRemoved, padapter->bDriverStopped); */
34 return;
35 }
36 schedule_work(&pLed->BlinkWorkItem);
37}
38
39/* */
40/* Description: */
41/* Callback function of LED BlinkWorkItem. */
42/* We dispatch acture LED blink action according to LedStrategy. */
43/* */
44void BlinkWorkItemCallback23a(struct work_struct *work)
45{
46 struct led_8723a *pLed = container_of(work, struct led_8723a, BlinkWorkItem);
47 BlinkHandler23a(pLed);
48}
49
50/* */
51/* Description: */
52/* Reset status of led_8723a object. */
53/* */
54void ResetLedStatus23a(struct led_8723a * pLed) {
55
56 pLed->CurrLedState = RTW_LED_OFF; /* Current LED state. */
57 pLed->bLedOn = false; /* true if LED is ON, false if LED is OFF. */
58
59 pLed->bLedBlinkInProgress = false; /* true if it is blinking, false o.w.. */
60 pLed->bLedWPSBlinkInProgress = false;
61
62 pLed->BlinkTimes = 0; /* Number of times to toggle led state for blinking. */
63 pLed->BlinkingLedState = LED_UNKNOWN; /* Next state for blinking, either RTW_LED_ON or RTW_LED_OFF are. */
64
65 pLed->bLedNoLinkBlinkInProgress = false;
66 pLed->bLedLinkBlinkInProgress = false;
67 pLed->bLedStartToLinkBlinkInProgress = false;
68 pLed->bLedScanBlinkInProgress = false;
69}
70
71 /* */
72/* Description: */
73/* Initialize an led_8723a object. */
74/* */
75void
76InitLed871x23a(struct rtw_adapter *padapter, struct led_8723a *pLed, enum led_pin_8723a LedPin)
77{
78 pLed->padapter = padapter;
79 pLed->LedPin = LedPin;
80
81 ResetLedStatus23a(pLed);
82
83 setup_timer(&pLed->BlinkTimer, BlinkTimerCallback, (unsigned long)pLed);
84
85 INIT_WORK(&pLed->BlinkWorkItem, BlinkWorkItemCallback23a);
86}
87
88/* */
89/* Description: */
90/* DeInitialize an led_8723a object. */
91/* */
92void
93DeInitLed871x23a(struct led_8723a *pLed)
94{
95 cancel_work_sync(&pLed->BlinkWorkItem);
96 del_timer_sync(&pLed->BlinkTimer);
97 ResetLedStatus23a(pLed);
98}
99
100/* Description: */
101/* Implementation of LED blinking behavior. */
102/* It toggle off LED and schedule corresponding timer if necessary. */
103
104static void SwLedBlink(struct led_8723a *pLed)
105{
106 struct rtw_adapter *padapter = pLed->padapter;
107 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
108 u8 bStopBlinking = false;
109
110 /* Change LED according to BlinkingLedState specified. */
111 if (pLed->BlinkingLedState == RTW_LED_ON) {
112 SwLedOn23a(padapter, pLed);
113 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
114 } else {
115 SwLedOff23a(padapter, pLed);
116 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
117 }
118
119 /* Determine if we shall change LED state again. */
120 pLed->BlinkTimes--;
121 switch (pLed->CurrLedState) {
122
123 case LED_BLINK_NORMAL:
124 if (pLed->BlinkTimes == 0)
125 bStopBlinking = true;
126 break;
127 case LED_BLINK_StartToBlink:
128 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
129 check_fwstate(pmlmepriv, WIFI_STATION_STATE))
130 bStopBlinking = true;
131 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
132 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
133 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)))
134 bStopBlinking = true;
135 else if (pLed->BlinkTimes == 0)
136 bStopBlinking = true;
137 break;
138 case LED_BLINK_WPS:
139 if (pLed->BlinkTimes == 0)
140 bStopBlinking = true;
141 break;
142 default:
143 bStopBlinking = true;
144 break;
145 }
146
147 if (bStopBlinking) {
148 if ((check_fwstate(pmlmepriv, _FW_LINKED)) && !pLed->bLedOn)
149 SwLedOn23a(padapter, pLed);
150 else if ((check_fwstate(pmlmepriv, _FW_LINKED)) && pLed->bLedOn)
151 SwLedOff23a(padapter, pLed);
152
153 pLed->BlinkTimes = 0;
154 pLed->bLedBlinkInProgress = false;
155 } else {
156 /* Assign LED state to toggle. */
157 if (pLed->BlinkingLedState == RTW_LED_ON)
158 pLed->BlinkingLedState = RTW_LED_OFF;
159 else
160 pLed->BlinkingLedState = RTW_LED_ON;
161
162 /* Schedule a timer to toggle LED state. */
163 switch (pLed->CurrLedState) {
164 case LED_BLINK_NORMAL:
165 mod_timer(&pLed->BlinkTimer, jiffies +
166 msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
167 break;
168 case LED_BLINK_SLOWLY:
169 case LED_BLINK_StartToBlink:
170 mod_timer(&pLed->BlinkTimer, jiffies +
171 msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
172 break;
173 case LED_BLINK_WPS:
174 mod_timer(&pLed->BlinkTimer, jiffies +
175 msecs_to_jiffies(LED_BLINK_LONG_INTERVAL));
176 break;
177 default:
178 mod_timer(&pLed->BlinkTimer, jiffies +
179 msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
180 break;
181 }
182 }
183}
184
185static void SwLedBlink1(struct led_8723a *pLed)
186{
187 struct rtw_adapter *padapter = pLed->padapter;
188 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
189 unsigned long delay = 0;
190 u8 bStopBlinking = false;
191
192 /* Change LED according to BlinkingLedState specified. */
193 if (pLed->BlinkingLedState == RTW_LED_ON) {
194 SwLedOn23a(padapter, pLed);
195 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
196 ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
197 } else {
198 SwLedOff23a(padapter, pLed);
199 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
200 ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
201 }
202
203 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
204 SwLedOff23a(padapter, pLed);
205 ResetLedStatus23a(pLed);
206 return;
207 }
208 switch (pLed->CurrLedState) {
209 case LED_BLINK_SLOWLY:
210 if (pLed->bLedOn)
211 pLed->BlinkingLedState = RTW_LED_OFF;
212 else
213 pLed->BlinkingLedState = RTW_LED_ON;
214 delay = LED_BLINK_NO_LINK_INTERVAL_ALPHA;
215 break;
216 case LED_BLINK_NORMAL:
217 if (pLed->bLedOn)
218 pLed->BlinkingLedState = RTW_LED_OFF;
219 else
220 pLed->BlinkingLedState = RTW_LED_ON;
221 delay = LED_BLINK_LINK_INTERVAL_ALPHA;
222 break;
223 case LED_BLINK_SCAN:
224 pLed->BlinkTimes--;
225 if (pLed->BlinkTimes == 0)
226 bStopBlinking = true;
227 if (bStopBlinking) {
228 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
229 pLed->bLedLinkBlinkInProgress = true;
230 pLed->CurrLedState = LED_BLINK_NORMAL;
231 if (pLed->bLedOn)
232 pLed->BlinkingLedState = RTW_LED_OFF;
233 else
234 pLed->BlinkingLedState = RTW_LED_ON;
235 delay = LED_BLINK_LINK_INTERVAL_ALPHA;
236 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
237 } else if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
238 pLed->bLedNoLinkBlinkInProgress = true;
239 pLed->CurrLedState = LED_BLINK_SLOWLY;
240 if (pLed->bLedOn)
241 pLed->BlinkingLedState = RTW_LED_OFF;
242 else
243 pLed->BlinkingLedState = RTW_LED_ON;
244 delay = LED_BLINK_NO_LINK_INTERVAL_ALPHA;
245 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
246 }
247 pLed->bLedScanBlinkInProgress = false;
248 } else {
249 if (pLed->bLedOn)
250 pLed->BlinkingLedState = RTW_LED_OFF;
251 else
252 pLed->BlinkingLedState = RTW_LED_ON;
253 delay = LED_BLINK_SCAN_INTERVAL_ALPHA;
254 }
255 break;
256 case LED_BLINK_TXRX:
257 pLed->BlinkTimes--;
258 if (pLed->BlinkTimes == 0)
259 bStopBlinking = true;
260 if (bStopBlinking) {
261 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
262 pLed->bLedLinkBlinkInProgress = true;
263 pLed->CurrLedState = LED_BLINK_NORMAL;
264 if (pLed->bLedOn)
265 pLed->BlinkingLedState = RTW_LED_OFF;
266 else
267 pLed->BlinkingLedState = RTW_LED_ON;
268 delay = LED_BLINK_LINK_INTERVAL_ALPHA;
269 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
270 } else if (check_fwstate(pmlmepriv,
271 _FW_LINKED) == false) {
272 pLed->bLedNoLinkBlinkInProgress = true;
273 pLed->CurrLedState = LED_BLINK_SLOWLY;
274 if (pLed->bLedOn)
275 pLed->BlinkingLedState = RTW_LED_OFF;
276 else
277 pLed->BlinkingLedState = RTW_LED_ON;
278 delay = LED_BLINK_NO_LINK_INTERVAL_ALPHA;
279 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
280 }
281 pLed->BlinkTimes = 0;
282 pLed->bLedBlinkInProgress = false;
283 } else {
284 if (pLed->bLedOn)
285 pLed->BlinkingLedState = RTW_LED_OFF;
286 else
287 pLed->BlinkingLedState = RTW_LED_ON;
288 delay = LED_BLINK_FASTER_INTERVAL_ALPHA;
289 }
290 break;
291 case LED_BLINK_WPS:
292 if (pLed->bLedOn)
293 pLed->BlinkingLedState = RTW_LED_OFF;
294 else
295 pLed->BlinkingLedState = RTW_LED_ON;
296 delay = LED_BLINK_SCAN_INTERVAL_ALPHA;
297 break;
298 case LED_BLINK_WPS_STOP: /* WPS success */
299 if (pLed->BlinkingLedState == RTW_LED_ON)
300 bStopBlinking = false;
301 else
302 bStopBlinking = true;
303 if (bStopBlinking) {
304 pLed->bLedLinkBlinkInProgress = true;
305 pLed->CurrLedState = LED_BLINK_NORMAL;
306 if (pLed->bLedOn)
307 pLed->BlinkingLedState = RTW_LED_OFF;
308 else
309 pLed->BlinkingLedState = RTW_LED_ON;
310 delay = LED_BLINK_LINK_INTERVAL_ALPHA;
311 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
312
313 pLed->bLedWPSBlinkInProgress = false;
314 } else {
315 pLed->BlinkingLedState = RTW_LED_OFF;
316 delay = LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA;
317 }
318 break;
319 default:
320 break;
321 }
322 if (delay)
323 mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(delay));
324}
325
326static void SwLedBlink2(struct led_8723a *pLed)
327{
328 struct rtw_adapter *padapter = pLed->padapter;
329 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
330 u8 bStopBlinking = false;
331
332 /* Change LED according to BlinkingLedState specified. */
333 if (pLed->BlinkingLedState == RTW_LED_ON) {
334 SwLedOn23a(padapter, pLed);
335 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
336 ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
337 } else {
338 SwLedOff23a(padapter, pLed);
339 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
340 ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
341 }
342 switch (pLed->CurrLedState) {
343 case LED_BLINK_SCAN:
344 pLed->BlinkTimes--;
345 if (pLed->BlinkTimes == 0)
346 bStopBlinking = true;
347 if (bStopBlinking) {
348 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
349 SwLedOff23a(padapter, pLed);
350 } else if (check_fwstate(pmlmepriv, _FW_LINKED)) {
351 pLed->CurrLedState = RTW_LED_ON;
352 pLed->BlinkingLedState = RTW_LED_ON;
353 SwLedOn23a(padapter, pLed);
354 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
355 ("stop scan blink CurrLedState %d\n",
356 pLed->CurrLedState));
357 } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
358 pLed->CurrLedState = RTW_LED_OFF;
359 pLed->BlinkingLedState = RTW_LED_OFF;
360 SwLedOff23a(padapter, pLed);
361 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
362 ("stop scan blink CurrLedState %d\n",
363 pLed->CurrLedState));
364 }
365 pLed->bLedScanBlinkInProgress = false;
366 } else {
367 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
368 SwLedOff23a(padapter, pLed);
369 } else {
370 if (pLed->bLedOn)
371 pLed->BlinkingLedState = RTW_LED_OFF;
372 else
373 pLed->BlinkingLedState = RTW_LED_ON;
374 mod_timer(&pLed->BlinkTimer,
375 jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
376 }
377 }
378 break;
379 case LED_BLINK_TXRX:
380 pLed->BlinkTimes--;
381 if (pLed->BlinkTimes == 0)
382 bStopBlinking = true;
383 if (bStopBlinking) {
384 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
385 SwLedOff23a(padapter, pLed);
386 } else if (check_fwstate(pmlmepriv, _FW_LINKED)) {
387 pLed->CurrLedState = RTW_LED_ON;
388 pLed->BlinkingLedState = RTW_LED_ON;
389 SwLedOn23a(padapter, pLed);
390 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
391 ("stop CurrLedState %d\n", pLed->CurrLedState));
392
393 } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
394 pLed->CurrLedState = RTW_LED_OFF;
395 pLed->BlinkingLedState = RTW_LED_OFF;
396 SwLedOff23a(padapter, pLed);
397 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
398 ("stop CurrLedState %d\n", pLed->CurrLedState));
399 }
400 pLed->bLedBlinkInProgress = false;
401 } else {
402 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
403 SwLedOff23a(padapter, pLed);
404 } else {
405 if (pLed->bLedOn)
406 pLed->BlinkingLedState = RTW_LED_OFF;
407 else
408 pLed->BlinkingLedState = RTW_LED_ON;
409 mod_timer(&pLed->BlinkTimer,
410 jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
411 }
412 }
413 break;
414 default:
415 break;
416 }
417}
418
419static void SwLedBlink3(struct led_8723a *pLed)
420{
421 struct rtw_adapter *padapter = pLed->padapter;
422 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
423 u8 bStopBlinking = false;
424
425 /* Change LED according to BlinkingLedState specified. */
426 if (pLed->BlinkingLedState == RTW_LED_ON)
427 {
428 SwLedOn23a(padapter, pLed);
429 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
430 }
431 else
432 {
433 if (pLed->CurrLedState != LED_BLINK_WPS_STOP)
434 SwLedOff23a(padapter, pLed);
435 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
436 }
437
438 switch (pLed->CurrLedState)
439 {
440 case LED_BLINK_SCAN:
441 pLed->BlinkTimes--;
442 if (pLed->BlinkTimes == 0)
443 {
444 bStopBlinking = true;
445 }
446
447 if (bStopBlinking)
448 {
449 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on)
450 {
451 SwLedOff23a(padapter, pLed);
452 }
453 else if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
454 {
455 pLed->CurrLedState = RTW_LED_ON;
456 pLed->BlinkingLedState = RTW_LED_ON;
457 if (!pLed->bLedOn)
458 SwLedOn23a(padapter, pLed);
459
460 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
461 }
462 else if (check_fwstate(pmlmepriv, _FW_LINKED) == false)
463 {
464 pLed->CurrLedState = RTW_LED_OFF;
465 pLed->BlinkingLedState = RTW_LED_OFF;
466 if (pLed->bLedOn)
467 SwLedOff23a(padapter, pLed);
468
469 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
470 }
471 pLed->bLedScanBlinkInProgress = false;
472 }
473 else
474 {
475 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on)
476 {
477 SwLedOff23a(padapter, pLed);
478 }
479 else
480 {
481 if (pLed->bLedOn)
482 pLed->BlinkingLedState = RTW_LED_OFF;
483 else
484 pLed->BlinkingLedState = RTW_LED_ON;
485 mod_timer(&pLed->BlinkTimer,
486 jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
487 }
488 }
489 break;
490
491 case LED_BLINK_TXRX:
492 pLed->BlinkTimes--;
493 if (pLed->BlinkTimes == 0)
494 {
495 bStopBlinking = true;
496 }
497 if (bStopBlinking)
498 {
499 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on)
500 {
501 SwLedOff23a(padapter, pLed);
502 }
503 else if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
504 {
505 pLed->CurrLedState = RTW_LED_ON;
506 pLed->BlinkingLedState = RTW_LED_ON;
507
508 if (!pLed->bLedOn)
509 SwLedOn23a(padapter, pLed);
510
511 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
512 }
513 else if (check_fwstate(pmlmepriv, _FW_LINKED) == false)
514 {
515 pLed->CurrLedState = RTW_LED_OFF;
516 pLed->BlinkingLedState = RTW_LED_OFF;
517
518 if (pLed->bLedOn)
519 SwLedOff23a(padapter, pLed);
520
521 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
522 }
523 pLed->bLedBlinkInProgress = false;
524 }
525 else
526 {
527 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on)
528 {
529 SwLedOff23a(padapter, pLed);
530 }
531 else
532 {
533 if (pLed->bLedOn)
534 pLed->BlinkingLedState = RTW_LED_OFF;
535 else
536 pLed->BlinkingLedState = RTW_LED_ON;
537 mod_timer(&pLed->BlinkTimer,
538 jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
539 }
540 }
541 break;
542
543 case LED_BLINK_WPS:
544 if (pLed->bLedOn)
545 pLed->BlinkingLedState = RTW_LED_OFF;
546 else
547 pLed->BlinkingLedState = RTW_LED_ON;
548 mod_timer(&pLed->BlinkTimer, jiffies +
549 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
550 break;
551
552 case LED_BLINK_WPS_STOP: /* WPS success */
553 if (pLed->BlinkingLedState == RTW_LED_ON)
554 {
555 pLed->BlinkingLedState = RTW_LED_OFF;
556 mod_timer(&pLed->BlinkTimer, jiffies +
557 msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA));
558 bStopBlinking = false;
559 } else {
560 bStopBlinking = true;
561 }
562
563 if (bStopBlinking)
564 {
565 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on)
566 {
567 SwLedOff23a(padapter, pLed);
568 }
569 else
570 {
571 pLed->CurrLedState = RTW_LED_ON;
572 pLed->BlinkingLedState = RTW_LED_ON;
573 SwLedOn23a(padapter, pLed);
574 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
575 }
576 pLed->bLedWPSBlinkInProgress = false;
577 }
578 break;
579
580 default:
581 break;
582 }
583}
584
585static void SwLedBlink4(struct led_8723a *pLed)
586{
587 struct rtw_adapter *padapter = pLed->padapter;
588 struct led_priv *ledpriv = &padapter->ledpriv;
589 struct led_8723a *pLed1 = &ledpriv->SwLed1;
590 u8 bStopBlinking = false;
591 unsigned long delay = 0;
592
593 /* Change LED according to BlinkingLedState specified. */
594 if (pLed->BlinkingLedState == RTW_LED_ON)
595 {
596 SwLedOn23a(padapter, pLed);
597 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
598 } else {
599 SwLedOff23a(padapter, pLed);
600 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
601 }
602
603 if (!pLed1->bLedWPSBlinkInProgress && pLed1->BlinkingLedState == LED_UNKNOWN)
604 {
605 pLed1->BlinkingLedState = RTW_LED_OFF;
606 pLed1->CurrLedState = RTW_LED_OFF;
607 SwLedOff23a(padapter, pLed1);
608 }
609
610 switch (pLed->CurrLedState)
611 {
612 case LED_BLINK_SLOWLY:
613 if (pLed->bLedOn)
614 pLed->BlinkingLedState = RTW_LED_OFF;
615 else
616 pLed->BlinkingLedState = RTW_LED_ON;
617 delay = LED_BLINK_NO_LINK_INTERVAL_ALPHA;
618 break;
619
620 case LED_BLINK_StartToBlink:
621 if (pLed->bLedOn) {
622 pLed->BlinkingLedState = RTW_LED_OFF;
623 delay = LED_BLINK_SLOWLY_INTERVAL;
624 } else {
625 pLed->BlinkingLedState = RTW_LED_ON;
626 delay = LED_BLINK_NORMAL_INTERVAL;
627 }
628 break;
629
630 case LED_BLINK_SCAN:
631 pLed->BlinkTimes--;
632 if (pLed->BlinkTimes == 0) {
633 bStopBlinking = false;
634 }
635
636 if (bStopBlinking) {
637 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
638 SwLedOff23a(padapter, pLed);
639 } else {
640 pLed->bLedNoLinkBlinkInProgress = false;
641 pLed->CurrLedState = LED_BLINK_SLOWLY;
642 if (pLed->bLedOn)
643 pLed->BlinkingLedState = RTW_LED_OFF;
644 else
645 pLed->BlinkingLedState = RTW_LED_ON;
646 delay = LED_BLINK_NO_LINK_INTERVAL_ALPHA;
647 }
648 pLed->bLedScanBlinkInProgress = false;
649 } else {
650 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
651 SwLedOff23a(padapter, pLed);
652 } else {
653 if (pLed->bLedOn)
654 pLed->BlinkingLedState = RTW_LED_OFF;
655 else
656 pLed->BlinkingLedState = RTW_LED_ON;
657 delay = LED_BLINK_SCAN_INTERVAL_ALPHA;
658 }
659 }
660 break;
661
662 case LED_BLINK_TXRX:
663 pLed->BlinkTimes--;
664 if (pLed->BlinkTimes == 0) {
665 bStopBlinking = true;
666 }
667 if (bStopBlinking) {
668 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
669 SwLedOff23a(padapter, pLed);
670 } else {
671 pLed->bLedNoLinkBlinkInProgress = true;
672 pLed->CurrLedState = LED_BLINK_SLOWLY;
673 if (pLed->bLedOn)
674 pLed->BlinkingLedState = RTW_LED_OFF;
675 else
676 pLed->BlinkingLedState = RTW_LED_ON;
677 delay = LED_BLINK_NO_LINK_INTERVAL_ALPHA;
678 }
679 pLed->bLedBlinkInProgress = false;
680 } else {
681 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
682 SwLedOff23a(padapter, pLed);
683 } else {
684 if (pLed->bLedOn)
685 pLed->BlinkingLedState = RTW_LED_OFF;
686 else
687 pLed->BlinkingLedState = RTW_LED_ON;
688 delay = LED_BLINK_FASTER_INTERVAL_ALPHA;
689 }
690 }
691 break;
692
693 case LED_BLINK_WPS:
694 if (pLed->bLedOn) {
695 pLed->BlinkingLedState = RTW_LED_OFF;
696 delay = LED_BLINK_SLOWLY_INTERVAL;
697 } else {
698 pLed->BlinkingLedState = RTW_LED_ON;
699 delay = LED_BLINK_NORMAL_INTERVAL;
700 }
701 break;
702
703 case LED_BLINK_WPS_STOP: /* WPS authentication fail */
704 if (pLed->bLedOn)
705 pLed->BlinkingLedState = RTW_LED_OFF;
706 else
707 pLed->BlinkingLedState = RTW_LED_ON;
708
709 delay = LED_BLINK_NORMAL_INTERVAL;
710 break;
711
712 case LED_BLINK_WPS_STOP_OVERLAP: /* WPS session overlap */
713 pLed->BlinkTimes--;
714 if (pLed->BlinkTimes == 0) {
715 if (pLed->bLedOn) {
716 pLed->BlinkTimes = 1;
717 } else {
718 bStopBlinking = true;
719 }
720 }
721
722 if (bStopBlinking) {
723 pLed->BlinkTimes = 10;
724 pLed->BlinkingLedState = RTW_LED_ON;
725 delay = LED_BLINK_LINK_INTERVAL_ALPHA;
726 } else {
727 if (pLed->bLedOn)
728 pLed->BlinkingLedState = RTW_LED_OFF;
729 else
730 pLed->BlinkingLedState = RTW_LED_ON;
731
732 delay = LED_BLINK_NORMAL_INTERVAL;
733 }
734 break;
735
736 default:
737 break;
738 }
739 if (delay)
740 mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(delay));
741
742 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("SwLedBlink4 CurrLedState %d\n", pLed->CurrLedState));
743}
744
745static void SwLedBlink5(struct led_8723a *pLed)
746{
747 struct rtw_adapter *padapter = pLed->padapter;
748 u8 bStopBlinking = false;
749 unsigned long delay = 0;
750
751 /* Change LED according to BlinkingLedState specified. */
752 if (pLed->BlinkingLedState == RTW_LED_ON) {
753 SwLedOn23a(padapter, pLed);
754 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
755 } else {
756 SwLedOff23a(padapter, pLed);
757 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
758 }
759
760 switch (pLed->CurrLedState)
761 {
762 case LED_BLINK_SCAN:
763 pLed->BlinkTimes--;
764 if (pLed->BlinkTimes == 0) {
765 bStopBlinking = true;
766 }
767
768 if (bStopBlinking) {
769 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
770 pLed->CurrLedState = RTW_LED_OFF;
771 pLed->BlinkingLedState = RTW_LED_OFF;
772 if (pLed->bLedOn)
773 SwLedOff23a(padapter, pLed);
774 } else {
775 pLed->CurrLedState = RTW_LED_ON;
776 pLed->BlinkingLedState = RTW_LED_ON;
777 if (!pLed->bLedOn)
778 delay = LED_BLINK_FASTER_INTERVAL_ALPHA;
779 }
780
781 pLed->bLedScanBlinkInProgress = false;
782 } else {
783 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
784 SwLedOff23a(padapter, pLed);
785 } else {
786 if (pLed->bLedOn)
787 pLed->BlinkingLedState = RTW_LED_OFF;
788 else
789 pLed->BlinkingLedState = RTW_LED_ON;
790 delay = LED_BLINK_SCAN_INTERVAL_ALPHA;
791 }
792 }
793 break;
794
795 case LED_BLINK_TXRX:
796 pLed->BlinkTimes--;
797 if (pLed->BlinkTimes == 0) {
798 bStopBlinking = true;
799 }
800
801 if (bStopBlinking) {
802 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
803 pLed->CurrLedState = RTW_LED_OFF;
804 pLed->BlinkingLedState = RTW_LED_OFF;
805 if (pLed->bLedOn)
806 SwLedOff23a(padapter, pLed);
807 } else {
808 pLed->CurrLedState = RTW_LED_ON;
809 pLed->BlinkingLedState = RTW_LED_ON;
810 if (!pLed->bLedOn)
811 delay = LED_BLINK_FASTER_INTERVAL_ALPHA;
812 }
813
814 pLed->bLedBlinkInProgress = false;
815 } else {
816 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
817 SwLedOff23a(padapter, pLed);
818 } else {
819 if (pLed->bLedOn)
820 pLed->BlinkingLedState = RTW_LED_OFF;
821 else
822 pLed->BlinkingLedState = RTW_LED_ON;
823 delay = LED_BLINK_FASTER_INTERVAL_ALPHA;
824 }
825 }
826 break;
827
828 default:
829 break;
830 }
831
832 if (delay)
833 mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(delay));
834
835 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("SwLedBlink5 CurrLedState %d\n", pLed->CurrLedState));
836}
837
838static void SwLedBlink6(struct led_8723a *pLed)
839{
840 struct rtw_adapter *padapter = pLed->padapter;
841
842 /* Change LED according to BlinkingLedState specified. */
843 if (pLed->BlinkingLedState == RTW_LED_ON) {
844 SwLedOn23a(padapter, pLed);
845 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
846 } else {
847 SwLedOff23a(padapter, pLed);
848 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
849 }
850 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("<==== blink6\n"));
851}
852
853/* ALPHA, added by chiyoko, 20090106 */
854static void
855SwLedControlMode1(struct rtw_adapter *padapter, enum led_ctl_mode LedAction)
856{
857 struct led_priv *ledpriv = &padapter->ledpriv;
858 struct led_8723a *pLed = &ledpriv->SwLed0;
859 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
860
861 long delay = -1;
862
863 switch (LedAction)
864 {
865 case LED_CTL_POWER_ON:
866 case LED_CTL_START_TO_LINK:
867 case LED_CTL_NO_LINK:
868 if (pLed->bLedNoLinkBlinkInProgress == false) {
869 if (pLed->CurrLedState == LED_BLINK_SCAN ||
870 IS_LED_WPS_BLINKING(pLed)) {
871 return;
872 }
873 if (pLed->bLedLinkBlinkInProgress == true) {
874 del_timer_sync(&pLed->BlinkTimer);
875 pLed->bLedLinkBlinkInProgress = false;
876 }
877 if (pLed->bLedBlinkInProgress == true) {
878 del_timer_sync(&pLed->BlinkTimer);
879 pLed->bLedBlinkInProgress = false;
880 }
881
882 pLed->bLedNoLinkBlinkInProgress = true;
883 pLed->CurrLedState = LED_BLINK_SLOWLY;
884 if (pLed->bLedOn)
885 pLed->BlinkingLedState = RTW_LED_OFF;
886 else
887 pLed->BlinkingLedState = RTW_LED_ON;
888 delay = LED_BLINK_NO_LINK_INTERVAL_ALPHA;
889 }
890 break;
891
892 case LED_CTL_LINK:
893 if (pLed->bLedLinkBlinkInProgress == false) {
894 if (pLed->CurrLedState == LED_BLINK_SCAN ||
895 IS_LED_WPS_BLINKING(pLed)) {
896 return;
897 }
898 if (pLed->bLedNoLinkBlinkInProgress == true) {
899 del_timer_sync(&pLed->BlinkTimer);
900 pLed->bLedNoLinkBlinkInProgress = false;
901 }
902 if (pLed->bLedBlinkInProgress == true) {
903 del_timer_sync(&pLed->BlinkTimer);
904 pLed->bLedBlinkInProgress = false;
905 }
906 pLed->bLedLinkBlinkInProgress = true;
907 pLed->CurrLedState = LED_BLINK_NORMAL;
908 if (pLed->bLedOn)
909 pLed->BlinkingLedState = RTW_LED_OFF;
910 else
911 pLed->BlinkingLedState = RTW_LED_ON;
912 delay = LED_BLINK_LINK_INTERVAL_ALPHA;
913 }
914 break;
915
916 case LED_CTL_SITE_SURVEY:
917 if ((pmlmepriv->LinkDetectInfo.bBusyTraffic) &&
918 (check_fwstate(pmlmepriv, _FW_LINKED) == true))
919 ;
920 else if (pLed->bLedScanBlinkInProgress == false) {
921 if (IS_LED_WPS_BLINKING(pLed))
922 return;
923
924 if (pLed->bLedNoLinkBlinkInProgress == true) {
925 del_timer_sync(&pLed->BlinkTimer);
926 pLed->bLedNoLinkBlinkInProgress = false;
927 }
928 if (pLed->bLedLinkBlinkInProgress == true) {
929 del_timer_sync(&pLed->BlinkTimer);
930 pLed->bLedLinkBlinkInProgress = false;
931 }
932 if (pLed->bLedBlinkInProgress == true) {
933 del_timer_sync(&pLed->BlinkTimer);
934 pLed->bLedBlinkInProgress = false;
935 }
936 pLed->bLedScanBlinkInProgress = true;
937 pLed->CurrLedState = LED_BLINK_SCAN;
938 pLed->BlinkTimes = 24;
939 if (pLed->bLedOn)
940 pLed->BlinkingLedState = RTW_LED_OFF;
941 else
942 pLed->BlinkingLedState = RTW_LED_ON;
943 delay = LED_BLINK_SCAN_INTERVAL_ALPHA;
944 }
945 break;
946
947 case LED_CTL_TX:
948 case LED_CTL_RX:
949 if (pLed->bLedBlinkInProgress == false) {
950 if (pLed->CurrLedState == LED_BLINK_SCAN ||
951 IS_LED_WPS_BLINKING(pLed)) {
952 return;
953 }
954 if (pLed->bLedNoLinkBlinkInProgress == true) {
955 del_timer_sync(&pLed->BlinkTimer);
956 pLed->bLedNoLinkBlinkInProgress = false;
957 }
958 if (pLed->bLedLinkBlinkInProgress == true) {
959 del_timer_sync(&pLed->BlinkTimer);
960 pLed->bLedLinkBlinkInProgress = false;
961 }
962 pLed->bLedBlinkInProgress = true;
963 pLed->CurrLedState = LED_BLINK_TXRX;
964 pLed->BlinkTimes = 2;
965 if (pLed->bLedOn)
966 pLed->BlinkingLedState = RTW_LED_OFF;
967 else
968 pLed->BlinkingLedState = RTW_LED_ON;
969 delay = LED_BLINK_FASTER_INTERVAL_ALPHA;
970 }
971 break;
972
973 case LED_CTL_START_WPS: /* wait until xinpin finish */
974 case LED_CTL_START_WPS_BOTTON:
975 if (pLed->bLedWPSBlinkInProgress == false) {
976 if (pLed->bLedNoLinkBlinkInProgress == true) {
977 del_timer_sync(&pLed->BlinkTimer);
978 pLed->bLedNoLinkBlinkInProgress = false;
979 }
980 if (pLed->bLedLinkBlinkInProgress == true) {
981 del_timer_sync(&pLed->BlinkTimer);
982 pLed->bLedLinkBlinkInProgress = false;
983 }
984 if (pLed->bLedBlinkInProgress == true) {
985 del_timer_sync(&pLed->BlinkTimer);
986 pLed->bLedBlinkInProgress = false;
987 }
988 if (pLed->bLedScanBlinkInProgress == true) {
989 del_timer_sync(&pLed->BlinkTimer);
990 pLed->bLedScanBlinkInProgress = false;
991 }
992 pLed->bLedWPSBlinkInProgress = true;
993 pLed->CurrLedState = LED_BLINK_WPS;
994 if (pLed->bLedOn)
995 pLed->BlinkingLedState = RTW_LED_OFF;
996 else
997 pLed->BlinkingLedState = RTW_LED_ON;
998 delay = LED_BLINK_SCAN_INTERVAL_ALPHA;
999 }
1000 break;
1001
1002 case LED_CTL_STOP_WPS:
1003 if (pLed->bLedNoLinkBlinkInProgress == true) {
1004 del_timer_sync(&pLed->BlinkTimer);
1005 pLed->bLedNoLinkBlinkInProgress = false;
1006 }
1007 if (pLed->bLedLinkBlinkInProgress == true) {
1008 del_timer_sync(&pLed->BlinkTimer);
1009 pLed->bLedLinkBlinkInProgress = false;
1010 }
1011 if (pLed->bLedBlinkInProgress == true) {
1012 del_timer_sync(&pLed->BlinkTimer);
1013 pLed->bLedBlinkInProgress = false;
1014 }
1015 if (pLed->bLedScanBlinkInProgress == true) {
1016 del_timer_sync(&pLed->BlinkTimer);
1017 pLed->bLedScanBlinkInProgress = false;
1018 }
1019 if (pLed->bLedWPSBlinkInProgress) {
1020 del_timer_sync(&pLed->BlinkTimer);
1021 } else {
1022 pLed->bLedWPSBlinkInProgress = true;
1023 }
1024
1025 pLed->CurrLedState = LED_BLINK_WPS_STOP;
1026 if (pLed->bLedOn) {
1027 pLed->BlinkingLedState = RTW_LED_OFF;
1028 delay = LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA;
1029 } else {
1030 pLed->BlinkingLedState = RTW_LED_ON;
1031 delay = 0;
1032 }
1033 break;
1034
1035 case LED_CTL_STOP_WPS_FAIL:
1036 if (pLed->bLedWPSBlinkInProgress) {
1037 del_timer_sync(&pLed->BlinkTimer);
1038 pLed->bLedWPSBlinkInProgress = false;
1039 }
1040
1041 pLed->bLedNoLinkBlinkInProgress = true;
1042 pLed->CurrLedState = LED_BLINK_SLOWLY;
1043 if (pLed->bLedOn)
1044 pLed->BlinkingLedState = RTW_LED_OFF;
1045 else
1046 pLed->BlinkingLedState = RTW_LED_ON;
1047 delay = LED_BLINK_NO_LINK_INTERVAL_ALPHA;
1048 break;
1049
1050 case LED_CTL_POWER_OFF:
1051 pLed->CurrLedState = RTW_LED_OFF;
1052 pLed->BlinkingLedState = RTW_LED_OFF;
1053 if (pLed->bLedNoLinkBlinkInProgress) {
1054 del_timer_sync(&pLed->BlinkTimer);
1055 pLed->bLedNoLinkBlinkInProgress = false;
1056 }
1057 if (pLed->bLedLinkBlinkInProgress) {
1058 del_timer_sync(&pLed->BlinkTimer);
1059 pLed->bLedLinkBlinkInProgress = false;
1060 }
1061 if (pLed->bLedBlinkInProgress) {
1062 del_timer_sync(&pLed->BlinkTimer);
1063 pLed->bLedBlinkInProgress = false;
1064 }
1065 if (pLed->bLedWPSBlinkInProgress) {
1066 del_timer_sync(&pLed->BlinkTimer);
1067 pLed->bLedWPSBlinkInProgress = false;
1068 }
1069 if (pLed->bLedScanBlinkInProgress) {
1070 del_timer_sync(&pLed->BlinkTimer);
1071 pLed->bLedScanBlinkInProgress = false;
1072 }
1073
1074 SwLedOff23a(padapter, pLed);
1075 break;
1076
1077 default:
1078 break;
1079
1080 }
1081
1082 if (delay != -1)
1083 mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(delay));
1084
1085 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Led %d\n", pLed->CurrLedState));
1086}
1087
1088 /* Arcadyan/Sitecom , added by chiyoko, 20090216 */
1089static void
1090SwLedControlMode2(struct rtw_adapter *padapter, enum led_ctl_mode LedAction)
1091{
1092 struct led_priv *ledpriv = &padapter->ledpriv;
1093 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1094 struct led_8723a *pLed = &ledpriv->SwLed0;
1095 long delay = -1;
1096
1097 switch (LedAction) {
1098 case LED_CTL_SITE_SURVEY:
1099 if (pmlmepriv->LinkDetectInfo.bBusyTraffic)
1100 ;
1101 else if (pLed->bLedScanBlinkInProgress == false) {
1102 if (IS_LED_WPS_BLINKING(pLed))
1103 return;
1104
1105 if (pLed->bLedBlinkInProgress == true) {
1106 del_timer_sync(&pLed->BlinkTimer);
1107 pLed->bLedBlinkInProgress = false;
1108 }
1109 pLed->bLedScanBlinkInProgress = true;
1110 pLed->CurrLedState = LED_BLINK_SCAN;
1111 pLed->BlinkTimes = 24;
1112 if (pLed->bLedOn)
1113 pLed->BlinkingLedState = RTW_LED_OFF;
1114 else
1115 pLed->BlinkingLedState = RTW_LED_ON;
1116 delay = LED_BLINK_SCAN_INTERVAL_ALPHA;
1117 }
1118 break;
1119 case LED_CTL_TX:
1120 case LED_CTL_RX:
1121 if ((pLed->bLedBlinkInProgress == false) &&
1122 (check_fwstate(pmlmepriv, _FW_LINKED) == true)) {
1123 if (pLed->CurrLedState == LED_BLINK_SCAN ||
1124 IS_LED_WPS_BLINKING(pLed)) {
1125 return;
1126 }
1127
1128 pLed->bLedBlinkInProgress = true;
1129 pLed->CurrLedState = LED_BLINK_TXRX;
1130 pLed->BlinkTimes = 2;
1131 if (pLed->bLedOn)
1132 pLed->BlinkingLedState = RTW_LED_OFF;
1133 else
1134 pLed->BlinkingLedState = RTW_LED_ON;
1135 delay = LED_BLINK_FASTER_INTERVAL_ALPHA;
1136 }
1137 break;
1138 case LED_CTL_LINK:
1139 pLed->CurrLedState = RTW_LED_ON;
1140 pLed->BlinkingLedState = RTW_LED_ON;
1141 if (pLed->bLedBlinkInProgress) {
1142 del_timer_sync(&pLed->BlinkTimer);
1143 pLed->bLedBlinkInProgress = false;
1144 }
1145 if (pLed->bLedScanBlinkInProgress) {
1146 del_timer_sync(&pLed->BlinkTimer);
1147 pLed->bLedScanBlinkInProgress = false;
1148 }
1149
1150 delay = 0;
1151 break;
1152 case LED_CTL_START_WPS: /* wait until xinpin finish */
1153 case LED_CTL_START_WPS_BOTTON:
1154 if (pLed->bLedWPSBlinkInProgress == false) {
1155 if (pLed->bLedBlinkInProgress == true) {
1156 del_timer_sync(&pLed->BlinkTimer);
1157 pLed->bLedBlinkInProgress = false;
1158 }
1159 if (pLed->bLedScanBlinkInProgress == true) {
1160 del_timer_sync(&pLed->BlinkTimer);
1161 pLed->bLedScanBlinkInProgress = false;
1162 }
1163 pLed->bLedWPSBlinkInProgress = true;
1164 pLed->CurrLedState = RTW_LED_ON;
1165 pLed->BlinkingLedState = RTW_LED_ON;
1166 delay = 0;
1167 }
1168 break;
1169 case LED_CTL_STOP_WPS:
1170 pLed->bLedWPSBlinkInProgress = false;
1171 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
1172 SwLedOff23a(padapter, pLed);
1173 } else {
1174 pLed->CurrLedState = RTW_LED_ON;
1175 pLed->BlinkingLedState = RTW_LED_ON;
1176 delay = 0;
1177 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
1178 }
1179 break;
1180 case LED_CTL_STOP_WPS_FAIL:
1181 pLed->bLedWPSBlinkInProgress = false;
1182 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
1183 SwLedOff23a(padapter, pLed);
1184 } else {
1185 pLed->CurrLedState = RTW_LED_OFF;
1186 pLed->BlinkingLedState = RTW_LED_OFF;
1187 delay = 0;
1188 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
1189 }
1190 break;
1191 case LED_CTL_START_TO_LINK:
1192 case LED_CTL_NO_LINK:
1193 if (!IS_LED_BLINKING(pLed))
1194 {
1195 pLed->CurrLedState = RTW_LED_OFF;
1196 pLed->BlinkingLedState = RTW_LED_OFF;
1197 delay = 0;
1198 }
1199 break;
1200 case LED_CTL_POWER_OFF:
1201 pLed->CurrLedState = RTW_LED_OFF;
1202 pLed->BlinkingLedState = RTW_LED_OFF;
1203 if (pLed->bLedBlinkInProgress) {
1204 del_timer_sync(&pLed->BlinkTimer);
1205 pLed->bLedBlinkInProgress = false;
1206 }
1207 if (pLed->bLedScanBlinkInProgress) {
1208 del_timer_sync(&pLed->BlinkTimer);
1209 pLed->bLedScanBlinkInProgress = false;
1210 }
1211 if (pLed->bLedWPSBlinkInProgress) {
1212 del_timer_sync(&pLed->BlinkTimer);
1213 pLed->bLedWPSBlinkInProgress = false;
1214 }
1215
1216 delay = 0;
1217 break;
1218 default:
1219 break;
1220
1221 }
1222
1223 if (delay != -1)
1224 mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(delay));
1225
1226 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
1227}
1228
1229 /* COREGA, added by chiyoko, 20090316 */
1230static void
1231SwLedControlMode3(struct rtw_adapter *padapter, enum led_ctl_mode LedAction)
1232{
1233 struct led_priv *ledpriv = &padapter->ledpriv;
1234 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1235 struct led_8723a *pLed = &ledpriv->SwLed0;
1236 long delay = -1;
1237
1238 switch (LedAction)
1239 {
1240 case LED_CTL_SITE_SURVEY:
1241 if (pmlmepriv->LinkDetectInfo.bBusyTraffic)
1242 ;
1243 else if (pLed->bLedScanBlinkInProgress == false) {
1244 if (IS_LED_WPS_BLINKING(pLed))
1245 return;
1246
1247 if (pLed->bLedBlinkInProgress == true) {
1248 del_timer_sync(&pLed->BlinkTimer);
1249 pLed->bLedBlinkInProgress = false;
1250 }
1251 pLed->bLedScanBlinkInProgress = true;
1252 pLed->CurrLedState = LED_BLINK_SCAN;
1253 pLed->BlinkTimes = 24;
1254 if (pLed->bLedOn)
1255 pLed->BlinkingLedState = RTW_LED_OFF;
1256 else
1257 pLed->BlinkingLedState = RTW_LED_ON;
1258 delay = LED_BLINK_SCAN_INTERVAL_ALPHA;
1259 }
1260 break;
1261
1262 case LED_CTL_TX:
1263 case LED_CTL_RX:
1264 if ((pLed->bLedBlinkInProgress == false) &&
1265 (check_fwstate(pmlmepriv, _FW_LINKED) == true)) {
1266 if (pLed->CurrLedState == LED_BLINK_SCAN ||
1267 IS_LED_WPS_BLINKING(pLed)) {
1268 return;
1269 }
1270
1271 pLed->bLedBlinkInProgress = true;
1272 pLed->CurrLedState = LED_BLINK_TXRX;
1273 pLed->BlinkTimes = 2;
1274 if (pLed->bLedOn)
1275 pLed->BlinkingLedState = RTW_LED_OFF;
1276 else
1277 pLed->BlinkingLedState = RTW_LED_ON;
1278 delay = LED_BLINK_FASTER_INTERVAL_ALPHA;
1279 }
1280 break;
1281
1282 case LED_CTL_LINK:
1283 if (IS_LED_WPS_BLINKING(pLed))
1284 return;
1285
1286 pLed->CurrLedState = RTW_LED_ON;
1287 pLed->BlinkingLedState = RTW_LED_ON;
1288 if (pLed->bLedBlinkInProgress) {
1289 del_timer_sync(&pLed->BlinkTimer);
1290 pLed->bLedBlinkInProgress = false;
1291 }
1292 if (pLed->bLedScanBlinkInProgress) {
1293 del_timer_sync(&pLed->BlinkTimer);
1294 pLed->bLedScanBlinkInProgress = false;
1295 }
1296
1297 delay = 0;
1298 break;
1299
1300 case LED_CTL_START_WPS: /* wait until xinpin finish */
1301 case LED_CTL_START_WPS_BOTTON:
1302 if (pLed->bLedWPSBlinkInProgress == false) {
1303 if (pLed->bLedBlinkInProgress == true) {
1304 del_timer_sync(&pLed->BlinkTimer);
1305 pLed->bLedBlinkInProgress = false;
1306 }
1307 if (pLed->bLedScanBlinkInProgress == true) {
1308 del_timer_sync(&pLed->BlinkTimer);
1309 pLed->bLedScanBlinkInProgress = false;
1310 }
1311 pLed->bLedWPSBlinkInProgress = true;
1312 pLed->CurrLedState = LED_BLINK_WPS;
1313 if (pLed->bLedOn)
1314 pLed->BlinkingLedState = RTW_LED_OFF;
1315 else
1316 pLed->BlinkingLedState = RTW_LED_ON;
1317 delay = LED_BLINK_SCAN_INTERVAL_ALPHA;
1318 }
1319 break;
1320
1321 case LED_CTL_STOP_WPS:
1322 if (pLed->bLedWPSBlinkInProgress) {
1323 del_timer_sync(&pLed->BlinkTimer);
1324 pLed->bLedWPSBlinkInProgress = false;
1325 } else {
1326 pLed->bLedWPSBlinkInProgress = true;
1327 }
1328
1329 pLed->CurrLedState = LED_BLINK_WPS_STOP;
1330 if (pLed->bLedOn) {
1331 pLed->BlinkingLedState = RTW_LED_OFF;
1332 delay = LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA;
1333 } else {
1334 pLed->BlinkingLedState = RTW_LED_ON;
1335 delay = 0;
1336 }
1337
1338 break;
1339
1340 case LED_CTL_STOP_WPS_FAIL:
1341 if (pLed->bLedWPSBlinkInProgress) {
1342 del_timer_sync(&pLed->BlinkTimer);
1343 pLed->bLedWPSBlinkInProgress = false;
1344 }
1345
1346 pLed->CurrLedState = RTW_LED_OFF;
1347 pLed->BlinkingLedState = RTW_LED_OFF;
1348 delay = 0;
1349 break;
1350
1351 case LED_CTL_START_TO_LINK:
1352 case LED_CTL_NO_LINK:
1353 if (!IS_LED_BLINKING(pLed))
1354 {
1355 pLed->CurrLedState = RTW_LED_OFF;
1356 pLed->BlinkingLedState = RTW_LED_OFF;
1357 delay = 0;
1358 }
1359 break;
1360
1361 case LED_CTL_POWER_OFF:
1362 pLed->CurrLedState = RTW_LED_OFF;
1363 pLed->BlinkingLedState = RTW_LED_OFF;
1364 if (pLed->bLedBlinkInProgress) {
1365 del_timer_sync(&pLed->BlinkTimer);
1366 pLed->bLedBlinkInProgress = false;
1367 }
1368 if (pLed->bLedScanBlinkInProgress) {
1369 del_timer_sync(&pLed->BlinkTimer);
1370 pLed->bLedScanBlinkInProgress = false;
1371 }
1372 if (pLed->bLedWPSBlinkInProgress) {
1373 del_timer_sync(&pLed->BlinkTimer);
1374 pLed->bLedWPSBlinkInProgress = false;
1375 }
1376
1377 delay = 0;
1378 break;
1379
1380 default:
1381 break;
1382
1383 }
1384
1385 if (delay != -1)
1386 mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(delay));
1387
1388 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
1389}
1390
1391 /* Edimax-Belkin, added by chiyoko, 20090413 */
1392static void
1393SwLedControlMode4(struct rtw_adapter *padapter, enum led_ctl_mode LedAction)
1394{
1395 struct led_priv *ledpriv = &padapter->ledpriv;
1396 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1397 struct led_8723a *pLed = &ledpriv->SwLed0;
1398 struct led_8723a *pLed1 = &ledpriv->SwLed1;
1399
1400 switch (LedAction)
1401 {
1402 case LED_CTL_START_TO_LINK:
1403 if (pLed1->bLedWPSBlinkInProgress) {
1404 pLed1->bLedWPSBlinkInProgress = false;
1405 del_timer_sync(&pLed1->BlinkTimer);
1406
1407 pLed1->BlinkingLedState = RTW_LED_OFF;
1408 pLed1->CurrLedState = RTW_LED_OFF;
1409
1410 if (pLed1->bLedOn)
1411 mod_timer(&pLed->BlinkTimer, jiffies);
1412 }
1413
1414 if (pLed->bLedStartToLinkBlinkInProgress == false) {
1415 if (pLed->CurrLedState == LED_BLINK_SCAN ||
1416 IS_LED_WPS_BLINKING(pLed)) {
1417 return;
1418 }
1419 if (pLed->bLedBlinkInProgress == true) {
1420 del_timer_sync(&pLed->BlinkTimer);
1421 pLed->bLedBlinkInProgress = false;
1422 }
1423 if (pLed->bLedNoLinkBlinkInProgress == true) {
1424 del_timer_sync(&pLed->BlinkTimer);
1425 pLed->bLedNoLinkBlinkInProgress = false;
1426 }
1427
1428 pLed->bLedStartToLinkBlinkInProgress = true;
1429 pLed->CurrLedState = LED_BLINK_StartToBlink;
1430 if (pLed->bLedOn) {
1431 pLed->BlinkingLedState = RTW_LED_OFF;
1432 mod_timer(&pLed->BlinkTimer,
1433 jiffies + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
1434 } else {
1435 pLed->BlinkingLedState = RTW_LED_ON;
1436 mod_timer(&pLed->BlinkTimer,
1437 jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
1438 }
1439 }
1440 break;
1441
1442 case LED_CTL_LINK:
1443 case LED_CTL_NO_LINK:
1444 /* LED1 settings */
1445 if (LedAction == LED_CTL_LINK) {
1446 if (pLed1->bLedWPSBlinkInProgress) {
1447 pLed1->bLedWPSBlinkInProgress = false;
1448 del_timer_sync(&pLed1->BlinkTimer);
1449
1450 pLed1->BlinkingLedState = RTW_LED_OFF;
1451 pLed1->CurrLedState = RTW_LED_OFF;
1452
1453 if (pLed1->bLedOn)
1454 mod_timer(&pLed->BlinkTimer, jiffies);
1455 }
1456 }
1457
1458 if (pLed->bLedNoLinkBlinkInProgress == false) {
1459 if (pLed->CurrLedState == LED_BLINK_SCAN ||
1460 IS_LED_WPS_BLINKING(pLed)) {
1461 return;
1462 }
1463 if (pLed->bLedBlinkInProgress == true) {
1464 del_timer_sync(&pLed->BlinkTimer);
1465 pLed->bLedBlinkInProgress = false;
1466 }
1467
1468 pLed->bLedNoLinkBlinkInProgress = true;
1469 pLed->CurrLedState = LED_BLINK_SLOWLY;
1470 if (pLed->bLedOn)
1471 pLed->BlinkingLedState = RTW_LED_OFF;
1472 else
1473 pLed->BlinkingLedState = RTW_LED_ON;
1474 mod_timer(&pLed->BlinkTimer, jiffies +
1475 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
1476 }
1477 break;
1478
1479 case LED_CTL_SITE_SURVEY:
1480 if ((pmlmepriv->LinkDetectInfo.bBusyTraffic) &&
1481 (check_fwstate(pmlmepriv, _FW_LINKED) == true))
1482 ;
1483 else if (pLed->bLedScanBlinkInProgress == false) {
1484 if (IS_LED_WPS_BLINKING(pLed))
1485 return;
1486
1487 if (pLed->bLedNoLinkBlinkInProgress == true) {
1488 del_timer_sync(&pLed->BlinkTimer);
1489 pLed->bLedNoLinkBlinkInProgress = false;
1490 }
1491 if (pLed->bLedBlinkInProgress == true) {
1492 del_timer_sync(&pLed->BlinkTimer);
1493 pLed->bLedBlinkInProgress = false;
1494 }
1495 pLed->bLedScanBlinkInProgress = true;
1496 pLed->CurrLedState = LED_BLINK_SCAN;
1497 pLed->BlinkTimes = 24;
1498 if (pLed->bLedOn)
1499 pLed->BlinkingLedState = RTW_LED_OFF;
1500 else
1501 pLed->BlinkingLedState = RTW_LED_ON;
1502 mod_timer(&pLed->BlinkTimer, jiffies +
1503 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
1504 }
1505 break;
1506
1507 case LED_CTL_TX:
1508 case LED_CTL_RX:
1509 if (pLed->bLedBlinkInProgress == false) {
1510 if (pLed->CurrLedState == LED_BLINK_SCAN ||
1511 IS_LED_WPS_BLINKING(pLed)) {
1512 return;
1513 }
1514 if (pLed->bLedNoLinkBlinkInProgress == true) {
1515 del_timer_sync(&pLed->BlinkTimer);
1516 pLed->bLedNoLinkBlinkInProgress = false;
1517 }
1518 pLed->bLedBlinkInProgress = true;
1519 pLed->CurrLedState = LED_BLINK_TXRX;
1520 pLed->BlinkTimes = 2;
1521 if (pLed->bLedOn)
1522 pLed->BlinkingLedState = RTW_LED_OFF;
1523 else
1524 pLed->BlinkingLedState = RTW_LED_ON;
1525 mod_timer(&pLed->BlinkTimer, jiffies +
1526 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
1527 }
1528 break;
1529
1530 case LED_CTL_START_WPS: /* wait until xinpin finish */
1531 case LED_CTL_START_WPS_BOTTON:
1532 if (pLed1->bLedWPSBlinkInProgress) {
1533 pLed1->bLedWPSBlinkInProgress = false;
1534 del_timer_sync(&pLed1->BlinkTimer);
1535
1536 pLed1->BlinkingLedState = RTW_LED_OFF;
1537 pLed1->CurrLedState = RTW_LED_OFF;
1538
1539 if (pLed1->bLedOn)
1540 mod_timer(&pLed->BlinkTimer, jiffies);
1541 }
1542
1543 if (pLed->bLedWPSBlinkInProgress == false) {
1544 if (pLed->bLedNoLinkBlinkInProgress == true) {
1545 del_timer_sync(&pLed->BlinkTimer);
1546 pLed->bLedNoLinkBlinkInProgress = false;
1547 }
1548 if (pLed->bLedBlinkInProgress == true) {
1549 del_timer_sync(&pLed->BlinkTimer);
1550 pLed->bLedBlinkInProgress = false;
1551 }
1552 if (pLed->bLedScanBlinkInProgress == true) {
1553 del_timer_sync(&pLed->BlinkTimer);
1554 pLed->bLedScanBlinkInProgress = false;
1555 }
1556 pLed->bLedWPSBlinkInProgress = true;
1557 pLed->CurrLedState = LED_BLINK_WPS;
1558 if (pLed->bLedOn)
1559 {
1560 pLed->BlinkingLedState = RTW_LED_OFF;
1561 mod_timer(&pLed->BlinkTimer, jiffies +
1562 msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
1563 } else {
1564 pLed->BlinkingLedState = RTW_LED_ON;
1565 mod_timer(&pLed->BlinkTimer, jiffies +
1566 msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
1567 }
1568 }
1569 break;
1570
1571 case LED_CTL_STOP_WPS: /* WPS connect success */
1572 if (pLed->bLedWPSBlinkInProgress) {
1573 del_timer_sync(&pLed->BlinkTimer);
1574 pLed->bLedWPSBlinkInProgress = false;
1575 }
1576
1577 pLed->bLedNoLinkBlinkInProgress = true;
1578 pLed->CurrLedState = LED_BLINK_SLOWLY;
1579 if (pLed->bLedOn)
1580 pLed->BlinkingLedState = RTW_LED_OFF;
1581 else
1582 pLed->BlinkingLedState = RTW_LED_ON;
1583 mod_timer(&pLed->BlinkTimer, jiffies +
1584 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
1585 break;
1586
1587 case LED_CTL_STOP_WPS_FAIL: /* WPS authentication fail */
1588 if (pLed->bLedWPSBlinkInProgress) {
1589 del_timer_sync(&pLed->BlinkTimer);
1590 pLed->bLedWPSBlinkInProgress = false;
1591 }
1592
1593 pLed->bLedNoLinkBlinkInProgress = true;
1594 pLed->CurrLedState = LED_BLINK_SLOWLY;
1595 if (pLed->bLedOn)
1596 pLed->BlinkingLedState = RTW_LED_OFF;
1597 else
1598 pLed->BlinkingLedState = RTW_LED_ON;
1599 mod_timer(&pLed->BlinkTimer, jiffies +
1600 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
1601
1602 /* LED1 settings */
1603 if (pLed1->bLedWPSBlinkInProgress)
1604 del_timer_sync(&pLed1->BlinkTimer);
1605 else
1606 pLed1->bLedWPSBlinkInProgress = true;
1607
1608 pLed1->CurrLedState = LED_BLINK_WPS_STOP;
1609 if (pLed1->bLedOn)
1610 pLed1->BlinkingLedState = RTW_LED_OFF;
1611 else
1612 pLed1->BlinkingLedState = RTW_LED_ON;
1613 mod_timer(&pLed->BlinkTimer, jiffies +
1614 msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
1615
1616 break;
1617
1618 case LED_CTL_STOP_WPS_FAIL_OVERLAP: /* WPS session overlap */
1619 if (pLed->bLedWPSBlinkInProgress) {
1620 del_timer_sync(&pLed->BlinkTimer);
1621 pLed->bLedWPSBlinkInProgress = false;
1622 }
1623
1624 pLed->bLedNoLinkBlinkInProgress = true;
1625 pLed->CurrLedState = LED_BLINK_SLOWLY;
1626 if (pLed->bLedOn)
1627 pLed->BlinkingLedState = RTW_LED_OFF;
1628 else
1629 pLed->BlinkingLedState = RTW_LED_ON;
1630 mod_timer(&pLed->BlinkTimer, jiffies +
1631 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
1632
1633 /* LED1 settings */
1634 if (pLed1->bLedWPSBlinkInProgress)
1635 del_timer_sync(&pLed1->BlinkTimer);
1636 else
1637 pLed1->bLedWPSBlinkInProgress = true;
1638
1639 pLed1->CurrLedState = LED_BLINK_WPS_STOP_OVERLAP;
1640 pLed1->BlinkTimes = 10;
1641 if (pLed1->bLedOn)
1642 pLed1->BlinkingLedState = RTW_LED_OFF;
1643 else
1644 pLed1->BlinkingLedState = RTW_LED_ON;
1645 mod_timer(&pLed->BlinkTimer, jiffies +
1646 msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
1647
1648 break;
1649
1650 case LED_CTL_POWER_OFF:
1651 pLed->CurrLedState = RTW_LED_OFF;
1652 pLed->BlinkingLedState = RTW_LED_OFF;
1653
1654 if (pLed->bLedNoLinkBlinkInProgress) {
1655 del_timer_sync(&pLed->BlinkTimer);
1656 pLed->bLedNoLinkBlinkInProgress = false;
1657 }
1658 if (pLed->bLedLinkBlinkInProgress) {
1659 del_timer_sync(&pLed->BlinkTimer);
1660 pLed->bLedLinkBlinkInProgress = false;
1661 }
1662 if (pLed->bLedBlinkInProgress) {
1663 del_timer_sync(&pLed->BlinkTimer);
1664 pLed->bLedBlinkInProgress = false;
1665 }
1666 if (pLed->bLedWPSBlinkInProgress) {
1667 del_timer_sync(&pLed->BlinkTimer);
1668 pLed->bLedWPSBlinkInProgress = false;
1669 }
1670 if (pLed->bLedScanBlinkInProgress) {
1671 del_timer_sync(&pLed->BlinkTimer);
1672 pLed->bLedScanBlinkInProgress = false;
1673 }
1674 if (pLed->bLedStartToLinkBlinkInProgress) {
1675 del_timer_sync(&pLed->BlinkTimer);
1676 pLed->bLedStartToLinkBlinkInProgress = false;
1677 }
1678
1679 if (pLed1->bLedWPSBlinkInProgress) {
1680 del_timer_sync(&pLed1->BlinkTimer);
1681 pLed1->bLedWPSBlinkInProgress = false;
1682 }
1683
1684 pLed1->BlinkingLedState = LED_UNKNOWN;
1685 SwLedOff23a(padapter, pLed);
1686 SwLedOff23a(padapter, pLed1);
1687 break;
1688
1689 default:
1690 break;
1691
1692 }
1693
1694 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Led %d\n", pLed->CurrLedState));
1695}
1696
1697 /* Sercomm-Belkin, added by chiyoko, 20090415 */
1698static void
1699SwLedControlMode5(struct rtw_adapter *padapter, enum led_ctl_mode LedAction)
1700{
1701 struct led_priv *ledpriv = &padapter->ledpriv;
1702 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1703 struct led_8723a *pLed = &ledpriv->SwLed0;
1704
1705 switch (LedAction)
1706 {
1707 case LED_CTL_POWER_ON:
1708 case LED_CTL_NO_LINK:
1709 case LED_CTL_LINK: /* solid blue */
1710 pLed->CurrLedState = RTW_LED_ON;
1711 pLed->BlinkingLedState = RTW_LED_ON;
1712
1713 mod_timer(&pLed->BlinkTimer, jiffies);
1714 break;
1715
1716 case LED_CTL_SITE_SURVEY:
1717 if ((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED) == true))
1718 ;
1719 else if (pLed->bLedScanBlinkInProgress == false)
1720 {
1721 if (pLed->bLedBlinkInProgress == true)
1722 {
1723 del_timer_sync(&pLed->BlinkTimer);
1724 pLed->bLedBlinkInProgress = false;
1725 }
1726 pLed->bLedScanBlinkInProgress = true;
1727 pLed->CurrLedState = LED_BLINK_SCAN;
1728 pLed->BlinkTimes = 24;
1729 if (pLed->bLedOn)
1730 pLed->BlinkingLedState = RTW_LED_OFF;
1731 else
1732 pLed->BlinkingLedState = RTW_LED_ON;
1733 mod_timer(&pLed->BlinkTimer, jiffies +
1734 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
1735 }
1736 break;
1737
1738 case LED_CTL_TX:
1739 case LED_CTL_RX:
1740 if (pLed->bLedBlinkInProgress == false) {
1741 if (pLed->CurrLedState == LED_BLINK_SCAN) {
1742 return;
1743 }
1744 pLed->bLedBlinkInProgress = true;
1745 pLed->CurrLedState = LED_BLINK_TXRX;
1746 pLed->BlinkTimes = 2;
1747 if (pLed->bLedOn)
1748 pLed->BlinkingLedState = RTW_LED_OFF;
1749 else
1750 pLed->BlinkingLedState = RTW_LED_ON;
1751 mod_timer(&pLed->BlinkTimer, jiffies +
1752 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
1753 }
1754 break;
1755
1756 case LED_CTL_POWER_OFF:
1757 pLed->CurrLedState = RTW_LED_OFF;
1758 pLed->BlinkingLedState = RTW_LED_OFF;
1759
1760 if (pLed->bLedBlinkInProgress) {
1761 del_timer_sync(&pLed->BlinkTimer);
1762 pLed->bLedBlinkInProgress = false;
1763 }
1764
1765 SwLedOff23a(padapter, pLed);
1766 break;
1767
1768 default:
1769 break;
1770
1771 }
1772
1773 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Led %d\n", pLed->CurrLedState));
1774}
1775
1776 /* WNC-Corega, added by chiyoko, 20090902 */
1777static void SwLedControlMode6(struct rtw_adapter *padapter,
1778 enum led_ctl_mode LedAction)
1779{
1780 struct led_priv *ledpriv = &padapter->ledpriv;
1781 struct led_8723a *pLed0 = &ledpriv->SwLed0;
1782
1783 switch (LedAction) {
1784 case LED_CTL_POWER_ON:
1785 case LED_CTL_LINK:
1786 case LED_CTL_NO_LINK:
1787 del_timer_sync(&pLed0->BlinkTimer);
1788 pLed0->CurrLedState = RTW_LED_ON;
1789 pLed0->BlinkingLedState = RTW_LED_ON;
1790 mod_timer(&pLed0->BlinkTimer, jiffies);
1791 break;
1792 case LED_CTL_POWER_OFF:
1793 SwLedOff23a(padapter, pLed0);
1794 break;
1795 default:
1796 break;
1797 }
1798
1799 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("ledcontrol 6 Led %d\n", pLed0->CurrLedState));
1800}
1801
1802/* */
1803/* Description: */
1804/* Handler function of LED Blinking. */
1805/* We dispatch acture LED blink action according to LedStrategy. */
1806/* */
1807void BlinkHandler23a(struct led_8723a *pLed)
1808{
1809 struct rtw_adapter *padapter = pLed->padapter;
1810 struct led_priv *ledpriv = &padapter->ledpriv;
1811
1812 /* DBG_8723A("%s (%s:%d)\n", __func__, current->comm, current->pid); */
1813
1814 if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped))
1815 return;
1816
1817 switch (ledpriv->LedStrategy) {
1818 case SW_LED_MODE0:
1819 SwLedBlink(pLed);
1820 break;
1821 case SW_LED_MODE1:
1822 SwLedBlink1(pLed);
1823 break;
1824 case SW_LED_MODE2:
1825 SwLedBlink2(pLed);
1826 break;
1827 case SW_LED_MODE3:
1828 SwLedBlink3(pLed);
1829 break;
1830 case SW_LED_MODE4:
1831 SwLedBlink4(pLed);
1832 break;
1833 case SW_LED_MODE5:
1834 SwLedBlink5(pLed);
1835 break;
1836 case SW_LED_MODE6:
1837 SwLedBlink6(pLed);
1838 break;
1839 default:
1840 break;
1841 }
1842}
1843
1844void
1845LedControl871x23a(struct rtw_adapter *padapter, enum led_ctl_mode LedAction) {
1846 struct led_priv *ledpriv = &padapter->ledpriv;
1847
1848 if ((padapter->bSurpriseRemoved == true) ||
1849 (padapter->bDriverStopped == true) ||
1850 (padapter->hw_init_completed == false)) {
1851 return;
1852 }
1853
1854 if (ledpriv->bRegUseLed == false)
1855 return;
1856
1857 /* if (!priv->up) */
1858 /* return; */
1859
1860 /* if (priv->bInHctTest) */
1861 /* return; */
1862
1863 if ((padapter->pwrctrlpriv.rf_pwrstate != rf_on &&
1864 padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) &&
1865 (LedAction == LED_CTL_TX || LedAction == LED_CTL_RX ||
1866 LedAction == LED_CTL_SITE_SURVEY ||
1867 LedAction == LED_CTL_LINK ||
1868 LedAction == LED_CTL_NO_LINK ||
1869 LedAction == LED_CTL_POWER_ON)) {
1870 return;
1871 }
1872
1873 switch (ledpriv->LedStrategy) {
1874 case SW_LED_MODE0:
1875 break;
1876 case SW_LED_MODE1:
1877 SwLedControlMode1(padapter, LedAction);
1878 break;
1879 case SW_LED_MODE2:
1880 SwLedControlMode2(padapter, LedAction);
1881 break;
1882 case SW_LED_MODE3:
1883 SwLedControlMode3(padapter, LedAction);
1884 break;
1885 case SW_LED_MODE4:
1886 SwLedControlMode4(padapter, LedAction);
1887 break;
1888 case SW_LED_MODE5:
1889 SwLedControlMode5(padapter, LedAction);
1890 break;
1891 case SW_LED_MODE6:
1892 SwLedControlMode6(padapter, LedAction);
1893 break;
1894 default:
1895 break;
1896 }
1897
1898 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("LedStrategy:%d, LedAction %d\n", ledpriv->LedStrategy, LedAction));
1899}
diff --git a/drivers/staging/rtl8723au/core/rtw_mlme.c b/drivers/staging/rtl8723au/core/rtw_mlme.c
new file mode 100644
index 000000000000..71749a37a78e
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_mlme.c
@@ -0,0 +1,2499 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _RTW_MLME_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <recv_osdep.h>
20#include <xmit_osdep.h>
21#include <hal_intf.h>
22#include <mlme_osdep.h>
23#include <sta_info.h>
24#include <linux/ieee80211.h>
25#include <wifi.h>
26#include <wlan_bssdef.h>
27#include <rtw_ioctl_set.h>
28
29extern u8 rtw_do_join23a(struct rtw_adapter * padapter);
30
31static void rtw_init_mlme_timer(struct rtw_adapter *padapter)
32{
33 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
34
35 setup_timer(&pmlmepriv->assoc_timer, rtw23a_join_to_handler,
36 (unsigned long)padapter);
37
38 setup_timer(&pmlmepriv->scan_to_timer, rtw_scan_timeout_handler23a,
39 (unsigned long)padapter);
40
41 setup_timer(&pmlmepriv->dynamic_chk_timer,
42 rtw_dynamic_check_timer_handler, (unsigned long)padapter);
43
44 setup_timer(&pmlmepriv->set_scan_deny_timer,
45 rtw_set_scan_deny_timer_hdl, (unsigned long)padapter);
46}
47
48int _rtw_init_mlme_priv23a(struct rtw_adapter *padapter)
49{
50 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
51 int res = _SUCCESS;
52
53 pmlmepriv->nic_hdl = padapter;
54
55 pmlmepriv->fw_state = 0;
56 pmlmepriv->cur_network.network.InfrastructureMode = Ndis802_11AutoUnknown;
57 pmlmepriv->scan_mode=SCAN_ACTIVE;/* 1: active, 0: pasive. Maybe someday we should rename this varable to "active_mode" (Jeff) */
58
59 spin_lock_init(&pmlmepriv->lock);
60 _rtw_init_queue23a(&pmlmepriv->scanned_queue);
61
62 memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct cfg80211_ssid));
63
64 /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
65
66 rtw_clear_scan_deny(padapter);
67
68 rtw_init_mlme_timer(padapter);
69 return res;
70}
71
72static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen)
73{
74 if(*ppie)
75 {
76 kfree(*ppie);
77 *plen = 0;
78 *ppie=NULL;
79 }
80}
81
82void rtw23a_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
83{
84#ifdef CONFIG_8723AU_AP_MODE
85 kfree(pmlmepriv->assoc_req);
86 kfree(pmlmepriv->assoc_rsp);
87 rtw_free_mlme_ie_data(&pmlmepriv->wps_beacon_ie, &pmlmepriv->wps_beacon_ie_len);
88 rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie, &pmlmepriv->wps_probe_req_ie_len);
89 rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_resp_ie, &pmlmepriv->wps_probe_resp_ie_len);
90 rtw_free_mlme_ie_data(&pmlmepriv->wps_assoc_resp_ie, &pmlmepriv->wps_assoc_resp_ie_len);
91
92 rtw_free_mlme_ie_data(&pmlmepriv->p2p_beacon_ie, &pmlmepriv->p2p_beacon_ie_len);
93 rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_req_ie, &pmlmepriv->p2p_probe_req_ie_len);
94 rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_resp_ie, &pmlmepriv->p2p_probe_resp_ie_len);
95 rtw_free_mlme_ie_data(&pmlmepriv->p2p_go_probe_resp_ie, &pmlmepriv->p2p_go_probe_resp_ie_len);
96 rtw_free_mlme_ie_data(&pmlmepriv->p2p_assoc_req_ie, &pmlmepriv->p2p_assoc_req_ie_len);
97#endif
98
99#if defined(CONFIG_8723AU_P2P)
100 rtw_free_mlme_ie_data(&pmlmepriv->wfd_beacon_ie, &pmlmepriv->wfd_beacon_ie_len);
101 rtw_free_mlme_ie_data(&pmlmepriv->wfd_probe_req_ie, &pmlmepriv->wfd_probe_req_ie_len);
102 rtw_free_mlme_ie_data(&pmlmepriv->wfd_probe_resp_ie, &pmlmepriv->wfd_probe_resp_ie_len);
103 rtw_free_mlme_ie_data(&pmlmepriv->wfd_go_probe_resp_ie, &pmlmepriv->wfd_go_probe_resp_ie_len);
104 rtw_free_mlme_ie_data(&pmlmepriv->wfd_assoc_req_ie, &pmlmepriv->wfd_assoc_req_ie_len);
105#endif
106}
107
108void _rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv)
109{
110
111 rtw23a_free_mlme_priv_ie_data(pmlmepriv);
112
113}
114
115struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv)
116{
117 struct wlan_network *pnetwork;
118
119 pnetwork = kzalloc(sizeof(struct wlan_network), GFP_ATOMIC);
120 if (pnetwork) {
121 INIT_LIST_HEAD(&pnetwork->list);
122 pnetwork->network_type = 0;
123 pnetwork->fixed = false;
124 pnetwork->last_scanned = jiffies;
125 pnetwork->aid = 0;
126 pnetwork->join_res = 0;
127 }
128
129 return pnetwork;
130}
131
132void _rtw_free_network23a(struct mlme_priv *pmlmepriv,
133 struct wlan_network *pnetwork, u8 isfreeall)
134{
135 u32 lifetime = SCANQUEUE_LIFETIME;
136
137 if (!pnetwork)
138 return;
139
140 if (pnetwork->fixed == true)
141 return;
142
143 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
144 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true))
145 lifetime = 1;
146
147 list_del_init(&pnetwork->list);
148
149 kfree(pnetwork);
150}
151
152void _rtw_free_network23a_nolock23a(struct mlme_priv *pmlmepriv,
153 struct wlan_network *pnetwork)
154{
155
156 if (pnetwork == NULL)
157 return;
158
159 if (pnetwork->fixed == true)
160 return;
161
162 list_del_init(&pnetwork->list);
163
164 kfree(pnetwork);
165}
166
167/*
168 return the wlan_network with the matching addr
169
170 Shall be calle under atomic context... to avoid possible racing condition...
171*/
172struct wlan_network *
173_rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr)
174{
175 struct list_head *phead, *plist;
176 struct wlan_network *pnetwork = NULL;
177
178 if (is_zero_ether_addr(addr)) {
179 pnetwork = NULL;
180 goto exit;
181 }
182
183 /* spin_lock_bh(&scanned_queue->lock); */
184
185 phead = get_list_head(scanned_queue);
186 plist = phead->next;
187
188 while (plist != phead) {
189 pnetwork = container_of(plist, struct wlan_network, list);
190
191 if (ether_addr_equal(addr, pnetwork->network.MacAddress))
192 break;
193
194 plist = plist->next;
195 }
196
197 if(plist == phead)
198 pnetwork = NULL;
199
200 /* spin_unlock_bh(&scanned_queue->lock); */
201
202exit:
203
204 return pnetwork;
205}
206
207void _rtw_free_network23a_queue23a(struct rtw_adapter *padapter, u8 isfreeall)
208{
209 struct list_head *phead, *plist, *ptmp;
210 struct wlan_network *pnetwork;
211 struct mlme_priv* pmlmepriv = &padapter->mlmepriv;
212 struct rtw_queue *scanned_queue = &pmlmepriv->scanned_queue;
213
214 spin_lock_bh(&scanned_queue->lock);
215
216 phead = get_list_head(scanned_queue);
217
218 list_for_each_safe(plist, ptmp, phead) {
219 pnetwork = container_of(plist, struct wlan_network, list);
220
221 _rtw_free_network23a(pmlmepriv,pnetwork, isfreeall);
222 }
223
224 spin_unlock_bh(&scanned_queue->lock);
225
226}
227
228int rtw_if_up23a(struct rtw_adapter *padapter) {
229
230 int res;
231
232 if(padapter->bDriverStopped || padapter->bSurpriseRemoved ||
233 (check_fwstate(&padapter->mlmepriv, _FW_LINKED)== false)) {
234 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_if_up23a:bDriverStopped(%d) OR bSurpriseRemoved(%d)", padapter->bDriverStopped, padapter->bSurpriseRemoved));
235 res=false;
236 }
237 else
238 res= true;
239
240 return res;
241}
242
243void rtw_generate_random_ibss23a(u8* pibss)
244{
245 unsigned long curtime = jiffies;
246
247 pibss[0] = 0x02; /* in ad-hoc mode bit1 must set to 1 */
248 pibss[1] = 0x11;
249 pibss[2] = 0x87;
250 pibss[3] = (u8)(curtime & 0xff) ;/* p[0]; */
251 pibss[4] = (u8)((curtime>>8) & 0xff) ;/* p[1]; */
252 pibss[5] = (u8)((curtime>>16) & 0xff) ;/* p[2]; */
253
254 return;
255}
256
257u8 *rtw_get_capability23a_from_ie(u8 *ie)
258{
259 return ie + 8 + 2;
260}
261
262u16 rtw_get_capability23a(struct wlan_bssid_ex *bss)
263{
264 u16 val;
265
266 memcpy((u8 *)&val, rtw_get_capability23a_from_ie(bss->IEs), 2);
267
268 return le16_to_cpu(val);
269}
270
271u8 *rtw_get_timestampe_from_ie23a(u8 *ie)
272{
273 return ie + 0;
274}
275
276u8 *rtw_get_beacon_interval23a_from_ie(u8 *ie)
277{
278 return ie + 8;
279}
280
281int rtw_init_mlme_priv23a (struct rtw_adapter *padapter)/* struct mlme_priv *pmlmepriv) */
282{
283 int res;
284
285 res = _rtw_init_mlme_priv23a(padapter);/* (pmlmepriv); */
286
287 return res;
288}
289
290void rtw_free_mlme_priv23a (struct mlme_priv *pmlmepriv)
291{
292
293 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_mlme_priv23a\n"));
294 _rtw_free_mlme_priv23a(pmlmepriv);
295
296}
297
298void rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 is_freeall);
299void rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 is_freeall)/* struct wlan_network *pnetwork, _queue *free_queue) */
300{
301
302 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
303 ("rtw_free_network ==> ssid = %s\n\n" ,
304 pnetwork->network.Ssid.ssid));
305 _rtw_free_network23a(pmlmepriv, pnetwork, is_freeall);
306
307}
308
309void rtw_free_network_nolock(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork);
310void rtw_free_network_nolock(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork)
311{
312
313 /* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_network ==> ssid = %s\n\n" , pnetwork->network.Ssid.ssid)); */
314 _rtw_free_network23a_nolock23a(pmlmepriv, pnetwork);
315
316}
317
318void rtw_free_network_queue23a(struct rtw_adapter* dev, u8 isfreeall)
319{
320
321 _rtw_free_network23a_queue23a(dev, isfreeall);
322
323}
324
325/*
326 return the wlan_network with the matching addr
327
328 Shall be calle under atomic context... to avoid possible racing condition...
329*/
330struct wlan_network *
331rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr)
332{
333 struct wlan_network *pnetwork;
334
335 pnetwork = _rtw_find_network23a(scanned_queue, addr);
336
337 return pnetwork;
338}
339
340int rtw_is_same_ibss23a(struct rtw_adapter *adapter, struct wlan_network *pnetwork)
341{
342 int ret = true;
343 struct security_priv *psecuritypriv = &adapter->securitypriv;
344
345 if ((psecuritypriv->dot11PrivacyAlgrthm != _NO_PRIVACY_) &&
346 (pnetwork->network.Privacy == 0))
347 {
348 ret = false;
349 }
350 else if ((psecuritypriv->dot11PrivacyAlgrthm == _NO_PRIVACY_) &&
351 (pnetwork->network.Privacy == 1))
352 {
353 ret = false;
354 }
355 else
356 {
357 ret = true;
358 }
359
360 return ret;
361}
362
363inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b);
364inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b)
365{
366 /* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("(%s,%d)(%s,%d)\n", */
367 /* a->Ssid.Ssid, a->Ssid.SsidLength, b->Ssid.Ssid, b->Ssid.SsidLength)); */
368 return (a->Ssid.ssid_len == b->Ssid.ssid_len) &&
369 !memcmp(a->Ssid.ssid, b->Ssid.ssid, a->Ssid.ssid_len);
370}
371
372int is_same_network23a(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst)
373{
374 u16 s_cap, d_cap;
375
376 memcpy((u8 *)&s_cap, rtw_get_capability23a_from_ie(src->IEs), 2);
377 memcpy((u8 *)&d_cap, rtw_get_capability23a_from_ie(dst->IEs), 2);
378
379 s_cap = le16_to_cpu(s_cap);
380 d_cap = le16_to_cpu(d_cap);
381
382 return ((src->Ssid.ssid_len == dst->Ssid.ssid_len) &&
383 /* (src->Configuration.DSConfig == dst->Configuration.DSConfig) && */
384 ether_addr_equal(src->MacAddress, dst->MacAddress) &&
385 ((!memcmp(src->Ssid.ssid, dst->Ssid.ssid, src->Ssid.ssid_len))) &&
386 ((s_cap & WLAN_CAPABILITY_IBSS) ==
387 (d_cap & WLAN_CAPABILITY_IBSS)) &&
388 ((s_cap & WLAN_CAPABILITY_ESS) ==
389 (d_cap & WLAN_CAPABILITY_ESS)));
390}
391
392struct wlan_network *rtw_get_oldest_wlan_network23a(struct rtw_queue *scanned_queue)
393{
394 struct list_head *plist, *phead;
395
396 struct wlan_network *pwlan;
397 struct wlan_network *oldest = NULL;
398
399 phead = get_list_head(scanned_queue);
400
401 list_for_each(plist, phead) {
402 pwlan = container_of(plist, struct wlan_network, list);
403
404 if (pwlan->fixed != true) {
405 if (!oldest || time_after(oldest->last_scanned,
406 pwlan->last_scanned))
407 oldest = pwlan;
408 }
409 }
410
411 return oldest;
412}
413
414void update_network23a(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
415 struct rtw_adapter * padapter, bool update_ie)
416{
417 u8 ss_ori = dst->PhyInfo.SignalStrength;
418 u8 sq_ori = dst->PhyInfo.SignalQuality;
419 long rssi_ori = dst->Rssi;
420
421 u8 ss_smp = src->PhyInfo.SignalStrength;
422 u8 sq_smp = src->PhyInfo.SignalQuality;
423 long rssi_smp = src->Rssi;
424
425 u8 ss_final;
426 u8 sq_final;
427 long rssi_final;
428
429 DBG_8723A("%s %s(%pM, ch%u) ss_ori:%3u, sq_ori:%3u, rssi_ori:%3ld, ss_smp:%3u, sq_smp:%3u, rssi_smp:%3ld\n",
430 __func__, src->Ssid.ssid, src->MacAddress,
431 src->Configuration.DSConfig, ss_ori, sq_ori, rssi_ori,
432 ss_smp, sq_smp, rssi_smp
433 );
434
435 /* The rule below is 1/5 for sample value, 4/5 for history value */
436 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && is_same_network23a(&padapter->mlmepriv.cur_network.network, src)) {
437 /* Take the recvpriv's value for the connected AP*/
438 ss_final = padapter->recvpriv.signal_strength;
439 sq_final = padapter->recvpriv.signal_qual;
440 /* the rssi value here is undecorated, and will be used for antenna diversity */
441 if (sq_smp != 101) /* from the right channel */
442 rssi_final = (src->Rssi+dst->Rssi*4)/5;
443 else
444 rssi_final = rssi_ori;
445 }
446 else {
447 if (sq_smp != 101) { /* from the right channel */
448 ss_final = ((u32)(src->PhyInfo.SignalStrength)+(u32)(dst->PhyInfo.SignalStrength)*4)/5;
449 sq_final = ((u32)(src->PhyInfo.SignalQuality)+(u32)(dst->PhyInfo.SignalQuality)*4)/5;
450 rssi_final = (src->Rssi+dst->Rssi*4)/5;
451 } else {
452 /* bss info not receving from the right channel, use the original RX signal infos */
453 ss_final = dst->PhyInfo.SignalStrength;
454 sq_final = dst->PhyInfo.SignalQuality;
455 rssi_final = dst->Rssi;
456 }
457
458 }
459
460 if (update_ie)
461 memcpy((u8 *)dst, (u8 *)src, get_wlan_bssid_ex_sz(src));
462
463 dst->PhyInfo.SignalStrength = ss_final;
464 dst->PhyInfo.SignalQuality = sq_final;
465 dst->Rssi = rssi_final;
466
467 DBG_8723A("%s %s(%pM), SignalStrength:%u, SignalQuality:%u, RawRSSI:%ld\n",
468 __func__, dst->Ssid.ssid, dst->MacAddress,
469 dst->PhyInfo.SignalStrength,
470 dst->PhyInfo.SignalQuality, dst->Rssi);
471
472}
473
474static void update_current_network(struct rtw_adapter *adapter, struct wlan_bssid_ex *pnetwork)
475{
476 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
477
478 if ((check_fwstate(pmlmepriv, _FW_LINKED)== true) && (is_same_network23a(&pmlmepriv->cur_network.network, pnetwork)))
479 {
480 /* RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,"Same Network\n"); */
481
482 /* if(pmlmepriv->cur_network.network.IELength<= pnetwork->IELength) */
483 {
484 update_network23a(&pmlmepriv->cur_network.network, pnetwork,adapter, true);
485 rtw_update_protection23a(adapter, (pmlmepriv->cur_network.network.IEs) + sizeof (struct ndis_802_11_fixed_ies),
486 pmlmepriv->cur_network.network.IELength);
487 }
488 }
489
490}
491
492/*
493
494Caller must hold pmlmepriv->lock first.
495
496*/
497void rtw_update_scanned_network23a(struct rtw_adapter *adapter, struct wlan_bssid_ex *target)
498{
499 struct list_head *plist, *phead;
500 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
501 struct wlan_network *pnetwork = NULL;
502 struct wlan_network *oldest = NULL;
503 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
504 u32 bssid_ex_sz;
505 int found = 0;
506
507 spin_lock_bh(&queue->lock);
508 phead = get_list_head(queue);
509
510 list_for_each(plist, phead) {
511 pnetwork = container_of(plist, struct wlan_network, list);
512
513 if (is_same_network23a(&pnetwork->network, target)) {
514 found = 1;
515 break;
516 }
517 if (!oldest || time_after(oldest->last_scanned,
518 pnetwork->last_scanned))
519 oldest = pnetwork;
520 }
521
522 /* If we didn't find a match, then get a new network slot to initialize
523 * with this beacon's information */
524 if (!found) {
525 pnetwork = rtw_alloc_network(pmlmepriv);
526 if (!pnetwork) {
527 if (!oldest) {
528 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
529 ("\n\n\nsomething wrong here\n\n\n"));
530 goto exit;
531 }
532 pnetwork = oldest;
533 } else
534 list_add_tail(&pnetwork->list, &queue->queue);
535
536 bssid_ex_sz = get_wlan_bssid_ex_sz(target);
537 target->Length = bssid_ex_sz;
538 memcpy(&pnetwork->network, target, bssid_ex_sz);
539
540 /* variable initialize */
541 pnetwork->fixed = false;
542 pnetwork->last_scanned = jiffies;
543
544 pnetwork->network_type = 0;
545 pnetwork->aid = 0;
546 pnetwork->join_res = 0;
547
548 /* bss info not receving from the right channel */
549 if (pnetwork->network.PhyInfo.SignalQuality == 101)
550 pnetwork->network.PhyInfo.SignalQuality = 0;
551 } else {
552 /*
553 * we have an entry and we are going to update it. But
554 * this entry may be already expired. In this case we
555 * do the same as we found a new net and call the
556 * new_net handler
557 */
558 bool update_ie = true;
559
560 pnetwork->last_scanned = jiffies;
561
562 /* target.reserved == 1, means that scanned network is
563 * a bcn frame. */
564 if ((pnetwork->network.IELength>target->IELength) &&
565 (target->reserved == 1))
566 update_ie = false;
567
568 update_network23a(&pnetwork->network, target,adapter, update_ie);
569 }
570
571exit:
572 spin_unlock_bh(&queue->lock);
573
574}
575
576void rtw_add_network(struct rtw_adapter *adapter, struct wlan_bssid_ex *pnetwork)
577{
578 update_current_network(adapter, pnetwork);
579 rtw_update_scanned_network23a(adapter, pnetwork);
580}
581
582/* select the desired network based on the capability of the (i)bss. */
583/* check items: (1) security */
584/* (2) network_type */
585/* (3) WMM */
586/* (4) HT */
587/* (5) others */
588int rtw_is_desired_network(struct rtw_adapter *adapter, struct wlan_network *pnetwork)
589{
590 struct security_priv *psecuritypriv = &adapter->securitypriv;
591 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
592 u32 desired_encmode;
593 u32 privacy;
594
595 /* u8 wps_ie[512]; */
596 uint wps_ielen;
597
598 int bselected = true;
599
600 desired_encmode = psecuritypriv->ndisencryptstatus;
601 privacy = pnetwork->network.Privacy;
602
603 if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS))
604 {
605 if (rtw_get_wps_ie23a(pnetwork->network.IEs+_FIXED_IE_LENGTH_, pnetwork->network.IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen)!= NULL)
606 {
607 return true;
608 }
609 else
610 {
611 return false;
612 }
613 }
614 if (adapter->registrypriv.wifi_spec == 1) /* for correct flow of 8021X to do.... */
615 {
616 if ((desired_encmode == Ndis802_11EncryptionDisabled) && (privacy != 0))
617 bselected = false;
618 }
619
620 if ((desired_encmode != Ndis802_11EncryptionDisabled) && (privacy == 0)) {
621 DBG_8723A("desired_encmode: %d, privacy: %d\n", desired_encmode, privacy);
622 bselected = false;
623 }
624
625 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)
626 {
627 if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
628 bselected = false;
629 }
630
631 return bselected;
632}
633
634/* TODO: Perry : For Power Management */
635void rtw_atimdone_event_callback23a(struct rtw_adapter *adapter , u8 *pbuf)
636{
637
638 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("receive atimdone_evet\n"));
639
640 return;
641}
642
643void rtw_survey_event_cb23a(struct rtw_adapter *adapter, u8 *pbuf)
644{
645 u32 len;
646 struct wlan_bssid_ex *pnetwork;
647 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
648
649 pnetwork = (struct wlan_bssid_ex *)pbuf;
650
651 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_survey_event_cb23a, ssid=%s\n", pnetwork->Ssid.ssid));
652
653 len = get_wlan_bssid_ex_sz(pnetwork);
654 if(len > (sizeof(struct wlan_bssid_ex)))
655 {
656 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("\n ****rtw_survey_event_cb23a: return a wrong bss ***\n"));
657 return;
658 }
659
660 spin_lock_bh(&pmlmepriv->lock);
661
662 /* update IBSS_network 's timestamp */
663 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true)
664 {
665 /* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,"rtw_survey_event_cb23a : WIFI_ADHOC_MASTER_STATE\n\n"); */
666 if (ether_addr_equal(pmlmepriv->cur_network.network.MacAddress,
667 pnetwork->MacAddress)) {
668 struct wlan_network* ibss_wlan = NULL;
669
670 memcpy(pmlmepriv->cur_network.network.IEs, pnetwork->IEs, 8);
671 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
672 ibss_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pnetwork->MacAddress);
673 if (ibss_wlan)
674 {
675 memcpy(ibss_wlan->network.IEs , pnetwork->IEs, 8);
676 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
677 goto exit;
678 }
679 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
680 }
681 }
682
683 /* lock pmlmepriv->lock when you accessing network_q */
684 if ((check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) == false)
685 {
686 if (pnetwork->Ssid.ssid[0] == 0)
687 pnetwork->Ssid.ssid_len = 0;
688
689 rtw_add_network(adapter, pnetwork);
690 }
691
692exit:
693
694 spin_unlock_bh(&pmlmepriv->lock);
695
696 return;
697}
698
699void rtw_surveydone_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
700{
701 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
702 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
703
704 spin_lock_bh(&pmlmepriv->lock);
705
706 if (pmlmepriv->wps_probe_req_ie) {
707 pmlmepriv->wps_probe_req_ie_len = 0;
708 kfree(pmlmepriv->wps_probe_req_ie);
709 pmlmepriv->wps_probe_req_ie = NULL;
710 }
711
712 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_surveydone_event_callback23a: fw_state:%x\n\n", get_fwstate(pmlmepriv)));
713
714 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
715 del_timer_sync(&pmlmepriv->scan_to_timer);
716
717 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
718 } else {
719
720 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("nic status =%x, survey done event comes too late!\n", get_fwstate(pmlmepriv)));
721 }
722
723 rtw_set_signal_stat_timer(&adapter->recvpriv);
724
725 if (pmlmepriv->to_join == true) {
726 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
727 if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
728 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
729
730 if (rtw_select_and_join_from_scanned_queue23a(pmlmepriv) == _SUCCESS) {
731 mod_timer(&pmlmepriv->assoc_timer,
732 jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
733 } else {
734 struct wlan_bssid_ex *pdev_network = &adapter->registrypriv.dev_network;
735 u8 *pibss = adapter->registrypriv.dev_network.MacAddress;
736
737 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
738
739 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("switching to adhoc master\n"));
740
741 memset(&pdev_network->Ssid, 0, sizeof(struct cfg80211_ssid));
742 memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct cfg80211_ssid));
743
744 rtw_update_registrypriv_dev_network23a(adapter);
745 rtw_generate_random_ibss23a(pibss);
746
747 pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
748
749 if (rtw_createbss_cmd23a(adapter)!= _SUCCESS)
750 {
751 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Error =>rtw_createbss_cmd23a status FAIL\n"));
752 }
753
754 pmlmepriv->to_join = false;
755 }
756 }
757 } else {
758 int ret;
759 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
760 pmlmepriv->to_join = false;
761 ret = rtw_select_and_join_from_scanned_queue23a(pmlmepriv);
762 if (ret == _SUCCESS) {
763 unsigned long e;
764 e = msecs_to_jiffies(MAX_JOIN_TIMEOUT);
765 mod_timer(&pmlmepriv->assoc_timer, jiffies + e);
766 } else if (ret == 2)/* there is no need to wait for join */
767 {
768 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
769 rtw_indicate_connect23a(adapter);
770 } else {
771 DBG_8723A("try_to_join, but select scanning queue fail, to_roaming:%d\n", rtw_to_roaming(adapter));
772 if (rtw_to_roaming(adapter) != 0) {
773 if (--pmlmepriv->to_roaming == 0
774 || _SUCCESS != rtw_sitesurvey_cmd23a(adapter, &pmlmepriv->assoc_ssid, 1, NULL, 0)
775 ) {
776 rtw_set_roaming(adapter, 0);
777 rtw_free_assoc_resources23a(adapter, 1);
778 rtw_indicate_disconnect23a(adapter);
779 } else {
780 pmlmepriv->to_join = true;
781 }
782 }
783 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
784 }
785 }
786 }
787
788 spin_unlock_bh(&pmlmepriv->lock);
789
790#ifdef CONFIG_8723AU_P2P
791 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
792 p2p_ps_wk_cmd23a(adapter, P2P_PS_SCAN_DONE, 0);
793#endif /* CONFIG_8723AU_P2P */
794
795 rtw_os_xmit_schedule23a(adapter);
796
797 if(pmlmeext->sitesurvey_res.bss_cnt == 0)
798 rtw_hal_sreset_reset23a(adapter);
799
800 rtw_cfg80211_surveydone_event_callback(adapter);
801
802}
803
804void rtw_dummy_event_callback23a(struct rtw_adapter *adapter , u8 *pbuf)
805{
806}
807
808void rtw23a_fwdbg_event_callback(struct rtw_adapter *adapter , u8 *pbuf)
809{
810}
811
812static void free_scanqueue(struct mlme_priv *pmlmepriv)
813{
814 struct wlan_network *pnetwork;
815 struct rtw_queue *scan_queue = &pmlmepriv->scanned_queue;
816 struct list_head *plist, *phead, *ptemp;
817
818 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+free_scanqueue\n"));
819 spin_lock_bh(&scan_queue->lock);
820
821 phead = get_list_head(scan_queue);
822
823 list_for_each_safe(plist, ptemp, phead) {
824 list_del_init(plist);
825 pnetwork = container_of(plist, struct wlan_network, list);
826 kfree(pnetwork);
827 }
828
829 spin_unlock_bh(&scan_queue->lock);
830
831}
832
833/*
834*rtw_free_assoc_resources23a: the caller has to lock pmlmepriv->lock
835*/
836void rtw_free_assoc_resources23a(struct rtw_adapter *adapter, int lock_scanned_queue)
837{
838 struct wlan_network* pwlan = NULL;
839 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
840 struct sta_priv *pstapriv = &adapter->stapriv;
841 struct wlan_network *tgt_network = &pmlmepriv->cur_network;
842
843 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_free_assoc_resources23a\n"));
844 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("tgt_network->network.MacAddress="MAC_FMT" ssid=%s\n",
845 MAC_ARG(tgt_network->network.MacAddress), tgt_network->network.Ssid.ssid));
846
847 if(check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_AP_STATE))
848 {
849 struct sta_info* psta;
850
851 psta = rtw_get_stainfo23a(&adapter->stapriv, tgt_network->network.MacAddress);
852
853 {
854 spin_lock_bh(&pstapriv->sta_hash_lock);
855 rtw_free_stainfo23a(adapter, psta);
856 }
857
858 spin_unlock_bh(&pstapriv->sta_hash_lock);
859
860 }
861
862 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE))
863 {
864 struct sta_info* psta;
865
866 rtw_free_all_stainfo23a(adapter);
867
868 psta = rtw_get_bcmc_stainfo23a(adapter);
869 spin_lock_bh(&pstapriv->sta_hash_lock);
870 rtw_free_stainfo23a(adapter, psta);
871 spin_unlock_bh(&pstapriv->sta_hash_lock);
872
873 rtw_init_bcmc_stainfo23a(adapter);
874 }
875
876 if(lock_scanned_queue)
877 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
878
879 pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
880 if(pwlan)
881 pwlan->fixed = false;
882 else
883 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("rtw_free_assoc_resources23a : pwlan== NULL\n\n"));
884
885 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && (adapter->stapriv.asoc_sta_count == 1))
886 rtw_free_network_nolock(pmlmepriv, pwlan);
887
888 if(lock_scanned_queue)
889 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
890
891 pmlmepriv->key_mask = 0;
892
893}
894
895/*
896*rtw_indicate_connect23a: the caller has to lock pmlmepriv->lock
897*/
898void rtw_indicate_connect23a(struct rtw_adapter *padapter)
899{
900 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
901
902 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_indicate_connect23a\n"));
903
904 pmlmepriv->to_join = false;
905
906 if(!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
907 set_fwstate(pmlmepriv, _FW_LINKED);
908
909 rtw_led_control(padapter, LED_CTL_LINK);
910
911 rtw_os_indicate_connect23a(padapter);
912 }
913
914 rtw_set_roaming(padapter, 0);
915
916 rtw_set_scan_deny(padapter, 3000);
917
918 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("-rtw_indicate_connect23a: fw_state=0x%08x\n", get_fwstate(pmlmepriv)));
919
920}
921
922/*
923*rtw_indicate_disconnect23a: the caller has to lock pmlmepriv->lock
924*/
925void rtw_indicate_disconnect23a(struct rtw_adapter *padapter)
926{
927 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
928
929 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_indicate_disconnect23a\n"));
930
931 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING|WIFI_UNDER_WPS);
932
933 /* DBG_8723A("clear wps when %s\n", __func__); */
934
935 if (rtw_to_roaming(padapter) > 0)
936 _clr_fwstate_(pmlmepriv, _FW_LINKED);
937
938 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) ||
939 (rtw_to_roaming(padapter) <= 0)) {
940 rtw_os_indicate_disconnect23a(padapter);
941
942 /* set ips_deny_time to avoid enter IPS before LPS leave */
943 padapter->pwrctrlpriv.ips_deny_time =
944 rtw_get_current_time() + rtw_ms_to_systime23a(3000);
945
946 _clr_fwstate_(pmlmepriv, _FW_LINKED);
947
948 rtw_led_control(padapter, LED_CTL_NO_LINK);
949
950 rtw_clear_scan_deny(padapter);
951
952 }
953
954#ifdef CONFIG_8723AU_P2P
955 p2p_ps_wk_cmd23a(padapter, P2P_PS_DISABLE, 1);
956#endif /* CONFIG_8723AU_P2P */
957
958 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_DISCONNECT, 1);
959
960}
961
962inline void rtw_indicate_scan_done23a(struct rtw_adapter *padapter, bool aborted)
963{
964 rtw_os_indicate_scan_done23a(padapter, aborted);
965}
966
967void rtw_scan_abort23a(struct rtw_adapter *adapter)
968{
969 unsigned long start;
970 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
971 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
972
973 start = jiffies;
974 pmlmeext->scan_abort = true;
975 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) &&
976 jiffies_to_msecs(jiffies - start) <= 200) {
977
978 if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
979 break;
980
981 DBG_8723A(FUNC_NDEV_FMT"fw_state = _FW_UNDER_SURVEY!\n", FUNC_NDEV_ARG(adapter->pnetdev));
982 msleep(20);
983 }
984
985 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
986 if (!adapter->bDriverStopped && !adapter->bSurpriseRemoved)
987 DBG_8723A(FUNC_NDEV_FMT"waiting for scan_abort time out!\n", FUNC_NDEV_ARG(adapter->pnetdev));
988 rtw_indicate_scan_done23a(adapter, true);
989 }
990 pmlmeext->scan_abort = false;
991}
992
993static struct sta_info *rtw_joinbss_update_stainfo(struct rtw_adapter *padapter, struct wlan_network *pnetwork)
994{
995 int i;
996 struct sta_info *bmc_sta, *psta = NULL;
997 struct recv_reorder_ctrl *preorder_ctrl;
998 struct sta_priv *pstapriv = &padapter->stapriv;
999
1000 psta = rtw_get_stainfo23a(pstapriv, pnetwork->network.MacAddress);
1001 if (psta == NULL) {
1002 psta = rtw_alloc_stainfo23a(pstapriv, pnetwork->network.MacAddress);
1003 }
1004
1005 if (psta) /* update ptarget_sta */
1006 {
1007 DBG_8723A("%s\n", __func__);
1008
1009 psta->aid = pnetwork->join_res;
1010 psta->mac_id = 0;
1011
1012 /* sta mode */
1013 rtw_hal_set_odm_var23a(padapter, HAL_ODM_STA_INFO, psta, true);
1014
1015 /* security related */
1016 if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
1017 {
1018 padapter->securitypriv.binstallGrpkey = false;
1019 padapter->securitypriv.busetkipkey = false;
1020 padapter->securitypriv.bgrpkey_handshake = false;
1021
1022 psta->ieee8021x_blocked = true;
1023 psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
1024
1025 memset((u8 *)&psta->dot118021x_UncstKey, 0, sizeof (union Keytype));
1026
1027 memset((u8 *)&psta->dot11tkiprxmickey, 0, sizeof (union Keytype));
1028 memset((u8 *)&psta->dot11tkiptxmickey, 0, sizeof (union Keytype));
1029
1030 memset((u8 *)&psta->dot11txpn, 0, sizeof (union pn48));
1031 memset((u8 *)&psta->dot11rxpn, 0, sizeof (union pn48));
1032 }
1033
1034 /* Commented by Albert 2012/07/21 */
1035 /* When doing the WPS, the wps_ie_len won't equal to 0 */
1036 /* And the Wi-Fi driver shouldn't allow the data packet to be tramsmitted. */
1037 if (padapter->securitypriv.wps_ie_len != 0)
1038 {
1039 psta->ieee8021x_blocked = true;
1040 padapter->securitypriv.wps_ie_len = 0;
1041 }
1042
1043 /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info */
1044 /* if A-MPDU Rx is enabled, reseting rx_ordering_ctrl wstart_b(indicate_seq) to default value = 0xffff */
1045 /* todo: check if AP can send A-MPDU packets */
1046 for (i = 0; i < 16 ; i++)
1047 {
1048 /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
1049 preorder_ctrl = &psta->recvreorder_ctrl[i];
1050 preorder_ctrl->enable = false;
1051 preorder_ctrl->indicate_seq = 0xffff;
1052 preorder_ctrl->wend_b = 0xffff;
1053 preorder_ctrl->wsize_b = 64;/* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */
1054 }
1055
1056 bmc_sta = rtw_get_bcmc_stainfo23a(padapter);
1057 if (bmc_sta)
1058 {
1059 for (i = 0; i < 16 ; i++)
1060 {
1061 /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
1062 preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
1063 preorder_ctrl->enable = false;
1064 preorder_ctrl->indicate_seq = 0xffff;
1065 preorder_ctrl->wend_b = 0xffff;
1066 preorder_ctrl->wsize_b = 64;/* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */
1067 }
1068 }
1069
1070 /* misc. */
1071 update_sta_info23a(padapter, psta);
1072
1073 }
1074
1075 return psta;
1076}
1077
1078/* pnetwork : returns from rtw23a_joinbss_event_cb */
1079/* ptarget_wlan: found from scanned_queue */
1080static void rtw_joinbss_update_network23a(struct rtw_adapter *padapter, struct wlan_network *ptarget_wlan, struct wlan_network *pnetwork)
1081{
1082 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1083 struct wlan_network *cur_network = &pmlmepriv->cur_network;
1084
1085 DBG_8723A("%s\n", __func__);
1086
1087 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\nfw_state:%x, BSSID:"MAC_FMT"\n"
1088 , get_fwstate(pmlmepriv), MAC_ARG(pnetwork->network.MacAddress)));
1089
1090 /* why not use ptarget_wlan?? */
1091 memcpy(&cur_network->network, &pnetwork->network, pnetwork->network.Length);
1092 /* some IEs in pnetwork is wrong, so we should use ptarget_wlan IEs */
1093 cur_network->network.IELength = ptarget_wlan->network.IELength;
1094 memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0], MAX_IE_SZ);
1095
1096 cur_network->aid = pnetwork->join_res;
1097
1098 rtw_set_signal_stat_timer(&padapter->recvpriv);
1099 padapter->recvpriv.signal_strength = ptarget_wlan->network.PhyInfo.SignalStrength;
1100 padapter->recvpriv.signal_qual = ptarget_wlan->network.PhyInfo.SignalQuality;
1101 /* the ptarget_wlan->network.Rssi is raw data, we use ptarget_wlan->network.PhyInfo.SignalStrength instead (has scaled) */
1102 padapter->recvpriv.rssi = translate_percentage_to_dbm(ptarget_wlan->network.PhyInfo.SignalStrength);
1103 DBG_8723A("%s signal_strength:%3u, rssi:%3d, signal_qual:%3u\n",
1104 __func__, padapter->recvpriv.signal_strength,
1105 padapter->recvpriv.rssi, padapter->recvpriv.signal_qual);
1106 rtw_set_signal_stat_timer(&padapter->recvpriv);
1107
1108 /* update fw_state will clr _FW_UNDER_LINKING here indirectly */
1109 switch (pnetwork->network.InfrastructureMode) {
1110 case Ndis802_11Infrastructure:
1111 if (pmlmepriv->fw_state&WIFI_UNDER_WPS)
1112 pmlmepriv->fw_state = WIFI_STATION_STATE|WIFI_UNDER_WPS;
1113 else
1114 pmlmepriv->fw_state = WIFI_STATION_STATE;
1115 break;
1116 case Ndis802_11IBSS:
1117 pmlmepriv->fw_state = WIFI_ADHOC_STATE;
1118 break;
1119 default:
1120 pmlmepriv->fw_state = WIFI_NULL_STATE;
1121 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Invalid network_mode\n"));
1122 break;
1123 }
1124
1125 rtw_update_protection23a(padapter, (cur_network->network.IEs) + sizeof (struct ndis_802_11_fixed_ies),
1126 (cur_network->network.IELength));
1127
1128 rtw_update_ht_cap23a(padapter, cur_network->network.IEs, cur_network->network.IELength);
1129}
1130
1131/* Notes: the fucntion could be > passive_level (the same context as Rx tasklet) */
1132/* pnetwork : returns from rtw23a_joinbss_event_cb */
1133/* ptarget_wlan: found from scanned_queue */
1134/* if join_res > 0, for (fw_state==WIFI_STATION_STATE), we check if "ptarget_sta" & "ptarget_wlan" exist. */
1135/* if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), we only check if "ptarget_wlan" exist. */
1136/* if join_res > 0, update "cur_network->network" from "pnetwork->network" if (ptarget_wlan !=NULL). */
1137
1138void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf)
1139{
1140 static u8 retry=0;
1141 struct sta_info *ptarget_sta= NULL, *pcur_sta = NULL;
1142 struct sta_priv *pstapriv = &adapter->stapriv;
1143 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1144 struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
1145 struct wlan_network *cur_network = &pmlmepriv->cur_network;
1146 struct wlan_network *pcur_wlan = NULL, *ptarget_wlan = NULL;
1147 unsigned int the_same_macaddr = false;
1148
1149 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("joinbss event call back received with res=%d\n", pnetwork->join_res));
1150
1151 rtw_get_encrypt_decrypt_from_registrypriv23a(adapter);
1152
1153 if (pmlmepriv->assoc_ssid.ssid_len == 0) {
1154 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("@@@@@ joinbss event call back for Any SSid\n"));
1155 } else {
1156 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,
1157 ("@@@@@ rtw23a_joinbss_event_cb for SSid:%s\n",
1158 pmlmepriv->assoc_ssid.ssid));
1159 }
1160
1161 if (ether_addr_equal(pnetwork->network.MacAddress,
1162 cur_network->network.MacAddress))
1163 the_same_macaddr = true;
1164 else
1165 the_same_macaddr = false;
1166
1167 pnetwork->network.Length = get_wlan_bssid_ex_sz(&pnetwork->network);
1168 if(pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
1169 {
1170 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("\n\n ***joinbss_evt_callback return a wrong bss ***\n\n"));
1171 return;
1172 }
1173
1174 spin_lock_bh(&pmlmepriv->lock);
1175
1176 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n rtw23a_joinbss_event_cb !! _enter_critical\n"));
1177
1178 if(pnetwork->join_res > 0)
1179 {
1180 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1181 retry = 0;
1182 if (check_fwstate(pmlmepriv,_FW_UNDER_LINKING))
1183 {
1184 /* s1. find ptarget_wlan */
1185 if(check_fwstate(pmlmepriv, _FW_LINKED))
1186 {
1187 if(the_same_macaddr == true)
1188 {
1189 ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1190 }
1191 else
1192 {
1193 pcur_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1194 if(pcur_wlan) pcur_wlan->fixed = false;
1195
1196 pcur_sta = rtw_get_stainfo23a(pstapriv, cur_network->network.MacAddress);
1197 if(pcur_sta) {
1198 spin_lock_bh(&pstapriv->sta_hash_lock);
1199 rtw_free_stainfo23a(adapter, pcur_sta);
1200 spin_unlock_bh(&pstapriv->sta_hash_lock);
1201 }
1202
1203 ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
1204 if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1205 if(ptarget_wlan) ptarget_wlan->fixed = true;
1206 }
1207 }
1208
1209 }
1210 else
1211 {
1212 ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
1213 if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1214 if(ptarget_wlan) ptarget_wlan->fixed = true;
1215 }
1216 }
1217
1218 /* s2. update cur_network */
1219 if(ptarget_wlan)
1220 {
1221 rtw_joinbss_update_network23a(adapter, ptarget_wlan, pnetwork);
1222 }
1223 else
1224 {
1225 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Can't find ptarget_wlan when joinbss_event callback\n"));
1226 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1227 goto ignore_joinbss_callback;
1228 }
1229
1230 /* s3. find ptarget_sta & update ptarget_sta after update cur_network only for station mode */
1231 if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
1232 {
1233 ptarget_sta = rtw_joinbss_update_stainfo(adapter, pnetwork);
1234 if(ptarget_sta==NULL)
1235 {
1236 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Can't update stainfo when joinbss_event callback\n"));
1237 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1238 goto ignore_joinbss_callback;
1239 }
1240 }
1241
1242 /* s4. indicate connect */
1243 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
1244 {
1245 rtw_indicate_connect23a(adapter);
1246 } else {
1247 /* adhoc mode will rtw_indicate_connect23a when rtw_stassoc_event_callback23a */
1248 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("adhoc mode, fw_state:%x", get_fwstate(pmlmepriv)));
1249 }
1250
1251 /* s5. Cancle assoc_timer */
1252 del_timer_sync(&pmlmepriv->assoc_timer);
1253
1254 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("Cancle assoc_timer\n"));
1255 } else {
1256 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1257 ("rtw23a_joinbss_event_cb err: fw_state:%x",
1258 get_fwstate(pmlmepriv)));
1259 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1260 goto ignore_joinbss_callback;
1261 }
1262 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1263 } else if(pnetwork->join_res == -4) {
1264 rtw_reset_securitypriv23a(adapter);
1265 mod_timer(&pmlmepriv->assoc_timer,
1266 jiffies + msecs_to_jiffies(1));
1267
1268 /* rtw_free_assoc_resources23a(adapter, 1); */
1269
1270 if((check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) {
1271 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1272 ("fail! clear _FW_UNDER_LINKING ^^^fw_state=%x\n",
1273 get_fwstate(pmlmepriv)));
1274 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1275 }
1276
1277 } else {
1278 /* if join_res < 0 (join fails), then try again */
1279 mod_timer(&pmlmepriv->assoc_timer,
1280 jiffies + msecs_to_jiffies(1));
1281 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1282 }
1283
1284ignore_joinbss_callback:
1285
1286 spin_unlock_bh(&pmlmepriv->lock);
1287}
1288
1289void rtw23a_joinbss_event_cb(struct rtw_adapter *adapter, u8 *pbuf)
1290{
1291 struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
1292
1293 mlmeext_joinbss_event_callback23a(adapter, pnetwork->join_res);
1294
1295 rtw_os_xmit_schedule23a(adapter);
1296
1297}
1298
1299/* FOR AP , AD-HOC mode */
1300void rtw_stassoc_hw_rpt23a(struct rtw_adapter *adapter, struct sta_info *psta)
1301{
1302 u16 media_status;
1303
1304 if (psta == NULL) return;
1305
1306 media_status = (psta->mac_id<<8)|1; /* MACID|OPMODE:1 connect */
1307 rtw_hal_set_hwreg23a(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
1308}
1309
1310void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
1311{
1312 struct sta_info *psta;
1313 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1314 struct stassoc_event *pstassoc = (struct stassoc_event*)pbuf;
1315 struct wlan_network *cur_network = &pmlmepriv->cur_network;
1316 struct wlan_network *ptarget_wlan = NULL;
1317
1318 if(rtw_access_ctrl23a(adapter, pstassoc->macaddr) == false)
1319 return;
1320
1321#ifdef CONFIG_8723AU_AP_MODE
1322 if(check_fwstate(pmlmepriv, WIFI_AP_STATE))
1323 {
1324 psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr);
1325 if (psta) {
1326 /* bss_cap_update_on_sta_join23a(adapter, psta); */
1327 /* sta_info_update23a(adapter, psta); */
1328 ap_sta_info_defer_update23a(adapter, psta);
1329
1330 rtw_stassoc_hw_rpt23a(adapter,psta);
1331 }
1332 return;
1333 }
1334#endif
1335 /* for AD-HOC mode */
1336 psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr);
1337 if (psta != NULL) {
1338 /* the sta have been in sta_info_queue => do nothing */
1339 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Error: rtw_stassoc_event_callback23a: sta has been in sta_hash_queue\n"));
1340 return; /* between drv has received this event before and fw have not yet to set key to CAM_ENTRY) */
1341 }
1342
1343 psta = rtw_alloc_stainfo23a(&adapter->stapriv, pstassoc->macaddr);
1344 if (psta == NULL) {
1345 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Can't alloc sta_info when rtw_stassoc_event_callback23a\n"));
1346 return;
1347 }
1348
1349 /* to do : init sta_info variable */
1350 psta->qos_option = 0;
1351 psta->mac_id = (uint)pstassoc->cam_id;
1352 /* psta->aid = (uint)pstassoc->cam_id; */
1353 DBG_8723A("%s\n",__func__);
1354 /* for ad-hoc mode */
1355 rtw_hal_set_odm_var23a(adapter,HAL_ODM_STA_INFO,psta,true);
1356
1357 rtw_stassoc_hw_rpt23a(adapter,psta);
1358
1359 if(adapter->securitypriv.dot11AuthAlgrthm==dot11AuthAlgrthm_8021X)
1360 psta->dot118021XPrivacy = adapter->securitypriv.dot11PrivacyAlgrthm;
1361
1362 psta->ieee8021x_blocked = false;
1363
1364 spin_lock_bh(&pmlmepriv->lock);
1365
1366 if ( (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)==true ) ||
1367 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)==true ) )
1368 {
1369 if(adapter->stapriv.asoc_sta_count== 2)
1370 {
1371 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1372 ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1373 if(ptarget_wlan) ptarget_wlan->fixed = true;
1374 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1375 /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
1376 rtw_indicate_connect23a(adapter);
1377 }
1378 }
1379
1380 spin_unlock_bh(&pmlmepriv->lock);
1381
1382 mlmeext_sta_add_event_callback23a(adapter, psta);
1383}
1384
1385void rtw_stadel_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
1386{
1387 int mac_id=-1;
1388 struct sta_info *psta;
1389 struct wlan_network* pwlan = NULL;
1390 struct wlan_bssid_ex *pdev_network=NULL;
1391 u8* pibss = NULL;
1392 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1393 struct stadel_event *pstadel = (struct stadel_event*)pbuf;
1394 struct sta_priv *pstapriv = &adapter->stapriv;
1395 struct wlan_network *tgt_network = &pmlmepriv->cur_network;
1396
1397 psta = rtw_get_stainfo23a(&adapter->stapriv, pstadel->macaddr);
1398 if(psta)
1399 mac_id = psta->mac_id;
1400 else
1401 mac_id = pstadel->mac_id;
1402
1403 DBG_8723A("%s(mac_id=%d)=" MAC_FMT "\n", __func__, mac_id, MAC_ARG(pstadel->macaddr));
1404
1405 if(mac_id>=0) {
1406 u16 media_status;
1407 media_status = (mac_id<<8)|0; /* MACID|OPMODE:0 means disconnect */
1408 /* for STA,AP,ADHOC mode, report disconnect stauts to FW */
1409 rtw_hal_set_hwreg23a(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
1410 }
1411
1412 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
1413 {
1414 return;
1415 }
1416
1417 mlmeext_sta_del_event_callback23a(adapter);
1418
1419 spin_lock_bh(&pmlmepriv->lock);
1420
1421 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
1422 {
1423 if (rtw_to_roaming(adapter) > 0)
1424 pmlmepriv->to_roaming--; /* this stadel_event is caused by roaming, decrease to_roaming */
1425 else if (rtw_to_roaming(adapter) == 0)
1426 rtw_set_roaming(adapter, adapter->registrypriv.max_roaming_times);
1427 if (*((unsigned short *)(pstadel->rsvd)) != WLAN_REASON_EXPIRATION_CHK)
1428 rtw_set_roaming(adapter, 0); /* don't roam */
1429
1430 rtw_free_uc_swdec_pending_queue23a(adapter);
1431
1432 rtw_free_assoc_resources23a(adapter, 1);
1433 rtw_indicate_disconnect23a(adapter);
1434 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1435 /* remove the network entry in scanned_queue */
1436 pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
1437 if (pwlan) {
1438 pwlan->fixed = false;
1439 rtw_free_network_nolock(pmlmepriv, pwlan);
1440 }
1441 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1442
1443 _rtw23a_roaming(adapter, tgt_network);
1444 }
1445
1446 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1447 check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
1448 {
1449
1450 spin_lock_bh(&pstapriv->sta_hash_lock);
1451 rtw_free_stainfo23a(adapter, psta);
1452 spin_unlock_bh(&pstapriv->sta_hash_lock);
1453
1454 if (adapter->stapriv.asoc_sta_count == 1) /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
1455 {
1456 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1457 /* free old ibss network */
1458 /* pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pstadel->macaddr); */
1459 pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
1460 if (pwlan)
1461 {
1462 pwlan->fixed = false;
1463 rtw_free_network_nolock(pmlmepriv, pwlan);
1464 }
1465 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1466 /* re-create ibss */
1467 pdev_network = &adapter->registrypriv.dev_network;
1468 pibss = adapter->registrypriv.dev_network.MacAddress;
1469
1470 memcpy(pdev_network, &tgt_network->network, get_wlan_bssid_ex_sz(&tgt_network->network));
1471
1472 memset(&pdev_network->Ssid, 0,
1473 sizeof(struct cfg80211_ssid));
1474 memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid,
1475 sizeof(struct cfg80211_ssid));
1476
1477 rtw_update_registrypriv_dev_network23a(adapter);
1478
1479 rtw_generate_random_ibss23a(pibss);
1480
1481 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
1482 {
1483 set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
1484 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
1485 }
1486
1487 if (rtw_createbss_cmd23a(adapter)!= _SUCCESS)
1488 {
1489
1490 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("***Error =>stadel_event_callback: rtw_createbss_cmd23a status FAIL***\n "));
1491
1492 }
1493
1494 }
1495
1496 }
1497
1498 spin_unlock_bh(&pmlmepriv->lock);
1499
1500}
1501
1502void rtw_cpwm_event_callback23a(struct rtw_adapter *padapter, u8 *pbuf)
1503{
1504
1505 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("+rtw_cpwm_event_callback23a !!!\n"));
1506
1507}
1508
1509/*
1510* rtw23a_join_to_handler - Timeout/faliure handler for CMD JoinBss
1511* @adapter: pointer to _adapter structure
1512*/
1513void rtw23a_join_to_handler (unsigned long data)
1514{
1515 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1516 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1517 int do_join_r;
1518
1519 DBG_8723A("%s, fw_state=%x\n", __func__, get_fwstate(pmlmepriv));
1520
1521 if(adapter->bDriverStopped ||adapter->bSurpriseRemoved)
1522 return;
1523
1524 spin_lock_bh(&pmlmepriv->lock);
1525
1526 if (rtw_to_roaming(adapter) > 0) { /* join timeout caused by roaming */
1527 while(1) {
1528 pmlmepriv->to_roaming--;
1529 if (rtw_to_roaming(adapter) != 0) { /* try another */
1530 DBG_8723A("%s try another roaming\n", __func__);
1531 if (_SUCCESS!= (do_join_r = rtw_do_join23a(adapter))) {
1532 DBG_8723A("%s roaming do_join return %d\n", __func__ , do_join_r);
1533 continue;
1534 }
1535 break;
1536 } else {
1537 DBG_8723A("%s We've try roaming but fail\n", __func__);
1538 rtw_indicate_disconnect23a(adapter);
1539 break;
1540 }
1541 }
1542 } else {
1543 rtw_indicate_disconnect23a(adapter);
1544 free_scanqueue(pmlmepriv);/* */
1545
1546 /* indicate disconnect for the case that join_timeout and check_fwstate != FW_LINKED */
1547 rtw_cfg80211_indicate_disconnect(adapter);
1548 }
1549
1550 spin_unlock_bh(&pmlmepriv->lock);
1551
1552}
1553
1554/*
1555* rtw_scan_timeout_handler23a - Timeout/Faliure handler for CMD SiteSurvey
1556* @data: pointer to _adapter structure
1557*/
1558void rtw_scan_timeout_handler23a(unsigned long data)
1559{
1560 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1561 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1562
1563 DBG_8723A(FUNC_ADPT_FMT" fw_state =%x\n", FUNC_ADPT_ARG(adapter), get_fwstate(pmlmepriv));
1564
1565 spin_lock_bh(&pmlmepriv->lock);
1566
1567 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1568
1569 spin_unlock_bh(&pmlmepriv->lock);
1570
1571 rtw_indicate_scan_done23a(adapter, true);
1572}
1573
1574static void rtw_auto_scan_handler(struct rtw_adapter *padapter)
1575{
1576 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1577
1578 /* auto site survey per 60sec */
1579 if (pmlmepriv->scan_interval > 0) {
1580 pmlmepriv->scan_interval--;
1581 if (pmlmepriv->scan_interval == 0) {
1582 DBG_8723A("%s\n", __func__);
1583 rtw_set_802_11_bssid23a_list_scan(padapter, NULL, 0);
1584 pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
1585 }
1586 }
1587}
1588
1589void rtw_dynamic_check_timer_handler(unsigned long data)
1590{
1591 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1592 struct registry_priv *pregistrypriv = &adapter->registrypriv;
1593
1594 if (adapter->hw_init_completed == false)
1595 goto out;
1596
1597 if ((adapter->bDriverStopped == true)||(adapter->bSurpriseRemoved == true))
1598 goto out;
1599
1600 if (adapter->net_closed == true)
1601 goto out;
1602
1603 rtw_dynamic_chk_wk_cmd23a(adapter);
1604
1605 if (pregistrypriv->wifi_spec == 1)
1606 {
1607#ifdef CONFIG_8723AU_P2P
1608 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
1609 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1610#endif
1611 {
1612 /* auto site survey */
1613 rtw_auto_scan_handler(adapter);
1614 }
1615 }
1616out:
1617 mod_timer(&adapter->mlmepriv.dynamic_chk_timer,
1618 jiffies + msecs_to_jiffies(2000));
1619}
1620
1621inline bool rtw_is_scan_deny(struct rtw_adapter *adapter)
1622{
1623 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1624 return (atomic_read(&mlmepriv->set_scan_deny) != 0) ? true : false;
1625}
1626
1627void rtw_clear_scan_deny(struct rtw_adapter *adapter)
1628{
1629 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1630 atomic_set(&mlmepriv->set_scan_deny, 0);
1631 if (0)
1632 DBG_8723A(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
1633}
1634
1635void rtw_set_scan_deny_timer_hdl(unsigned long data)
1636{
1637 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1638 rtw_clear_scan_deny(adapter);
1639}
1640
1641void rtw_set_scan_deny(struct rtw_adapter *adapter, u32 ms)
1642{
1643 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1644
1645 if (0)
1646 DBG_8723A(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
1647 atomic_set(&mlmepriv->set_scan_deny, 1);
1648 mod_timer(&mlmepriv->set_scan_deny_timer,
1649 jiffies + msecs_to_jiffies(ms));
1650
1651}
1652
1653#if defined(IEEE80211_SCAN_RESULT_EXPIRE)
1654#define RTW_SCAN_RESULT_EXPIRE IEEE80211_SCAN_RESULT_EXPIRE/HZ*1000 -1000 /* 3000 -1000 */
1655#else
1656#define RTW_SCAN_RESULT_EXPIRE 2000
1657#endif
1658
1659/*
1660* Select a new join candidate from the original @param candidate and @param competitor
1661* @return true: candidate is updated
1662* @return false: candidate is not updated
1663*/
1664static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv
1665 , struct wlan_network **candidate, struct wlan_network *competitor)
1666{
1667 int updated = false;
1668 struct rtw_adapter *adapter = container_of(pmlmepriv, struct rtw_adapter, mlmepriv);
1669
1670 /* check bssid, if needed */
1671 if (pmlmepriv->assoc_by_bssid == true) {
1672 if (!ether_addr_equal(competitor->network.MacAddress,
1673 pmlmepriv->assoc_bssid))
1674 goto exit;
1675 }
1676
1677 /* check ssid, if needed */
1678 if (pmlmepriv->assoc_ssid.ssid && pmlmepriv->assoc_ssid.ssid_len) {
1679 if (competitor->network.Ssid.ssid_len !=
1680 pmlmepriv->assoc_ssid.ssid_len ||
1681 memcmp(competitor->network.Ssid.ssid,
1682 pmlmepriv->assoc_ssid.ssid,
1683 pmlmepriv->assoc_ssid.ssid_len))
1684 goto exit;
1685 }
1686
1687 if (rtw_is_desired_network(adapter, competitor) == false)
1688 goto exit;
1689
1690 if (rtw_to_roaming(adapter) > 0) {
1691 unsigned int passed;
1692
1693 passed = jiffies_to_msecs(jiffies - competitor->last_scanned);
1694 if (passed >= RTW_SCAN_RESULT_EXPIRE ||
1695 is_same_ess(&competitor->network,
1696 &pmlmepriv->cur_network.network) == false)
1697 goto exit;
1698 }
1699
1700 if (*candidate == NULL ||(*candidate)->network.Rssi<competitor->network.Rssi) {
1701 *candidate = competitor;
1702 updated = true;
1703 }
1704
1705 if (updated) {
1706 DBG_8723A("[by_bssid:%u][assoc_ssid:%s][to_roaming:%u] new candidate: %s("MAC_FMT") rssi:%d\n",
1707 pmlmepriv->assoc_by_bssid,
1708 pmlmepriv->assoc_ssid.ssid,
1709 rtw_to_roaming(adapter),
1710 (*candidate)->network.Ssid.ssid,
1711 MAC_ARG((*candidate)->network.MacAddress),
1712 (int)(*candidate)->network.Rssi);
1713 }
1714
1715exit:
1716 return updated;
1717}
1718
1719/*
1720Calling context:
1721The caller of the sub-routine will be in critical section...
1722
1723The caller must hold the following spinlock
1724
1725pmlmepriv->lock
1726
1727*/
1728
1729int rtw_select_and_join_from_scanned_queue23a(struct mlme_priv *pmlmepriv)
1730{
1731 int ret;
1732 struct list_head *phead, *plist, *ptmp;
1733 struct rtw_adapter *adapter;
1734 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
1735 struct wlan_network *pnetwork = NULL;
1736 struct wlan_network *candidate = NULL;
1737
1738 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1739 phead = get_list_head(queue);
1740 adapter = pmlmepriv->nic_hdl;
1741
1742 list_for_each_safe(plist, ptmp, phead) {
1743 pnetwork = container_of(plist, struct wlan_network, list);
1744 if (!pnetwork) {
1745 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1746 ("%s return _FAIL:(pnetwork == NULL)\n",
1747 __func__));
1748 ret = _FAIL;
1749 goto exit;
1750 }
1751
1752 rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork);
1753 }
1754
1755 if (!candidate) {
1756 DBG_8723A("%s: return _FAIL(candidate == NULL)\n", __func__);
1757 ret = _FAIL;
1758 goto exit;
1759 } else {
1760 DBG_8723A("%s: candidate: %s("MAC_FMT", ch:%u)\n", __func__,
1761 candidate->network.Ssid.ssid,
1762 MAC_ARG(candidate->network.MacAddress),
1763 candidate->network.Configuration.DSConfig);
1764 }
1765
1766 /* check for situation of _FW_LINKED */
1767 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
1768 DBG_8723A("%s: _FW_LINKED while ask_for_joinbss!!!\n",
1769 __func__);
1770
1771 rtw_disassoc_cmd23a(adapter, 0, true);
1772 rtw_indicate_disconnect23a(adapter);
1773 rtw_free_assoc_resources23a(adapter, 0);
1774 }
1775 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
1776 ret = rtw_joinbss_cmd23a(adapter, candidate);
1777
1778exit:
1779 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1780
1781 return ret;
1782}
1783
1784int rtw_set_auth23a(struct rtw_adapter * adapter,
1785 struct security_priv *psecuritypriv)
1786{
1787 struct cmd_obj* pcmd;
1788 struct setauth_parm *psetauthparm;
1789 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1790 int res = _SUCCESS;
1791
1792 pcmd = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1793 if (!pcmd) {
1794 res = _FAIL; /* try again */
1795 goto exit;
1796 }
1797
1798 psetauthparm = (struct setauth_parm*)
1799 kzalloc(sizeof(struct setauth_parm), GFP_KERNEL);
1800 if (!psetauthparm) {
1801 kfree(pcmd);
1802 res = _FAIL;
1803 goto exit;
1804 }
1805
1806 psetauthparm->mode = (unsigned char)psecuritypriv->dot11AuthAlgrthm;
1807
1808 pcmd->cmdcode = _SetAuth_CMD_;
1809 pcmd->parmbuf = (unsigned char *)psetauthparm;
1810 pcmd->cmdsz = (sizeof(struct setauth_parm));
1811 pcmd->rsp = NULL;
1812 pcmd->rspsz = 0;
1813
1814 INIT_LIST_HEAD(&pcmd->list);
1815
1816 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,
1817 ("after enqueue set_auth_cmd, auth_mode=%x\n",
1818 psecuritypriv->dot11AuthAlgrthm));
1819
1820 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
1821
1822exit:
1823
1824 return res;
1825}
1826
1827int rtw_set_key23a(struct rtw_adapter *adapter,
1828 struct security_priv *psecuritypriv, int keyid, u8 set_tx)
1829{
1830 u8 keylen;
1831 struct cmd_obj *pcmd;
1832 struct setkey_parm *psetkeyparm;
1833 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1834 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1835 int res = _SUCCESS;
1836
1837 pcmd = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1838 if (!pcmd) {
1839 res = _FAIL; /* try again */
1840 goto exit;
1841 }
1842 psetkeyparm = (struct setkey_parm *)
1843 kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
1844 if (!psetkeyparm) {
1845 kfree(pcmd);
1846 res = _FAIL;
1847 goto exit;
1848 }
1849
1850 if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
1851 psetkeyparm->algorithm = (unsigned char)
1852 psecuritypriv->dot118021XGrpPrivacy;
1853 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1854 ("\n rtw_set_key23a: psetkeyparm->algorithm = (unsigned "
1855 "char)psecuritypriv->dot118021XGrpPrivacy =%d\n",
1856 psetkeyparm->algorithm));
1857 } else {
1858 psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm;
1859 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1860 ("\n rtw_set_key23a: psetkeyparm->algorithm = (u8)"
1861 "psecuritypriv->dot11PrivacyAlgrthm =%d\n",
1862 psetkeyparm->algorithm));
1863 }
1864 psetkeyparm->keyid = (u8)keyid;/* 0~3 */
1865 psetkeyparm->set_tx = set_tx;
1866 if (is_wep_enc(psetkeyparm->algorithm))
1867 pmlmepriv->key_mask |= CHKBIT(psetkeyparm->keyid);
1868
1869 DBG_8723A("==> rtw_set_key23a algorithm(%x), keyid(%x), key_mask(%x)\n",
1870 psetkeyparm->algorithm, psetkeyparm->keyid,
1871 pmlmepriv->key_mask);
1872 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1873 ("\n rtw_set_key23a: psetkeyparm->algorithm =%d psetkeyparm->"
1874 "keyid = (u8)keyid =%d\n", psetkeyparm->algorithm, keyid));
1875
1876 switch (psetkeyparm->algorithm) {
1877 case _WEP40_:
1878 keylen = 5;
1879 memcpy(&psetkeyparm->key[0],
1880 &psecuritypriv->dot11DefKey[keyid].skey[0], keylen);
1881 break;
1882 case _WEP104_:
1883 keylen = 13;
1884 memcpy(&psetkeyparm->key[0],
1885 &psecuritypriv->dot11DefKey[keyid].skey[0], keylen);
1886 break;
1887 case _TKIP_:
1888 keylen = 16;
1889 memcpy(&psetkeyparm->key,
1890 &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1891 psetkeyparm->grpkey = 1;
1892 break;
1893 case _AES_:
1894 keylen = 16;
1895 memcpy(&psetkeyparm->key,
1896 &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1897 psetkeyparm->grpkey = 1;
1898 break;
1899 default:
1900 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1901 ("\n rtw_set_key23a:psecuritypriv->dot11PrivacyAlgrthm = "
1902 "%x (must be 1 or 2 or 4 or 5)\n",
1903 psecuritypriv->dot11PrivacyAlgrthm));
1904 res = _FAIL;
1905 goto exit;
1906 }
1907
1908 pcmd->cmdcode = _SetKey_CMD_;
1909 pcmd->parmbuf = (u8 *)psetkeyparm;
1910 pcmd->cmdsz = (sizeof(struct setkey_parm));
1911 pcmd->rsp = NULL;
1912 pcmd->rspsz = 0;
1913
1914 INIT_LIST_HEAD(&pcmd->list);
1915
1916 /* sema_init(&pcmd->cmd_sem, 0); */
1917
1918 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
1919
1920exit:
1921
1922 return res;
1923}
1924
1925/* adjust IEs for rtw_joinbss_cmd23a in WMM */
1926int rtw_restruct_wmm_ie23a(struct rtw_adapter *adapter, u8 *in_ie,
1927 u8 *out_ie, uint in_len, uint initial_out_len)
1928{
1929 unsigned int ielength = 0;
1930 unsigned int i, j;
1931
1932 i = 12; /* after the fixed IE */
1933 while(i < in_len) {
1934 ielength = initial_out_len;
1935
1936 /* WMM element ID and OUI */
1937 if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 &&
1938 in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 &&
1939 in_ie[i + 5] == 0x02 && i+5 < in_len) {
1940
1941 /* Append WMM IE to the last index of out_ie */
1942 for (j = i; j < i + 9; j++) {
1943 out_ie[ielength] = in_ie[j];
1944 ielength++;
1945 }
1946 out_ie[initial_out_len + 1] = 0x07;
1947 out_ie[initial_out_len + 6] = 0x00;
1948 out_ie[initial_out_len + 8] = 0x00;
1949
1950 break;
1951 }
1952
1953 i += (in_ie[i + 1] + 2); /* to the next IE element */
1954 }
1955
1956 return ielength;
1957}
1958
1959/* */
1960/* Ported from 8185: IsInPreAuthKeyList().
1961 (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.) */
1962/* Added by Annie, 2006-05-07. */
1963/* */
1964/* Search by BSSID, */
1965/* Return Value: */
1966/* -1 :if there is no pre-auth key in the table */
1967/* >= 0 :if there is pre-auth key, and return the entry id */
1968/* */
1969/* */
1970
1971static int SecIsInPMKIDList(struct rtw_adapter *Adapter, u8 *bssid)
1972{
1973 struct security_priv *psecuritypriv = &Adapter->securitypriv;
1974 int i = 0;
1975
1976 do {
1977 if (psecuritypriv->PMKIDList[i].bUsed &&
1978 ether_addr_equal(psecuritypriv->PMKIDList[i].Bssid, bssid)) {
1979 break;
1980 } else {
1981 i++;
1982 /* continue; */
1983 }
1984 } while(i < NUM_PMKID_CACHE);
1985
1986 if (i == NUM_PMKID_CACHE) {
1987 i = -1;/* Could not find. */
1988 } else {
1989 /* There is one Pre-Authentication Key for
1990 the specific BSSID. */
1991 }
1992
1993 return i;
1994}
1995
1996/* */
1997/* Check the RSN IE length */
1998/* If the RSN IE length <= 20, the RSN IE didn't include
1999 the PMKID information */
2000/* 0-11th element in the array are the fixed IE */
2001/* 12th element in the array is the IE */
2002/* 13th element in the array is the IE length */
2003/* */
2004
2005static int rtw_append_pmkid(struct rtw_adapter *Adapter, int iEntry,
2006 u8 *ie, uint ie_len)
2007{
2008 struct security_priv *psecuritypriv = &Adapter->securitypriv;
2009
2010 if (ie[13] <= 20) {
2011 /* The RSN IE didn't include the PMK ID,
2012 append the PMK information */
2013 ie[ie_len] = 1;
2014 ie_len++;
2015 ie[ie_len] = 0; /* PMKID count = 0x0100 */
2016 ie_len++;
2017 memcpy(&ie[ie_len],
2018 &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
2019
2020 ie_len += 16;
2021 ie[13] += 18;/* PMKID length = 2+16 */
2022 }
2023 return ie_len;
2024}
2025int rtw_restruct_sec_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie,
2026 uint in_len)
2027{
2028 u8 authmode;
2029 uint ielength;
2030 int iEntry;
2031 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2032 struct security_priv *psecuritypriv = &adapter->securitypriv;
2033 uint ndisauthmode = psecuritypriv->ndisauthtype;
2034 uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
2035
2036 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2037 ("+rtw_restruct_sec_ie23a: ndisauthmode=%d ndissecuritytype=%d\n",
2038 ndisauthmode, ndissecuritytype));
2039
2040 /* copy fixed ie only */
2041 memcpy(out_ie, in_ie, 12);
2042 ielength = 12;
2043 if ((ndisauthmode==Ndis802_11AuthModeWPA) ||
2044 (ndisauthmode==Ndis802_11AuthModeWPAPSK))
2045 authmode=_WPA_IE_ID_;
2046 if ((ndisauthmode==Ndis802_11AuthModeWPA2) ||
2047 (ndisauthmode==Ndis802_11AuthModeWPA2PSK))
2048 authmode=_WPA2_IE_ID_;
2049
2050 if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
2051 memcpy(out_ie + ielength, psecuritypriv->wps_ie,
2052 psecuritypriv->wps_ie_len);
2053
2054 ielength += psecuritypriv->wps_ie_len;
2055 } else if ((authmode==_WPA_IE_ID_) || (authmode==_WPA2_IE_ID_)) {
2056 /* copy RSN or SSN */
2057 memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0],
2058 psecuritypriv->supplicant_ie[1] + 2);
2059 ielength += psecuritypriv->supplicant_ie[1] + 2;
2060 rtw_report_sec_ie23a(adapter, authmode,
2061 psecuritypriv->supplicant_ie);
2062 }
2063
2064 iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
2065 if (iEntry < 0) {
2066 return ielength;
2067 } else {
2068 if (authmode == _WPA2_IE_ID_) {
2069 ielength=rtw_append_pmkid(adapter, iEntry,
2070 out_ie, ielength);
2071 }
2072 }
2073
2074 return ielength;
2075}
2076
2077void rtw_init_registrypriv_dev_network23a(struct rtw_adapter* adapter)
2078{
2079 struct registry_priv* pregistrypriv = &adapter->registrypriv;
2080 struct eeprom_priv* peepriv = &adapter->eeprompriv;
2081 struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
2082 u8 *myhwaddr = myid(peepriv);
2083
2084 ether_addr_copy(pdev_network->MacAddress, myhwaddr);
2085
2086 memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
2087 sizeof(struct cfg80211_ssid));
2088
2089 pdev_network->Configuration.Length=sizeof(struct ndis_802_11_config);
2090 pdev_network->Configuration.BeaconPeriod = 100;
2091 pdev_network->Configuration.FHConfig.Length = 0;
2092 pdev_network->Configuration.FHConfig.HopPattern = 0;
2093 pdev_network->Configuration.FHConfig.HopSet = 0;
2094 pdev_network->Configuration.FHConfig.DwellTime = 0;
2095
2096}
2097
2098void rtw_update_registrypriv_dev_network23a(struct rtw_adapter* adapter)
2099{
2100 int sz = 0;
2101 struct registry_priv* pregistrypriv = &adapter->registrypriv;
2102 struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
2103 struct security_priv *psecuritypriv = &adapter->securitypriv;
2104 struct wlan_network *cur_network = &adapter->mlmepriv.cur_network;
2105 /* struct xmit_priv *pxmitpriv = &adapter->xmitpriv; */
2106
2107 pdev_network->Privacy =
2108 (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0);
2109
2110 pdev_network->Rssi = 0;
2111
2112 switch (pregistrypriv->wireless_mode)
2113 {
2114 case WIRELESS_11B:
2115 pdev_network->NetworkTypeInUse = Ndis802_11DS;
2116 break;
2117 case WIRELESS_11G:
2118 case WIRELESS_11BG:
2119 case WIRELESS_11_24N:
2120 case WIRELESS_11G_24N:
2121 case WIRELESS_11BG_24N:
2122 pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
2123 break;
2124 case WIRELESS_11A:
2125 case WIRELESS_11A_5N:
2126 pdev_network->NetworkTypeInUse = Ndis802_11OFDM5;
2127 break;
2128 case WIRELESS_11ABGN:
2129 if (pregistrypriv->channel > 14)
2130 pdev_network->NetworkTypeInUse = Ndis802_11OFDM5;
2131 else
2132 pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
2133 break;
2134 default :
2135 /* TODO */
2136 break;
2137 }
2138
2139 pdev_network->Configuration.DSConfig = pregistrypriv->channel;
2140 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
2141 ("pregistrypriv->channel =%d, pdev_network->Configuration."
2142 "DSConfig = 0x%x\n", pregistrypriv->channel,
2143 pdev_network->Configuration.DSConfig));
2144
2145 if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
2146 pdev_network->Configuration.ATIMWindow = 0;
2147
2148 pdev_network->InfrastructureMode =
2149 cur_network->network.InfrastructureMode;
2150
2151 /* 1. Supported rates */
2152 /* 2. IE */
2153
2154 sz = rtw_generate_ie23a(pregistrypriv);
2155
2156 pdev_network->IELength = sz;
2157
2158 pdev_network->Length =
2159 get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
2160
2161 /* notes: translate IELength & Length after assign the
2162 Length to cmdsz in createbss_cmd(); */
2163 /* pdev_network->IELength = cpu_to_le32(sz); */
2164
2165}
2166
2167void rtw_get_encrypt_decrypt_from_registrypriv23a(struct rtw_adapter* adapter)
2168{
2169
2170}
2171
2172/* the fucntion is at passive_level */
2173void rtw_joinbss_reset23a(struct rtw_adapter *padapter)
2174{
2175 u8 threshold;
2176 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2177 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2178
2179 /* todo: if you want to do something io/reg/hw setting
2180 before join_bss, please add code here */
2181
2182 pmlmepriv->num_FortyMHzIntolerant = 0;
2183
2184 pmlmepriv->num_sta_no_ht = 0;
2185
2186 phtpriv->ampdu_enable = false;/* reset to disabled */
2187
2188 /* TH = 1 => means that invalidate usb rx aggregation */
2189 /* TH = 0 => means that validate usb rx aggregation, use init value. */
2190 if (phtpriv->ht_option) {
2191 if (padapter->registrypriv.wifi_spec == 1)
2192 threshold = 1;
2193 else
2194 threshold = 0;
2195 rtw_hal_set_hwreg23a(padapter, HW_VAR_RXDMA_AGG_PG_TH,
2196 (u8 *)(&threshold));
2197 } else {
2198 threshold = 1;
2199 rtw_hal_set_hwreg23a(padapter, HW_VAR_RXDMA_AGG_PG_TH,
2200 (u8 *)(&threshold));
2201 }
2202}
2203
2204/* the fucntion is >= passive_level */
2205unsigned int rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie,
2206 u8 *out_ie, uint in_len, uint *pout_len)
2207{
2208 u32 ielen, out_len;
2209 int max_rx_ampdu_factor;
2210 unsigned char *p, *pframe;
2211 struct ieee80211_ht_cap ht_capie;
2212 unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
2213 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2214 struct qos_priv *pqospriv = &pmlmepriv->qospriv;
2215 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2216
2217 phtpriv->ht_option = false;
2218
2219 p = rtw_get_ie23a(in_ie + 12, _HT_CAPABILITY_IE_, &ielen, in_len - 12);
2220
2221 if (p && ielen > 0) {
2222 u32 rx_packet_offset, max_recvbuf_sz;
2223 if (pqospriv->qos_option == 0) {
2224 out_len = *pout_len;
2225 pframe = rtw_set_ie23a(out_ie + out_len,
2226 _VENDOR_SPECIFIC_IE_,
2227 _WMM_IE_Length_, WMM_IE, pout_len);
2228
2229 pqospriv->qos_option = 1;
2230 }
2231
2232 out_len = *pout_len;
2233
2234 memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
2235
2236 ht_capie.cap_info = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
2237 IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 |
2238 IEEE80211_HT_CAP_TX_STBC | IEEE80211_HT_CAP_DSSSCCK40;
2239
2240 rtw_hal_get_def_var23a(padapter, HAL_DEF_RX_PACKET_OFFSET,
2241 &rx_packet_offset);
2242 rtw_hal_get_def_var23a(padapter, HAL_DEF_MAX_RECVBUF_SZ,
2243 &max_recvbuf_sz);
2244
2245 rtw_hal_get_def_var23a(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
2246 &max_rx_ampdu_factor);
2247 ht_capie.ampdu_params_info = max_rx_ampdu_factor & 0x03;
2248
2249 if (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
2250 ht_capie.ampdu_params_info |=
2251 (IEEE80211_HT_AMPDU_PARM_DENSITY& (0x07 << 2));
2252 else
2253 ht_capie.ampdu_params_info |=
2254 (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00);
2255
2256 pframe = rtw_set_ie23a(out_ie + out_len, _HT_CAPABILITY_IE_,
2257 sizeof(struct ieee80211_ht_cap),
2258 (unsigned char*)&ht_capie, pout_len);
2259
2260 phtpriv->ht_option = true;
2261
2262 p = rtw_get_ie23a(in_ie + 12, _HT_ADD_INFO_IE_, &ielen, in_len-12);
2263 if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) {
2264 out_len = *pout_len;
2265 pframe = rtw_set_ie23a(out_ie + out_len, _HT_ADD_INFO_IE_,
2266 ielen, p + 2 , pout_len);
2267 }
2268 }
2269
2270 return phtpriv->ht_option;
2271}
2272
2273/* the fucntion is > passive_level (in critical_section) */
2274void rtw_update_ht_cap23a(struct rtw_adapter *padapter, u8 *pie, uint ie_len)
2275{
2276 u8 *p, max_ampdu_sz;
2277 int len;
2278 /* struct sta_info *bmc_sta, *psta; */
2279 struct ieee80211_ht_cap *pht_capie;
2280 struct ieee80211_ht_addt_info *pht_addtinfo;
2281 /* struct recv_reorder_ctrl *preorder_ctrl; */
2282 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2283 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2284 /* struct recv_priv *precvpriv = &padapter->recvpriv; */
2285 struct registry_priv *pregistrypriv = &padapter->registrypriv;
2286 /* struct wlan_network *pcur_network = &pmlmepriv->cur_network;; */
2287 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2288 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2289
2290 if (!phtpriv->ht_option)
2291 return;
2292
2293 if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable))
2294 return;
2295
2296 DBG_8723A("+rtw_update_ht_cap23a()\n");
2297
2298 /* maybe needs check if ap supports rx ampdu. */
2299 if ((phtpriv->ampdu_enable == false) && (pregistrypriv->ampdu_enable == 1)) {
2300 if (pregistrypriv->wifi_spec == 1)
2301 phtpriv->ampdu_enable = false;
2302 else
2303 phtpriv->ampdu_enable = true;
2304 } else if (pregistrypriv->ampdu_enable == 2) {
2305 phtpriv->ampdu_enable = true;
2306 }
2307
2308 /* check Max Rx A-MPDU Size */
2309 len = 0;
2310 p = rtw_get_ie23a(pie+sizeof (struct ndis_802_11_fixed_ies), _HT_CAPABILITY_IE_, &len, ie_len-sizeof (struct ndis_802_11_fixed_ies));
2311 if (p && len > 0) {
2312 pht_capie = (struct ieee80211_ht_cap *)(p+2);
2313 max_ampdu_sz = (pht_capie->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_FACTOR);
2314 max_ampdu_sz = 1 << (max_ampdu_sz+3); /* max_ampdu_sz (kbytes); */
2315
2316 /* DBG_8723A("rtw_update_ht_cap23a(): max_ampdu_sz =%d\n", max_ampdu_sz); */
2317 phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
2318
2319 }
2320
2321 len = 0;
2322 p = rtw_get_ie23a(pie+sizeof (struct ndis_802_11_fixed_ies), _HT_ADD_INFO_IE_, &len, ie_len-sizeof (struct ndis_802_11_fixed_ies));
2323 if (p && len>0)
2324 {
2325 pht_addtinfo = (struct ieee80211_ht_addt_info *)(p+2);
2326 /* todo: */
2327 }
2328
2329 /* update cur_bwmode & cur_ch_offset */
2330 if ((pregistrypriv->cbw40_enable) &&
2331 (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & BIT(1)) &&
2332 (pmlmeinfo->HT_info.infos[0] & BIT(2)))
2333 {
2334 int i;
2335 u8 rf_type;
2336
2337 padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
2338
2339 /* update the MCS rates */
2340 for (i = 0; i < 16; i++)
2341 {
2342 if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R))
2343 pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_1R23A[i];
2344 else
2345 pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_2R23A[i];
2346 }
2347 /* switch to the 40M Hz mode accoring to the AP */
2348 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
2349 switch ((pmlmeinfo->HT_info.infos[0] & 0x3))
2350 {
2351 case HT_EXTCHNL_OFFSET_UPPER:
2352 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
2353 break;
2354
2355 case HT_EXTCHNL_OFFSET_LOWER:
2356 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
2357 break;
2358
2359 default:
2360 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2361 break;
2362 }
2363 }
2364
2365 /* */
2366 /* Config SM Power Save setting */
2367 /* */
2368 pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;
2369 if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
2370 DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
2371
2372 /* */
2373 /* Config current HT Protection mode. */
2374 /* */
2375 pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;
2376}
2377
2378void rtw_issue_addbareq_cmd23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
2379{
2380 u8 issued;
2381 int priority;
2382 struct sta_info *psta = NULL;
2383 struct ht_priv *phtpriv;
2384 struct pkt_attrib *pattrib = &pxmitframe->attrib;
2385 s32 bmcst = is_multicast_ether_addr(pattrib->ra);
2386
2387 if (bmcst || (padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod<100))
2388 return;
2389
2390 priority = pattrib->priority;
2391
2392 if (pattrib->psta)
2393 psta = pattrib->psta;
2394 else
2395 {
2396 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
2397 psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra);
2398 }
2399
2400 if (psta == NULL)
2401 {
2402 DBG_8723A("%s, psta == NUL\n", __func__);
2403 return;
2404 }
2405
2406 if (!(psta->state &_FW_LINKED))
2407 {
2408 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
2409 return;
2410 }
2411
2412 phtpriv = &psta->htpriv;
2413
2414 if ((phtpriv->ht_option == true) && (phtpriv->ampdu_enable == true))
2415 {
2416 issued = (phtpriv->agg_enable_bitmap>>priority)&0x1;
2417 issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1;
2418
2419 if (0 == issued)
2420 {
2421 DBG_8723A("rtw_issue_addbareq_cmd23a, p =%d\n", priority);
2422 psta->htpriv.candidate_tid_bitmap |= CHKBIT((u8)priority);
2423 rtw_addbareq_cmd23a(padapter, (u8) priority, pattrib->ra);
2424 }
2425 }
2426}
2427
2428inline void rtw_set_roaming(struct rtw_adapter *adapter, u8 to_roaming)
2429{
2430 if (to_roaming == 0)
2431 adapter->mlmepriv.to_join = false;
2432 adapter->mlmepriv.to_roaming = to_roaming;
2433}
2434
2435inline u8 rtw_to_roaming(struct rtw_adapter *adapter)
2436{
2437 return adapter->mlmepriv.to_roaming;
2438}
2439
2440void rtw23a_roaming(struct rtw_adapter *padapter, struct wlan_network *tgt_network)
2441{
2442 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2443
2444 spin_lock_bh(&pmlmepriv->lock);
2445 _rtw23a_roaming(padapter, tgt_network);
2446 spin_unlock_bh(&pmlmepriv->lock);
2447}
2448void _rtw23a_roaming(struct rtw_adapter *padapter, struct wlan_network *tgt_network)
2449{
2450 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2451 struct wlan_network *pnetwork;
2452 int do_join_r;
2453
2454 if (tgt_network != NULL)
2455 pnetwork = tgt_network;
2456 else
2457 pnetwork = &pmlmepriv->cur_network;
2458
2459 if (0 < rtw_to_roaming(padapter)) {
2460 DBG_8723A("roaming from %s("MAC_FMT"), length:%d\n",
2461 pnetwork->network.Ssid.ssid,
2462 MAC_ARG(pnetwork->network.MacAddress),
2463 pnetwork->network.Ssid.ssid_len);
2464 memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.Ssid,
2465 sizeof(struct cfg80211_ssid));
2466
2467 pmlmepriv->assoc_by_bssid = false;
2468
2469 while(1) {
2470 if (_SUCCESS == (do_join_r = rtw_do_join23a(padapter))) {
2471 break;
2472 } else {
2473 DBG_8723A("roaming do_join return %d\n", do_join_r);
2474 pmlmepriv->to_roaming--;
2475
2476 if (0 < rtw_to_roaming(padapter)) {
2477 continue;
2478 } else {
2479 DBG_8723A("%s(%d) -to roaming fail, indicate_disconnect\n", __func__, __LINE__);
2480 rtw_indicate_disconnect23a(padapter);
2481 break;
2482 }
2483 }
2484 }
2485 }
2486}
2487
2488int rtw_linked_check(struct rtw_adapter *padapter)
2489{
2490 if ((check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE)) ||
2491 (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE))) {
2492 if (padapter->stapriv.asoc_sta_count > 2)
2493 return true;
2494 } else { /* Station mode */
2495 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == true)
2496 return true;
2497 }
2498 return false;
2499}
diff --git a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c
new file mode 100644
index 000000000000..75ccdec881e5
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c
@@ -0,0 +1,9988 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _RTW_MLME_EXT_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <wifi.h>
20#include <rtw_mlme_ext.h>
21#include <wlan_bssdef.h>
22#include <mlme_osdep.h>
23#include <recv_osdep.h>
24#include <ethernet.h>
25#include <linux/ieee80211.h>
26
27#ifdef CONFIG_8723AU_BT_COEXIST
28#include <rtl8723a_hal.h>
29#endif
30
31static struct mlme_handler mlme_sta_tbl[]={
32 {"OnAssocReq23a", &OnAssocReq23a},
33 {"OnAssocRsp23a", &OnAssocRsp23a},
34 {"OnReAssocReq", &OnAssocReq23a},
35 {"OnReAssocRsp", &OnAssocRsp23a},
36 {"OnProbeReq23a", &OnProbeReq23a},
37 {"OnProbeRsp23a", &OnProbeRsp23a},
38
39 /*----------------------------------------------------------
40 below 2 are reserved
41 -----------------------------------------------------------*/
42 {"DoReserved23a", &DoReserved23a},
43 {"DoReserved23a", &DoReserved23a},
44 {"OnBeacon23a", &OnBeacon23a},
45 {"OnATIM", &OnAtim23a},
46 {"OnDisassoc23a", &OnDisassoc23a},
47 {"OnAuth23a", &OnAuth23aClient23a},
48 {"OnDeAuth23a", &OnDeAuth23a},
49 {"OnAction23a", &OnAction23a},
50};
51
52static struct action_handler OnAction23a_tbl[]={
53 {WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct23a},
54 {WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction23a_qos},
55 {WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction23a_dls},
56 {WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction23a_back23a},
57 {WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public23a},
58 {WLAN_CATEGORY_HT, "ACTION_HT", &OnAction23a_ht},
59 {WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved23a},
60 {WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction23a_wmm},
61 {WLAN_CATEGORY_VENDOR_SPECIFIC, "ACTION_P2P", &OnAction23a_p2p},
62};
63
64static u8 null_addr[ETH_ALEN]= {0, 0, 0, 0, 0, 0};
65
66/**************************************************
67OUI definitions for the vendor specific IE
68***************************************************/
69unsigned char RTW_WPA_OUI23A[] = {0x00, 0x50, 0xf2, 0x01};
70unsigned char WMM_OUI23A[] = {0x00, 0x50, 0xf2, 0x02};
71unsigned char WPS_OUI23A[] = {0x00, 0x50, 0xf2, 0x04};
72unsigned char P2P_OUI23A[] = {0x50, 0x6F, 0x9A, 0x09};
73unsigned char WFD_OUI23A[] = {0x50, 0x6F, 0x9A, 0x0A};
74
75unsigned char WMM_INFO_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
76unsigned char WMM_PARA_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
77
78unsigned char WPA_TKIP_CIPHER23A[4] = {0x00, 0x50, 0xf2, 0x02};
79unsigned char RSN_TKIP_CIPHER23A[4] = {0x00, 0x0f, 0xac, 0x02};
80
81
82/********************************************************
83MCS rate definitions
84*********************************************************/
85unsigned char MCS_rate_2R23A[16] = {
86 0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
87unsigned char MCS_rate_1R23A[16] = {
88 0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
89
90/********************************************************
91ChannelPlan definitions
92*********************************************************/
93
94static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
95 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
96 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
97 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
98 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
99 {{10, 11, 12, 13}, 4}, /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
100 {{}, 0}, /* 0x05, RT_CHANNEL_DOMAIN_2G_NULL */
101};
102
103static struct rt_channel_plan_5g RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = {
104 {{}, 0}, /* 0x00, RT_CHANNEL_DOMAIN_5G_NULL */
105 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19}, /* 0x01, RT_CHANNEL_DOMAIN_5G_ETSI1 */
106 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24}, /* 0x02, RT_CHANNEL_DOMAIN_5G_ETSI2 */
107 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22}, /* 0x03, RT_CHANNEL_DOMAIN_5G_ETSI3 */
108 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24}, /* 0x04, RT_CHANNEL_DOMAIN_5G_FCC1 */
109 {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9}, /* 0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */
110 {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13}, /* 0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */
111 {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12}, /* 0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */
112 {{149, 153, 157, 161, 165}, 5}, /* 0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */
113 {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */
114 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 20}, /* 0x0A, RT_CHANNEL_DOMAIN_5G_FCC7_IC1 */
115 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, 165}, 20}, /* 0x0B, RT_CHANNEL_DOMAIN_5G_KCC1 */
116 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19}, /* 0x0C, RT_CHANNEL_DOMAIN_5G_MKK1 */
117 {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */
118 {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11}, /* 0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */
119 {{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 15}, /* 0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */
120 {{56, 60, 64, 149, 153, 157, 161, 165}, 8}, /* 0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */
121
122 /* Driver self defined for old channel plan Compatible , Remember to modify if have new channel plan definition ===== */
123 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 21}, /* 0x11, RT_CHANNEL_DOMAIN_5G_FCC */
124 {{36, 40, 44, 48}, 4}, /* 0x12, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */
125 {{36, 40, 44, 48, 149, 153, 157, 161}, 8}, /* 0x13, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */
126};
127
128static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
129 /* 0x00 ~ 0x1F , Old Define ===== */
130 {0x02, 0x11}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
131 {0x02, 0x0A}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
132 {0x01, 0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
133 {0x01, 0x00}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
134 {0x01, 0x00}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
135 {0x03, 0x00}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
136 {0x03, 0x00}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
137 {0x01, 0x09}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
138 {0x03, 0x09}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
139 {0x03, 0x00}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
140 {0x00, 0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
141 {0x02, 0x0F}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
142 {0x01, 0x08}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
143 {0x02, 0x06}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
144 {0x02, 0x0B}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
145 {0x02, 0x09}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
146 {0x01, 0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
147 {0x02, 0x05}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
148 {0x01, 0x12}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
149 {0x00, 0x04}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
150 {0x02, 0x10}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
151 {0x00, 0x12}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
152 {0x00, 0x13}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
153 {0x03, 0x12}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
154 {0x05, 0x08}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
155 {0x02, 0x08}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
156 {0x00, 0x00}, /* 0x1A, */
157 {0x00, 0x00}, /* 0x1B, */
158 {0x00, 0x00}, /* 0x1C, */
159 {0x00, 0x00}, /* 0x1D, */
160 {0x00, 0x00}, /* 0x1E, */
161 {0x05, 0x04}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
162 /* 0x20 ~ 0x7F , New Define ===== */
163 {0x00, 0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
164 {0x01, 0x00}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
165 {0x02, 0x00}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
166 {0x03, 0x00}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
167 {0x04, 0x00}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
168 {0x02, 0x04}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
169 {0x00, 0x01}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
170 {0x03, 0x0C}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
171 {0x00, 0x0B}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
172 {0x00, 0x05}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
173 {0x00, 0x00}, /* 0x2A, */
174 {0x00, 0x00}, /* 0x2B, */
175 {0x00, 0x00}, /* 0x2C, */
176 {0x00, 0x00}, /* 0x2D, */
177 {0x00, 0x00}, /* 0x2E, */
178 {0x00, 0x00}, /* 0x2F, */
179 {0x00, 0x06}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
180 {0x00, 0x07}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
181 {0x00, 0x08}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
182 {0x00, 0x09}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
183 {0x02, 0x0A}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
184 {0x00, 0x02}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
185 {0x00, 0x03}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
186 {0x03, 0x0D}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
187 {0x03, 0x0E}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
188 {0x02, 0x0F}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
189 {0x00, 0x00}, /* 0x3A, */
190 {0x00, 0x00}, /* 0x3B, */
191 {0x00, 0x00}, /* 0x3C, */
192 {0x00, 0x00}, /* 0x3D, */
193 {0x00, 0x00}, /* 0x3E, */
194 {0x00, 0x00}, /* 0x3F, */
195 {0x02, 0x10}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
196 {0x03, 0x00}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
197};
198
199static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03, 0x02}; /* use the conbination for max channel numbers */
200
201static struct fwevent wlanevents[] =
202{
203 {0, rtw_dummy_event_callback23a}, /*0*/
204 {0, NULL},
205 {0, NULL},
206 {0, NULL},
207 {0, NULL},
208 {0, NULL},
209 {0, NULL},
210 {0, NULL},
211 {0, &rtw_survey_event_cb23a}, /*8*/
212 {sizeof (struct surveydone_event), &rtw_surveydone_event_callback23a}, /*9*/
213
214 {0, &rtw23a_joinbss_event_cb}, /*10*/
215 {sizeof(struct stassoc_event), &rtw_stassoc_event_callback23a},
216 {sizeof(struct stadel_event), &rtw_stadel_event_callback23a},
217 {0, &rtw_atimdone_event_callback23a},
218 {0, rtw_dummy_event_callback23a},
219 {0, NULL}, /*15*/
220 {0, NULL},
221 {0, NULL},
222 {0, NULL},
223 {0, rtw23a_fwdbg_event_callback},
224 {0, NULL}, /*20*/
225 {0, NULL},
226 {0, NULL},
227 {0, &rtw_cpwm_event_callback23a},
228 {0, NULL},
229};
230
231
232/*
233 * Search the @param channel_num in given @param channel_set
234 * @ch_set: the given channel set
235 * @ch: the given channel number
236 *
237 * return the index of channel_num in channel_set, -1 if not found
238 */
239int rtw_ch_set_search_ch23a(struct rt_channel_info *ch_set, const u32 ch)
240{
241 int i;
242 for (i = 0; ch_set[i]. ChannelNum != 0; i++) {
243 if (ch == ch_set[i].ChannelNum)
244 break;
245 }
246
247 if (i >= ch_set[i].ChannelNum)
248 return -1;
249 return i;
250}
251
252/****************************************************************************
253
254Following are the initialization functions for WiFi MLME
255
256*****************************************************************************/
257
258int init_hw_mlme_ext23a(struct rtw_adapter *padapter)
259{
260 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
261
262 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
263 pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
264 return _SUCCESS;
265}
266
267static void init_mlme_ext_priv23a_value(struct rtw_adapter* padapter)
268{
269 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
270 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
271 unsigned char mixed_datarate[NumRates] = {
272 _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
273 _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_,
274 _48M_RATE_, _54M_RATE_, 0xff};
275 unsigned char mixed_basicrate[NumRates] = {
276 _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
277 _12M_RATE_, _24M_RATE_, 0xff,};
278
279 atomic_set(&pmlmeext->event_seq, 0);
280 /* reset to zero when disconnect at client mode */
281 pmlmeext->mgnt_seq = 0;
282
283 pmlmeext->cur_channel = padapter->registrypriv.channel;
284 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
285 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
286
287 pmlmeext->retry = 0;
288
289 pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
290
291 memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
292 memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
293
294 if (pmlmeext->cur_channel > 14)
295 pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB;
296 else
297 pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
298
299 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
300 pmlmeext->sitesurvey_res.channel_idx = 0;
301 pmlmeext->sitesurvey_res.bss_cnt = 0;
302 pmlmeext->scan_abort = false;
303
304 pmlmeinfo->state = WIFI_FW_NULL_STATE;
305 pmlmeinfo->reauth_count = 0;
306 pmlmeinfo->reassoc_count = 0;
307 pmlmeinfo->link_count = 0;
308 pmlmeinfo->auth_seq = 0;
309 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
310 pmlmeinfo->key_index = 0;
311 pmlmeinfo->iv = 0;
312
313 pmlmeinfo->enc_algo = _NO_PRIVACY_;
314 pmlmeinfo->authModeToggle = 0;
315
316 memset(pmlmeinfo->chg_txt, 0, 128);
317
318 pmlmeinfo->slotTime = SHORT_SLOT_TIME;
319 pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
320
321 pmlmeinfo->dialogToken = 0;
322
323 pmlmeext->action_public_rxseq = 0xffff;
324 pmlmeext->action_public_dialog_token = 0xff;
325}
326
327static int has_channel(struct rt_channel_info *channel_set,
328 u8 chanset_size, u8 chan) {
329 int i;
330
331 for (i = 0; i < chanset_size; i++) {
332 if (channel_set[i].ChannelNum == chan)
333 return 1;
334 }
335
336 return 0;
337}
338
339static void init_channel_list(struct rtw_adapter *padapter,
340 struct rt_channel_info *channel_set,
341 u8 chanset_size,
342 struct p2p_channels *channel_list) {
343
344 struct p2p_oper_class_map op_class[] = {
345 { IEEE80211G, 81, 1, 13, 1, BW20 },
346 { IEEE80211G, 82, 14, 14, 1, BW20 },
347 { IEEE80211A, 115, 36, 48, 4, BW20 },
348 { IEEE80211A, 116, 36, 44, 8, BW40PLUS },
349 { IEEE80211A, 117, 40, 48, 8, BW40MINUS },
350 { IEEE80211A, 124, 149, 161, 4, BW20 },
351 { IEEE80211A, 125, 149, 169, 4, BW20 },
352 { IEEE80211A, 126, 149, 157, 8, BW40PLUS },
353 { IEEE80211A, 127, 153, 161, 8, BW40MINUS },
354 { -1, 0, 0, 0, 0, BW20 }
355 };
356
357 int cla, op;
358
359 cla = 0;
360
361 for (op = 0; op_class[op].op_class; op++) {
362 u8 ch;
363 struct p2p_oper_class_map *o = &op_class[op];
364 struct p2p_reg_class *reg = NULL;
365
366 for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
367 if (!has_channel(channel_set, chanset_size, ch))
368 continue;
369
370 if ((0 == padapter->registrypriv.ht_enable) &&
371 (o->inc == 8))
372 continue;
373
374 if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) &&
375 ((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
376 continue;
377
378 if (reg == NULL) {
379 reg = &channel_list->reg_class[cla];
380 cla++;
381 reg->reg_class = o->op_class;
382 reg->channels = 0;
383 }
384 reg->channel[reg->channels] = ch;
385 reg->channels++;
386 }
387 }
388 channel_list->reg_classes = cla;
389}
390
391static u8 init_channel_set(struct rtw_adapter* padapter, u8 ChannelPlan,
392 struct rt_channel_info *channel_set)
393{
394 u8 index, chanset_size = 0;
395 u8 b5GBand = false, b2_4GBand = false;
396 u8 Index2G = 0, Index5G = 0;
397
398 memset(channel_set, 0, sizeof(struct rt_channel_info)*MAX_CHANNEL_NUM);
399
400 if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX &&
401 ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
402 DBG_8723A("ChannelPlan ID %x error !!!!!\n", ChannelPlan);
403 return chanset_size;
404 }
405
406 if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
407 b2_4GBand = true;
408 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
409 Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
410 else
411 Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
412 }
413
414 if (padapter->registrypriv.wireless_mode & WIRELESS_11A) {
415 b5GBand = true;
416 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
417 Index5G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index5G;
418 else
419 Index5G = RTW_ChannelPlanMap[ChannelPlan].Index5G;
420 }
421
422 if (b2_4GBand) {
423 for (index = 0; index<RTW_ChannelPlan2G[Index2G].Len; index++) {
424 channel_set[chanset_size].ChannelNum =
425 RTW_ChannelPlan2G[Index2G].Channel[index];
426
427 if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||
428 /* Channel 1~11 is active, and 12~14 is passive */
429 (RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == ChannelPlan)){
430 if (channel_set[chanset_size].ChannelNum >= 1 &&
431 channel_set[chanset_size].ChannelNum <= 11)
432 channel_set[chanset_size].ScanType =
433 SCAN_ACTIVE;
434 else if ((channel_set[chanset_size].ChannelNum >= 12 &&
435 channel_set[chanset_size].ChannelNum <= 14))
436 channel_set[chanset_size].ScanType =
437 SCAN_PASSIVE;
438 } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 ==
439 ChannelPlan ||
440 RT_CHANNEL_DOMAIN_WORLD_WIDE_5G ==
441 ChannelPlan ||
442 RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) {
443 /* channel 12~13, passive scan */
444 if (channel_set[chanset_size].ChannelNum <= 11)
445 channel_set[chanset_size].ScanType =
446 SCAN_ACTIVE;
447 else
448 channel_set[chanset_size].ScanType =
449 SCAN_PASSIVE;
450 } else
451 channel_set[chanset_size].ScanType =
452 SCAN_ACTIVE;
453
454 chanset_size++;
455 }
456 }
457
458 if (b5GBand) {
459 for (index = 0;index<RTW_ChannelPlan5G[Index5G].Len;index++) {
460 if (RTW_ChannelPlan5G[Index5G].Channel[index] <= 48 ||
461 RTW_ChannelPlan5G[Index5G].Channel[index] >= 149) {
462 channel_set[chanset_size].ChannelNum =
463 RTW_ChannelPlan5G[Index5G].Channel[index];
464 if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G ==
465 ChannelPlan) {
466 /* passive scan for all 5G channels */
467 channel_set[chanset_size].ScanType =
468 SCAN_PASSIVE;
469 } else
470 channel_set[chanset_size].ScanType =
471 SCAN_ACTIVE;
472 DBG_8723A("%s(): channel_set[%d].ChannelNum = "
473 "%d\n", __func__, chanset_size,
474 channel_set[chanset_size].ChannelNum);
475 chanset_size++;
476 }
477 }
478 }
479
480 return chanset_size;
481}
482
483int init_mlme_ext_priv23a(struct rtw_adapter* padapter)
484{
485 int res = _SUCCESS;
486 struct registry_priv* pregistrypriv = &padapter->registrypriv;
487 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
488 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
489 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
490
491 pmlmeext->padapter = padapter;
492
493 init_mlme_ext_priv23a_value(padapter);
494 pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
495
496 init_mlme_ext_timer23a(padapter);
497
498#ifdef CONFIG_8723AU_AP_MODE
499 init_mlme_ap_info23a(padapter);
500#endif
501
502 pmlmeext->max_chan_nums = init_channel_set(padapter,
503 pmlmepriv->ChannelPlan,
504 pmlmeext->channel_set);
505 init_channel_list(padapter, pmlmeext->channel_set,
506 pmlmeext->max_chan_nums, &pmlmeext->channel_list);
507
508 pmlmeext->chan_scan_time = SURVEY_TO;
509 pmlmeext->mlmeext_init = true;
510
511 pmlmeext->active_keep_alive_check = true;
512 return res;
513}
514
515void free_mlme_ext_priv23a (struct mlme_ext_priv *pmlmeext)
516{
517 struct rtw_adapter *padapter = pmlmeext->padapter;
518
519 if (!padapter)
520 return;
521
522 if (padapter->bDriverStopped == true) {
523 del_timer_sync(&pmlmeext->survey_timer);
524 del_timer_sync(&pmlmeext->link_timer);
525 /* del_timer_sync(&pmlmeext->ADDBA_timer); */
526 }
527}
528
529static void
530_mgt_dispatcher23a(struct rtw_adapter *padapter, struct mlme_handler *ptable,
531 struct recv_frame *precv_frame)
532{
533 struct sk_buff *skb = precv_frame->pkt;
534 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
535
536 if (ptable->func) {
537 /* receive the frames that ra(a1) is my address
538 or ra(a1) is bc address. */
539 if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv))&&
540 !is_broadcast_ether_addr(hdr->addr1))
541 return;
542
543 ptable->func(padapter, precv_frame);
544 }
545}
546
547void mgt_dispatcher23a(struct rtw_adapter *padapter,
548 struct recv_frame *precv_frame)
549{
550 int index;
551 struct mlme_handler *ptable;
552#ifdef CONFIG_8723AU_AP_MODE
553 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
554#endif /* CONFIG_8723AU_AP_MODE */
555 struct sk_buff *skb = precv_frame->pkt;
556 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
557 u16 stype;
558 struct sta_info *psta;
559
560 if (!ieee80211_is_mgmt(hdr->frame_control))
561 return;
562
563 /* receive the frames that ra(a1) is my address or ra(a1) is
564 bc address. */
565 if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv)) &&
566 !is_broadcast_ether_addr(hdr->addr1))
567 return;
568
569 ptable = mlme_sta_tbl;
570
571 stype = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE;
572 index = stype >> 4;
573
574 if (index > 13) {
575 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
576 ("Currently we do not support reserved sub-fr-type ="
577 "%d\n", index));
578 return;
579 }
580 ptable += index;
581
582 psta = rtw_get_stainfo23a(&padapter->stapriv, hdr->addr2);
583
584 if (psta) {
585 if (ieee80211_has_retry(hdr->frame_control)) {
586 if (precv_frame->attrib.seq_num ==
587 psta->RxMgmtFrameSeqNum) {
588 /* drop the duplicate management frame */
589 DBG_8723A("Drop duplicate management frame "
590 "with seq_num = %d.\n",
591 precv_frame->attrib.seq_num);
592 return;
593 }
594 }
595 psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num;
596 }
597
598#ifdef CONFIG_8723AU_AP_MODE
599 switch (stype)
600 {
601 case IEEE80211_STYPE_AUTH:
602 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
603 ptable->func = &OnAuth23a;
604 else
605 ptable->func = &OnAuth23aClient23a;
606 /* pass through */
607 case IEEE80211_STYPE_ASSOC_REQ:
608 case IEEE80211_STYPE_REASSOC_REQ:
609 _mgt_dispatcher23a(padapter, ptable, precv_frame);
610 break;
611 case IEEE80211_STYPE_PROBE_REQ:
612 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
613 _mgt_dispatcher23a(padapter, ptable, precv_frame);
614 else
615 _mgt_dispatcher23a(padapter, ptable, precv_frame);
616 break;
617 case IEEE80211_STYPE_BEACON:
618 _mgt_dispatcher23a(padapter, ptable, precv_frame);
619 break;
620 case IEEE80211_STYPE_ACTION:
621 /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) */
622 _mgt_dispatcher23a(padapter, ptable, precv_frame);
623 break;
624 default:
625 _mgt_dispatcher23a(padapter, ptable, precv_frame);
626 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
627 rtw_hostapd_mlme_rx23a(padapter, precv_frame);
628 break;
629 }
630#else
631 _mgt_dispatcher23a(padapter, ptable, precv_frame);
632#endif
633}
634
635#ifdef CONFIG_8723AU_P2P
636static u32 p2p_listen_state_process(struct rtw_adapter *padapter,
637 unsigned char *da)
638{
639 bool response = true;
640
641 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == false ||
642 padapter->mlmepriv.wps_probe_resp_ie == NULL ||
643 padapter->mlmepriv.p2p_probe_resp_ie == NULL) {
644 DBG_8723A("DON'T issue_probersp23a_p2p23a: p2p_enabled:%d, "
645 "wps_probe_resp_ie:%p, p2p_probe_resp_ie:%p\n",
646 wdev_to_priv(padapter->rtw_wdev)->p2p_enabled,
647 padapter->mlmepriv.wps_probe_resp_ie,
648 padapter->mlmepriv.p2p_probe_resp_ie);
649 response = false;
650 }
651
652 if (response == true)
653 issue_probersp23a_p2p23a(padapter, da);
654
655 return _SUCCESS;
656}
657#endif /* CONFIG_8723AU_P2P */
658
659/****************************************************************************
660
661Following are the callback functions for each subtype of the management frames
662
663*****************************************************************************/
664
665unsigned int OnProbeReq23a(struct rtw_adapter *padapter,
666 struct recv_frame *precv_frame)
667{
668 unsigned int ielen;
669 unsigned char *p;
670 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
671 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
672 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
673 struct wlan_bssid_ex *cur = &pmlmeinfo->network;
674 struct sk_buff *skb = precv_frame->pkt;
675 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
676 u8 *pframe = skb->data;
677 uint len = skb->len;
678 u8 is_valid_p2p_probereq = false;
679
680#ifdef CONFIG_8723AU_P2P
681 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
682 u8 wifi_test_chk_rate = 1;
683
684 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&
685 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE) &&
686 !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) &&
687 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH) &&
688 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)) {
689 /* mcs_rate = 0 -> CCK 1M rate */
690 /* mcs_rate = 1 -> CCK 2M rate */
691 /* mcs_rate = 2 -> CCK 5.5M rate */
692 /* mcs_rate = 3 -> CCK 11M rate */
693 /* In the P2P mode, the driver should not support
694 the CCK rate */
695
696 /* IOT issue: Google Nexus7 use 1M rate to send
697 p2p_probe_req after GO nego completed and Nexus7
698 is client */
699 if (wifi_test_chk_rate == 1) {
700 if ((is_valid_p2p_probereq =
701 process_probe_req_p2p_ie23a(pwdinfo, pframe,
702 len)) == true) {
703 if (rtw_p2p_chk_role(pwdinfo,
704 P2P_ROLE_DEVICE)) {
705 u8 *sa = ieee80211_get_SA(hdr);
706 p2p_listen_state_process(padapter, sa);
707 return _SUCCESS;
708 }
709
710 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
711 goto _continue;
712 }
713 }
714 }
715 }
716
717_continue:
718#endif /* CONFIG_8723AU_P2P */
719
720 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
721 return _SUCCESS;
722 }
723
724 if (check_fwstate(pmlmepriv, _FW_LINKED) == false &&
725 check_fwstate(pmlmepriv,
726 WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE) == false) {
727 return _SUCCESS;
728 }
729
730 p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) +
731 _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen,
732 len - sizeof(struct ieee80211_hdr_3addr) -
733 _PROBEREQ_IE_OFFSET_);
734
735 /* check (wildcard) SSID */
736 if (p) {
737 if (is_valid_p2p_probereq == true) {
738 goto _issue_probersp23a;
739 }
740
741 if ((ielen != 0 &&
742 memcmp((void *)(p+2), cur->Ssid.ssid,
743 cur->Ssid.ssid_len)) ||
744 (ielen == 0 && pmlmeinfo->hidden_ssid_mode)) {
745 return _SUCCESS;
746 }
747
748_issue_probersp23a:
749
750 if (check_fwstate(pmlmepriv, _FW_LINKED) == true &&
751 pmlmepriv->cur_network.join_res == true) {
752 /* DBG_8723A("+issue_probersp23a during ap mode\n"); */
753 issue_probersp23a(padapter, ieee80211_get_SA(hdr),
754 is_valid_p2p_probereq);
755 }
756 }
757
758 return _SUCCESS;
759}
760
761unsigned int OnProbeRsp23a(struct rtw_adapter *padapter,
762 struct recv_frame *precv_frame)
763{
764 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
765 struct sk_buff *skb = precv_frame->pkt;
766 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
767#ifdef CONFIG_8723AU_P2P
768 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
769#endif
770
771#ifdef CONFIG_8723AU_P2P
772 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
773 if (pwdinfo->tx_prov_disc_info.benable == true) {
774 if (ether_addr_equal(pwdinfo->tx_prov_disc_info.peerIFAddr,
775 hdr->addr2)) {
776 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
777 pwdinfo->tx_prov_disc_info.benable = false;
778 issue_p2p_provision_request23a(padapter,
779 pwdinfo->tx_prov_disc_info.ssid.ssid,
780 pwdinfo->tx_prov_disc_info.ssid.ssid_len,
781 pwdinfo->tx_prov_disc_info.peerDevAddr);
782 }
783 else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
784 {
785 pwdinfo->tx_prov_disc_info.benable = false;
786 issue_p2p_provision_request23a(padapter,
787 NULL,
788 0,
789 pwdinfo->tx_prov_disc_info.peerDevAddr);
790 }
791 }
792 }
793 return _SUCCESS;
794 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
795 if (pwdinfo->nego_req_info.benable == true) {
796 DBG_8723A("[%s] P2P State is GONEGO ING!\n", __func__);
797 if (ether_addr_equal(pwdinfo->nego_req_info.peerDevAddr,
798 hdr->addr2)) {
799 pwdinfo->nego_req_info.benable = false;
800 issue_p2p_GO_request23a(padapter, pwdinfo->nego_req_info.peerDevAddr);
801 }
802 }
803 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {
804 if (pwdinfo->invitereq_info.benable == true) {
805 DBG_8723A("[%s] P2P_STATE_TX_INVITE_REQ!\n", __func__);
806 if (ether_addr_equal(
807 pwdinfo->invitereq_info.peer_macaddr,
808 hdr->addr2)) {
809 pwdinfo->invitereq_info.benable = false;
810 issue_p2p_invitation_request23a(padapter, pwdinfo->invitereq_info.peer_macaddr);
811 }
812 }
813 }
814#endif
815
816 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
817 report_survey_event23a(padapter, precv_frame);
818 return _SUCCESS;
819 }
820
821 return _SUCCESS;
822}
823
824unsigned int OnBeacon23a(struct rtw_adapter *padapter,
825 struct recv_frame *precv_frame)
826{
827 int cam_idx;
828 struct sta_info *psta;
829 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
830 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
831 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
832 struct sta_priv *pstapriv = &padapter->stapriv;
833 struct sk_buff *skb = precv_frame->pkt;
834 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
835 u8 *pframe = skb->data;
836 uint len = skb->len;
837 struct wlan_bssid_ex *pbss;
838 int ret = _SUCCESS;
839 u8 *p = NULL;
840 u32 ielen = 0;
841
842 p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) +
843 _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ielen,
844 len - sizeof(struct ieee80211_hdr_3addr) -
845 _BEACON_IE_OFFSET_);
846 if ((p != NULL) && (ielen > 0)) {
847 if ((*(p + 1 + ielen) == 0x2D) && (*(p + 2 + ielen) != 0x2D)) {
848 /* Invalid value 0x2D is detected in Extended Supported
849 * Rates (ESR) IE. Try to fix the IE length to avoid
850 * failed Beacon parsing.
851 */
852 DBG_8723A("[WIFIDBG] Error in ESR IE is detected in "
853 "Beacon of BSSID: %pM. Fix the length of "
854 "ESR IE to avoid failed Beacon parsing.\n",
855 hdr->addr3);
856 *(p + 1) = ielen - 1;
857 }
858 }
859
860 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
861 report_survey_event23a(padapter, precv_frame);
862 return _SUCCESS;
863 }
864
865 if (ether_addr_equal(hdr->addr3, get_my_bssid23a(&pmlmeinfo->network))){
866 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
867 /* we should update current network before auth,
868 or some IE is wrong */
869 pbss = (struct wlan_bssid_ex *)
870 kmalloc(sizeof(struct wlan_bssid_ex),
871 GFP_ATOMIC);
872 if (pbss) {
873 if (collect_bss_info23a(padapter, precv_frame,
874 pbss) == _SUCCESS) {
875 update_network23a(&pmlmepriv->cur_network.network, pbss, padapter, true);
876 rtw_get_bcn_info23a(&pmlmepriv->cur_network);
877 }
878 kfree(pbss);
879 }
880
881 /* check the vendor of the assoc AP */
882 pmlmeinfo->assoc_AP_vendor = check_assoc_AP23a(pframe + sizeof(struct ieee80211_hdr_3addr), len-sizeof(struct ieee80211_hdr_3addr));
883
884 /* update TSF Value */
885 update_TSF23a(pmlmeext, pframe, len);
886
887 /* start auth */
888 start_clnt_auth23a(padapter);
889
890 return _SUCCESS;
891 }
892
893 if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) &&
894 (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
895 psta = rtw_get_stainfo23a(pstapriv, hdr->addr2);
896 if (psta) {
897 ret = rtw_check_bcn_info23a(padapter, pframe,
898 len);
899 if (!ret) {
900 DBG_8723A_LEVEL(_drv_always_,
901 "ap has changed, "
902 "disconnect now\n");
903 receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress, 65535);
904 return _SUCCESS;
905 }
906 /* update WMM, ERP in the beacon */
907 /* todo: the timer is used instead of
908 the number of the beacon received */
909 if ((sta_rx_pkts(psta) & 0xf) == 0) {
910 /* DBG_8723A("update_bcn_info\n"); */
911 update_beacon23a_info(padapter, pframe,
912 len, psta);
913 }
914
915#ifdef CONFIG_8723AU_P2P
916 process_p2p_ps_ie23a(padapter, (pframe + sizeof(struct ieee80211_hdr_3addr)), (len - sizeof(struct ieee80211_hdr_3addr)));
917#endif /* CONFIG_8723AU_P2P */
918 }
919 } else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
920 psta = rtw_get_stainfo23a(pstapriv, hdr->addr2);
921 if (psta) {
922 /* update WMM, ERP in the beacon */
923 /* todo: the timer is used instead of the
924 number of the beacon received */
925 if ((sta_rx_pkts(psta) & 0xf) == 0) {
926 /* DBG_8723A("update_bcn_info\n"); */
927 update_beacon23a_info(padapter, pframe,
928 len, psta);
929 }
930 } else {
931 /* allocate a new CAM entry for IBSS station */
932 cam_idx = allocate_fw_sta_entry23a(padapter);
933 if (cam_idx == NUM_STA)
934 goto _END_ONBEACON_;
935
936 /* get supported rate */
937 if (update_sta_support_rate23a(padapter, (pframe + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_), (len - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_), cam_idx) == _FAIL) {
938 pmlmeinfo->FW_sta_info[cam_idx].status = 0;
939 goto _END_ONBEACON_;
940 }
941
942 /* update TSF Value */
943 update_TSF23a(pmlmeext, pframe, len);
944
945 /* report sta add event */
946 report_add_sta_event23a(padapter, hdr->addr2,
947 cam_idx);
948 }
949 }
950 }
951
952_END_ONBEACON_:
953
954 return _SUCCESS;
955}
956
957unsigned int OnAuth23a(struct rtw_adapter *padapter,
958 struct recv_frame *precv_frame)
959{
960#ifdef CONFIG_8723AU_AP_MODE
961 unsigned int auth_mode, seq, ie_len;
962 unsigned char *sa, *p;
963 u16 algorithm;
964 int status;
965 static struct sta_info stat;
966 struct sta_info *pstat = NULL;
967 struct sta_priv *pstapriv = &padapter->stapriv;
968 struct security_priv *psecuritypriv = &padapter->securitypriv;
969 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
970 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
971 struct sk_buff *skb = precv_frame->pkt;
972 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
973 u8 *pframe = skb->data;
974 uint len = skb->len;
975
976 if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
977 return _FAIL;
978
979 DBG_8723A("+OnAuth23a\n");
980
981 sa = hdr->addr2;
982
983 auth_mode = psecuritypriv->dot11AuthAlgrthm;
984 seq = cpu_to_le16(*(u16*)((unsigned long)pframe +
985 sizeof(struct ieee80211_hdr_3addr) + 2));
986 algorithm = cpu_to_le16(*(u16*)((unsigned long)pframe +
987 sizeof(struct ieee80211_hdr_3addr)));
988
989 DBG_8723A("auth alg =%x, seq =%X\n", algorithm, seq);
990
991 if (auth_mode == 2 &&
992 psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
993 psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
994 auth_mode = 0;
995
996 /* rx a shared-key auth but shared not enabled, or */
997 /* rx a open-system auth but shared-key is enabled */
998 if ((algorithm > 0 && auth_mode == 0) ||
999 (algorithm == 0 && auth_mode == 1)) {
1000 DBG_8723A("auth rejected due to bad alg [alg =%d, auth_mib "
1001 "=%d] %02X%02X%02X%02X%02X%02X\n",
1002 algorithm, auth_mode,
1003 sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
1004
1005 status = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1006
1007 goto auth_fail;
1008 }
1009
1010 if (rtw_access_ctrl23a(padapter, sa) == false) {
1011 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1012 goto auth_fail;
1013 }
1014
1015 pstat = rtw_get_stainfo23a(pstapriv, sa);
1016 if (!pstat) {
1017 /* allocate a new one */
1018 DBG_8723A("going to alloc stainfo for sa ="MAC_FMT"\n",
1019 MAC_ARG(sa));
1020 pstat = rtw_alloc_stainfo23a(pstapriv, sa);
1021 if (!pstat) {
1022 DBG_8723A(" Exceed the upper limit of supported "
1023 "clients...\n");
1024 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1025 goto auth_fail;
1026 }
1027
1028 pstat->state = WIFI_FW_AUTH_NULL;
1029 pstat->auth_seq = 0;
1030
1031 /* pstat->flags = 0; */
1032 /* pstat->capability = 0; */
1033 } else {
1034 spin_lock_bh(&pstapriv->asoc_list_lock);
1035 if (!list_empty(&pstat->asoc_list)) {
1036 list_del_init(&pstat->asoc_list);
1037 pstapriv->asoc_list_cnt--;
1038 if (pstat->expire_to > 0)
1039 {
1040 /* TODO: STA re_auth within expire_to */
1041 }
1042 }
1043 spin_unlock_bh(&pstapriv->asoc_list_lock);
1044
1045 if (seq == 1) {
1046 /* TODO: STA re_auth and auth timeout */
1047 }
1048 }
1049
1050 spin_lock_bh(&pstapriv->auth_list_lock);
1051 if (list_empty(&pstat->auth_list)) {
1052 list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
1053 pstapriv->auth_list_cnt++;
1054 }
1055 spin_unlock_bh(&pstapriv->auth_list_lock);
1056
1057 if (pstat->auth_seq == 0)
1058 pstat->expire_to = pstapriv->auth_to;
1059
1060 if ((pstat->auth_seq + 1) != seq) {
1061 DBG_8723A("(1)auth rejected because out of seq [rx_seq =%d, "
1062 "exp_seq =%d]!\n", seq, pstat->auth_seq+1);
1063 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1064 goto auth_fail;
1065 }
1066
1067 if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2)) {
1068 if (seq == 1) {
1069 pstat->state &= ~WIFI_FW_AUTH_NULL;
1070 pstat->state |= WIFI_FW_AUTH_SUCCESS;
1071 pstat->expire_to = pstapriv->assoc_to;
1072 pstat->authalg = algorithm;
1073 } else {
1074 DBG_8723A("(2)auth rejected because out of seq "
1075 "[rx_seq =%d, exp_seq =%d]!\n",
1076 seq, pstat->auth_seq+1);
1077 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1078 goto auth_fail;
1079 }
1080 } else { /* shared system or auto authentication */
1081 if (seq == 1) {
1082 /* prepare for the challenging txt... */
1083 pstat->state &= ~WIFI_FW_AUTH_NULL;
1084 pstat->state |= WIFI_FW_AUTH_STATE;
1085 pstat->authalg = algorithm;
1086 pstat->auth_seq = 2;
1087 } else if (seq == 3) {
1088 /* checking for challenging txt... */
1089 DBG_8723A("checking for challenging txt...\n");
1090
1091 p = rtw_get_ie23a(pframe +
1092 sizeof(struct ieee80211_hdr_3addr) +
1093 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_,
1094 (int *)&ie_len, len -
1095 sizeof(struct ieee80211_hdr_3addr) -
1096 _AUTH_IE_OFFSET_ - 4);
1097
1098 if ((p == NULL) || (ie_len<= 0)) {
1099 DBG_8723A("auth rejected because challenge "
1100 "failure!(1)\n");
1101 status = WLAN_STATUS_CHALLENGE_FAIL;
1102 goto auth_fail;
1103 }
1104
1105 if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
1106 pstat->state &= (~WIFI_FW_AUTH_STATE);
1107 pstat->state |= WIFI_FW_AUTH_SUCCESS;
1108 /* challenging txt is correct... */
1109 pstat->expire_to = pstapriv->assoc_to;
1110 } else {
1111 DBG_8723A("auth rejected because challenge "
1112 "failure!\n");
1113 status = WLAN_STATUS_CHALLENGE_FAIL;
1114 goto auth_fail;
1115 }
1116 } else {
1117 DBG_8723A("(3)auth rejected because out of seq "
1118 "[rx_seq =%d, exp_seq =%d]!\n",
1119 seq, pstat->auth_seq+1);
1120 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1121 goto auth_fail;
1122 }
1123 }
1124
1125 /* Now, we are going to issue_auth23a... */
1126 pstat->auth_seq = seq + 1;
1127
1128 issue_auth23a(padapter, pstat, (unsigned short)WLAN_STATUS_SUCCESS);
1129
1130 if (pstat->state & WIFI_FW_AUTH_SUCCESS)
1131 pstat->auth_seq = 0;
1132
1133 return _SUCCESS;
1134
1135auth_fail:
1136
1137 if (pstat)
1138 rtw_free_stainfo23a(padapter, pstat);
1139
1140 pstat = &stat;
1141 memset((char *)pstat, '\0', sizeof(stat));
1142 pstat->auth_seq = 2;
1143 memcpy(pstat->hwaddr, sa, 6);
1144
1145 issue_auth23a(padapter, pstat, (unsigned short)status);
1146
1147#endif
1148 return _FAIL;
1149}
1150
1151unsigned int OnAuth23aClient23a(struct rtw_adapter *padapter,
1152 struct recv_frame *precv_frame)
1153{
1154 unsigned int seq, len, status, algthm, offset;
1155 unsigned char *p;
1156 unsigned int go2asoc = 0;
1157 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1158 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1159 struct sk_buff *skb = precv_frame->pkt;
1160 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1161 u8 *pframe = skb->data;
1162 uint pkt_len = skb->len;
1163
1164 DBG_8723A("%s\n", __func__);
1165
1166 /* check A1 matches or not */
1167 if (!ether_addr_equal(myid(&padapter->eeprompriv),
1168 ieee80211_get_DA(hdr)))
1169 return _SUCCESS;
1170
1171 if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
1172 return _SUCCESS;
1173
1174 offset = ieee80211_has_protected(hdr->frame_control) ? 4: 0;
1175
1176 algthm = le16_to_cpu(*(unsigned short *)((unsigned long)pframe + sizeof(struct ieee80211_hdr_3addr) + offset));
1177 seq = le16_to_cpu(*(unsigned short *)((unsigned long)pframe + sizeof(struct ieee80211_hdr_3addr) + offset + 2));
1178 status = le16_to_cpu(*(unsigned short *)((unsigned long)pframe + sizeof(struct ieee80211_hdr_3addr) + offset + 4));
1179
1180 if (status != 0)
1181 {
1182 DBG_8723A("clnt auth fail, status: %d\n", status);
1183 if (status == 13)/* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
1184 {
1185 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1186 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
1187 else
1188 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
1189 /* pmlmeinfo->reauth_count = 0; */
1190 }
1191
1192 set_link_timer(pmlmeext, 1);
1193 goto authclnt_fail;
1194 }
1195
1196 if (seq == 2)
1197 {
1198 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1199 {
1200 /* legendary shared system */
1201 p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,
1202 pkt_len - sizeof(struct ieee80211_hdr_3addr) - _AUTH_IE_OFFSET_);
1203
1204 if (p == NULL)
1205 {
1206 /* DBG_8723A("marc: no challenge text?\n"); */
1207 goto authclnt_fail;
1208 }
1209
1210 memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
1211 pmlmeinfo->auth_seq = 3;
1212 issue_auth23a(padapter, NULL, 0);
1213 set_link_timer(pmlmeext, REAUTH_TO);
1214
1215 return _SUCCESS;
1216 }
1217 else
1218 {
1219 /* open system */
1220 go2asoc = 1;
1221 }
1222 }
1223 else if (seq == 4)
1224 {
1225 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1226 {
1227 go2asoc = 1;
1228 }
1229 else
1230 {
1231 goto authclnt_fail;
1232 }
1233 }
1234 else
1235 {
1236 /* this is also illegal */
1237 /* DBG_8723A("marc: clnt auth failed due to illegal seq =%x\n", seq); */
1238 goto authclnt_fail;
1239 }
1240
1241 if (go2asoc)
1242 {
1243 DBG_8723A_LEVEL(_drv_always_, "auth success, start assoc\n");
1244 start_clnt_assoc23a(padapter);
1245 return _SUCCESS;
1246 }
1247
1248authclnt_fail:
1249
1250 /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */
1251
1252 return _FAIL;
1253}
1254
1255unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1256{
1257#ifdef CONFIG_8723AU_AP_MODE
1258 u16 capab_info, listen_interval;
1259 struct rtw_ieee802_11_elems elems;
1260 struct sta_info *pstat;
1261 unsigned char reassoc, *p, *pos, *wpa_ie;
1262 unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
1263 int i, ie_len, wpa_ie_len, left;
1264 unsigned char supportRate[16];
1265 int supportRateNum;
1266 unsigned short status = WLAN_STATUS_SUCCESS;
1267 unsigned short ie_offset;
1268 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1269 struct security_priv *psecuritypriv = &padapter->securitypriv;
1270 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1271 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1272 struct wlan_bssid_ex *cur = &pmlmeinfo->network;
1273 struct sta_priv *pstapriv = &padapter->stapriv;
1274 struct sk_buff *skb = precv_frame->pkt;
1275 u8 *pframe = skb->data;
1276 uint pkt_len = skb->len;
1277 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1278 u16 frame_control;
1279#ifdef CONFIG_8723AU_P2P
1280 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1281 u8 p2p_status_code = P2P_STATUS_SUCCESS;
1282 u8 *p2pie;
1283 u32 p2pielen = 0;
1284 u8 wfd_ie[ 128 ] = { 0x00 };
1285 u32 wfd_ielen = 0;
1286#endif /* CONFIG_8723AU_P2P */
1287
1288 if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1289 return _FAIL;
1290
1291 frame_control = hdr->frame_control;
1292 if (ieee80211_is_assoc_req(frame_control)) {
1293 reassoc = 0;
1294 ie_offset = _ASOCREQ_IE_OFFSET_;
1295 } else { /* WIFI_REASSOCREQ */
1296 reassoc = 1;
1297 ie_offset = _REASOCREQ_IE_OFFSET_;
1298 }
1299
1300 if (pkt_len < sizeof(struct ieee80211_hdr_3addr) + ie_offset) {
1301 DBG_8723A("handle_assoc(reassoc =%d) - too short payload (len =%lu)"
1302 "\n", reassoc, (unsigned long)pkt_len);
1303 return _FAIL;
1304 }
1305
1306 pstat = rtw_get_stainfo23a(pstapriv, hdr->addr2);
1307 if (!pstat) {
1308 status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
1309 goto asoc_class2_error;
1310 }
1311
1312 capab_info = RTW_GET_LE16(pframe + sizeof(struct ieee80211_hdr_3addr));
1313 /* capab_info = le16_to_cpu(*(unsigned short *)(pframe + sizeof(struct ieee80211_hdr_3addr))); */
1314 /* listen_interval = le16_to_cpu(*(unsigned short *)(pframe + sizeof(struct ieee80211_hdr_3addr)+2)); */
1315 listen_interval = RTW_GET_LE16(pframe + sizeof(struct ieee80211_hdr_3addr)+2);
1316
1317 left = pkt_len - (sizeof(struct ieee80211_hdr_3addr) + ie_offset);
1318 pos = pframe + (sizeof(struct ieee80211_hdr_3addr) + ie_offset);
1319
1320 DBG_8723A("%s\n", __func__);
1321
1322 /* check if this stat has been successfully authenticated/assocated */
1323 if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS))
1324 {
1325 if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS))
1326 {
1327 status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
1328 goto asoc_class2_error;
1329 }
1330 else
1331 {
1332 pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
1333 pstat->state |= WIFI_FW_ASSOC_STATE;
1334 }
1335 }
1336 else
1337 {
1338 pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
1339 pstat->state |= WIFI_FW_ASSOC_STATE;
1340 }
1341
1342 pstat->capability = capab_info;
1343
1344 /* now parse all ieee802_11 ie to point to elems */
1345 if (rtw_ieee802_11_parse_elems23a(pos, left, &elems, 1) == ParseFailed ||
1346 !elems.ssid) {
1347 DBG_8723A("STA " MAC_FMT " sent invalid association request\n",
1348 MAC_ARG(pstat->hwaddr));
1349 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1350 goto OnAssocReq23aFail;
1351 }
1352
1353 /* now we should check all the fields... */
1354 /* checking SSID */
1355 p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset, _SSID_IE_, &ie_len,
1356 pkt_len - sizeof(struct ieee80211_hdr_3addr) - ie_offset);
1357 if (p == NULL)
1358 {
1359 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1360 }
1361
1362 if (ie_len == 0) /* broadcast ssid, however it is not allowed in assocreq */
1363 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1364 else {
1365 /* check if ssid match */
1366 if (memcmp((void *)(p+2), cur->Ssid.ssid, cur->Ssid.ssid_len))
1367 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1368
1369 if (ie_len != cur->Ssid.ssid_len)
1370 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1371 }
1372
1373 if (WLAN_STATUS_SUCCESS != status)
1374 goto OnAssocReq23aFail;
1375
1376 /* check if the supported rate is ok */
1377 p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - sizeof(struct ieee80211_hdr_3addr) - ie_offset);
1378 if (p == NULL) {
1379 DBG_8723A("Rx a sta assoc-req which supported rate is empty!\n");
1380 /* use our own rate set as statoin used */
1381 /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
1382 /* supportRateNum = AP_BSSRATE_LEN; */
1383
1384 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1385 goto OnAssocReq23aFail;
1386 } else {
1387 memcpy(supportRate, p+2, ie_len);
1388 supportRateNum = ie_len;
1389
1390 p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len,
1391 pkt_len - sizeof(struct ieee80211_hdr_3addr) - ie_offset);
1392 if (p != NULL) {
1393
1394 if (supportRateNum<= sizeof(supportRate))
1395 {
1396 memcpy(supportRate+supportRateNum, p+2, ie_len);
1397 supportRateNum += ie_len;
1398 }
1399 }
1400 }
1401
1402 /* todo: mask supportRate between AP & STA -> move to update raid */
1403 /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
1404
1405 /* update station supportRate */
1406 pstat->bssratelen = supportRateNum;
1407 memcpy(pstat->bssrateset, supportRate, supportRateNum);
1408 Update23aTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
1409
1410 /* check RSN/WPA/WPS */
1411 pstat->dot8021xalg = 0;
1412 pstat->wpa_psk = 0;
1413 pstat->wpa_group_cipher = 0;
1414 pstat->wpa2_group_cipher = 0;
1415 pstat->wpa_pairwise_cipher = 0;
1416 pstat->wpa2_pairwise_cipher = 0;
1417 memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
1418 if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
1419
1420 int group_cipher = 0, pairwise_cipher = 0;
1421
1422 wpa_ie = elems.rsn_ie;
1423 wpa_ie_len = elems.rsn_ie_len;
1424
1425 if (rtw_parse_wpa2_ie23a(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1426 pstat->dot8021xalg = 1;/* psk, todo:802.1x */
1427 pstat->wpa_psk |= BIT(1);
1428
1429 pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher;
1430 pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher;
1431
1432 if (!pstat->wpa2_group_cipher)
1433 status = WLAN_REASON_INVALID_GROUP_CIPHER;
1434
1435 if (!pstat->wpa2_pairwise_cipher)
1436 status = WLAN_REASON_INVALID_PAIRWISE_CIPHER;
1437 } else {
1438 status = WLAN_STATUS_INVALID_IE;
1439 }
1440
1441 } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
1442
1443 int group_cipher = 0, pairwise_cipher = 0;
1444
1445 wpa_ie = elems.wpa_ie;
1446 wpa_ie_len = elems.wpa_ie_len;
1447
1448 if (rtw_parse_wpa_ie23a(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1449 pstat->dot8021xalg = 1;/* psk, todo:802.1x */
1450 pstat->wpa_psk |= BIT(0);
1451
1452 pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher;
1453 pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher;
1454
1455 if (!pstat->wpa_group_cipher)
1456 status = WLAN_STATUS_INVALID_GROUP_CIPHER;
1457
1458 if (!pstat->wpa_pairwise_cipher)
1459 status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
1460
1461 } else {
1462 status = WLAN_STATUS_INVALID_IE;
1463 }
1464
1465 } else {
1466 wpa_ie = NULL;
1467 wpa_ie_len = 0;
1468 }
1469
1470 if (WLAN_STATUS_SUCCESS != status)
1471 goto OnAssocReq23aFail;
1472
1473 pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
1474 if (wpa_ie == NULL) {
1475 if (elems.wps_ie) {
1476 DBG_8723A("STA included WPS IE in "
1477 "(Re)Association Request - assume WPS is "
1478 "used\n");
1479 pstat->flags |= WLAN_STA_WPS;
1480 } else {
1481 DBG_8723A("STA did not include WPA/RSN IE "
1482 "in (Re)Association Request - possible WPS "
1483 "use\n");
1484 pstat->flags |= WLAN_STA_MAYBE_WPS;
1485 }
1486
1487 /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
1488 /* that the selected registrar of AP is _FLASE */
1489 if ((psecuritypriv->wpa_psk > 0) &&
1490 (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) {
1491 if (pmlmepriv->wps_beacon_ie) {
1492 u8 selected_registrar = 0;
1493
1494 rtw_get_wps_attr_content23a(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len,
1495 WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL);
1496
1497 if (!selected_registrar) {
1498 DBG_8723A("selected_registrar is false , or AP is not ready to do WPS\n");
1499
1500 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1501
1502 goto OnAssocReq23aFail;
1503 }
1504 }
1505 }
1506 } else {
1507 int copy_len;
1508
1509 if (psecuritypriv->wpa_psk == 0) {
1510 DBG_8723A("STA " MAC_FMT ": WPA/RSN IE in association "
1511 "request, but AP don't support WPA/RSN\n", MAC_ARG(pstat->hwaddr));
1512
1513 status = WLAN_STATUS_INVALID_IE;
1514
1515 goto OnAssocReq23aFail;
1516 }
1517
1518 if (elems.wps_ie) {
1519 DBG_8723A("STA included WPS IE in "
1520 "(Re)Association Request - WPS is "
1521 "used\n");
1522 pstat->flags |= WLAN_STA_WPS;
1523 copy_len = 0;
1524 } else {
1525 copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)):(wpa_ie_len+2);
1526 }
1527
1528 if (copy_len>0)
1529 memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
1530
1531 }
1532
1533 /* check if there is WMM IE & support WWM-PS */
1534 pstat->flags &= ~WLAN_STA_WME;
1535 pstat->qos_option = 0;
1536 pstat->qos_info = 0;
1537 pstat->has_legacy_ac = true;
1538 pstat->uapsd_vo = 0;
1539 pstat->uapsd_vi = 0;
1540 pstat->uapsd_be = 0;
1541 pstat->uapsd_bk = 0;
1542 if (pmlmepriv->qospriv.qos_option)
1543 {
1544 p = pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset; ie_len = 0;
1545 for (;;)
1546 {
1547 p = rtw_get_ie23a(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - sizeof(struct ieee80211_hdr_3addr) - ie_offset);
1548 if (p != NULL) {
1549 if (!memcmp(p+2, WMM_IE, 6)) {
1550
1551 pstat->flags |= WLAN_STA_WME;
1552
1553 pstat->qos_option = 1;
1554 pstat->qos_info = *(p+8);
1555
1556 pstat->max_sp_len = (pstat->qos_info>>5)&0x3;
1557
1558 if ((pstat->qos_info&0xf) != 0xf)
1559 pstat->has_legacy_ac = true;
1560 else
1561 pstat->has_legacy_ac = false;
1562
1563 if (pstat->qos_info&0xf)
1564 {
1565 if (pstat->qos_info&BIT(0))
1566 pstat->uapsd_vo = BIT(0)|BIT(1);
1567 else
1568 pstat->uapsd_vo = 0;
1569
1570 if (pstat->qos_info&BIT(1))
1571 pstat->uapsd_vi = BIT(0)|BIT(1);
1572 else
1573 pstat->uapsd_vi = 0;
1574
1575 if (pstat->qos_info&BIT(2))
1576 pstat->uapsd_bk = BIT(0)|BIT(1);
1577 else
1578 pstat->uapsd_bk = 0;
1579
1580 if (pstat->qos_info&BIT(3))
1581 pstat->uapsd_be = BIT(0)|BIT(1);
1582 else
1583 pstat->uapsd_be = 0;
1584
1585 }
1586
1587 break;
1588 }
1589 }
1590 else {
1591 break;
1592 }
1593 p = p + ie_len + 2;
1594 }
1595 }
1596
1597 /* save HT capabilities in the sta object */
1598 memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap));
1599 if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap))
1600 {
1601 pstat->flags |= WLAN_STA_HT;
1602
1603 pstat->flags |= WLAN_STA_WME;
1604
1605 memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct ieee80211_ht_cap));
1606
1607 } else
1608 pstat->flags &= ~WLAN_STA_HT;
1609
1610 if ((pmlmepriv->htpriv.ht_option == false) && (pstat->flags&WLAN_STA_HT))
1611 {
1612 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1613 goto OnAssocReq23aFail;
1614 }
1615
1616 if ((pstat->flags & WLAN_STA_HT) &&
1617 ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
1618 (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP)))
1619 {
1620 DBG_8723A("HT: " MAC_FMT " tried to "
1621 "use TKIP with HT association\n", MAC_ARG(pstat->hwaddr));
1622
1623 /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
1624 /* goto OnAssocReq23aFail; */
1625 }
1626
1627 /* */
1628 pstat->flags |= WLAN_STA_NONERP;
1629 for (i = 0; i < pstat->bssratelen; i++) {
1630 if ((pstat->bssrateset[i] & 0x7f) > 22) {
1631 pstat->flags &= ~WLAN_STA_NONERP;
1632 break;
1633 }
1634 }
1635
1636 if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1637 pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
1638 else
1639 pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1640
1641 if (status != WLAN_STATUS_SUCCESS)
1642 goto OnAssocReq23aFail;
1643
1644#ifdef CONFIG_8723AU_P2P
1645 pstat->is_p2p_device = false;
1646 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
1647 {
1648 if ((p2pie = rtw_get_p2p_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset, pkt_len - sizeof(struct ieee80211_hdr_3addr) - ie_offset, NULL, &p2pielen)))
1649 {
1650 pstat->is_p2p_device = true;
1651 if ((p2p_status_code = (u8)process_assoc_req_p2p_ie23a(pwdinfo, pframe, pkt_len, pstat))>0)
1652 {
1653 pstat->p2p_status_code = p2p_status_code;
1654 status = WLAN_STATUS_CAPS_UNSUPPORTED;
1655 goto OnAssocReq23aFail;
1656 }
1657 }
1658#ifdef CONFIG_8723AU_P2P
1659 if (rtw_get_wfd_ie(pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset, pkt_len - sizeof(struct ieee80211_hdr_3addr) - ie_offset, wfd_ie, &wfd_ielen))
1660 {
1661 u8 attr_content[ 10 ] = { 0x00 };
1662 u32 attr_contentlen = 0;
1663
1664 DBG_8723A("[%s] WFD IE Found!!\n", __func__);
1665 rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
1666 if (attr_contentlen)
1667 {
1668 pwdinfo->wfd_info->peer_rtsp_ctrlport = RTW_GET_BE16(attr_content + 2);
1669 DBG_8723A("[%s] Peer PORT NUM = %d\n", __func__, pwdinfo->wfd_info->peer_rtsp_ctrlport);
1670 }
1671 }
1672#endif
1673 }
1674 pstat->p2p_status_code = p2p_status_code;
1675#endif /* CONFIG_8723AU_P2P */
1676
1677 /* TODO: identify_proprietary_vendor_ie(); */
1678 /* Realtek proprietary IE */
1679 /* identify if this is Broadcom sta */
1680 /* identify if this is ralink sta */
1681 /* Customer proprietary IE */
1682
1683 /* get a unique AID */
1684 if (pstat->aid > 0) {
1685 DBG_8723A(" old AID %d\n", pstat->aid);
1686 } else {
1687 for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
1688 if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
1689 break;
1690
1691 if (pstat->aid > NUM_STA)
1692 pstat->aid = NUM_STA;
1693 if (pstat->aid > pstapriv->max_num_sta) {
1694
1695 pstat->aid = 0;
1696
1697 DBG_8723A(" no room for more AIDs\n");
1698
1699 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1700
1701 goto OnAssocReq23aFail;
1702
1703 } else {
1704 pstapriv->sta_aid[pstat->aid - 1] = pstat;
1705 DBG_8723A("allocate new AID = (%d)\n", pstat->aid);
1706 }
1707 }
1708
1709 pstat->state &= (~WIFI_FW_ASSOC_STATE);
1710 pstat->state |= WIFI_FW_ASSOC_SUCCESS;
1711
1712 spin_lock_bh(&pstapriv->auth_list_lock);
1713 if (!list_empty(&pstat->auth_list)) {
1714 list_del_init(&pstat->auth_list);
1715 pstapriv->auth_list_cnt--;
1716 }
1717 spin_unlock_bh(&pstapriv->auth_list_lock);
1718
1719 spin_lock_bh(&pstapriv->asoc_list_lock);
1720 if (list_empty(&pstat->asoc_list)) {
1721 pstat->expire_to = pstapriv->expire_to;
1722 list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
1723 pstapriv->asoc_list_cnt++;
1724 }
1725 spin_unlock_bh(&pstapriv->asoc_list_lock);
1726
1727 /* now the station is qualified to join our BSS... */
1728 if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) &&
1729 (WLAN_STATUS_SUCCESS == status)) {
1730#ifdef CONFIG_8723AU_AP_MODE
1731 /* 1 bss_cap_update & sta_info_update23a */
1732 bss_cap_update_on_sta_join23a(padapter, pstat);
1733 sta_info_update23a(padapter, pstat);
1734
1735 /* issue assoc rsp before notify station join event. */
1736 if (ieee80211_is_assoc_req(frame_control))
1737 issue_asocrsp23a(padapter, status, pstat, WIFI_ASSOCRSP);
1738 else
1739 issue_asocrsp23a(padapter, status, pstat, WIFI_REASSOCRSP);
1740
1741 /* 2 - report to upper layer */
1742 DBG_8723A("indicate_sta_join_event to upper layer - hostapd\n");
1743 rtw_cfg80211_indicate_sta_assoc(padapter, pframe, pkt_len);
1744
1745 /* 3-(1) report sta add event */
1746 report_add_sta_event23a(padapter, pstat->hwaddr, pstat->aid);
1747#endif
1748 }
1749
1750 return _SUCCESS;
1751
1752asoc_class2_error:
1753
1754#ifdef CONFIG_8723AU_AP_MODE
1755 issue_deauth23a(padapter, hdr->addr2, status);
1756#endif
1757
1758 return _FAIL;
1759
1760OnAssocReq23aFail:
1761
1762#ifdef CONFIG_8723AU_AP_MODE
1763 pstat->aid = 0;
1764 if (ieee80211_is_assoc_req(frame_control))
1765 issue_asocrsp23a(padapter, status, pstat, WIFI_ASSOCRSP);
1766 else
1767 issue_asocrsp23a(padapter, status, pstat, WIFI_REASSOCRSP);
1768#endif
1769
1770#endif /* CONFIG_8723AU_AP_MODE */
1771
1772 return _FAIL;
1773}
1774
1775unsigned int OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1776{
1777 uint i;
1778 int res;
1779 unsigned short status;
1780 struct ndis_802_11_var_ies *pIE;
1781 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1782 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1783 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1784 struct sk_buff *skb = precv_frame->pkt;
1785 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1786 u8 *pframe = skb->data;
1787 uint pkt_len = skb->len;
1788
1789 DBG_8723A("%s\n", __func__);
1790
1791 /* check A1 matches or not */
1792 if (!ether_addr_equal(myid(&padapter->eeprompriv),
1793 ieee80211_get_DA(hdr)))
1794 return _SUCCESS;
1795
1796 if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
1797 return _SUCCESS;
1798
1799 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
1800 return _SUCCESS;
1801
1802 del_timer_sync(&pmlmeext->link_timer);
1803
1804 /* status */
1805 if ((status = le16_to_cpu(*(unsigned short *)(pframe + sizeof(struct ieee80211_hdr_3addr) + 2))) > 0)
1806 {
1807 DBG_8723A("assoc reject, status code: %d\n", status);
1808 pmlmeinfo->state = WIFI_FW_NULL_STATE;
1809 res = -4;
1810 goto report_assoc_result;
1811 }
1812
1813 /* get capabilities */
1814 pmlmeinfo->capability = le16_to_cpu(*(unsigned short *)(pframe + sizeof(struct ieee80211_hdr_3addr)));
1815
1816 /* set slot time */
1817 pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10))? 9: 20;
1818
1819 /* AID */
1820 res = pmlmeinfo->aid = (int)(le16_to_cpu(*(unsigned short *)(pframe + sizeof(struct ieee80211_hdr_3addr) + 4))&0x3fff);
1821
1822 /* following are moved to join event callback function */
1823 /* to handle HT, WMM, rate adaptive, update MAC reg */
1824 /* for not to handle the synchronous IO in the tasklet */
1825 for (i = (6 + sizeof(struct ieee80211_hdr_3addr)); i < pkt_len;) {
1826 pIE = (struct ndis_802_11_var_ies *)(pframe + i);
1827
1828 switch (pIE->ElementID)
1829 {
1830 case _VENDOR_SPECIFIC_IE_:
1831 if (!memcmp(pIE->data, WMM_PARA_OUI23A, 6))/* WMM */
1832 WMM_param_handler23a(padapter, pIE);
1833#if defined(CONFIG_8723AU_P2P)
1834 else if (!memcmp(pIE->data, WFD_OUI23A, 4)) { /* WFD */
1835 DBG_8723A("[%s] Found WFD IE\n", __func__);
1836 WFD_info_handler(padapter, pIE);
1837 }
1838#endif
1839 break;
1840
1841 case _HT_CAPABILITY_IE_: /* HT caps */
1842 HT_caps_handler23a(padapter, pIE);
1843 break;
1844
1845 case _HT_EXTRA_INFO_IE_: /* HT info */
1846 HT_info_handler23a(padapter, pIE);
1847 break;
1848
1849 case _ERPINFO_IE_:
1850 ERP_IE_handler23a(padapter, pIE);
1851
1852 default:
1853 break;
1854 }
1855
1856 i += (pIE->Length + 2);
1857 }
1858
1859 pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
1860 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
1861
1862 /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
1863 UpdateBrateTbl23a(padapter, pmlmeinfo->network.SupportedRates);
1864
1865report_assoc_result:
1866 pmlmepriv->assoc_rsp_len = 0;
1867 if (res > 0) {
1868 kfree(pmlmepriv->assoc_rsp);
1869 pmlmepriv->assoc_rsp = kmalloc(pkt_len, GFP_ATOMIC);
1870 if (pmlmepriv->assoc_rsp) {
1871 memcpy(pmlmepriv->assoc_rsp, pframe, pkt_len);
1872 pmlmepriv->assoc_rsp_len = pkt_len;
1873 }
1874 } else
1875 kfree(pmlmepriv->assoc_rsp);
1876
1877 report_join_res23a(padapter, res);
1878
1879 return _SUCCESS;
1880}
1881
1882unsigned int OnDeAuth23a(struct rtw_adapter *padapter,
1883 struct recv_frame *precv_frame)
1884{
1885 unsigned short reason;
1886 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1887 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1888 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1889 struct sk_buff *skb = precv_frame->pkt;
1890 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1891 u8 *pframe = skb->data;
1892#ifdef CONFIG_8723AU_P2P
1893 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1894#endif /* CONFIG_8723AU_P2P */
1895
1896 /* check A3 */
1897 if (!ether_addr_equal(hdr->addr3, get_my_bssid23a(&pmlmeinfo->network)))
1898 return _SUCCESS;
1899
1900#ifdef CONFIG_8723AU_P2P
1901 if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
1902 mod_timer(&pwdinfo->reset_ch_sitesurvey,
1903 jiffies + msecs_to_jiffies(10));
1904 }
1905#endif /* CONFIG_8723AU_P2P */
1906
1907 reason = le16_to_cpu(*(unsigned short *)(pframe + sizeof(struct ieee80211_hdr_3addr)));
1908
1909 DBG_8723A("%s Reason code(%d)\n", __func__, reason);
1910
1911#ifdef CONFIG_8723AU_AP_MODE
1912 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
1913 struct sta_info *psta;
1914 struct sta_priv *pstapriv = &padapter->stapriv;
1915
1916 DBG_8723A_LEVEL(_drv_always_, "ap recv deauth reason code(%d) "
1917 "sta:%pM\n", reason, hdr->addr2);
1918
1919 psta = rtw_get_stainfo23a(pstapriv, hdr->addr2);
1920 if (psta) {
1921 u8 updated = 0;
1922
1923 spin_lock_bh(&pstapriv->asoc_list_lock);
1924 if (!list_empty(&psta->asoc_list)) {
1925 list_del_init(&psta->asoc_list);
1926 pstapriv->asoc_list_cnt--;
1927 updated = ap_free_sta23a(padapter, psta,
1928 false, reason);
1929 }
1930 spin_unlock_bh(&pstapriv->asoc_list_lock);
1931
1932 associated_clients_update23a(padapter, updated);
1933 }
1934
1935 return _SUCCESS;
1936 }
1937 else
1938#endif
1939 {
1940 DBG_8723A_LEVEL(_drv_always_, "sta recv deauth reason code(%d) "
1941 "sta:%pM\n", reason, hdr->addr3);
1942
1943 receive_disconnect23a(padapter, hdr->addr3, reason);
1944 }
1945 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1946 return _SUCCESS;
1947}
1948
1949unsigned int OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1950{
1951 unsigned short reason;
1952 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1953 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1954 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1955 struct sk_buff *skb = precv_frame->pkt;
1956 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1957 u8 *pframe = skb->data;
1958#ifdef CONFIG_8723AU_P2P
1959 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1960#endif /* CONFIG_8723AU_P2P */
1961
1962 /* check A3 */
1963 if (!ether_addr_equal(hdr->addr3, get_my_bssid23a(&pmlmeinfo->network)))
1964 return _SUCCESS;
1965
1966#ifdef CONFIG_8723AU_P2P
1967 if (pwdinfo->rx_invitereq_info.scan_op_ch_only)
1968 {
1969 mod_timer(&pwdinfo->reset_ch_sitesurvey,
1970 jiffies + msecs_to_jiffies(10));
1971 }
1972#endif /* CONFIG_8723AU_P2P */
1973
1974 reason = le16_to_cpu(*(unsigned short *)
1975 (pframe + sizeof(struct ieee80211_hdr_3addr)));
1976
1977 DBG_8723A("%s Reason code(%d)\n", __func__, reason);
1978
1979#ifdef CONFIG_8723AU_AP_MODE
1980 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1981 struct sta_info *psta;
1982 struct sta_priv *pstapriv = &padapter->stapriv;
1983
1984 DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason code(%d)"
1985 " sta:%pM\n", reason, hdr->addr2);
1986
1987 psta = rtw_get_stainfo23a(pstapriv, hdr->addr2);
1988 if (psta) {
1989 u8 updated = 0;
1990
1991 spin_lock_bh(&pstapriv->asoc_list_lock);
1992 if (!list_empty(&psta->asoc_list)) {
1993 list_del_init(&psta->asoc_list);
1994 pstapriv->asoc_list_cnt--;
1995 updated = ap_free_sta23a(padapter, psta,
1996 false, reason);
1997 }
1998 spin_unlock_bh(&pstapriv->asoc_list_lock);
1999
2000 associated_clients_update23a(padapter, updated);
2001 }
2002
2003 return _SUCCESS;
2004 }
2005 else
2006#endif
2007 {
2008 DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason "
2009 "code(%d) sta:%pM\n", reason, hdr->addr3);
2010
2011 receive_disconnect23a(padapter, hdr->addr3, reason);
2012 }
2013 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
2014 return _SUCCESS;
2015}
2016
2017unsigned int OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2018{
2019 DBG_8723A("%s\n", __func__);
2020 return _SUCCESS;
2021}
2022
2023unsigned int on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2024{
2025 return _FAIL;
2026}
2027
2028unsigned int OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2029{
2030 return _SUCCESS;
2031}
2032
2033unsigned int OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2034{
2035 return _SUCCESS;
2036}
2037
2038unsigned int OnAction23a_back23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2039{
2040 u8 *addr;
2041 struct sta_info *psta = NULL;
2042 struct recv_reorder_ctrl *preorder_ctrl;
2043 unsigned char *frame_body;
2044 unsigned char category, action;
2045 unsigned short tid, status, reason_code = 0;
2046 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2047 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2048 struct sk_buff *skb = precv_frame->pkt;
2049 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2050 u8 *pframe = skb->data;
2051 struct sta_priv *pstapriv = &padapter->stapriv;
2052
2053 /* check RA matches or not */
2054 if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
2055 return _SUCCESS;
2056
2057 DBG_8723A("%s\n", __func__);
2058
2059 if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
2060 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
2061 return _SUCCESS;
2062
2063 addr = hdr->addr2;
2064 psta = rtw_get_stainfo23a(pstapriv, addr);
2065
2066 if (!psta)
2067 return _SUCCESS;
2068
2069 frame_body = (unsigned char *)
2070 (pframe + sizeof(struct ieee80211_hdr_3addr));
2071
2072 category = frame_body[0];
2073 if (category == WLAN_CATEGORY_BACK) { /* representing Block Ack */
2074 if (!pmlmeinfo->HT_enable)
2075 return _SUCCESS;
2076 action = frame_body[1];
2077 DBG_8723A("%s, action =%d\n", __func__, action);
2078 switch (action) {
2079 case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
2080 memcpy(&pmlmeinfo->ADDBA_req, &frame_body[2],
2081 sizeof(struct ADDBA_request));
2082 process_addba_req23a(padapter,
2083 (u8 *)&pmlmeinfo->ADDBA_req, addr);
2084 if (pmlmeinfo->bAcceptAddbaReq == true)
2085 issue_action_BA23a(padapter, addr,
2086 WLAN_ACTION_ADDBA_RESP, 0);
2087 else {
2088 /* reject ADDBA Req */
2089 issue_action_BA23a(padapter, addr,
2090 WLAN_ACTION_ADDBA_RESP, 37);
2091 }
2092 break;
2093 case WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
2094 status = RTW_GET_LE16(&frame_body[3]);
2095 tid = ((frame_body[5] >> 2) & 0x7);
2096 if (status == 0) { /* successful */
2097 DBG_8723A("agg_enable for TID =%d\n", tid);
2098 psta->htpriv.agg_enable_bitmap |= 1 << tid;
2099 psta->htpriv.candidate_tid_bitmap &=
2100 ~CHKBIT(tid);
2101 } else
2102 psta->htpriv.agg_enable_bitmap &= ~CHKBIT(tid);
2103 break;
2104
2105 case WLAN_ACTION_DELBA: /* DELBA */
2106 if ((frame_body[3] & BIT(3)) == 0) {
2107 psta->htpriv.agg_enable_bitmap &=
2108 ~(1 << ((frame_body[3] >> 4) & 0xf));
2109 psta->htpriv.candidate_tid_bitmap &=
2110 ~(1 << ((frame_body[3] >> 4) & 0xf));
2111
2112 /* reason_code = frame_body[4] | (frame_body[5] << 8); */
2113 reason_code = RTW_GET_LE16(&frame_body[4]);
2114 } else if ((frame_body[3] & BIT(3)) == BIT(3)) {
2115 tid = (frame_body[3] >> 4) & 0x0F;
2116
2117 preorder_ctrl = &psta->recvreorder_ctrl[tid];
2118 preorder_ctrl->enable = false;
2119 preorder_ctrl->indicate_seq = 0xffff;
2120 }
2121
2122 DBG_8723A("%s(): DELBA: %x(%x)\n", __func__,
2123 pmlmeinfo->agg_enable_bitmap, reason_code);
2124 /* todo: how to notify the host while receiving
2125 DELETE BA */
2126 break;
2127 default:
2128 break;
2129 }
2130 }
2131 return _SUCCESS;
2132}
2133
2134#ifdef CONFIG_8723AU_P2P
2135
2136static int get_reg_classes_full_count(struct p2p_channels channel_list) {
2137 int cnt = 0;
2138 int i;
2139
2140 for (i = 0; i < channel_list.reg_classes; i++)
2141 cnt += channel_list.reg_class[i].channels;
2142
2143 return cnt;
2144}
2145
2146void issue_p2p_GO_request23a(struct rtw_adapter *padapter, u8* raddr)
2147{
2148 unsigned char category = WLAN_CATEGORY_PUBLIC;
2149 u8 action = P2P_PUB_ACTION_ACTION;
2150 u32 p2poui = cpu_to_be32(P2POUI);
2151 u8 oui_subtype = P2P_GO_NEGO_REQ;
2152 u8 wpsie[ 255 ] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
2153 u8 wpsielen = 0, p2pielen = 0;
2154 u16 len_channellist_attr = 0;
2155#ifdef CONFIG_8723AU_P2P
2156 u32 wfdielen = 0;
2157#endif /* CONFIG_8723AU_P2P */
2158
2159 struct xmit_frame *pmgntframe;
2160 struct pkt_attrib *pattrib;
2161 unsigned char *pframe;
2162 struct ieee80211_hdr *pwlanhdr;
2163 unsigned short *fctrl;
2164 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2165 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2166 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2167
2168 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
2169 return;
2170
2171 DBG_8723A("[%s] In\n", __func__);
2172 /* update attribute */
2173 pattrib = &pmgntframe->attrib;
2174 update_mgntframe_attrib23a(padapter, pattrib);
2175
2176 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2177
2178 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2179 pwlanhdr = (struct ieee80211_hdr *)pframe;
2180
2181 fctrl = &pwlanhdr->frame_control;
2182 *fctrl = 0;
2183
2184 ether_addr_copy(pwlanhdr->addr1, raddr);
2185 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
2186 ether_addr_copy(pwlanhdr->addr3, myid(&padapter->eeprompriv));
2187
2188 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2189 pmlmeext->mgnt_seq++;
2190 SetFrameSubType(pframe, WIFI_ACTION);
2191
2192 pframe += sizeof(struct ieee80211_hdr_3addr);
2193 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2194
2195 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
2196 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
2197 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui,
2198 &pattrib->pktlen);
2199 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
2200 pwdinfo->negotiation_dialog_token = 1; /*Initialize the dialog value*/
2201 pframe = rtw_set_fixed_ie23a(pframe, 1,
2202 &pwdinfo->negotiation_dialog_token,
2203 &pattrib->pktlen);
2204
2205 /* WPS Section */
2206 wpsielen = 0;
2207 /* WPS OUI */
2208 *(u32*) (wpsie) = cpu_to_be32(WPSOUI);
2209 wpsielen += 4;
2210
2211 /* WPS version */
2212 /* Type: */
2213 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
2214 wpsielen += 2;
2215
2216 /* Length: */
2217 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
2218 wpsielen += 2;
2219
2220 /* Value: */
2221 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
2222
2223 /* Device Password ID */
2224 /* Type: */
2225 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
2226 wpsielen += 2;
2227
2228 /* Length: */
2229 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002);
2230 wpsielen += 2;
2231
2232 /* Value: */
2233
2234 if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN)
2235 {
2236 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
2237 }
2238 else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN)
2239 {
2240 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
2241 }
2242 else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC)
2243 {
2244 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
2245 }
2246
2247 wpsielen += 2;
2248
2249 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);
2250
2251 /* P2P IE Section. */
2252
2253 /* P2P OUI */
2254 p2pielen = 0;
2255 p2pie[p2pielen++] = 0x50;
2256 p2pie[p2pielen++] = 0x6F;
2257 p2pie[p2pielen++] = 0x9A;
2258 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
2259
2260 /* Commented by Albert 20110306 */
2261 /* According to the P2P Specification, the group negoitation request frame should contain 9 P2P attributes */
2262 /* 1. P2P Capability */
2263 /* 2. Group Owner Intent */
2264 /* 3. Configuration Timeout */
2265 /* 4. Listen Channel */
2266 /* 5. Extended Listen Timing */
2267 /* 6. Intended P2P Interface Address */
2268 /* 7. Channel List */
2269 /* 8. P2P Device Info */
2270 /* 9. Operating Channel */
2271
2272 /* P2P Capability */
2273 /* Type: */
2274 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
2275
2276 /* Length: */
2277 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
2278 p2pielen += 2;
2279
2280 /* Value: */
2281 /* Device Capability Bitmap, 1 byte */
2282 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
2283
2284 /* Group Capability Bitmap, 1 byte */
2285 if (pwdinfo->persistent_supported)
2286 {
2287 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
2288 }
2289 else
2290 {
2291 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
2292 }
2293
2294 /* Group Owner Intent */
2295 /* Type: */
2296 p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
2297
2298 /* Length: */
2299 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0001);
2300 p2pielen += 2;
2301
2302 /* Value: */
2303 /* Todo the tie breaker bit. */
2304 p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
2305
2306 /* Configuration Timeout */
2307 /* Type: */
2308 p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
2309
2310 /* Length: */
2311 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
2312 p2pielen += 2;
2313
2314 /* Value: */
2315 p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */
2316 p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */
2317
2318 /* Listen Channel */
2319 /* Type: */
2320 p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
2321
2322 /* Length: */
2323 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
2324 p2pielen += 2;
2325
2326 /* Value: */
2327 /* Country String */
2328 p2pie[p2pielen++] = 'X';
2329 p2pie[p2pielen++] = 'X';
2330
2331 /* The third byte should be set to 0x04. */
2332 /* Described in the "Operating Channel Attribute" section. */
2333 p2pie[p2pielen++] = 0x04;
2334
2335 /* Operating Class */
2336 p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
2337
2338 /* Channel Number */
2339 p2pie[p2pielen++] = pwdinfo->listen_channel; /* listening channel number */
2340
2341 /* Extended Listen Timing ATTR */
2342 /* Type: */
2343 p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
2344
2345 /* Length: */
2346 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0004);
2347 p2pielen += 2;
2348
2349 /* Value: */
2350 /* Availability Period */
2351 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF);
2352 p2pielen += 2;
2353
2354 /* Availability Interval */
2355 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF);
2356 p2pielen += 2;
2357
2358 /* Intended P2P Interface Address */
2359 /* Type: */
2360 p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR;
2361
2362 /* Length: */
2363 *(u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
2364 p2pielen += 2;
2365
2366 /* Value: */
2367 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2368 p2pielen += ETH_ALEN;
2369
2370 /* Channel List */
2371 /* Type: */
2372 p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2373
2374 /* Length: */
2375 /* Country String(3) */
2376 /* + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
2377 /* + number of channels in all classes */
2378 len_channellist_attr = 3
2379 + (1 + 1) * (u16)(pmlmeext->channel_list.reg_classes)
2380 + get_reg_classes_full_count(pmlmeext->channel_list);
2381
2382 *(u16*) (p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
2383 p2pielen += 2;
2384
2385 /* Value: */
2386 /* Country String */
2387 p2pie[p2pielen++] = 'X';
2388 p2pie[p2pielen++] = 'X';
2389
2390 /* The third byte should be set to 0x04. */
2391 /* Described in the "Operating Channel Attribute" section. */
2392 p2pie[p2pielen++] = 0x04;
2393
2394 /* Channel Entry List */
2395
2396 {
2397 int i, j;
2398 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
2399 /* Operating Class */
2400 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
2401
2402 /* Number of Channels */
2403 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
2404
2405 /* Channel List */
2406 for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
2407 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
2408 }
2409 }
2410 }
2411
2412 /* Device Info */
2413 /* Type: */
2414 p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
2415
2416 /* Length: */
2417 /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
2418 /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
2419 *(u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
2420 p2pielen += 2;
2421
2422 /* Value: */
2423 /* P2P Device Address */
2424 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2425 p2pielen += ETH_ALEN;
2426
2427 /* Config Method */
2428 /* This field should be big endian. Noted by P2P specification. */
2429
2430 *(u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
2431
2432 p2pielen += 2;
2433
2434 /* Primary Device Type */
2435 /* Category ID */
2436 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
2437 p2pielen += 2;
2438
2439 /* OUI */
2440 *(u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI);
2441 p2pielen += 4;
2442
2443 /* Sub Category ID */
2444 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
2445 p2pielen += 2;
2446
2447 /* Number of Secondary Device Types */
2448 p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
2449
2450 /* Device Name */
2451 /* Type: */
2452 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
2453 p2pielen += 2;
2454
2455 /* Length: */
2456 *(u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
2457 p2pielen += 2;
2458
2459 /* Value: */
2460 memcpy(p2pie + p2pielen, pwdinfo->device_name,
2461 pwdinfo->device_name_len);
2462 p2pielen += pwdinfo->device_name_len;
2463
2464 /* Operating Channel */
2465 /* Type: */
2466 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2467
2468 /* Length: */
2469 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
2470 p2pielen += 2;
2471
2472 /* Value: */
2473 /* Country String */
2474 p2pie[p2pielen++] = 'X';
2475 p2pie[p2pielen++] = 'X';
2476
2477 /* The third byte should be set to 0x04. */
2478 /* Described in the "Operating Channel Attribute" section. */
2479 p2pie[p2pielen++] = 0x04;
2480
2481 /* Operating Class */
2482 if (pwdinfo->operating_channel <= 14)
2483 {
2484 /* Operating Class */
2485 p2pie[p2pielen++] = 0x51;
2486 }
2487 else if ((pwdinfo->operating_channel >= 36) && (pwdinfo->operating_channel <= 48))
2488 {
2489 /* Operating Class */
2490 p2pie[p2pielen++] = 0x73;
2491 }
2492 else
2493 {
2494 /* Operating Class */
2495 p2pie[p2pielen++] = 0x7c;
2496 }
2497
2498 /* Channel Number */
2499 p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */
2500
2501 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen);
2502
2503#ifdef CONFIG_8723AU_P2P
2504 wfdielen = build_nego_req_wfd_ie(pwdinfo, pframe);
2505 pframe += wfdielen;
2506 pattrib->pktlen += wfdielen;
2507#endif /* CONFIG_8723AU_P2P */
2508
2509 pattrib->last_txcmdsz = pattrib->pktlen;
2510
2511 dump_mgntframe23a(padapter, pmgntframe);
2512
2513 return;
2514}
2515
2516static void issue_p2p_GO_response(struct rtw_adapter *padapter, u8* raddr, u8* frame_body, uint len, u8 result)
2517{
2518
2519 unsigned char category = WLAN_CATEGORY_PUBLIC;
2520 u8 action = P2P_PUB_ACTION_ACTION;
2521 u32 p2poui = cpu_to_be32(P2POUI);
2522 u8 oui_subtype = P2P_GO_NEGO_RESP;
2523 u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
2524 u8 p2pielen = 0;
2525 uint wpsielen = 0;
2526 u16 wps_devicepassword_id = 0x0000;
2527 uint wps_devicepassword_id_len = 0;
2528 u16 len_channellist_attr = 0;
2529 int i, j;
2530 struct xmit_frame *pmgntframe;
2531 struct pkt_attrib *pattrib;
2532 unsigned char *pframe;
2533 struct ieee80211_hdr *pwlanhdr;
2534 unsigned short *fctrl;
2535 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2536 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2537 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2538#ifdef CONFIG_8723AU_P2P
2539 u32 wfdielen = 0;
2540#endif /* CONFIG_8723AU_P2P */
2541
2542 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
2543 return;
2544
2545 DBG_8723A("[%s] In, result = %d\n", __func__, result);
2546 /* update attribute */
2547 pattrib = &pmgntframe->attrib;
2548 update_mgntframe_attrib23a(padapter, pattrib);
2549
2550 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2551
2552 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2553 pwlanhdr = (struct ieee80211_hdr *)pframe;
2554
2555 fctrl = &pwlanhdr->frame_control;
2556 *fctrl = 0;
2557
2558 ether_addr_copy(pwlanhdr->addr1, raddr);
2559 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
2560 ether_addr_copy(pwlanhdr->addr3, myid(&padapter->eeprompriv));
2561
2562 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2563 pmlmeext->mgnt_seq++;
2564 SetFrameSubType(pframe, WIFI_ACTION);
2565
2566 pframe += sizeof(struct ieee80211_hdr_3addr);
2567 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2568
2569 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
2570 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
2571 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *) &p2poui,
2572 &pattrib->pktlen);
2573 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
2574 /* The Dialog Token of provisioning discovery request frame. */
2575 pwdinfo->negotiation_dialog_token = frame_body[7];
2576 pframe = rtw_set_fixed_ie23a(pframe, 1,
2577 &pwdinfo->negotiation_dialog_token,
2578 &pattrib->pktlen);
2579
2580 /* Commented by Albert 20110328 */
2581 /* Try to get the device password ID from the WPS IE of group
2582 negotiation request frame */
2583 /* WiFi Direct test plan 5.1.15 */
2584 rtw_get_wps_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
2585 len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);
2586 rtw_get_wps_attr_content23a(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID,
2587 (u8 *)&wps_devicepassword_id,
2588 &wps_devicepassword_id_len);
2589 wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id);
2590
2591 memset(wpsie, 0x00, 255);
2592 wpsielen = 0;
2593
2594 /* WPS Section */
2595 wpsielen = 0;
2596 /* WPS OUI */
2597 *(u32*) (wpsie) = cpu_to_be32(WPSOUI);
2598 wpsielen += 4;
2599
2600 /* WPS version */
2601 /* Type: */
2602 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
2603 wpsielen += 2;
2604
2605 /* Length: */
2606 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
2607 wpsielen += 2;
2608
2609 /* Value: */
2610 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
2611
2612 /* Device Password ID */
2613 /* Type: */
2614 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
2615 wpsielen += 2;
2616
2617 /* Length: */
2618 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002);
2619 wpsielen += 2;
2620
2621 /* Value: */
2622 if (wps_devicepassword_id == WPS_DPID_USER_SPEC) {
2623 *(u16*) (wpsie + wpsielen) =
2624 cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
2625 } else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC) {
2626 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
2627 } else {
2628 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
2629 }
2630 wpsielen += 2;
2631
2632 /* Commented by Kurt 20120113 */
2633 /* If some device wants to do p2p handshake without sending prov_disc_req */
2634 /* We have to get peer_req_cm from here. */
2635 if (!memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
2636 if (wps_devicepassword_id == WPS_DPID_USER_SPEC) {
2637 memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
2638 } else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC) {
2639 memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
2640 } else {
2641 memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
2642 }
2643 }
2644
2645 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen,
2646 (unsigned char *) wpsie, &pattrib->pktlen);
2647
2648 /* P2P IE Section. */
2649
2650 /* P2P OUI */
2651 p2pielen = 0;
2652 p2pie[p2pielen++] = 0x50;
2653 p2pie[p2pielen++] = 0x6F;
2654 p2pie[p2pielen++] = 0x9A;
2655 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
2656
2657 /* Commented by Albert 20100908 */
2658 /* According to the P2P Specification, the group negoitation
2659 response frame should contain 9 P2P attributes */
2660 /* 1. Status */
2661 /* 2. P2P Capability */
2662 /* 3. Group Owner Intent */
2663 /* 4. Configuration Timeout */
2664 /* 5. Operating Channel */
2665 /* 6. Intended P2P Interface Address */
2666 /* 7. Channel List */
2667 /* 8. Device Info */
2668 /* 9. Group ID (Only GO) */
2669
2670 /* ToDo: */
2671
2672 /* P2P Status */
2673 /* Type: */
2674 p2pie[p2pielen++] = P2P_ATTR_STATUS;
2675
2676 /* Length: */
2677 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0001);
2678 p2pielen += 2;
2679
2680 /* Value: */
2681 p2pie[p2pielen++] = result;
2682
2683 /* P2P Capability */
2684 /* Type: */
2685 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
2686
2687 /* Length: */
2688 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
2689 p2pielen += 2;
2690
2691 /* Value: */
2692 /* Device Capability Bitmap, 1 byte */
2693
2694 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
2695 /* Commented by Albert 2011/03/08 */
2696 /* According to the P2P specification */
2697 /* if the sending device will be client, the P2P
2698 Capability should be reserved of group negotation
2699 response frame */
2700 p2pie[p2pielen++] = 0;
2701 } else {
2702 /* Be group owner or meet the error case */
2703 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
2704 }
2705
2706 /* Group Capability Bitmap, 1 byte */
2707 if (pwdinfo->persistent_supported) {
2708 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN |
2709 P2P_GRPCAP_PERSISTENT_GROUP;
2710 } else {
2711 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
2712 }
2713
2714 /* Group Owner Intent */
2715 /* Type: */
2716 p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
2717
2718 /* Length: */
2719 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0001);
2720 p2pielen += 2;
2721
2722 /* Value: */
2723 if (pwdinfo->peer_intent & 0x01) {
2724 /* Peer's tie breaker bit is 1, our tie breaker
2725 bit should be 0 */
2726 p2pie[p2pielen++] = (pwdinfo->intent << 1);
2727 } else {
2728 /* Peer's tie breaker bit is 0, our tie breaker bit
2729 should be 1 */
2730 p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
2731 }
2732
2733 /* Configuration Timeout */
2734 /* Type: */
2735 p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
2736
2737 /* Length: */
2738 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
2739 p2pielen += 2;
2740
2741 /* Value: */
2742 /* 2 seconds needed to be the P2P GO */
2743 p2pie[p2pielen++] = 200;
2744 /* 2 seconds needed to be the P2P Client */
2745 p2pie[p2pielen++] = 200;
2746
2747 /* Operating Channel */
2748 /* Type: */
2749 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2750
2751 /* Length: */
2752 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
2753 p2pielen += 2;
2754
2755 /* Value: */
2756 /* Country String */
2757 p2pie[p2pielen++] = 'X';
2758 p2pie[p2pielen++] = 'X';
2759
2760 /* The third byte should be set to 0x04. */
2761 /* Described in the "Operating Channel Attribute" section. */
2762 p2pie[p2pielen++] = 0x04;
2763
2764 /* Operating Class */
2765 if (pwdinfo->operating_channel <= 14) {
2766 /* Operating Class */
2767 p2pie[p2pielen++] = 0x51;
2768 } else if ((pwdinfo->operating_channel >= 36) &&
2769 (pwdinfo->operating_channel <= 48)) {
2770 /* Operating Class */
2771 p2pie[p2pielen++] = 0x73;
2772 } else {
2773 /* Operating Class */
2774 p2pie[p2pielen++] = 0x7c;
2775 }
2776
2777 /* Channel Number */
2778 /* operating channel number */
2779 p2pie[p2pielen++] = pwdinfo->operating_channel;
2780
2781 /* Intended P2P Interface Address */
2782 /* Type: */
2783 p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR;
2784
2785 /* Length: */
2786 *(u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
2787 p2pielen += 2;
2788
2789 /* Value: */
2790 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2791 p2pielen += ETH_ALEN;
2792
2793 /* Channel List */
2794 /* Type: */
2795 p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2796
2797 /* Country String(3) */
2798 /* + (Operating Class (1) + Number of Channels(1)) *
2799 Operation Classes (?) */
2800 /* + number of channels in all classes */
2801 len_channellist_attr = 3 +
2802 (1 + 1) * (u16)pmlmeext->channel_list.reg_classes +
2803 get_reg_classes_full_count(pmlmeext->channel_list);
2804
2805 *(u16*) (p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
2806
2807 p2pielen += 2;
2808
2809 /* Value: */
2810 /* Country String */
2811 p2pie[p2pielen++] = 'X';
2812 p2pie[p2pielen++] = 'X';
2813
2814 /* The third byte should be set to 0x04. */
2815 /* Described in the "Operating Channel Attribute" section. */
2816 p2pie[p2pielen++] = 0x04;
2817
2818 /* Channel Entry List */
2819
2820 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
2821 /* Operating Class */
2822 p2pie[p2pielen++] =
2823 pmlmeext->channel_list.reg_class[j].reg_class;
2824
2825 /* Number of Channels */
2826 p2pie[p2pielen++] =
2827 pmlmeext->channel_list.reg_class[j].channels;
2828
2829 /* Channel List */
2830 for (i = 0;
2831 i < pmlmeext->channel_list.reg_class[j].channels; i++) {
2832 p2pie[p2pielen++] =
2833 pmlmeext->channel_list.reg_class[j].channel[i];
2834 }
2835 }
2836
2837 /* Device Info */
2838 /* Type: */
2839 p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
2840
2841 /* Length: */
2842 /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) +
2843 Primary Device Type (8bytes) */
2844 /* + NumofSecondDevType (1byte) + WPS Device Name ID field
2845 (2bytes) + WPS Device Name Len field (2bytes) */
2846 *(u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
2847 p2pielen += 2;
2848
2849 /* Value: */
2850 /* P2P Device Address */
2851 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2852 p2pielen += ETH_ALEN;
2853
2854 /* Config Method */
2855 /* This field should be big endian. Noted by P2P specification. */
2856
2857 *(u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
2858
2859 p2pielen += 2;
2860
2861 /* Primary Device Type */
2862 /* Category ID */
2863 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
2864 p2pielen += 2;
2865
2866 /* OUI */
2867 *(u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI);
2868 p2pielen += 4;
2869
2870 /* Sub Category ID */
2871 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
2872 p2pielen += 2;
2873
2874 /* Number of Secondary Device Types */
2875 p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
2876
2877 /* Device Name */
2878 /* Type: */
2879 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
2880 p2pielen += 2;
2881
2882 /* Length: */
2883 *(u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
2884 p2pielen += 2;
2885
2886 /* Value: */
2887 memcpy(p2pie + p2pielen, pwdinfo->device_name,
2888 pwdinfo->device_name_len);
2889 p2pielen += pwdinfo->device_name_len;
2890
2891 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2892 {
2893 /* Group ID Attribute */
2894 /* Type: */
2895 p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
2896
2897 /* Length: */
2898 *(u16*) (p2pie + p2pielen) =
2899 cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
2900 p2pielen += 2;
2901
2902 /* Value: */
2903 /* p2P Device Address */
2904 memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
2905 p2pielen += ETH_ALEN;
2906
2907 /* SSID */
2908 memcpy(p2pie + p2pielen, pwdinfo->nego_ssid,
2909 pwdinfo->nego_ssidlen);
2910 p2pielen += pwdinfo->nego_ssidlen;
2911
2912 }
2913
2914 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen,
2915 (unsigned char *) p2pie, &pattrib->pktlen);
2916
2917#ifdef CONFIG_8723AU_P2P
2918 wfdielen = build_nego_resp_wfd_ie(pwdinfo, pframe);
2919 pframe += wfdielen;
2920 pattrib->pktlen += wfdielen;
2921#endif /* CONFIG_8723AU_P2P */
2922
2923 pattrib->last_txcmdsz = pattrib->pktlen;
2924
2925 dump_mgntframe23a(padapter, pmgntframe);
2926
2927 return;
2928}
2929
2930static void issue_p2p_GO_confirm(struct rtw_adapter *padapter, u8* raddr,
2931 u8 result)
2932{
2933
2934 unsigned char category = WLAN_CATEGORY_PUBLIC;
2935 u8 action = P2P_PUB_ACTION_ACTION;
2936 u32 p2poui = cpu_to_be32(P2POUI);
2937 u8 oui_subtype = P2P_GO_NEGO_CONF;
2938 u8 p2pie[ 255 ] = { 0x00 };
2939 u8 p2pielen = 0;
2940 struct xmit_frame *pmgntframe;
2941 struct pkt_attrib *pattrib;
2942 unsigned char *pframe;
2943 struct ieee80211_hdr *pwlanhdr;
2944 unsigned short *fctrl;
2945 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2946 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2947 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2948#ifdef CONFIG_8723AU_P2P
2949 u32 wfdielen = 0;
2950#endif /* CONFIG_8723AU_P2P */
2951
2952 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
2953 return;
2954
2955 DBG_8723A("[%s] In\n", __func__);
2956 /* update attribute */
2957 pattrib = &pmgntframe->attrib;
2958 update_mgntframe_attrib23a(padapter, pattrib);
2959
2960 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2961
2962 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2963 pwlanhdr = (struct ieee80211_hdr *)pframe;
2964
2965 fctrl = &pwlanhdr->frame_control;
2966 *fctrl = 0;
2967
2968 ether_addr_copy(pwlanhdr->addr1, raddr);
2969 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
2970 ether_addr_copy(pwlanhdr->addr3, myid(&padapter->eeprompriv));
2971
2972 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2973 pmlmeext->mgnt_seq++;
2974 SetFrameSubType(pframe, WIFI_ACTION);
2975
2976 pframe += sizeof(struct ieee80211_hdr_3addr);
2977 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2978
2979 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
2980 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
2981 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui,
2982 &pattrib->pktlen);
2983 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
2984 pframe = rtw_set_fixed_ie23a(pframe, 1,
2985 &pwdinfo->negotiation_dialog_token,
2986 &pattrib->pktlen);
2987 /* P2P OUI */
2988 p2pielen = 0;
2989 p2pie[p2pielen++] = 0x50;
2990 p2pie[p2pielen++] = 0x6F;
2991 p2pie[p2pielen++] = 0x9A;
2992 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
2993
2994 /* Commented by Albert 20110306 */
2995 /* According to the P2P Specification, the group negoitation
2996 request frame should contain 5 P2P attributes */
2997 /* 1. Status */
2998 /* 2. P2P Capability */
2999 /* 3. Operating Channel */
3000 /* 4. Channel List */
3001 /* 5. Group ID (if this WiFi is GO) */
3002
3003 /* P2P Status */
3004 /* Type: */
3005 p2pie[p2pielen++] = P2P_ATTR_STATUS;
3006
3007 /* Length: */
3008 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0001);
3009 p2pielen += 2;
3010
3011 /* Value: */
3012 p2pie[p2pielen++] = result;
3013
3014 /* P2P Capability */
3015 /* Type: */
3016 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
3017
3018 /* Length: */
3019 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
3020 p2pielen += 2;
3021
3022 /* Value: */
3023 /* Device Capability Bitmap, 1 byte */
3024 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
3025
3026 /* Group Capability Bitmap, 1 byte */
3027 if (pwdinfo->persistent_supported) {
3028 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN |
3029 P2P_GRPCAP_PERSISTENT_GROUP;
3030 } else {
3031 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
3032 }
3033
3034 /* Operating Channel */
3035 /* Type: */
3036 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
3037
3038 /* Length: */
3039 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
3040 p2pielen += 2;
3041
3042 /* Value: */
3043 /* Country String */
3044 p2pie[p2pielen++] = 'X';
3045 p2pie[p2pielen++] = 'X';
3046
3047 /* The third byte should be set to 0x04. */
3048 /* Described in the "Operating Channel Attribute" section. */
3049 p2pie[p2pielen++] = 0x04;
3050
3051 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
3052 if (pwdinfo->peer_operating_ch <= 14) {
3053 /* Operating Class */
3054 p2pie[p2pielen++] = 0x51;
3055 } else if ((pwdinfo->peer_operating_ch >= 36) &&
3056 (pwdinfo->peer_operating_ch <= 48)) {
3057 /* Operating Class */
3058 p2pie[p2pielen++] = 0x73;
3059 } else {
3060 /* Operating Class */
3061 p2pie[p2pielen++] = 0x7c;
3062 }
3063
3064 p2pie[p2pielen++] = pwdinfo->peer_operating_ch;
3065 } else {
3066 if (pwdinfo->operating_channel <= 14) {
3067 /* Operating Class */
3068 p2pie[p2pielen++] = 0x51;
3069 }
3070 else if ((pwdinfo->operating_channel >= 36) &&
3071 (pwdinfo->operating_channel <= 48)) {
3072 /* Operating Class */
3073 p2pie[p2pielen++] = 0x73;
3074 } else {
3075 /* Operating Class */
3076 p2pie[p2pielen++] = 0x7c;
3077 }
3078
3079 /* Channel Number */
3080 /* Use the listen channel as the operating channel */
3081 p2pie[p2pielen++] = pwdinfo->operating_channel;
3082 }
3083
3084 /* Channel List */
3085 /* Type: */
3086 p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
3087
3088 /* Length: */
3089 *(u16*) (p2pie + p2pielen) =
3090 cpu_to_le16(pwdinfo->channel_list_attr_len);
3091 p2pielen += 2;
3092
3093 /* Value: */
3094 memcpy(p2pie + p2pielen, pwdinfo->channel_list_attr,
3095 pwdinfo->channel_list_attr_len);
3096 p2pielen += pwdinfo->channel_list_attr_len;
3097
3098 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
3099 /* Group ID Attribute */
3100 /* Type: */
3101 p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
3102
3103 /* Length: */
3104 *(u16*) (p2pie + p2pielen) =
3105 cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
3106 p2pielen += 2;
3107
3108 /* Value: */
3109 /* p2P Device Address */
3110 memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
3111 p2pielen += ETH_ALEN;
3112
3113 /* SSID */
3114 memcpy(p2pie + p2pielen, pwdinfo->nego_ssid,
3115 pwdinfo->nego_ssidlen);
3116 p2pielen += pwdinfo->nego_ssidlen;
3117 }
3118
3119 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen,
3120 (unsigned char *)p2pie, &pattrib->pktlen);
3121
3122#ifdef CONFIG_8723AU_P2P
3123 wfdielen = build_nego_confirm_wfd_ie(pwdinfo, pframe);
3124 pframe += wfdielen;
3125 pattrib->pktlen += wfdielen;
3126#endif /* CONFIG_8723AU_P2P */
3127
3128 pattrib->last_txcmdsz = pattrib->pktlen;
3129
3130 dump_mgntframe23a(padapter, pmgntframe);
3131
3132 return;
3133}
3134
3135void issue_p2p_invitation_request23a(struct rtw_adapter *padapter, u8* raddr)
3136{
3137 unsigned char category = WLAN_CATEGORY_PUBLIC;
3138 u8 action = P2P_PUB_ACTION_ACTION;
3139 u32 p2poui = cpu_to_be32(P2POUI);
3140 u8 oui_subtype = P2P_INVIT_REQ;
3141 u8 p2pie[ 255 ] = { 0x00 };
3142 u8 p2pielen = 0;
3143 u8 dialogToken = 3;
3144 u16 len_channellist_attr = 0;
3145#ifdef CONFIG_8723AU_P2P
3146 u32 wfdielen = 0;
3147#endif /* CONFIG_8723AU_P2P */
3148 int i, j;
3149 struct xmit_frame *pmgntframe;
3150 struct pkt_attrib *pattrib;
3151 unsigned char *pframe;
3152 struct ieee80211_hdr *pwlanhdr;
3153 unsigned short *fctrl;
3154 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3155 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3156 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3157
3158 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
3159 return;
3160
3161 /* update attribute */
3162 pattrib = &pmgntframe->attrib;
3163 update_mgntframe_attrib23a(padapter, pattrib);
3164
3165 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3166
3167 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3168 pwlanhdr = (struct ieee80211_hdr *)pframe;
3169
3170 fctrl = &pwlanhdr->frame_control;
3171 *fctrl = 0;
3172
3173 ether_addr_copy(pwlanhdr->addr1, raddr);
3174 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3175 ether_addr_copy(pwlanhdr->addr3, raddr);
3176
3177 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3178 pmlmeext->mgnt_seq++;
3179 SetFrameSubType(pframe, WIFI_ACTION);
3180
3181 pframe += sizeof(struct ieee80211_hdr_3addr);
3182 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3183
3184 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
3185 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
3186 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *) &p2poui,
3187 &pattrib->pktlen);
3188 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
3189 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
3190
3191 /* P2P IE Section. */
3192
3193 /* P2P OUI */
3194 p2pielen = 0;
3195 p2pie[p2pielen++] = 0x50;
3196 p2pie[p2pielen++] = 0x6F;
3197 p2pie[p2pielen++] = 0x9A;
3198 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
3199
3200 /* Commented by Albert 20101011 */
3201 /* According to the P2P Specification, the P2P Invitation
3202 request frame should contain 7 P2P attributes */
3203 /* 1. Configuration Timeout */
3204 /* 2. Invitation Flags */
3205 /* 3. Operating Channel (Only GO) */
3206 /* 4. P2P Group BSSID (Should be included if I am the GO) */
3207 /* 5. Channel List */
3208 /* 6. P2P Group ID */
3209 /* 7. P2P Device Info */
3210
3211 /* Configuration Timeout */
3212 /* Type: */
3213 p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
3214
3215 /* Length: */
3216 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
3217 p2pielen += 2;
3218
3219 /* Value: */
3220 /* 2 seconds needed to be the P2P GO */
3221 p2pie[p2pielen++] = 200;
3222 /* 2 seconds needed to be the P2P Client */
3223 p2pie[p2pielen++] = 200;
3224
3225 /* Invitation Flags */
3226 /* Type: */
3227 p2pie[p2pielen++] = P2P_ATTR_INVITATION_FLAGS;
3228
3229 /* Length: */
3230 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0001);
3231 p2pielen += 2;
3232
3233 /* Value: */
3234 p2pie[p2pielen++] = P2P_INVITATION_FLAGS_PERSISTENT;
3235
3236 /* Operating Channel */
3237 /* Type: */
3238 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
3239
3240 /* Length: */
3241 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
3242 p2pielen += 2;
3243
3244 /* Value: */
3245 /* Country String */
3246 p2pie[p2pielen++] = 'X';
3247 p2pie[p2pielen++] = 'X';
3248
3249 /* The third byte should be set to 0x04. */
3250 /* Described in the "Operating Channel Attribute" section. */
3251 p2pie[p2pielen++] = 0x04;
3252
3253 /* Operating Class */
3254 if (pwdinfo->invitereq_info.operating_ch <= 14)
3255 p2pie[p2pielen++] = 0x51;
3256 else if ((pwdinfo->invitereq_info.operating_ch >= 36) &&
3257 (pwdinfo->invitereq_info.operating_ch <= 48))
3258 p2pie[p2pielen++] = 0x73;
3259 else
3260 p2pie[p2pielen++] = 0x7c;
3261
3262 /* Channel Number */
3263 /* operating channel number */
3264 p2pie[p2pielen++] = pwdinfo->invitereq_info.operating_ch;
3265
3266 if (ether_addr_equal(myid(&padapter->eeprompriv),
3267 pwdinfo->invitereq_info.go_bssid)) {
3268 /* P2P Group BSSID */
3269 /* Type: */
3270 p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
3271
3272 /* Length: */
3273 *(u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
3274 p2pielen += 2;
3275
3276 /* Value: */
3277 /* P2P Device Address for GO */
3278 memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid,
3279 ETH_ALEN);
3280 p2pielen += ETH_ALEN;
3281 }
3282
3283 /* Channel List */
3284 /* Type: */
3285 p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
3286
3287 /* Length: */
3288 /* Country String(3) */
3289 /* + (Operating Class (1) + Number of Channels(1)) *
3290 Operation Classes (?) */
3291 /* + number of channels in all classes */
3292 len_channellist_attr = 3 +
3293 (1 + 1) * (u16)pmlmeext->channel_list.reg_classes +
3294 get_reg_classes_full_count(pmlmeext->channel_list);
3295
3296 *(u16*) (p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
3297 p2pielen += 2;
3298
3299 /* Value: */
3300 /* Country String */
3301 p2pie[p2pielen++] = 'X';
3302 p2pie[p2pielen++] = 'X';
3303
3304 /* The third byte should be set to 0x04. */
3305 /* Described in the "Operating Channel Attribute" section. */
3306 p2pie[p2pielen++] = 0x04;
3307
3308 /* Channel Entry List */
3309 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
3310 /* Operating Class */
3311 p2pie[p2pielen++] =
3312 pmlmeext->channel_list.reg_class[j].reg_class;
3313
3314 /* Number of Channels */
3315 p2pie[p2pielen++] =
3316 pmlmeext->channel_list.reg_class[j].channels;
3317
3318 /* Channel List */
3319 for (i = 0;
3320 i < pmlmeext->channel_list.reg_class[j].channels; i++) {
3321 p2pie[p2pielen++] =
3322 pmlmeext->channel_list.reg_class[j].channel[i];
3323 }
3324 }
3325
3326 /* P2P Group ID */
3327 /* Type: */
3328 p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
3329
3330 /* Length: */
3331 *(u16*) (p2pie + p2pielen) =
3332 cpu_to_le16(6 + pwdinfo->invitereq_info.ssidlen);
3333 p2pielen += 2;
3334
3335 /* Value: */
3336 /* P2P Device Address for GO */
3337 memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);
3338 p2pielen += ETH_ALEN;
3339
3340 /* SSID */
3341 memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_ssid,
3342 pwdinfo->invitereq_info.ssidlen);
3343 p2pielen += pwdinfo->invitereq_info.ssidlen;
3344
3345 /* Device Info */
3346 /* Type: */
3347 p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
3348
3349 /* Length: */
3350 /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) +
3351 Primary Device Type (8bytes) */
3352 /* + NumofSecondDevType (1byte) + WPS Device Name ID field
3353 (2bytes) + WPS Device Name Len field (2bytes) */
3354 *(u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
3355 p2pielen += 2;
3356
3357 /* Value: */
3358 /* P2P Device Address */
3359 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
3360 p2pielen += ETH_ALEN;
3361
3362 /* Config Method */
3363 /* This field should be big endian. Noted by P2P specification. */
3364 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
3365 p2pielen += 2;
3366
3367 /* Primary Device Type */
3368 /* Category ID */
3369 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
3370 p2pielen += 2;
3371
3372 /* OUI */
3373 *(u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI);
3374 p2pielen += 4;
3375
3376 /* Sub Category ID */
3377 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
3378 p2pielen += 2;
3379
3380 /* Number of Secondary Device Types */
3381 p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
3382
3383 /* Device Name */
3384 /* Type: */
3385 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
3386 p2pielen += 2;
3387
3388 /* Length: */
3389 *(u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
3390 p2pielen += 2;
3391
3392 /* Value: */
3393 memcpy(p2pie + p2pielen, pwdinfo->device_name,
3394 pwdinfo->device_name_len);
3395 p2pielen += pwdinfo->device_name_len;
3396
3397 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen,
3398 (unsigned char *) p2pie, &pattrib->pktlen);
3399
3400#ifdef CONFIG_8723AU_P2P
3401 wfdielen = build_invitation_req_wfd_ie(pwdinfo, pframe);
3402 pframe += wfdielen;
3403 pattrib->pktlen += wfdielen;
3404#endif /* CONFIG_8723AU_P2P */
3405
3406 pattrib->last_txcmdsz = pattrib->pktlen;
3407
3408 dump_mgntframe23a(padapter, pmgntframe);
3409
3410 return;
3411}
3412
3413void issue_p2p_invitation_response23a(struct rtw_adapter *padapter, u8 *raddr,
3414 u8 dialogToken, u8 status_code)
3415{
3416 unsigned char category = WLAN_CATEGORY_PUBLIC;
3417 u8 action = P2P_PUB_ACTION_ACTION;
3418 u32 p2poui = cpu_to_be32(P2POUI);
3419 u8 oui_subtype = P2P_INVIT_RESP;
3420 u8 p2pie[ 255 ] = { 0x00 };
3421 u8 p2pielen = 0;
3422 u16 len_channellist_attr = 0;
3423#ifdef CONFIG_8723AU_P2P
3424 u32 wfdielen = 0;
3425#endif /* CONFIG_8723AU_P2P */
3426 int i, j;
3427
3428 struct xmit_frame *pmgntframe;
3429 struct pkt_attrib *pattrib;
3430 unsigned char *pframe;
3431 struct ieee80211_hdr *pwlanhdr;
3432 unsigned short *fctrl;
3433 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3434 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3435 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3436
3437 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
3438 return;
3439
3440 /* update attribute */
3441 pattrib = &pmgntframe->attrib;
3442 update_mgntframe_attrib23a(padapter, pattrib);
3443
3444 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3445
3446 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3447 pwlanhdr = (struct ieee80211_hdr *)pframe;
3448
3449 fctrl = &pwlanhdr->frame_control;
3450 *fctrl = 0;
3451
3452 ether_addr_copy(pwlanhdr->addr1, raddr);
3453 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3454 ether_addr_copy(pwlanhdr->addr3, raddr);
3455
3456 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3457 pmlmeext->mgnt_seq++;
3458 SetFrameSubType(pframe, WIFI_ACTION);
3459
3460 pframe += sizeof(struct ieee80211_hdr_3addr);
3461 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3462
3463 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
3464 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
3465 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui,
3466 &pattrib->pktlen);
3467 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
3468 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
3469
3470 /* P2P IE Section. */
3471
3472 /* P2P OUI */
3473 p2pielen = 0;
3474 p2pie[p2pielen++] = 0x50;
3475 p2pie[p2pielen++] = 0x6F;
3476 p2pie[p2pielen++] = 0x9A;
3477 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
3478
3479 /* Commented by Albert 20101005 */
3480 /* According to the P2P Specification, the P2P Invitation
3481 response frame should contain 5 P2P attributes */
3482 /* 1. Status */
3483 /* 2. Configuration Timeout */
3484 /* 3. Operating Channel (Only GO) */
3485 /* 4. P2P Group BSSID (Only GO) */
3486 /* 5. Channel List */
3487
3488 /* P2P Status */
3489 /* Type: */
3490 p2pie[p2pielen++] = P2P_ATTR_STATUS;
3491
3492 /* Length: */
3493 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0001);
3494 p2pielen += 2;
3495
3496 /* Value: */
3497 /* When status code is P2P_STATUS_FAIL_INFO_UNAVAILABLE. */
3498 /* Sent the event receiving the P2P Invitation Req frame
3499 to DMP UI. */
3500 /* DMP had to compare the MAC address to find out the profile. */
3501 /* So, the WiFi driver will send the
3502 P2P_STATUS_FAIL_INFO_UNAVAILABLE to NB. */
3503 /* If the UI found the corresponding profile, the WiFi driver
3504 sends the P2P Invitation Req */
3505 /* to NB to rebuild the persistent group. */
3506 p2pie[p2pielen++] = status_code;
3507
3508 /* Configuration Timeout */
3509 /* Type: */
3510 p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
3511
3512 /* Length: */
3513 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
3514 p2pielen += 2;
3515
3516 /* Value: */
3517 /* 2 seconds needed to be the P2P GO */
3518 p2pie[p2pielen++] = 200;
3519 /* 2 seconds needed to be the P2P Client */
3520 p2pie[p2pielen++] = 200;
3521
3522 if (status_code == P2P_STATUS_SUCCESS) {
3523 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
3524 /* The P2P Invitation request frame asks this
3525 Wi-Fi device to be the P2P GO */
3526 /* In this case, the P2P Invitation response
3527 frame should carry the two more P2P attributes. */
3528 /* First one is operating channel attribute. */
3529 /* Second one is P2P Group BSSID attribute. */
3530
3531 /* Operating Channel */
3532 /* Type: */
3533 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
3534
3535 /* Length: */
3536 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
3537 p2pielen += 2;
3538
3539 /* Value: */
3540 /* Country String */
3541 p2pie[p2pielen++] = 'X';
3542 p2pie[p2pielen++] = 'X';
3543
3544 /* The third byte should be set to 0x04. */
3545 /* Described in the "Operating Channel Attribute"
3546 section. */
3547 p2pie[p2pielen++] = 0x04;
3548
3549 /* Operating Class */
3550 /* Copy from SD7 */
3551 p2pie[p2pielen++] = 0x51;
3552
3553 /* Channel Number */
3554 /* operating channel number */
3555 p2pie[p2pielen++] = pwdinfo->operating_channel;
3556
3557 /* P2P Group BSSID */
3558 /* Type: */
3559 p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
3560
3561 /* Length: */
3562 *(u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
3563 p2pielen += 2;
3564
3565 /* Value: */
3566 /* P2P Device Address for GO */
3567 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv),
3568 ETH_ALEN);
3569 p2pielen += ETH_ALEN;
3570 }
3571
3572 /* Channel List */
3573 /* Type: */
3574 p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
3575
3576 /* Length: */
3577 /* Country String(3) */
3578 /* + (Operating Class (1) + Number of Channels(1)) *
3579 Operation Classes (?) */
3580 /* + number of channels in all classes */
3581 len_channellist_attr = 3 +
3582 (1 + 1) * (u16)pmlmeext->channel_list.reg_classes +
3583 get_reg_classes_full_count(pmlmeext->channel_list);
3584
3585 *(u16*) (p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
3586 p2pielen += 2;
3587
3588 /* Value: */
3589 /* Country String */
3590 p2pie[p2pielen++] = 'X';
3591 p2pie[p2pielen++] = 'X';
3592
3593 /* The third byte should be set to 0x04. */
3594 /* Described in the "Operating Channel Attribute" section. */
3595 p2pie[p2pielen++] = 0x04;
3596
3597 /* Channel Entry List */
3598 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
3599 /* Operating Class */
3600 p2pie[p2pielen++] =
3601 pmlmeext->channel_list.reg_class[j].reg_class;
3602
3603 /* Number of Channels */
3604 p2pie[p2pielen++] =
3605 pmlmeext->channel_list.reg_class[j].channels;
3606
3607 /* Channel List */
3608 for (i = 0;
3609 i < pmlmeext->channel_list.reg_class[j].channels;
3610 i++) {
3611 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
3612 }
3613 }
3614 }
3615
3616 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen,
3617 (unsigned char *)p2pie, &pattrib->pktlen);
3618
3619#ifdef CONFIG_8723AU_P2P
3620 wfdielen = build_invitation_resp_wfd_ie(pwdinfo, pframe);
3621 pframe += wfdielen;
3622 pattrib->pktlen += wfdielen;
3623#endif /* CONFIG_8723AU_P2P */
3624
3625 pattrib->last_txcmdsz = pattrib->pktlen;
3626
3627 dump_mgntframe23a(padapter, pmgntframe);
3628
3629 return;
3630}
3631
3632void issue_p2p_provision_request23a(struct rtw_adapter *padapter, u8 *pssid,
3633 u8 ussidlen, u8 *pdev_raddr)
3634{
3635 unsigned char category = WLAN_CATEGORY_PUBLIC;
3636 u8 action = P2P_PUB_ACTION_ACTION;
3637 u8 dialogToken = 1;
3638 u32 p2poui = cpu_to_be32(P2POUI);
3639 u8 oui_subtype = P2P_PROVISION_DISC_REQ;
3640 u8 wpsie[100] = { 0x00 };
3641 u8 wpsielen = 0;
3642 u32 p2pielen = 0;
3643#ifdef CONFIG_8723AU_P2P
3644 u32 wfdielen = 0;
3645#endif /* CONFIG_8723AU_P2P */
3646 struct xmit_frame *pmgntframe;
3647 struct pkt_attrib *pattrib;
3648 unsigned char *pframe;
3649 struct ieee80211_hdr *pwlanhdr;
3650 unsigned short *fctrl;
3651 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3652 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3653 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3654
3655 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
3656 return;
3657
3658 DBG_8723A("[%s] In\n", __func__);
3659 /* update attribute */
3660 pattrib = &pmgntframe->attrib;
3661 update_mgntframe_attrib23a(padapter, pattrib);
3662
3663 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3664
3665 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3666 pwlanhdr = (struct ieee80211_hdr *)pframe;
3667
3668 fctrl = &pwlanhdr->frame_control;
3669 *fctrl = 0;
3670
3671 ether_addr_copy(pwlanhdr->addr1, pdev_raddr);
3672 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3673 ether_addr_copy(pwlanhdr->addr3, pdev_raddr);
3674
3675 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3676 pmlmeext->mgnt_seq++;
3677 SetFrameSubType(pframe, WIFI_ACTION);
3678
3679 pframe += sizeof(struct ieee80211_hdr_3addr);
3680 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3681
3682 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
3683 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
3684 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui,
3685 &pattrib->pktlen);
3686 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
3687 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
3688
3689 p2pielen = build_prov_disc_request_p2p_ie23a(pwdinfo, pframe, pssid,
3690 ussidlen, pdev_raddr);
3691
3692 pframe += p2pielen;
3693 pattrib->pktlen += p2pielen;
3694
3695 wpsielen = 0;
3696 /* WPS OUI */
3697 *(u32*) (wpsie) = cpu_to_be32(WPSOUI);
3698 wpsielen += 4;
3699
3700 /* WPS version */
3701 /* Type: */
3702 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
3703 wpsielen += 2;
3704
3705 /* Length: */
3706 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
3707 wpsielen += 2;
3708
3709 /* Value: */
3710 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
3711
3712 /* Config Method */
3713 /* Type: */
3714 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
3715 wpsielen += 2;
3716
3717 /* Length: */
3718 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002);
3719 wpsielen += 2;
3720
3721 /* Value: */
3722 *(u16*) (wpsie + wpsielen) = cpu_to_be16(pwdinfo->tx_prov_disc_info.wps_config_method_request);
3723 wpsielen += 2;
3724
3725 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen,
3726 (unsigned char *) wpsie, &pattrib->pktlen);
3727
3728#ifdef CONFIG_8723AU_P2P
3729 wfdielen = build_provdisc_req_wfd_ie(pwdinfo, pframe);
3730 pframe += wfdielen;
3731 pattrib->pktlen += wfdielen;
3732#endif /* CONFIG_8723AU_P2P */
3733
3734 pattrib->last_txcmdsz = pattrib->pktlen;
3735
3736 dump_mgntframe23a(padapter, pmgntframe);
3737
3738 return;
3739}
3740
3741static u8 is_matched_in_profilelist(u8 *peermacaddr,
3742 struct profile_info *profileinfo)
3743{
3744 u8 i, match_result = 0;
3745
3746 DBG_8723A("[%s] peermac = %.2X %.2X %.2X %.2X %.2X %.2X\n", __func__,
3747 peermacaddr[0], peermacaddr[1], peermacaddr[2],
3748 peermacaddr[3], peermacaddr[4], peermacaddr[5]);
3749
3750 for (i = 0; i < P2P_MAX_PERSISTENT_GROUP_NUM; i++, profileinfo++) {
3751 DBG_8723A("[%s] profileinfo_mac = %.2X %.2X %.2X %.2X %.2X "
3752 "%.2X\n", __func__, profileinfo->peermac[0],
3753 profileinfo->peermac[1], profileinfo->peermac[2],
3754 profileinfo->peermac[3], profileinfo->peermac[4],
3755 profileinfo->peermac[5]);
3756 if (ether_addr_equal(peermacaddr, profileinfo->peermac)) {
3757 match_result = 1;
3758 DBG_8723A("[%s] Match!\n", __func__);
3759 break;
3760 }
3761 }
3762
3763 return match_result;
3764}
3765
3766void issue_probersp23a_p2p23a(struct rtw_adapter *padapter, unsigned char *da)
3767{
3768 struct xmit_frame *pmgntframe;
3769 struct pkt_attrib *pattrib;
3770 unsigned char *pframe;
3771 struct ieee80211_hdr *pwlanhdr;
3772 unsigned short *fctrl;
3773 unsigned char *mac;
3774 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3775 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3776 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3777 u16 beacon_interval = 100;
3778 u16 capInfo = 0;
3779 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3780 u8 wpsie[255] = { 0x00 };
3781 u32 wpsielen = 0, p2pielen = 0;
3782#ifdef CONFIG_8723AU_P2P
3783 u32 wfdielen = 0;
3784#endif /* CONFIG_8723AU_P2P */
3785 struct cfg80211_wifidirect_info *pcfg80211_wdinfo =
3786 &padapter->cfg80211_wdinfo;
3787 struct ieee80211_channel *ieee_ch =
3788 &pcfg80211_wdinfo->remain_on_ch_channel;
3789 u8 listen_channel =
3790 (u8)ieee80211_frequency_to_channel(ieee_ch->center_freq);
3791
3792 /* DBG_8723A("%s\n", __func__); */
3793
3794 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
3795 {
3796 return;
3797 }
3798
3799 /* update attribute */
3800 pattrib = &pmgntframe->attrib;
3801 update_mgntframe_attrib23a(padapter, pattrib);
3802
3803 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3804
3805 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3806 pwlanhdr = (struct ieee80211_hdr *)pframe;
3807
3808 mac = myid(&padapter->eeprompriv);
3809
3810 fctrl = &pwlanhdr->frame_control;
3811 *fctrl = 0;
3812 ether_addr_copy(pwlanhdr->addr1, da);
3813 ether_addr_copy(pwlanhdr->addr2, mac);
3814
3815 /* Use the device address for BSSID field. */
3816 ether_addr_copy(pwlanhdr->addr3, mac);
3817
3818 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3819 pmlmeext->mgnt_seq++;
3820 SetFrameSubType(fctrl, WIFI_PROBERSP);
3821
3822 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
3823 pattrib->pktlen = pattrib->hdrlen;
3824 pframe += pattrib->hdrlen;
3825
3826 /* timestamp will be inserted by hardware */
3827 pframe += 8;
3828 pattrib->pktlen += 8;
3829
3830 /* beacon interval: 2 bytes */
3831 memcpy(pframe, (unsigned char *) &beacon_interval, 2);
3832 pframe += 2;
3833 pattrib->pktlen += 2;
3834
3835 /* capability info: 2 bytes */
3836 /* ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of
3837 WiFi Direct Spec) */
3838 capInfo |= cap_ShortPremble;
3839 capInfo |= cap_ShortSlot;
3840
3841 memcpy(pframe, (unsigned char *) &capInfo, 2);
3842 pframe += 2;
3843 pattrib->pktlen += 2;
3844
3845 /* SSID */
3846 pframe = rtw_set_ie23a(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid,
3847 &pattrib->pktlen);
3848
3849 /* supported rates... */
3850 /* Use the OFDM rate in the P2P probe response frame.
3851 (6(B), 9(B), 12, 18, 24, 36, 48, 54) */
3852 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, 8,
3853 pwdinfo->support_rate, &pattrib->pktlen);
3854
3855 /* DS parameter set */
3856 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled &&
3857 listen_channel != 0) {
3858 pframe = rtw_set_ie23a(pframe, _DSSET_IE_, 1, (unsigned char *)
3859 &listen_channel, &pattrib->pktlen);
3860 } else {
3861 pframe = rtw_set_ie23a(pframe, _DSSET_IE_, 1, (unsigned char *)
3862 &pwdinfo->listen_channel,
3863 &pattrib->pktlen);
3864 }
3865
3866 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
3867 if (pmlmepriv->wps_probe_resp_ie &&
3868 pmlmepriv->p2p_probe_resp_ie) {
3869 /* WPS IE */
3870 memcpy(pframe, pmlmepriv->wps_probe_resp_ie,
3871 pmlmepriv->wps_probe_resp_ie_len);
3872 pattrib->pktlen += pmlmepriv->wps_probe_resp_ie_len;
3873 pframe += pmlmepriv->wps_probe_resp_ie_len;
3874
3875 /* P2P IE */
3876 memcpy(pframe, pmlmepriv->p2p_probe_resp_ie,
3877 pmlmepriv->p2p_probe_resp_ie_len);
3878 pattrib->pktlen += pmlmepriv->p2p_probe_resp_ie_len;
3879 pframe += pmlmepriv->p2p_probe_resp_ie_len;
3880 }
3881 } else {
3882
3883 /* Todo: WPS IE */
3884 /* Noted by Albert 20100907 */
3885 /* According to the WPS specification, all the WPS
3886 attribute is presented by Big Endian. */
3887
3888 wpsielen = 0;
3889 /* WPS OUI */
3890 *(u32*) (wpsie) = cpu_to_be32(WPSOUI);
3891 wpsielen += 4;
3892
3893 /* WPS version */
3894 /* Type: */
3895 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
3896 wpsielen += 2;
3897
3898 /* Length: */
3899 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
3900 wpsielen += 2;
3901
3902 /* Value: */
3903 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
3904
3905 /* WiFi Simple Config State */
3906 /* Type: */
3907 *(u16*) (wpsie + wpsielen) =
3908 cpu_to_be16(WPS_ATTR_SIMPLE_CONF_STATE);
3909 wpsielen += 2;
3910
3911 /* Length: */
3912 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
3913 wpsielen += 2;
3914
3915 /* Value: */
3916 wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG;
3917
3918 /* Response Type */
3919 /* Type: */
3920 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_RESP_TYPE);
3921 wpsielen += 2;
3922
3923 /* Length: */
3924 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
3925 wpsielen += 2;
3926
3927 /* Value: */
3928 wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X;
3929
3930 /* UUID-E */
3931 /* Type: */
3932 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);
3933 wpsielen += 2;
3934
3935 /* Length: */
3936 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0010);
3937 wpsielen += 2;
3938
3939 /* Value: */
3940 memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv), ETH_ALEN);
3941 wpsielen += 0x10;
3942
3943 /* Manufacturer */
3944 /* Type: */
3945 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MANUFACTURER);
3946 wpsielen += 2;
3947
3948 /* Length: */
3949 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0007);
3950 wpsielen += 2;
3951
3952 /* Value: */
3953 memcpy(wpsie + wpsielen, "Realtek", 7);
3954 wpsielen += 7;
3955
3956 /* Model Name */
3957 /* Type: */
3958 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NAME);
3959 wpsielen += 2;
3960
3961 /* Length: */
3962 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0006);
3963 wpsielen += 2;
3964
3965 /* Value: */
3966 memcpy(wpsie + wpsielen, "8192CU", 6);
3967 wpsielen += 6;
3968
3969 /* Model Number */
3970 /* Type: */
3971 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NUMBER);
3972 wpsielen += 2;
3973
3974 /* Length: */
3975 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
3976 wpsielen += 2;
3977
3978 /* Value: */
3979 wpsie[ wpsielen++ ] = 0x31; /* character 1 */
3980
3981 /* Serial Number */
3982 /* Type: */
3983 *(u16*) (wpsie + wpsielen) =
3984 cpu_to_be16(WPS_ATTR_SERIAL_NUMBER);
3985 wpsielen += 2;
3986
3987 /* Length: */
3988 *(u16*) (wpsie + wpsielen) = cpu_to_be16(ETH_ALEN);
3989 wpsielen += 2;
3990
3991 /* Value: */
3992 memcpy(wpsie + wpsielen, "123456", ETH_ALEN);
3993 wpsielen += ETH_ALEN;
3994
3995 /* Primary Device Type */
3996 /* Type: */
3997 *(u16*) (wpsie + wpsielen) =
3998 cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
3999 wpsielen += 2;
4000
4001 /* Length: */
4002 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0008);
4003 wpsielen += 2;
4004
4005 /* Value: */
4006 /* Category ID */
4007 *(u16*) (wpsie + wpsielen) =
4008 cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
4009 wpsielen += 2;
4010
4011 /* OUI */
4012 *(u32*) (wpsie + wpsielen) = cpu_to_be32(WPSOUI);
4013 wpsielen += 4;
4014
4015 /* Sub Category ID */
4016 *(u16*) (wpsie + wpsielen) =
4017 cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
4018 wpsielen += 2;
4019
4020 /* Device Name */
4021 /* Type: */
4022 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
4023 wpsielen += 2;
4024
4025 /* Length: */
4026 *(u16*) (wpsie + wpsielen) =
4027 cpu_to_be16(pwdinfo->device_name_len);
4028 wpsielen += 2;
4029
4030 /* Value: */
4031 if (pwdinfo->device_name_len) {
4032 memcpy(wpsie + wpsielen, pwdinfo->device_name,
4033 pwdinfo->device_name_len);
4034 wpsielen += pwdinfo->device_name_len;
4035 }
4036
4037 /* Config Method */
4038 /* Type: */
4039 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
4040 wpsielen += 2;
4041
4042 /* Length: */
4043 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002);
4044 wpsielen += 2;
4045
4046 /* Value: */
4047 *(u16*) (wpsie + wpsielen) =
4048 cpu_to_be16(pwdinfo->supported_wps_cm);
4049 wpsielen += 2;
4050
4051 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen,
4052 (unsigned char *)wpsie,
4053 &pattrib->pktlen);
4054
4055 p2pielen = build_probe_resp_p2p_ie23a(pwdinfo, pframe);
4056 pframe += p2pielen;
4057 pattrib->pktlen += p2pielen;
4058 }
4059
4060#ifdef CONFIG_8723AU_P2P
4061 if (pwdinfo->wfd_info->wfd_enable) {
4062 wfdielen = build_probe_resp_wfd_ie(pwdinfo, pframe, 0);
4063 pframe += wfdielen;
4064 pattrib->pktlen += wfdielen;
4065 } else if (pmlmepriv->wfd_probe_resp_ie &&
4066 pmlmepriv->wfd_probe_resp_ie_len > 0) {
4067 /* WFD IE */
4068 memcpy(pframe, pmlmepriv->wfd_probe_resp_ie,
4069 pmlmepriv->wfd_probe_resp_ie_len);
4070 pattrib->pktlen += pmlmepriv->wfd_probe_resp_ie_len;
4071 pframe += pmlmepriv->wfd_probe_resp_ie_len;
4072 }
4073#endif /* CONFIG_8723AU_P2P */
4074
4075 pattrib->last_txcmdsz = pattrib->pktlen;
4076
4077 dump_mgntframe23a(padapter, pmgntframe);
4078
4079 return;
4080}
4081
4082static int _issue23a_probereq_p2p(struct rtw_adapter *padapter, u8 *da,
4083 int wait_ack)
4084{
4085 int ret = _FAIL;
4086 struct xmit_frame *pmgntframe;
4087 struct pkt_attrib *pattrib;
4088 unsigned char *pframe;
4089 struct ieee80211_hdr *pwlanhdr;
4090 unsigned short *fctrl;
4091 unsigned char *mac;
4092 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
4093 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4094 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
4095 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
4096 u8 wpsie[255] = {0x00}, p2pie[255] = {0x00};
4097 u16 wpsielen = 0, p2pielen = 0;
4098#ifdef CONFIG_8723AU_P2P
4099 u32 wfdielen = 0;
4100#endif /* CONFIG_8723AU_P2P */
4101 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4102
4103 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
4104 goto exit;
4105
4106 /* update attribute */
4107 pattrib = &pmgntframe->attrib;
4108 update_mgntframe_attrib23a(padapter, pattrib);
4109
4110 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4111
4112 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4113 pwlanhdr = (struct ieee80211_hdr *)pframe;
4114
4115 mac = myid(&padapter->eeprompriv);
4116
4117 fctrl = &pwlanhdr->frame_control;
4118 *fctrl = 0;
4119
4120 if (da) {
4121 ether_addr_copy(pwlanhdr->addr1, da);
4122 ether_addr_copy(pwlanhdr->addr3, da);
4123 } else {
4124 if ((pwdinfo->p2p_info.scan_op_ch_only) ||
4125 (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
4126 /* This two flags will be set when this is
4127 only the P2P client mode. */
4128 ether_addr_copy(pwlanhdr->addr1,
4129 pwdinfo->p2p_peer_interface_addr);
4130 ether_addr_copy(pwlanhdr->addr3,
4131 pwdinfo->p2p_peer_interface_addr);
4132 } else {
4133 /* broadcast probe request frame */
4134 ether_addr_copy(pwlanhdr->addr1, bc_addr);
4135 ether_addr_copy(pwlanhdr->addr3, bc_addr);
4136 }
4137 }
4138 ether_addr_copy(pwlanhdr->addr2, mac);
4139
4140 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4141 pmlmeext->mgnt_seq++;
4142 SetFrameSubType(pframe, WIFI_PROBEREQ);
4143
4144 pframe += sizeof (struct ieee80211_hdr_3addr);
4145 pattrib->pktlen = sizeof (struct ieee80211_hdr_3addr);
4146
4147 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
4148 pframe = rtw_set_ie23a(pframe, _SSID_IE_,
4149 pwdinfo->tx_prov_disc_info.ssid.ssid_len,
4150 pwdinfo->tx_prov_disc_info.ssid.ssid,
4151 &pattrib->pktlen);
4152 } else {
4153 pframe = rtw_set_ie23a(pframe, _SSID_IE_,
4154 P2P_WILDCARD_SSID_LEN,
4155 pwdinfo->p2p_wildcard_ssid,
4156 &pattrib->pktlen);
4157 }
4158 /* Use the OFDM rate in the P2P probe request frame.
4159 (6(B), 9(B), 12(B), 24(B), 36, 48, 54) */
4160 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, 8,
4161 pwdinfo->support_rate, &pattrib->pktlen);
4162
4163 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
4164 if (pmlmepriv->wps_probe_req_ie &&
4165 pmlmepriv->p2p_probe_req_ie) {
4166 /* WPS IE */
4167 memcpy(pframe, pmlmepriv->wps_probe_req_ie,
4168 pmlmepriv->wps_probe_req_ie_len);
4169 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
4170 pframe += pmlmepriv->wps_probe_req_ie_len;
4171
4172 /* P2P IE */
4173 memcpy(pframe, pmlmepriv->p2p_probe_req_ie,
4174 pmlmepriv->p2p_probe_req_ie_len);
4175 pattrib->pktlen += pmlmepriv->p2p_probe_req_ie_len;
4176 pframe += pmlmepriv->p2p_probe_req_ie_len;
4177 }
4178 } else {
4179
4180 /* WPS IE */
4181 /* Noted by Albert 20110221 */
4182 /* According to the WPS specification, all the WPS
4183 attribute is presented by Big Endian. */
4184
4185 wpsielen = 0;
4186 /* WPS OUI */
4187 *(u32*) (wpsie) = cpu_to_be32(WPSOUI);
4188 wpsielen += 4;
4189
4190 /* WPS version */
4191 /* Type: */
4192 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
4193 wpsielen += 2;
4194
4195 /* Length: */
4196 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
4197 wpsielen += 2;
4198
4199 /* Value: */
4200 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
4201
4202 if (pmlmepriv->wps_probe_req_ie == NULL) {
4203 /* UUID-E */
4204 /* Type: */
4205 *(u16*) (wpsie + wpsielen) =
4206 cpu_to_be16(WPS_ATTR_UUID_E);
4207 wpsielen += 2;
4208
4209 /* Length: */
4210 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0010);
4211 wpsielen += 2;
4212
4213 /* Value: */
4214 memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv),
4215 ETH_ALEN);
4216 wpsielen += 0x10;
4217
4218 /* Config Method */
4219 /* Type: */
4220 *(u16*) (wpsie + wpsielen) =
4221 cpu_to_be16(WPS_ATTR_CONF_METHOD);
4222 wpsielen += 2;
4223
4224 /* Length: */
4225 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002);
4226 wpsielen += 2;
4227
4228 /* Value: */
4229 *(u16*) (wpsie + wpsielen) =
4230 cpu_to_be16(pwdinfo->supported_wps_cm);
4231 wpsielen += 2;
4232 }
4233
4234 /* Device Name */
4235 /* Type: */
4236 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
4237 wpsielen += 2;
4238
4239 /* Length: */
4240 *(u16*) (wpsie + wpsielen) =
4241 cpu_to_be16(pwdinfo->device_name_len);
4242 wpsielen += 2;
4243
4244 /* Value: */
4245 memcpy(wpsie + wpsielen, pwdinfo->device_name,
4246 pwdinfo->device_name_len);
4247 wpsielen += pwdinfo->device_name_len;
4248
4249 /* Primary Device Type */
4250 /* Type: */
4251 *(u16*) (wpsie + wpsielen) =
4252 cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
4253 wpsielen += 2;
4254
4255 /* Length: */
4256 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0008);
4257 wpsielen += 2;
4258
4259 /* Value: */
4260 /* Category ID */
4261 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_RTK_WIDI);
4262 wpsielen += 2;
4263
4264 /* OUI */
4265 *(u32*) (wpsie + wpsielen) = cpu_to_be32(WPSOUI);
4266 wpsielen += 4;
4267
4268 /* Sub Category ID */
4269 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_RTK_DMP);
4270 wpsielen += 2;
4271
4272 /* Device Password ID */
4273 /* Type: */
4274 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
4275 wpsielen += 2;
4276
4277 /* Length: */
4278 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002);
4279 wpsielen += 2;
4280
4281 /* Value: */
4282 /* Registrar-specified */
4283 *(u16*) (wpsie + wpsielen) =
4284 cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
4285 wpsielen += 2;
4286
4287 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen,
4288 (unsigned char *)wpsie,
4289 &pattrib->pktlen);
4290
4291 /* P2P OUI */
4292 p2pielen = 0;
4293 p2pie[p2pielen++] = 0x50;
4294 p2pie[p2pielen++] = 0x6F;
4295 p2pie[p2pielen++] = 0x9A;
4296 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
4297
4298 /* Commented by Albert 20110221 */
4299 /* According to the P2P Specification, the probe request
4300 frame should contain 5 P2P attributes */
4301 /* 1. P2P Capability */
4302 /* 2. P2P Device ID if this probe request wants to
4303 find the specific P2P device */
4304 /* 3. Listen Channel */
4305 /* 4. Extended Listen Timing */
4306 /* 5. Operating Channel if this WiFi is working as
4307 the group owner now */
4308
4309 /* P2P Capability */
4310 /* Type: */
4311 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
4312
4313 /* Length: */
4314 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
4315 p2pielen += 2;
4316
4317 /* Value: */
4318 /* Device Capability Bitmap, 1 byte */
4319 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
4320
4321 /* Group Capability Bitmap, 1 byte */
4322 if (pwdinfo->persistent_supported)
4323 p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP |
4324 DMP_P2P_GRPCAP_SUPPORT;
4325 else
4326 p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
4327
4328 /* Listen Channel */
4329 /* Type: */
4330 p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
4331
4332 /* Length: */
4333 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
4334 p2pielen += 2;
4335
4336 /* Value: */
4337 /* Country String */
4338 p2pie[p2pielen++] = 'X';
4339 p2pie[p2pielen++] = 'X';
4340
4341 /* The third byte should be set to 0x04. */
4342 /* Described in the "Operating Channel Attribute" section. */
4343 p2pie[p2pielen++] = 0x04;
4344
4345 /* Operating Class */
4346 p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
4347
4348 /* Channel Number */
4349 /* listen channel */
4350 p2pie[p2pielen++] = pwdinfo->listen_channel;
4351
4352 /* Extended Listen Timing */
4353 /* Type: */
4354 p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
4355
4356 /* Length: */
4357 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0004);
4358 p2pielen += 2;
4359
4360 /* Value: */
4361 /* Availability Period */
4362 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF);
4363 p2pielen += 2;
4364
4365 /* Availability Interval */
4366 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF);
4367 p2pielen += 2;
4368
4369 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
4370 /* Operating Channel (if this WiFi is working as
4371 the group owner now) */
4372 /* Type: */
4373 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
4374
4375 /* Length: */
4376 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
4377 p2pielen += 2;
4378
4379 /* Value: */
4380 /* Country String */
4381 p2pie[p2pielen++] = 'X';
4382 p2pie[p2pielen++] = 'X';
4383
4384 /* The third byte should be set to 0x04. */
4385 /* Described in the "Operating Channel Attribute"
4386 section. */
4387 p2pie[p2pielen++] = 0x04;
4388
4389 /* Operating Class */
4390 p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
4391
4392 /* Channel Number */
4393 /* operating channel number */
4394 p2pie[p2pielen++] = pwdinfo->operating_channel;
4395 }
4396
4397 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen,
4398 (unsigned char *)p2pie,
4399 &pattrib->pktlen);
4400
4401 if (pmlmepriv->wps_probe_req_ie) {
4402 /* WPS IE */
4403 memcpy(pframe, pmlmepriv->wps_probe_req_ie,
4404 pmlmepriv->wps_probe_req_ie_len);
4405 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
4406 pframe += pmlmepriv->wps_probe_req_ie_len;
4407 }
4408 }
4409
4410#ifdef CONFIG_8723AU_P2P
4411 if (pwdinfo->wfd_info->wfd_enable) {
4412 wfdielen = build_probe_req_wfd_ie(pwdinfo, pframe);
4413 pframe += wfdielen;
4414 pattrib->pktlen += wfdielen;
4415 } else if (pmlmepriv->wfd_probe_req_ie &&
4416 pmlmepriv->wfd_probe_req_ie_len>0) {
4417 /* WFD IE */
4418 memcpy(pframe, pmlmepriv->wfd_probe_req_ie,
4419 pmlmepriv->wfd_probe_req_ie_len);
4420 pattrib->pktlen += pmlmepriv->wfd_probe_req_ie_len;
4421 pframe += pmlmepriv->wfd_probe_req_ie_len;
4422 }
4423#endif /* CONFIG_8723AU_P2P */
4424
4425 pattrib->last_txcmdsz = pattrib->pktlen;
4426
4427 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
4428 ("issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz));
4429
4430 if (wait_ack) {
4431 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
4432 } else {
4433 dump_mgntframe23a(padapter, pmgntframe);
4434 ret = _SUCCESS;
4435 }
4436
4437exit:
4438 return ret;
4439}
4440
4441inline void issue23a_probereq_p2p(struct rtw_adapter *adapter, u8 *da)
4442{
4443 _issue23a_probereq_p2p(adapter, da, false);
4444}
4445
4446int issue23a_probereq_p2p_ex(struct rtw_adapter *adapter, u8 *da,
4447 int try_cnt, int wait_ms)
4448{
4449 int ret;
4450 int i = 0;
4451 unsigned long start = jiffies;
4452
4453 do {
4454 ret = _issue23a_probereq_p2p(adapter, da,
4455 wait_ms > 0 ? true : false);
4456
4457 i++;
4458
4459 if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
4460 break;
4461
4462 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
4463 msleep(wait_ms);
4464
4465 } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
4466
4467 if (ret != _FAIL) {
4468 ret = _SUCCESS;
4469 goto exit;
4470 }
4471
4472 if (try_cnt && wait_ms) {
4473 if (da)
4474 DBG_8723A(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d "
4475 "in %u ms\n", FUNC_ADPT_ARG(adapter),
4476 MAC_ARG(da), rtw_get_oper_ch23a(adapter),
4477 ret == _SUCCESS?", acked":"", i, try_cnt,
4478 jiffies_to_msecs(jiffies - start));
4479 else
4480 DBG_8723A(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
4481 FUNC_ADPT_ARG(adapter),
4482 rtw_get_oper_ch23a(adapter),
4483 ret == _SUCCESS?", acked":"", i, try_cnt,
4484 jiffies_to_msecs(jiffies - start));
4485 }
4486exit:
4487 return ret;
4488}
4489
4490#endif /* CONFIG_8723AU_P2P */
4491
4492static s32 rtw_action_public_decache(struct recv_frame *recv_frame, s32 token)
4493{
4494 struct rtw_adapter *adapter = recv_frame->adapter;
4495 struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
4496 struct sk_buff *skb = recv_frame->pkt;
4497 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
4498 u16 seq_ctrl;
4499
4500 seq_ctrl = ((recv_frame->attrib.seq_num&0xffff) << 4) |
4501 (recv_frame->attrib.frag_num & 0xf);
4502
4503 if (ieee80211_has_retry(hdr->frame_control)) {
4504 if (token >= 0) {
4505 if ((seq_ctrl == mlmeext->action_public_rxseq) &&
4506 (token == mlmeext->action_public_dialog_token)) {
4507 DBG_8723A(FUNC_ADPT_FMT" seq_ctrl = 0x%x, "
4508 "rxseq = 0x%x, token:%d\n",
4509 FUNC_ADPT_ARG(adapter), seq_ctrl,
4510 mlmeext->action_public_rxseq, token);
4511 return _FAIL;
4512 }
4513 } else {
4514 if (seq_ctrl == mlmeext->action_public_rxseq) {
4515 DBG_8723A(FUNC_ADPT_FMT" seq_ctrl = 0x%x, "
4516 "rxseq = 0x%x\n",
4517 FUNC_ADPT_ARG(adapter), seq_ctrl,
4518 mlmeext->action_public_rxseq);
4519 return _FAIL;
4520 }
4521 }
4522 }
4523
4524 mlmeext->action_public_rxseq = seq_ctrl;
4525
4526 if (token >= 0)
4527 mlmeext->action_public_dialog_token = token;
4528
4529 return _SUCCESS;
4530}
4531
4532static unsigned int on_action_public23a_p2p(struct recv_frame *precv_frame)
4533{
4534 struct rtw_adapter *padapter = precv_frame->adapter;
4535 struct sk_buff *skb = precv_frame->pkt;
4536 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
4537 u8 *pframe = skb->data;
4538 uint len = skb->len;
4539 u8 *frame_body;
4540 u8 dialogToken = 0;
4541#ifdef CONFIG_8723AU_P2P
4542 u8 *p2p_ie;
4543 u32 p2p_ielen;
4544 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
4545 u8 result = P2P_STATUS_SUCCESS;
4546#endif /* CONFIG_8723AU_P2P */
4547
4548 frame_body = (unsigned char *)
4549 (pframe + sizeof(struct ieee80211_hdr_3addr));
4550
4551 dialogToken = frame_body[7];
4552
4553 if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
4554 return _FAIL;
4555
4556#ifdef CONFIG_8723AU_P2P
4557 del_timer_sync(&pwdinfo->reset_ch_sitesurvey);
4558 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
4559 rtw_cfg80211_rx_p2p_action_public(padapter, pframe, len);
4560 } else {
4561 /* Do nothing if the driver doesn't enable the P2P function. */
4562 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
4563 return _SUCCESS;
4564
4565 len -= sizeof(struct ieee80211_hdr_3addr);
4566
4567 switch (frame_body[ 6 ])/* OUI Subtype */
4568 {
4569 case P2P_GO_NEGO_REQ:
4570 DBG_8723A("[%s] Got GO Nego Req Frame\n", __func__);
4571 memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
4572
4573 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
4574 {
4575 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
4576 }
4577
4578 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
4579 {
4580 /* Commented by Albert 20110526 */
4581 /* In this case, this means the previous nego fail doesn't be reset yet. */
4582 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
4583 /* Restore the previous p2p state */
4584 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
4585 DBG_8723A("[%s] Restore the previous p2p state to %d\n", __func__, rtw_p2p_state(pwdinfo));
4586 }
4587
4588 /* Commented by Kurt 20110902 */
4589 /* Add if statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
4590 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
4591 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
4592
4593 /* Commented by Kurt 20120113 */
4594 /* Get peer_dev_addr here if peer doesn't issue prov_disc frame. */
4595 if (is_zero_ether_addr(pwdinfo->rx_prov_disc_info.peerDevAddr))
4596 ether_addr_copy(pwdinfo->rx_prov_disc_info.peerDevAddr, hdr->addr2);
4597
4598 result = process_p2p_group_negotation_req23a(pwdinfo, frame_body, len);
4599 issue_p2p_GO_response(padapter, hdr->addr2,
4600 frame_body, len, result);
4601
4602 /* Commented by Albert 20110718 */
4603 /* No matter negotiating or negotiation failure, the driver should set up the restore P2P state timer. */
4604 mod_timer(&pwdinfo->restore_p2p_state_timer,
4605 jiffies + msecs_to_jiffies(5000));
4606 break;
4607
4608 case P2P_GO_NEGO_RESP:
4609 DBG_8723A("[%s] Got GO Nego Resp Frame\n", __func__);
4610
4611 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
4612 {
4613 /* Commented by Albert 20110425 */
4614 /* The restore timer is enabled when issuing the nego request frame of rtw_p2p_connect function. */
4615 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
4616 pwdinfo->nego_req_info.benable = false;
4617 result = process_p2p_group_negotation_resp23a(pwdinfo, frame_body, len);
4618 issue_p2p_GO_confirm(pwdinfo->padapter,
4619 hdr->addr2,
4620 result);
4621 if (result == P2P_STATUS_SUCCESS) {
4622 if (rtw_p2p_role(pwdinfo) ==
4623 P2P_ROLE_CLIENT) {
4624 pwdinfo->p2p_info.operation_ch[ 0 ] = pwdinfo->peer_operating_ch;
4625 pwdinfo->p2p_info.scan_op_ch_only = 1;
4626 mod_timer(&pwdinfo->reset_ch_sitesurvey2, jiffies + msecs_to_jiffies(P2P_RESET_SCAN_CH));
4627 }
4628 }
4629
4630 /* Reset the dialog token for group negotiation frames. */
4631 pwdinfo->negotiation_dialog_token = 1;
4632
4633 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
4634 {
4635 mod_timer(&pwdinfo->restore_p2p_state_timer, jiffies + msecs_to_jiffies(5000));
4636 }
4637 } else {
4638 DBG_8723A("[%s] Skipped GO Nego Resp Frame (p2p_state != P2P_STATE_GONEGO_ING)\n", __func__);
4639 }
4640
4641 break;
4642
4643 case P2P_GO_NEGO_CONF:
4644
4645 DBG_8723A("[%s] Got GO Nego Confirm Frame\n", __func__);
4646 result = process_p2p_group_negotation_confirm23a(pwdinfo, frame_body, len);
4647 if (P2P_STATUS_SUCCESS == result)
4648 {
4649 if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT)
4650 {
4651 pwdinfo->p2p_info.operation_ch[ 0 ] = pwdinfo->peer_operating_ch;
4652 pwdinfo->p2p_info.scan_op_ch_only = 1;
4653 mod_timer(&pwdinfo->reset_ch_sitesurvey2, jiffies + msecs_to_jiffies(P2P_RESET_SCAN_CH));
4654 }
4655 }
4656 break;
4657
4658 case P2P_INVIT_REQ:
4659 /* Added by Albert 2010/10/05 */
4660 /* Received the P2P Invite Request frame. */
4661
4662 DBG_8723A("[%s] Got invite request frame!\n", __func__);
4663 if ((p2p_ie = rtw_get_p2p_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen)))
4664 {
4665 /* Parse the necessary information from the P2P Invitation Request frame. */
4666 /* For example: The MAC address of sending this P2P Invitation Request frame. */
4667 u32 attr_contentlen = 0;
4668 u8 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4669 struct group_id_info group_id;
4670 u8 invitation_flag = 0;
4671
4672 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, &invitation_flag, &attr_contentlen);
4673 if (attr_contentlen)
4674 {
4675
4676 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, pwdinfo->p2p_peer_interface_addr, &attr_contentlen);
4677 /* Commented by Albert 20120510 */
4678 /* Copy to the pwdinfo->p2p_peer_interface_addr. */
4679 /* So that the WFD UI (or Sigma) can get the peer interface address by using the following command. */
4680 /* #> iwpriv wlan0 p2p_get peer_ifa */
4681 /* After having the peer interface address, the sigma can find the correct conf file for wpa_supplicant. */
4682
4683 if (attr_contentlen)
4684 {
4685 DBG_8723A("[%s] GO's BSSID = %.2X %.2X %.2X %.2X %.2X %.2X\n", __func__,
4686 pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1],
4687 pwdinfo->p2p_peer_interface_addr[2], pwdinfo->p2p_peer_interface_addr[3],
4688 pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
4689 }
4690
4691 if (invitation_flag & P2P_INVITATION_FLAGS_PERSISTENT)
4692 {
4693 /* Re-invoke the persistent group. */
4694
4695 memset(&group_id, 0x00, sizeof(struct group_id_info));
4696 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8*) &group_id, &attr_contentlen);
4697 if (attr_contentlen) {
4698 if (ether_addr_equal(group_id.go_device_addr, myid(&padapter->eeprompriv))) {
4699 /* The p2p device sending this p2p invitation request wants this Wi-Fi device to be the persistent GO. */
4700 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_GO);
4701 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
4702 status_code = P2P_STATUS_SUCCESS;
4703 }
4704 else
4705 {
4706 /* The p2p device sending this p2p invitation request wants to be the persistent GO. */
4707 if (is_matched_in_profilelist(pwdinfo->p2p_peer_interface_addr, &pwdinfo->profileinfo[ 0 ]))
4708 {
4709 u8 operatingch_info[5] = { 0x00 };
4710 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
4711 {
4712 if (rtw_ch_set_search_ch23a(padapter->mlmeextpriv.channel_set, (u32)operatingch_info[4]))
4713 {
4714 /* The operating channel is acceptable for this device. */
4715 pwdinfo->rx_invitereq_info.operation_ch[0]= operatingch_info[4];
4716 pwdinfo->rx_invitereq_info.scan_op_ch_only = 1;
4717 mod_timer(&pwdinfo->reset_ch_sitesurvey, jiffies + msecs_to_jiffies(P2P_RESET_SCAN_CH));
4718 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
4719 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
4720 status_code = P2P_STATUS_SUCCESS;
4721 }
4722 else
4723 {
4724 /* The operating channel isn't supported by this device. */
4725 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
4726 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
4727 status_code = P2P_STATUS_FAIL_NO_COMMON_CH;
4728 mod_timer(&pwdinfo->restore_p2p_state_timer, jiffies + msecs_to_jiffies(3000));
4729 }
4730 }
4731 else {
4732 /* Commented by Albert 20121130 */
4733 /* Intel will use the different P2P IE to store the operating channel information */
4734 /* Workaround for Intel WiDi 3.5 */
4735 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
4736 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
4737 status_code = P2P_STATUS_SUCCESS;
4738 }
4739 }
4740 else
4741 {
4742 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
4743
4744 status_code = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
4745 }
4746 }
4747 }
4748 else
4749 {
4750 DBG_8723A("[%s] P2P Group ID Attribute NOT FOUND!\n", __func__);
4751 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4752 }
4753 }
4754 else
4755 {
4756 /* Received the invitation to join a P2P group. */
4757
4758 memset(&group_id, 0x00, sizeof(struct group_id_info));
4759 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8*) &group_id, &attr_contentlen);
4760 if (attr_contentlen)
4761 {
4762 if (ether_addr_equal(group_id.go_device_addr, myid(&padapter->eeprompriv))) {
4763 /* In this case, the GO can't be myself. */
4764 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
4765 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4766 }
4767 else
4768 {
4769 /* The p2p device sending this p2p invitation request wants to join an existing P2P group */
4770 /* Commented by Albert 2012/06/28 */
4771 /* In this case, this Wi-Fi device should use the iwpriv command to get the peer device address. */
4772 /* The peer device address should be the destination address for the provisioning discovery request. */
4773 /* Then, this Wi-Fi device should use the iwpriv command to get the peer interface address. */
4774 /* The peer interface address should be the address for WPS mac address */
4775 ether_addr_copy(pwdinfo->p2p_peer_device_addr, group_id.go_device_addr);
4776 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
4777 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_JOIN);
4778 status_code = P2P_STATUS_SUCCESS;
4779 }
4780 }
4781 else
4782 {
4783 DBG_8723A("[%s] P2P Group ID Attribute NOT FOUND!\n", __func__);
4784 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4785 }
4786 }
4787 }
4788 else
4789 {
4790 DBG_8723A("[%s] P2P Invitation Flags Attribute NOT FOUND!\n", __func__);
4791 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4792 }
4793
4794 DBG_8723A("[%s] status_code = %d\n", __func__, status_code);
4795
4796 pwdinfo->inviteresp_info.token = frame_body[ 7 ];
4797 issue_p2p_invitation_response23a(padapter, hdr->addr2, pwdinfo->inviteresp_info.token, status_code);
4798 }
4799 break;
4800
4801 case P2P_INVIT_RESP:
4802 {
4803 u8 attr_content = 0x00;
4804 u32 attr_contentlen = 0;
4805
4806 DBG_8723A("[%s] Got invite response frame!\n", __func__);
4807 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
4808 if ((p2p_ie = rtw_get_p2p_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen)))
4809 {
4810 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
4811
4812 if (attr_contentlen == 1)
4813 {
4814 DBG_8723A("[%s] Status = %d\n", __func__, attr_content);
4815 pwdinfo->invitereq_info.benable = false;
4816
4817 if (attr_content == P2P_STATUS_SUCCESS)
4818 {
4819 if (ether_addr_equal(pwdinfo->invitereq_info.go_bssid, myid(&padapter->eeprompriv))) {
4820 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
4821 }
4822 else
4823 {
4824 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
4825 }
4826 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_OK);
4827 }
4828 else
4829 {
4830 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
4831 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
4832 }
4833 }
4834 else
4835 {
4836 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
4837 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
4838 }
4839 }
4840 else
4841 {
4842 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
4843 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
4844 }
4845
4846 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL)) {
4847 mod_timer(&pwdinfo->restore_p2p_state_timer, jiffies + msecs_to_jiffies(5000));
4848 }
4849 break;
4850 }
4851 case P2P_DEVDISC_REQ:
4852
4853 process_p2p_devdisc_req23a(pwdinfo, pframe, len);
4854
4855 break;
4856
4857 case P2P_DEVDISC_RESP:
4858
4859 process_p2p_devdisc_resp23a(pwdinfo, pframe, len);
4860
4861 break;
4862
4863 case P2P_PROVISION_DISC_REQ:
4864 DBG_8723A("[%s] Got Provisioning Discovery Request Frame\n", __func__);
4865 process_p2p_provdisc_req23a(pwdinfo, pframe, len);
4866 ether_addr_copy(pwdinfo->rx_prov_disc_info.peerDevAddr, hdr->addr2);
4867
4868 /* 20110902 Kurt */
4869 /* Add the following statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
4870 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
4871 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
4872
4873 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ);
4874 mod_timer(&pwdinfo->restore_p2p_state_timer,
4875 jiffies + msecs_to_jiffies(P2P_PROVISION_TIMEOUT));
4876 break;
4877
4878 case P2P_PROVISION_DISC_RESP:
4879 /* Commented by Albert 20110707 */
4880 /* Should we check the pwdinfo->tx_prov_disc_info.bsent flag here?? */
4881 DBG_8723A("[%s] Got Provisioning Discovery Response Frame\n", __func__);
4882 /* Commented by Albert 20110426 */
4883 /* The restore timer is enabled when issuing the provisioing request frame in rtw_p2p_prov_disc function. */
4884 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
4885 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP);
4886 process_p2p_provdisc_resp23a(pwdinfo, pframe);
4887 mod_timer(&pwdinfo->restore_p2p_state_timer,
4888 jiffies + msecs_to_jiffies(P2P_PROVISION_TIMEOUT));
4889 break;
4890
4891 }
4892 }
4893#endif /* CONFIG_8723AU_P2P */
4894
4895 return _SUCCESS;
4896}
4897
4898static unsigned int on_action_public23a_vendor(struct recv_frame *precv_frame)
4899{
4900 unsigned int ret = _FAIL;
4901 struct sk_buff *skb = precv_frame->pkt;
4902 u8 *pframe = skb->data;
4903 u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
4904
4905 if (!memcmp(frame_body + 2, P2P_OUI23A, 4)) {
4906 ret = on_action_public23a_p2p(precv_frame);
4907 }
4908
4909 return ret;
4910}
4911
4912static unsigned int
4913on_action_public23a_default(struct recv_frame *precv_frame, u8 action)
4914{
4915 unsigned int ret = _FAIL;
4916 struct sk_buff *skb = precv_frame->pkt;
4917 u8 *pframe = skb->data;
4918 uint frame_len = skb->len;
4919 u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
4920 u8 token;
4921 struct rtw_adapter *adapter = precv_frame->adapter;
4922 int cnt = 0;
4923 char msg[64];
4924
4925 token = frame_body[2];
4926
4927 if (rtw_action_public_decache(precv_frame, token) == _FAIL)
4928 goto exit;
4929
4930 cnt += sprintf((msg+cnt), "%s(token:%u)",
4931 action_public_str23a(action), token);
4932 rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg);
4933
4934 ret = _SUCCESS;
4935
4936exit:
4937 return ret;
4938}
4939
4940unsigned int on_action_public23a(struct rtw_adapter *padapter,
4941 struct recv_frame *precv_frame)
4942{
4943 unsigned int ret = _FAIL;
4944 struct sk_buff *skb = precv_frame->pkt;
4945 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
4946 u8 *pframe = skb->data;
4947 u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
4948 u8 category, action;
4949
4950 /* check RA matches or not */
4951 if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
4952 goto exit;
4953
4954 category = frame_body[0];
4955 if (category != WLAN_CATEGORY_PUBLIC)
4956 goto exit;
4957
4958 action = frame_body[1];
4959 switch (action) {
4960 case ACT_PUBLIC_VENDOR:
4961 ret = on_action_public23a_vendor(precv_frame);
4962 break;
4963 default:
4964 ret = on_action_public23a_default(precv_frame, action);
4965 break;
4966 }
4967
4968exit:
4969 return ret;
4970}
4971
4972unsigned int OnAction23a_ht(struct rtw_adapter *padapter,
4973 struct recv_frame *precv_frame)
4974{
4975 return _SUCCESS;
4976}
4977
4978unsigned int OnAction23a_wmm(struct rtw_adapter *padapter,
4979 struct recv_frame *precv_frame)
4980{
4981 return _SUCCESS;
4982}
4983
4984unsigned int OnAction23a_p2p(struct rtw_adapter *padapter,
4985 struct recv_frame *precv_frame)
4986{
4987#ifdef CONFIG_8723AU_P2P
4988 u8 *frame_body;
4989 u8 category, OUI_Subtype, dialogToken = 0;
4990 struct sk_buff *skb = precv_frame->pkt;
4991 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
4992 u8 *pframe = skb->data;
4993 uint len = skb->len;
4994 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
4995
4996 DBG_8723A("%s\n", __func__);
4997
4998 /* check RA matches or not */
4999 if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
5000 return _SUCCESS;
5001
5002 frame_body = (unsigned char *)
5003 (pframe + sizeof(struct ieee80211_hdr_3addr));
5004
5005 category = frame_body[0];
5006 if (category != WLAN_CATEGORY_VENDOR_SPECIFIC)
5007 return _SUCCESS;
5008
5009 if (cpu_to_be32(*((u32*) (frame_body + 1))) != P2POUI)
5010 return _SUCCESS;
5011
5012 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
5013 rtw_cfg80211_rx_action_p2p(padapter, pframe, len);
5014 return _SUCCESS;
5015 } else {
5016 len -= sizeof(struct ieee80211_hdr_3addr);
5017 OUI_Subtype = frame_body[5];
5018 dialogToken = frame_body[6];
5019
5020 switch (OUI_Subtype)
5021 {
5022 case P2P_NOTICE_OF_ABSENCE:
5023 break;
5024
5025 case P2P_PRESENCE_REQUEST:
5026 process_p2p_presence_req23a(pwdinfo, pframe, len);
5027 break;
5028
5029 case P2P_PRESENCE_RESPONSE:
5030 break;
5031
5032 case P2P_GO_DISC_REQUEST:
5033 break;
5034
5035 default:
5036 break;
5037 }
5038 }
5039#endif /* CONFIG_8723AU_P2P */
5040
5041 return _SUCCESS;
5042}
5043
5044unsigned int OnAction23a(struct rtw_adapter *padapter,
5045 struct recv_frame *precv_frame)
5046{
5047 int i;
5048 unsigned char category;
5049 struct action_handler *ptable;
5050 unsigned char *frame_body;
5051 struct sk_buff *skb = precv_frame->pkt;
5052 u8 *pframe = skb->data;
5053
5054 frame_body = (unsigned char *)
5055 (pframe + sizeof(struct ieee80211_hdr_3addr));
5056
5057 category = frame_body[0];
5058
5059 for (i = 0;
5060 i < sizeof(OnAction23a_tbl) / sizeof(struct action_handler); i++) {
5061 ptable = &OnAction23a_tbl[i];
5062
5063 if (category == ptable->num)
5064 ptable->func(padapter, precv_frame);
5065 }
5066
5067 return _SUCCESS;
5068}
5069
5070unsigned int DoReserved23a(struct rtw_adapter *padapter,
5071 struct recv_frame *precv_frame)
5072{
5073 return _SUCCESS;
5074}
5075
5076struct xmit_frame *alloc_mgtxmitframe23a(struct xmit_priv *pxmitpriv)
5077{
5078 struct xmit_frame *pmgntframe;
5079 struct xmit_buf *pxmitbuf;
5080
5081 pmgntframe = rtw_alloc_xmitframe23a_ext(pxmitpriv);
5082
5083 if (!pmgntframe) {
5084 DBG_8723A(FUNC_ADPT_FMT" alloc xmitframe fail\n",
5085 FUNC_ADPT_ARG(pxmitpriv->adapter));
5086 goto exit;
5087 }
5088
5089 pxmitbuf = rtw_alloc_xmitbuf23a_ext(pxmitpriv);
5090 if (!pxmitbuf) {
5091 DBG_8723A(FUNC_ADPT_FMT" alloc xmitbuf fail\n",
5092 FUNC_ADPT_ARG(pxmitpriv->adapter));
5093 rtw_free_xmitframe23a(pxmitpriv, pmgntframe);
5094 pmgntframe = NULL;
5095 goto exit;
5096 }
5097
5098 pmgntframe->frame_tag = MGNT_FRAMETAG;
5099 pmgntframe->pxmitbuf = pxmitbuf;
5100 pmgntframe->buf_addr = pxmitbuf->pbuf;
5101 pxmitbuf->priv_data = pmgntframe;
5102
5103exit:
5104 return pmgntframe;
5105}
5106
5107/****************************************************************************
5108
5109Following are some TX fuctions for WiFi MLME
5110
5111*****************************************************************************/
5112
5113void update_mgnt_tx_rate23a(struct rtw_adapter *padapter, u8 rate)
5114{
5115 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5116
5117 pmlmeext->tx_rate = rate;
5118 DBG_8723A("%s(): rate = %x\n", __func__, rate);
5119}
5120
5121void update_mgntframe_attrib23a(struct rtw_adapter *padapter,
5122 struct pkt_attrib *pattrib)
5123{
5124 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5125
5126 memset((u8 *)pattrib, 0, sizeof(struct pkt_attrib));
5127
5128 pattrib->hdrlen = 24;
5129 pattrib->nr_frags = 1;
5130 pattrib->priority = 7;
5131 pattrib->mac_id = 0;
5132 pattrib->qsel = 0x12;
5133
5134 pattrib->pktlen = 0;
5135
5136 if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
5137 pattrib->raid = 6;/* b mode */
5138 else
5139 pattrib->raid = 5;/* a/g mode */
5140
5141 pattrib->encrypt = _NO_PRIVACY_;
5142 pattrib->bswenc = false;
5143
5144 pattrib->qos_en = false;
5145 pattrib->ht_en = false;
5146 pattrib->bwmode = HT_CHANNEL_WIDTH_20;
5147 pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5148 pattrib->sgi = false;
5149
5150 pattrib->seqnum = pmlmeext->mgnt_seq;
5151
5152 pattrib->retry_ctrl = true;
5153}
5154
5155void dump_mgntframe23a(struct rtw_adapter *padapter,
5156 struct xmit_frame *pmgntframe)
5157{
5158 if (padapter->bSurpriseRemoved == true ||
5159 padapter->bDriverStopped == true)
5160 return;
5161
5162 rtw_hal_mgnt_xmit23a(padapter, pmgntframe);
5163}
5164
5165s32 dump_mgntframe23a_and_wait(struct rtw_adapter *padapter,
5166 struct xmit_frame *pmgntframe, int timeout_ms)
5167{
5168 s32 ret = _FAIL;
5169 unsigned long irqL;
5170 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5171 struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
5172 struct submit_ctx sctx;
5173
5174 if (padapter->bSurpriseRemoved == true ||
5175 padapter->bDriverStopped == true)
5176 return ret;
5177
5178 rtw_sctx_init23a(&sctx, timeout_ms);
5179 pxmitbuf->sctx = &sctx;
5180
5181 ret = rtw_hal_mgnt_xmit23a(padapter, pmgntframe);
5182
5183 if (ret == _SUCCESS)
5184 ret = rtw_sctx_wait23a(&sctx);
5185
5186 spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
5187 pxmitbuf->sctx = NULL;
5188 spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
5189
5190 return ret;
5191}
5192
5193s32 dump_mgntframe23a_and_wait_ack23a(struct rtw_adapter *padapter,
5194 struct xmit_frame *pmgntframe)
5195{
5196 s32 ret = _FAIL;
5197 u32 timeout_ms = 500;/* 500ms */
5198 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5199
5200 if (padapter->bSurpriseRemoved == true ||
5201 padapter->bDriverStopped == true)
5202 return -1;
5203
5204 mutex_lock(&pxmitpriv->ack_tx_mutex);
5205 pxmitpriv->ack_tx = true;
5206
5207 pmgntframe->ack_report = 1;
5208 if (rtw_hal_mgnt_xmit23a(padapter, pmgntframe) == _SUCCESS) {
5209 ret = rtw_ack_tx_wait23a(pxmitpriv, timeout_ms);
5210 }
5211
5212 pxmitpriv->ack_tx = false;
5213 mutex_unlock(&pxmitpriv->ack_tx_mutex);
5214
5215 return ret;
5216}
5217
5218static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
5219{
5220 u8 *ssid_ie;
5221 int ssid_len_ori;
5222 int len_diff = 0;
5223 u8 *next_ie;
5224 u32 remain_len;
5225
5226 ssid_ie = rtw_get_ie23a(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len);
5227
5228 /* DBG_8723A("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n",
5229 __func__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */
5230
5231 if (ssid_ie && ssid_len_ori > 0) {
5232 switch (hidden_ssid_mode)
5233 {
5234 case 1:
5235 next_ie = ssid_ie + 2 + ssid_len_ori;
5236 remain_len = 0;
5237
5238 remain_len = ies_len -(next_ie-ies);
5239
5240 ssid_ie[1] = 0;
5241 memcpy(ssid_ie+2, next_ie, remain_len);
5242 len_diff -= ssid_len_ori;
5243
5244 break;
5245 case 2:
5246 memset(&ssid_ie[2], 0, ssid_len_ori);
5247 break;
5248 default:
5249 break;
5250 }
5251 }
5252
5253 return len_diff;
5254}
5255
5256void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms)
5257{
5258 struct xmit_frame *pmgntframe;
5259 struct pkt_attrib *pattrib;
5260 unsigned char *pframe;
5261 struct ieee80211_hdr *pwlanhdr;
5262 unsigned short *fctrl;
5263 unsigned int rate_len;
5264 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5265#ifdef CONFIG_8723AU_AP_MODE
5266 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5267#endif
5268 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5269 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5270 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
5271 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
5272#ifdef CONFIG_8723AU_P2P
5273 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
5274#endif /* CONFIG_8723AU_P2P */
5275 u8 *wps_ie;
5276 u32 wps_ielen;
5277 u8 sr = 0;
5278 int len_diff;
5279
5280 /* DBG_8723A("%s\n", __func__); */
5281
5282 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL) {
5283 DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
5284 return;
5285 }
5286#ifdef CONFIG_8723AU_AP_MODE
5287 spin_lock_bh(&pmlmepriv->bcn_update_lock);
5288#endif
5289
5290 /* update attribute */
5291 pattrib = &pmgntframe->attrib;
5292 update_mgntframe_attrib23a(padapter, pattrib);
5293 pattrib->qsel = 0x10;
5294
5295 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5296
5297 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5298 pwlanhdr = (struct ieee80211_hdr *)pframe;
5299
5300 fctrl = &pwlanhdr->frame_control;
5301 *fctrl = 0;
5302
5303 ether_addr_copy(pwlanhdr->addr1, bc_addr);
5304 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
5305 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(cur_network));
5306
5307 SetSeqNum(pwlanhdr, 0 /*pmlmeext->mgnt_seq*/);
5308 /* pmlmeext->mgnt_seq++; */
5309 SetFrameSubType(pframe, WIFI_BEACON);
5310
5311 pframe += sizeof(struct ieee80211_hdr_3addr);
5312 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
5313
5314 if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
5315 /* DBG_8723A("ie len =%d\n", cur_network->IELength); */
5316#ifdef CONFIG_8723AU_P2P
5317 /* for P2P : Primary Device Type & Device Name */
5318 u32 insert_len = 0;
5319 wps_ie = rtw_get_wps_ie23a(cur_network->IEs + _FIXED_IE_LENGTH_,
5320 cur_network->IELength -
5321 _FIXED_IE_LENGTH_, NULL, &wps_ielen);
5322
5323 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wps_ie &&
5324 wps_ielen > 0) {
5325 uint wps_offset, remainder_ielen;
5326 u8 *premainder_ie, *pframe_wscie;
5327
5328 wps_offset = (uint)(wps_ie - cur_network->IEs);
5329
5330 premainder_ie = wps_ie + wps_ielen;
5331
5332 remainder_ielen = cur_network->IELength - wps_offset -
5333 wps_ielen;
5334
5335 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
5336 if (pmlmepriv->wps_beacon_ie &&
5337 pmlmepriv->wps_beacon_ie_len>0) {
5338 memcpy(pframe, cur_network->IEs,
5339 wps_offset);
5340 pframe += wps_offset;
5341 pattrib->pktlen += wps_offset;
5342
5343 memcpy(pframe, pmlmepriv->wps_beacon_ie,
5344 pmlmepriv->wps_beacon_ie_len);
5345 pframe += pmlmepriv->wps_beacon_ie_len;
5346 pattrib->pktlen +=
5347 pmlmepriv->wps_beacon_ie_len;
5348
5349 /* copy remainder_ie to pframe */
5350 memcpy(pframe, premainder_ie,
5351 remainder_ielen);
5352 pframe += remainder_ielen;
5353 pattrib->pktlen += remainder_ielen;
5354 } else {
5355 memcpy(pframe, cur_network->IEs,
5356 cur_network->IELength);
5357 pframe += cur_network->IELength;
5358 pattrib->pktlen +=
5359 cur_network->IELength;
5360 }
5361 } else {
5362 pframe_wscie = pframe + wps_offset;
5363 memcpy(pframe, cur_network->IEs,
5364 wps_offset + wps_ielen);
5365 pframe += (wps_offset + wps_ielen);
5366 pattrib->pktlen += (wps_offset + wps_ielen);
5367
5368 /* now pframe is end of wsc ie, insert Primary
5369 Device Type & Device Name */
5370 /* Primary Device Type */
5371 /* Type: */
5372 *(u16*) (pframe + insert_len) =
5373 cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
5374 insert_len += 2;
5375
5376 /* Length: */
5377 *(u16*) (pframe + insert_len) =
5378 cpu_to_be16(0x0008);
5379 insert_len += 2;
5380
5381 /* Value: */
5382 /* Category ID */
5383 *(u16*) (pframe + insert_len) =
5384 cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
5385 insert_len += 2;
5386
5387 /* OUI */
5388 *(u32*) (pframe + insert_len) =
5389 cpu_to_be32(WPSOUI);
5390 insert_len += 4;
5391
5392 /* Sub Category ID */
5393 *(u16*) (pframe + insert_len) =
5394 cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
5395 insert_len += 2;
5396
5397 /* Device Name */
5398 /* Type: */
5399 *(u16*) (pframe + insert_len) =
5400 cpu_to_be16(WPS_ATTR_DEVICE_NAME);
5401 insert_len += 2;
5402
5403 /* Length: */
5404 *(u16*) (pframe + insert_len) =
5405 cpu_to_be16(pwdinfo->device_name_len);
5406 insert_len += 2;
5407
5408 /* Value: */
5409 memcpy(pframe + insert_len,
5410 pwdinfo->device_name,
5411 pwdinfo->device_name_len);
5412 insert_len += pwdinfo->device_name_len;
5413
5414 /* update wsc ie length */
5415 *(pframe_wscie+1) = (wps_ielen -2) + insert_len;
5416
5417 /* pframe move to end */
5418 pframe+= insert_len;
5419 pattrib->pktlen += insert_len;
5420
5421 /* copy remainder_ie to pframe */
5422 memcpy(pframe, premainder_ie, remainder_ielen);
5423 pframe += remainder_ielen;
5424 pattrib->pktlen += remainder_ielen;
5425 }
5426 } else
5427#endif /* CONFIG_8723AU_P2P */
5428 memcpy(pframe, cur_network->IEs, cur_network->IELength);
5429 len_diff = update_hidden_ssid(pframe + _BEACON_IE_OFFSET_,
5430 cur_network->IELength -
5431 _BEACON_IE_OFFSET_,
5432 pmlmeinfo->hidden_ssid_mode);
5433 pframe += (cur_network->IELength+len_diff);
5434 pattrib->pktlen += (cur_network->IELength+len_diff);
5435
5436 wps_ie = rtw_get_wps_ie23a(pmgntframe->buf_addr + TXDESC_OFFSET+
5437 sizeof (struct ieee80211_hdr_3addr) +
5438 _BEACON_IE_OFFSET_, pattrib->pktlen -
5439 sizeof (struct ieee80211_hdr_3addr) -
5440 _BEACON_IE_OFFSET_, NULL,
5441 &wps_ielen);
5442 if (wps_ie && wps_ielen > 0) {
5443 rtw_get_wps_attr_content23a(wps_ie, wps_ielen,
5444 WPS_ATTR_SELECTED_REGISTRAR,
5445 (u8*)&sr, NULL);
5446 }
5447 if (sr != 0)
5448 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
5449 else
5450 _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
5451
5452#ifdef CONFIG_8723AU_P2P
5453 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
5454 u32 len;
5455 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
5456 len = pmlmepriv->p2p_beacon_ie_len;
5457 if (pmlmepriv->p2p_beacon_ie && len > 0)
5458 memcpy(pframe,
5459 pmlmepriv->p2p_beacon_ie, len);
5460 } else
5461 len = build_beacon_p2p_ie23a(pwdinfo, pframe);
5462
5463 pframe += len;
5464 pattrib->pktlen += len;
5465
5466 if (true == pwdinfo->wfd_info->wfd_enable) {
5467 len = build_beacon_wfd_ie(pwdinfo, pframe);
5468 } else {
5469 len = 0;
5470 if (pmlmepriv->wfd_beacon_ie &&
5471 pmlmepriv->wfd_beacon_ie_len>0) {
5472 len = pmlmepriv->wfd_beacon_ie_len;
5473 memcpy(pframe,
5474 pmlmepriv->wfd_beacon_ie, len);
5475 }
5476 }
5477 pframe += len;
5478 pattrib->pktlen += len;
5479 }
5480#endif /* CONFIG_8723AU_P2P */
5481
5482 goto _issue_bcn;
5483 }
5484
5485 /* below for ad-hoc mode */
5486
5487 /* timestamp will be inserted by hardware */
5488 pframe += 8;
5489 pattrib->pktlen += 8;
5490
5491 /* beacon interval: 2 bytes */
5492
5493 memcpy(pframe, (unsigned char *)
5494 rtw_get_beacon_interval23a_from_ie(cur_network->IEs), 2);
5495
5496 pframe += 2;
5497 pattrib->pktlen += 2;
5498
5499 /* capability info: 2 bytes */
5500
5501 memcpy(pframe, (unsigned char *)
5502 rtw_get_capability23a_from_ie(cur_network->IEs), 2);
5503
5504 pframe += 2;
5505 pattrib->pktlen += 2;
5506
5507 /* SSID */
5508 pframe = rtw_set_ie23a(pframe, _SSID_IE_, cur_network->Ssid.ssid_len,
5509 cur_network->Ssid.ssid, &pattrib->pktlen);
5510
5511 /* supported rates... */
5512 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
5513 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_,
5514 ((rate_len > 8)? 8: rate_len),
5515 cur_network->SupportedRates, &pattrib->pktlen);
5516
5517 /* DS parameter set */
5518 pframe = rtw_set_ie23a(pframe, _DSSET_IE_, 1, (unsigned char *)
5519 &cur_network->Configuration.DSConfig,
5520 &pattrib->pktlen);
5521
5522 /* if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */
5523 {
5524 u8 erpinfo = 0;
5525 u32 ATIMWindow;
5526 /* IBSS Parameter Set... */
5527 /* ATIMWindow = cur->Configuration.ATIMWindow; */
5528 ATIMWindow = 0;
5529 pframe = rtw_set_ie23a(pframe, _IBSS_PARA_IE_, 2,
5530 (unsigned char *)&ATIMWindow,
5531 &pattrib->pktlen);
5532
5533 /* ERP IE */
5534 pframe = rtw_set_ie23a(pframe, _ERPINFO_IE_, 1,
5535 &erpinfo, &pattrib->pktlen);
5536 }
5537
5538 /* EXTERNDED SUPPORTED RATE */
5539 if (rate_len > 8)
5540 pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_,
5541 rate_len - 8,
5542 cur_network->SupportedRates + 8,
5543 &pattrib->pktlen);
5544
5545 /* todo:HT for adhoc */
5546
5547_issue_bcn:
5548
5549#ifdef CONFIG_8723AU_AP_MODE
5550 pmlmepriv->update_bcn = false;
5551
5552 spin_unlock_bh(&pmlmepriv->bcn_update_lock);
5553#endif
5554
5555 if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
5556 DBG_8723A("beacon frame too large\n");
5557 return;
5558 }
5559
5560 pattrib->last_txcmdsz = pattrib->pktlen;
5561
5562 /* DBG_8723A("issue bcn_sz =%d\n", pattrib->last_txcmdsz); */
5563 if (timeout_ms > 0)
5564 dump_mgntframe23a_and_wait(padapter, pmgntframe, timeout_ms);
5565 else
5566 dump_mgntframe23a(padapter, pmgntframe);
5567}
5568
5569void issue_probersp23a(struct rtw_adapter *padapter, unsigned char *da,
5570 u8 is_valid_p2p_probereq)
5571{
5572 struct xmit_frame *pmgntframe;
5573 struct pkt_attrib *pattrib;
5574 unsigned char *pframe;
5575 struct ieee80211_hdr *pwlanhdr;
5576 unsigned short *fctrl;
5577 unsigned char *mac, *bssid;
5578 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5579#ifdef CONFIG_8723AU_AP_MODE
5580 u8 *pwps_ie;
5581 uint wps_ielen;
5582 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5583#endif
5584 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5585 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5586 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
5587 unsigned int rate_len;
5588#ifdef CONFIG_8723AU_P2P
5589 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
5590#endif /* CONFIG_8723AU_P2P */
5591 u8 *ssid_ie;
5592 int ssid_ielen;
5593 int ssid_ielen_diff;
5594 u8 buf[MAX_IE_SZ];
5595 u8 *ies;
5596
5597 /* DBG_8723A("%s\n", __func__); */
5598
5599 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
5600 {
5601 DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
5602 return;
5603 }
5604
5605 /* update attribute */
5606 pattrib = &pmgntframe->attrib;
5607 update_mgntframe_attrib23a(padapter, pattrib);
5608
5609 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5610
5611 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5612 pwlanhdr = (struct ieee80211_hdr *)pframe;
5613
5614 mac = myid(&padapter->eeprompriv);
5615 bssid = cur_network->MacAddress;
5616
5617 fctrl = &pwlanhdr->frame_control;
5618 *fctrl = 0;
5619 ether_addr_copy(pwlanhdr->addr1, da);
5620 ether_addr_copy(pwlanhdr->addr2, mac);
5621 ether_addr_copy(pwlanhdr->addr3, bssid);
5622
5623 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5624 pmlmeext->mgnt_seq++;
5625 SetFrameSubType(fctrl, WIFI_PROBERSP);
5626
5627 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
5628 pattrib->pktlen = pattrib->hdrlen;
5629 pframe += pattrib->hdrlen;
5630
5631 if (cur_network->IELength > MAX_IE_SZ)
5632 return;
5633
5634#ifdef CONFIG_8723AU_AP_MODE
5635 if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
5636 pwps_ie = rtw_get_wps_ie23a(cur_network->IEs +
5637 _FIXED_IE_LENGTH_,
5638 cur_network->IELength -
5639 _FIXED_IE_LENGTH_, NULL,
5640 &wps_ielen);
5641
5642 /* inerset & update wps_probe_resp_ie */
5643 if ((pmlmepriv->wps_probe_resp_ie != NULL) && pwps_ie &&
5644 (wps_ielen > 0)) {
5645 uint wps_offset, remainder_ielen;
5646 u8 *premainder_ie;
5647
5648 wps_offset = (uint)(pwps_ie - cur_network->IEs);
5649
5650 premainder_ie = pwps_ie + wps_ielen;
5651
5652 remainder_ielen = cur_network->IELength - wps_offset -
5653 wps_ielen;
5654
5655 memcpy(pframe, cur_network->IEs, wps_offset);
5656 pframe += wps_offset;
5657 pattrib->pktlen += wps_offset;
5658
5659 /* to get ie data len */
5660 wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];
5661 if ((wps_offset+wps_ielen+2)<= MAX_IE_SZ) {
5662 memcpy(pframe, pmlmepriv->wps_probe_resp_ie,
5663 wps_ielen+2);
5664 pframe += wps_ielen+2;
5665 pattrib->pktlen += wps_ielen+2;
5666 }
5667
5668 if ((wps_offset+wps_ielen+2+remainder_ielen) <=
5669 MAX_IE_SZ) {
5670 memcpy(pframe, premainder_ie, remainder_ielen);
5671 pframe += remainder_ielen;
5672 pattrib->pktlen += remainder_ielen;
5673 }
5674 } else {
5675 memcpy(pframe, cur_network->IEs, cur_network->IELength);
5676 pframe += cur_network->IELength;
5677 pattrib->pktlen += cur_network->IELength;
5678 }
5679
5680 /* retrieve SSID IE from cur_network->Ssid */
5681 ies = pmgntframe->buf_addr + TXDESC_OFFSET +
5682 sizeof(struct ieee80211_hdr_3addr);
5683
5684 ssid_ie = rtw_get_ie23a(ies+_FIXED_IE_LENGTH_, _SSID_IE_,
5685 &ssid_ielen,
5686 (pframe-ies)-_FIXED_IE_LENGTH_);
5687
5688 ssid_ielen_diff = cur_network->Ssid.ssid_len - ssid_ielen;
5689
5690 if (ssid_ie && cur_network->Ssid.ssid_len) {
5691 uint remainder_ielen;
5692 u8 *remainder_ie;
5693 remainder_ie = ssid_ie + 2;
5694 remainder_ielen = (pframe-remainder_ie);
5695
5696 DBG_8723A_LEVEL(_drv_warning_, FUNC_ADPT_FMT
5697 " remainder_ielen > MAX_IE_SZ\n",
5698 FUNC_ADPT_ARG(padapter));
5699 if (remainder_ielen > MAX_IE_SZ) {
5700 remainder_ielen = MAX_IE_SZ;
5701 }
5702
5703 memcpy(buf, remainder_ie, remainder_ielen);
5704 memcpy(remainder_ie+ssid_ielen_diff, buf,
5705 remainder_ielen);
5706 *(ssid_ie+1) = cur_network->Ssid.ssid_len;
5707 memcpy(ssid_ie+2, cur_network->Ssid.ssid,
5708 cur_network->Ssid.ssid_len);
5709
5710 pframe += ssid_ielen_diff;
5711 pattrib->pktlen += ssid_ielen_diff;
5712 }
5713 } else
5714#endif
5715 {
5716
5717 /* timestamp will be inserted by hardware */
5718 pframe += 8;
5719 pattrib->pktlen += 8;
5720
5721 /* beacon interval: 2 bytes */
5722
5723 memcpy(pframe, (unsigned char *)
5724 rtw_get_beacon_interval23a_from_ie(cur_network->IEs), 2);
5725
5726 pframe += 2;
5727 pattrib->pktlen += 2;
5728
5729 /* capability info: 2 bytes */
5730
5731 memcpy(pframe, (unsigned char *)
5732 rtw_get_capability23a_from_ie(cur_network->IEs), 2);
5733
5734 pframe += 2;
5735 pattrib->pktlen += 2;
5736
5737 /* below for ad-hoc mode */
5738
5739 /* SSID */
5740 pframe = rtw_set_ie23a(pframe, _SSID_IE_,
5741 cur_network->Ssid.ssid_len,
5742 cur_network->Ssid.ssid, &pattrib->pktlen);
5743
5744 /* supported rates... */
5745 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
5746 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_,
5747 ((rate_len > 8)? 8: rate_len),
5748 cur_network->SupportedRates,
5749 &pattrib->pktlen);
5750
5751 /* DS parameter set */
5752 pframe = rtw_set_ie23a(pframe, _DSSET_IE_, 1, (unsigned char *)
5753 &cur_network->Configuration.DSConfig,
5754 &pattrib->pktlen);
5755
5756 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
5757 u8 erpinfo = 0;
5758 u32 ATIMWindow;
5759 /* IBSS Parameter Set... */
5760 /* ATIMWindow = cur->Configuration.ATIMWindow; */
5761 ATIMWindow = 0;
5762 pframe = rtw_set_ie23a(pframe, _IBSS_PARA_IE_, 2,
5763 (unsigned char *)&ATIMWindow,
5764 &pattrib->pktlen);
5765
5766 /* ERP IE */
5767 pframe = rtw_set_ie23a(pframe, _ERPINFO_IE_, 1,
5768 &erpinfo, &pattrib->pktlen);
5769 }
5770
5771 /* EXTERNDED SUPPORTED RATE */
5772 if (rate_len > 8)
5773 pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_,
5774 rate_len - 8,
5775 cur_network->SupportedRates + 8,
5776 &pattrib->pktlen);
5777
5778 /* todo:HT for adhoc */
5779 }
5780
5781#ifdef CONFIG_8723AU_P2P
5782 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && is_valid_p2p_probereq) {
5783 u32 len;
5784 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
5785 /* if pwdinfo->role == P2P_ROLE_DEVICE will call
5786 issue_probersp23a_p2p23a() */
5787 len = pmlmepriv->p2p_go_probe_resp_ie_len;
5788 if (pmlmepriv->p2p_go_probe_resp_ie && len>0)
5789 memcpy(pframe, pmlmepriv->p2p_go_probe_resp_ie,
5790 len);
5791 } else
5792 len = build_probe_resp_p2p_ie23a(pwdinfo, pframe);
5793
5794 pframe += len;
5795 pattrib->pktlen += len;
5796
5797 if (true == pwdinfo->wfd_info->wfd_enable) {
5798 len = build_probe_resp_wfd_ie(pwdinfo, pframe, 0);
5799 } else {
5800 len = 0;
5801 if (pmlmepriv->wfd_probe_resp_ie &&
5802 pmlmepriv->wfd_probe_resp_ie_len > 0) {
5803 len = pmlmepriv->wfd_probe_resp_ie_len;
5804 memcpy(pframe, pmlmepriv->wfd_probe_resp_ie,
5805 len);
5806 }
5807 }
5808 pframe += len;
5809 pattrib->pktlen += len;
5810 }
5811#endif /* CONFIG_8723AU_P2P */
5812
5813 pattrib->last_txcmdsz = pattrib->pktlen;
5814
5815 dump_mgntframe23a(padapter, pmgntframe);
5816
5817 return;
5818}
5819
5820static int _issue_probereq23a(struct rtw_adapter *padapter,
5821 struct cfg80211_ssid *pssid, u8 *da, int wait_ack)
5822{
5823 int ret = _FAIL;
5824 struct xmit_frame *pmgntframe;
5825 struct pkt_attrib *pattrib;
5826 unsigned char *pframe;
5827 struct ieee80211_hdr *pwlanhdr;
5828 unsigned short *fctrl;
5829 unsigned char *mac;
5830 unsigned char bssrate[NumRates];
5831 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5832 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5833 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5834 int bssrate_len = 0;
5835 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
5836
5837 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
5838 ("+issue_probereq23a\n"));
5839
5840 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
5841 goto exit;
5842
5843 /* update attribute */
5844 pattrib = &pmgntframe->attrib;
5845 update_mgntframe_attrib23a(padapter, pattrib);
5846
5847 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5848
5849 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5850 pwlanhdr = (struct ieee80211_hdr *)pframe;
5851
5852 mac = myid(&padapter->eeprompriv);
5853
5854 fctrl = &pwlanhdr->frame_control;
5855 *fctrl = 0;
5856
5857 if (da) {
5858 /* unicast probe request frame */
5859 ether_addr_copy(pwlanhdr->addr1, da);
5860 ether_addr_copy(pwlanhdr->addr3, da);
5861 } else {
5862 /* broadcast probe request frame */
5863 ether_addr_copy(pwlanhdr->addr1, bc_addr);
5864 ether_addr_copy(pwlanhdr->addr3, bc_addr);
5865 }
5866
5867 ether_addr_copy(pwlanhdr->addr2, mac);
5868
5869 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5870 pmlmeext->mgnt_seq++;
5871 SetFrameSubType(pframe, WIFI_PROBEREQ);
5872
5873 pframe += sizeof (struct ieee80211_hdr_3addr);
5874 pattrib->pktlen = sizeof (struct ieee80211_hdr_3addr);
5875
5876 if (pssid)
5877 pframe = rtw_set_ie23a(pframe, _SSID_IE_, pssid->ssid_len,
5878 pssid->ssid, &pattrib->pktlen);
5879 else
5880 pframe = rtw_set_ie23a(pframe, _SSID_IE_, 0, NULL,
5881 &pattrib->pktlen);
5882
5883 get_rate_set23a(padapter, bssrate, &bssrate_len);
5884
5885 if (bssrate_len > 8) {
5886 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, 8,
5887 bssrate, &pattrib->pktlen);
5888 pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_,
5889 (bssrate_len - 8), (bssrate + 8),
5890 &pattrib->pktlen);
5891 } else {
5892 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_,
5893 bssrate_len, bssrate, &pattrib->pktlen);
5894 }
5895
5896 /* add wps_ie for wps2.0 */
5897 if (pmlmepriv->wps_probe_req_ie_len>0 && pmlmepriv->wps_probe_req_ie) {
5898 memcpy(pframe, pmlmepriv->wps_probe_req_ie,
5899 pmlmepriv->wps_probe_req_ie_len);
5900 pframe += pmlmepriv->wps_probe_req_ie_len;
5901 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
5902 }
5903
5904 pattrib->last_txcmdsz = pattrib->pktlen;
5905
5906 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
5907 ("issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz));
5908
5909 if (wait_ack) {
5910 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
5911 } else {
5912 dump_mgntframe23a(padapter, pmgntframe);
5913 ret = _SUCCESS;
5914 }
5915
5916exit:
5917 return ret;
5918}
5919
5920inline void issue_probereq23a(struct rtw_adapter *padapter,
5921 struct cfg80211_ssid *pssid, u8 *da)
5922{
5923 _issue_probereq23a(padapter, pssid, da, false);
5924}
5925
5926int issue_probereq23a_ex23a(struct rtw_adapter *padapter,
5927 struct cfg80211_ssid *pssid, u8 *da,
5928 int try_cnt, int wait_ms)
5929{
5930 int ret;
5931 int i = 0;
5932 unsigned long start = jiffies;
5933
5934 do {
5935 ret = _issue_probereq23a(padapter, pssid, da,
5936 wait_ms > 0 ? true : false);
5937
5938 i++;
5939
5940 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
5941 break;
5942
5943 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
5944 msleep(wait_ms);
5945
5946 } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
5947
5948 if (ret != _FAIL) {
5949 ret = _SUCCESS;
5950 goto exit;
5951 }
5952
5953 if (try_cnt && wait_ms) {
5954 if (da)
5955 DBG_8723A(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d "
5956 "in %u ms\n", FUNC_ADPT_ARG(padapter),
5957 MAC_ARG(da), rtw_get_oper_ch23a(padapter),
5958 ret == _SUCCESS?", acked":"", i, try_cnt,
5959 jiffies_to_msecs(jiffies - start));
5960 else
5961 DBG_8723A(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
5962 FUNC_ADPT_ARG(padapter),
5963 rtw_get_oper_ch23a(padapter),
5964 ret == _SUCCESS?", acked":"", i, try_cnt,
5965 jiffies_to_msecs(jiffies - start));
5966 }
5967exit:
5968 return ret;
5969}
5970
5971/* if psta == NULL, indiate we are station(client) now... */
5972void issue_auth23a(struct rtw_adapter *padapter, struct sta_info *psta,
5973 unsigned short status)
5974{
5975 struct xmit_frame *pmgntframe;
5976 struct pkt_attrib *pattrib;
5977 unsigned char *pframe;
5978 struct ieee80211_hdr *pwlanhdr;
5979 unsigned short *fctrl;
5980 unsigned int val32;
5981 unsigned short val16;
5982 int use_shared_key = 0;
5983 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5984 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5985 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5986
5987 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
5988 return;
5989
5990 /* update attribute */
5991 pattrib = &pmgntframe->attrib;
5992 update_mgntframe_attrib23a(padapter, pattrib);
5993
5994 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5995
5996 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5997 pwlanhdr = (struct ieee80211_hdr *)pframe;
5998
5999 fctrl = &pwlanhdr->frame_control;
6000 *fctrl = 0;
6001
6002 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6003 pmlmeext->mgnt_seq++;
6004 SetFrameSubType(pframe, WIFI_AUTH);
6005
6006 pframe += sizeof(struct ieee80211_hdr_3addr);
6007 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
6008
6009 if (psta) { /* for AP mode */
6010#ifdef CONFIG_8723AU_AP_MODE
6011
6012 ether_addr_copy(pwlanhdr->addr1, psta->hwaddr);
6013 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
6014 ether_addr_copy(pwlanhdr->addr3, myid(&padapter->eeprompriv));
6015
6016 /* setting auth algo number */
6017 val16 = (u16)psta->authalg;
6018
6019 if (status != WLAN_STATUS_SUCCESS)
6020 val16 = 0;
6021
6022 if (val16) {
6023 val16 = cpu_to_le16(val16);
6024 use_shared_key = 1;
6025 }
6026
6027 pframe = rtw_set_fixed_ie23a(pframe, _AUTH_ALGM_NUM_,
6028 (unsigned char *)&val16,
6029 &pattrib->pktlen);
6030
6031 /* setting auth seq number */
6032 val16 = (u16)psta->auth_seq;
6033 val16 = cpu_to_le16(val16);
6034 pframe = rtw_set_fixed_ie23a(pframe, _AUTH_SEQ_NUM_,
6035 (unsigned char *)&val16,
6036 &pattrib->pktlen);
6037
6038 /* setting status code... */
6039 val16 = status;
6040 val16 = cpu_to_le16(val16);
6041 pframe = rtw_set_fixed_ie23a(pframe, _STATUS_CODE_,
6042 (unsigned char *)&val16,
6043 &pattrib->pktlen);
6044
6045 /* added challenging text... */
6046 if ((psta->auth_seq == 2) &&
6047 (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
6048 pframe = rtw_set_ie23a(pframe, _CHLGETXT_IE_, 128,
6049 psta->chg_txt, &pattrib->pktlen);
6050#endif
6051 } else {
6052 ether_addr_copy(pwlanhdr->addr1,
6053 get_my_bssid23a(&pmlmeinfo->network));
6054 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
6055 ether_addr_copy(pwlanhdr->addr3,
6056 get_my_bssid23a(&pmlmeinfo->network));
6057
6058 /* setting auth algo number */
6059 /* 0:OPEN System, 1:Shared key */
6060 val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)? 1: 0;
6061 if (val16) {
6062 val16 = cpu_to_le16(val16);
6063 use_shared_key = 1;
6064 }
6065 /* DBG_8723A("%s auth_algo = %s auth_seq =%d\n", __func__,
6066 (pmlmeinfo->auth_algo == 0)?"OPEN":"SHARED",
6067 pmlmeinfo->auth_seq); */
6068
6069 /* setting IV for auth seq #3 */
6070 if ((pmlmeinfo->auth_seq == 3) &&
6071 (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
6072 (use_shared_key == 1)) {
6073 /* DBG_8723A("==> iv(%d), key_index(%d)\n",
6074 pmlmeinfo->iv, pmlmeinfo->key_index); */
6075 val32 = ((pmlmeinfo->iv++) |
6076 (pmlmeinfo->key_index << 30));
6077 val32 = cpu_to_le32(val32);
6078 pframe = rtw_set_fixed_ie23a(pframe, 4,
6079 (unsigned char *)&val32,
6080 &pattrib->pktlen);
6081
6082 pattrib->iv_len = 4;
6083 }
6084
6085 pframe = rtw_set_fixed_ie23a(pframe, _AUTH_ALGM_NUM_,
6086 (unsigned char *)&val16,
6087 &pattrib->pktlen);
6088
6089 /* setting auth seq number */
6090 val16 = pmlmeinfo->auth_seq;
6091 val16 = cpu_to_le16(val16);
6092 pframe = rtw_set_fixed_ie23a(pframe, _AUTH_SEQ_NUM_,
6093 (unsigned char *)&val16,
6094 &pattrib->pktlen);
6095
6096 /* setting status code... */
6097 val16 = status;
6098 val16 = cpu_to_le16(val16);
6099 pframe = rtw_set_fixed_ie23a(pframe, _STATUS_CODE_,
6100 (unsigned char *)&val16,
6101 &pattrib->pktlen);
6102
6103 /* then checking to see if sending challenging text... */
6104 if ((pmlmeinfo->auth_seq == 3) &&
6105 (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
6106 (use_shared_key == 1)) {
6107 pframe = rtw_set_ie23a(pframe, _CHLGETXT_IE_, 128,
6108 pmlmeinfo->chg_txt,
6109 &pattrib->pktlen);
6110
6111 SetPrivacy(fctrl);
6112
6113 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
6114
6115 pattrib->encrypt = _WEP40_;
6116
6117 pattrib->icv_len = 4;
6118
6119 pattrib->pktlen += pattrib->icv_len;
6120 }
6121 }
6122
6123 pattrib->last_txcmdsz = pattrib->pktlen;
6124
6125 rtw_wep_encrypt23a(padapter, pmgntframe);
6126 DBG_8723A("%s\n", __func__);
6127 dump_mgntframe23a(padapter, pmgntframe);
6128
6129 return;
6130}
6131
6132void issue_asocrsp23a(struct rtw_adapter *padapter, unsigned short status,
6133 struct sta_info *pstat, int pkt_type)
6134{
6135#ifdef CONFIG_8723AU_AP_MODE
6136 struct xmit_frame *pmgntframe;
6137 struct ieee80211_hdr *pwlanhdr;
6138 struct pkt_attrib *pattrib;
6139 unsigned char *pbuf, *pframe;
6140 unsigned short val;
6141 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
6142 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
6143 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6144 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6145 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
6146 u8 *ie = pnetwork->IEs;
6147#ifdef CONFIG_8723AU_P2P
6148 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
6149 u32 wfdielen = 0;
6150#endif /* CONFIG_8723AU_P2P */
6151
6152 DBG_8723A("%s\n", __func__);
6153
6154 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
6155 return;
6156
6157 /* update attribute */
6158 pattrib = &pmgntframe->attrib;
6159 update_mgntframe_attrib23a(padapter, pattrib);
6160
6161 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6162
6163 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6164 pwlanhdr = (struct ieee80211_hdr *)pframe;
6165
6166 pwlanhdr->frame_control = 0;
6167
6168 ether_addr_copy(pwlanhdr->addr1, pstat->hwaddr);
6169 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
6170 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
6171
6172 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6173 pmlmeext->mgnt_seq++;
6174 if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
6175 SetFrameSubType(pwlanhdr, pkt_type);
6176 else
6177 return;
6178
6179 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
6180 pattrib->pktlen += pattrib->hdrlen;
6181 pframe += pattrib->hdrlen;
6182
6183 /* capability */
6184 val = *(unsigned short *)rtw_get_capability23a_from_ie(ie);
6185
6186 pframe = rtw_set_fixed_ie23a(pframe, _CAPABILITY_,
6187 (unsigned char *)&val, &pattrib->pktlen);
6188
6189 status = cpu_to_le16(status);
6190 pframe = rtw_set_fixed_ie23a(pframe, _STATUS_CODE_,
6191 (unsigned char *)&status,
6192 &pattrib->pktlen);
6193
6194 val = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
6195 pframe = rtw_set_fixed_ie23a(pframe, _ASOC_ID_, (unsigned char *)&val,
6196 &pattrib->pktlen);
6197
6198 if (pstat->bssratelen <= 8) {
6199 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_,
6200 pstat->bssratelen, pstat->bssrateset,
6201 &pattrib->pktlen);
6202 } else {
6203 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, 8,
6204 pstat->bssrateset, &pattrib->pktlen);
6205 pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_,
6206 pstat->bssratelen - 8,
6207 pstat->bssrateset + 8, &pattrib->pktlen);
6208 }
6209
6210 if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
6211 uint ie_len = 0;
6212
6213 /* FILL HT CAP INFO IE */
6214 /* p = hostapd_eid_ht_capabilities_info(hapd, p); */
6215 pbuf = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_,
6216 _HT_CAPABILITY_IE_, &ie_len,
6217 pnetwork->IELength - _BEACON_IE_OFFSET_);
6218 if (pbuf && ie_len>0) {
6219 memcpy(pframe, pbuf, ie_len + 2);
6220 pframe += (ie_len + 2);
6221 pattrib->pktlen += (ie_len + 2);
6222 }
6223
6224 /* FILL HT ADD INFO IE */
6225 /* p = hostapd_eid_ht_operation(hapd, p); */
6226 pbuf = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_,
6227 &ie_len,
6228 pnetwork->IELength - _BEACON_IE_OFFSET_);
6229 if (pbuf && ie_len > 0) {
6230 memcpy(pframe, pbuf, ie_len + 2);
6231 pframe += (ie_len + 2);
6232 pattrib->pktlen += (ie_len + 2);
6233 }
6234 }
6235
6236 /* FILL WMM IE */
6237 if ((pstat->flags & WLAN_STA_WME) && pmlmepriv->qospriv.qos_option) {
6238 uint ie_len = 0;
6239 unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02,
6240 0x01, 0x01};
6241
6242 for (pbuf = ie + _BEACON_IE_OFFSET_; ; pbuf += (ie_len + 2)) {
6243 pbuf = rtw_get_ie23a(pbuf, _VENDOR_SPECIFIC_IE_,
6244 &ie_len, (pnetwork->IELength -
6245 _BEACON_IE_OFFSET_ -
6246 (ie_len + 2)));
6247 if (pbuf && !memcmp(pbuf + 2, WMM_PARA_IE, 6)) {
6248 memcpy(pframe, pbuf, ie_len + 2);
6249 pframe += (ie_len + 2);
6250 pattrib->pktlen += (ie_len + 2);
6251
6252 break;
6253 }
6254
6255 if ((!pbuf) || (ie_len == 0))
6256 break;
6257 }
6258 }
6259
6260 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) {
6261 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, 6,
6262 REALTEK_96B_IE23A, &pattrib->pktlen);
6263 }
6264
6265 /* add WPS IE ie for wps 2.0 */
6266 if (pmlmepriv->wps_assoc_resp_ie &&
6267 pmlmepriv->wps_assoc_resp_ie_len > 0) {
6268 memcpy(pframe, pmlmepriv->wps_assoc_resp_ie,
6269 pmlmepriv->wps_assoc_resp_ie_len);
6270
6271 pframe += pmlmepriv->wps_assoc_resp_ie_len;
6272 pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
6273 }
6274
6275#ifdef CONFIG_8723AU_P2P
6276 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) &&
6277 pwdinfo->wfd_info->wfd_enable) {
6278 wfdielen = build_assoc_resp_wfd_ie(pwdinfo, pframe);
6279 pframe += wfdielen;
6280 pattrib->pktlen += wfdielen;
6281 }
6282#endif /* CONFIG_8723AU_P2P */
6283
6284 pattrib->last_txcmdsz = pattrib->pktlen;
6285
6286 dump_mgntframe23a(padapter, pmgntframe);
6287#endif
6288}
6289
6290void issue_assocreq23a(struct rtw_adapter *padapter)
6291{
6292 int ret = _FAIL;
6293 struct xmit_frame *pmgntframe;
6294 struct pkt_attrib *pattrib;
6295 unsigned char *pframe, *p;
6296 struct ieee80211_hdr *pwlanhdr;
6297 unsigned short *fctrl;
6298 unsigned short val16;
6299 unsigned int i, j, ie_len, index = 0;
6300 unsigned char rf_type, bssrate[NumRates], sta_bssrate[NumRates];
6301 struct ndis_802_11_var_ies *pIE;
6302 struct registry_priv *pregpriv = &padapter->registrypriv;
6303 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
6304 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
6305 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6306 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6307 int bssrate_len = 0, sta_bssrate_len = 0;
6308#ifdef CONFIG_8723AU_P2P
6309 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
6310 u8 p2pie[255] = { 0x00 };
6311 u16 p2pielen = 0;
6312 u32 wfdielen = 0;
6313#endif /* CONFIG_8723AU_P2P */
6314
6315 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
6316 goto exit;
6317
6318 /* update attribute */
6319 pattrib = &pmgntframe->attrib;
6320 update_mgntframe_attrib23a(padapter, pattrib);
6321
6322 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6323
6324 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6325 pwlanhdr = (struct ieee80211_hdr *)pframe;
6326
6327 fctrl = &pwlanhdr->frame_control;
6328 *fctrl = 0;
6329 ether_addr_copy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network));
6330 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
6331 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
6332
6333 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6334 pmlmeext->mgnt_seq++;
6335 SetFrameSubType(pframe, WIFI_ASSOCREQ);
6336
6337 pframe += sizeof(struct ieee80211_hdr_3addr);
6338 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
6339
6340 /* caps */
6341 memcpy(pframe, rtw_get_capability23a_from_ie(pmlmeinfo->network.IEs),
6342 2);
6343
6344 pframe += 2;
6345 pattrib->pktlen += 2;
6346
6347 /* listen interval */
6348 /* todo: listen interval for power saving */
6349 val16 = cpu_to_le16(3);
6350 memcpy(pframe, (unsigned char *)&val16, 2);
6351 pframe += 2;
6352 pattrib->pktlen += 2;
6353
6354 /* SSID */
6355 pframe = rtw_set_ie23a(pframe, _SSID_IE_,
6356 pmlmeinfo->network.Ssid.ssid_len,
6357 pmlmeinfo->network.Ssid.ssid, &pattrib->pktlen);
6358
6359 /* supported rate & extended supported rate */
6360
6361 get_rate_set23a(padapter, sta_bssrate, &sta_bssrate_len);
6362 /* DBG_8723A("sta_bssrate_len =%d\n", sta_bssrate_len); */
6363
6364 /* for JAPAN, channel 14 can only uses B Mode(CCK) */
6365 if (pmlmeext->cur_channel == 14)
6366 sta_bssrate_len = 4;
6367
6368 /* for (i = 0; i < sta_bssrate_len; i++) { */
6369 /* DBG_8723A("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */
6370 /* */
6371
6372 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
6373 if (pmlmeinfo->network.SupportedRates[i] == 0)
6374 break;
6375 DBG_8723A("network.SupportedRates[%d]=%02X\n", i,
6376 pmlmeinfo->network.SupportedRates[i]);
6377 }
6378
6379 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
6380 if (pmlmeinfo->network.SupportedRates[i] == 0)
6381 break;
6382
6383 /* Check if the AP's supported rates are also
6384 supported by STA. */
6385 for (j = 0; j < sta_bssrate_len; j++) {
6386 /* Avoid the proprietary data rate (22Mbps) of
6387 Handlink WSG-4000 AP */
6388 if ((pmlmeinfo->network.SupportedRates[i] |
6389 IEEE80211_BASIC_RATE_MASK) ==
6390 (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)) {
6391 /* DBG_8723A("match i = %d, j =%d\n", i, j); */
6392 break;
6393 }
6394 }
6395
6396 if (j == sta_bssrate_len) {
6397 /* the rate is not supported by STA */
6398 DBG_8723A("%s(): the rate[%d]=%02X is not supported by "
6399 "STA!\n", __func__, i,
6400 pmlmeinfo->network.SupportedRates[i]);
6401 } else {
6402 /* the rate is supported by STA */
6403 bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
6404 }
6405 }
6406
6407 bssrate_len = index;
6408 DBG_8723A("bssrate_len = %d\n", bssrate_len);
6409
6410 if (bssrate_len == 0) {
6411 rtw_free_xmitbuf23a(pxmitpriv, pmgntframe->pxmitbuf);
6412 rtw_free_xmitframe23a(pxmitpriv, pmgntframe);
6413 goto exit; /* don't connect to AP if no joint supported rate */
6414 }
6415
6416 if (bssrate_len > 8) {
6417 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, 8,
6418 bssrate, &pattrib->pktlen);
6419 pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_,
6420 (bssrate_len - 8), (bssrate + 8),
6421 &pattrib->pktlen);
6422 } else
6423 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_,
6424 bssrate_len, bssrate, &pattrib->pktlen);
6425
6426 /* RSN */
6427 p = rtw_get_ie23a((pmlmeinfo->network.IEs +
6428 sizeof(struct ndis_802_11_fixed_ies)), _RSN_IE_2_,
6429 &ie_len, (pmlmeinfo->network.IELength -
6430 sizeof(struct ndis_802_11_fixed_ies)));
6431 if (p)
6432 pframe = rtw_set_ie23a(pframe, _RSN_IE_2_, ie_len, (p + 2),
6433 &pattrib->pktlen);
6434
6435 /* HT caps */
6436 if (padapter->mlmepriv.htpriv.ht_option == true) {
6437 p = rtw_get_ie23a((pmlmeinfo->network.IEs +
6438 sizeof(struct ndis_802_11_fixed_ies)),
6439 _HT_CAPABILITY_IE_, &ie_len,
6440 (pmlmeinfo->network.IELength -
6441 sizeof(struct ndis_802_11_fixed_ies)));
6442 if ((p != NULL) && (!(is_ap_in_tkip23a(padapter)))) {
6443 memcpy(&pmlmeinfo->HT_caps, (p + 2),
6444 sizeof(struct HT_caps_element));
6445
6446 /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
6447 if (pregpriv->cbw40_enable == 0) {
6448 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info &= (~(BIT(6) | BIT(1)));
6449 } else {
6450 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= BIT(1);
6451 }
6452
6453 /* todo: disable SM power save mode */
6454 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |=
6455 0x000c;
6456
6457 rtw23a_hal_get_hwreg(padapter, HW_VAR_RF_TYPE,
6458 (u8 *)(&rf_type));
6459 /* switch (pregpriv->rf_config) */
6460 switch (rf_type)
6461 {
6462 case RF_1T1R:
6463
6464 if (pregpriv->rx_stbc)
6465 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */
6466
6467 memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_1R23A, 16);
6468 break;
6469
6470 case RF_2T2R:
6471 case RF_1T2R:
6472 default:
6473
6474 /* enable for 2.4/5 GHz */
6475 if ((pregpriv->rx_stbc == 0x3) ||
6476 ((pmlmeext->cur_wireless_mode &
6477 WIRELESS_11_24N) &&
6478 /* enable for 2.4GHz */
6479 (pregpriv->rx_stbc == 0x1)) ||
6480 ((pmlmeext->cur_wireless_mode &
6481 WIRELESS_11_5N) &&
6482 (pregpriv->rx_stbc == 0x2)) ||
6483 /* enable for 5GHz */
6484 (pregpriv->wifi_spec == 1)) {
6485 DBG_8723A("declare supporting RX "
6486 "STBC\n");
6487 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0200);/* RX STBC two spatial stream */
6488 }
6489 memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_2R23A, 16);
6490 break;
6491 }
6492 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info =
6493 cpu_to_le16(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info);
6494
6495#ifdef CONFIG_8723AU_BT_COEXIST
6496 if (BT_1Ant(padapter) == true) {
6497 /* set to 8K */
6498 pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para &= (u8)~IEEE80211_HT_AMPDU_PARM_FACTOR;
6499/* pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para |= MAX_AMPDU_FACTOR_8K */
6500 }
6501#endif
6502
6503 pframe = rtw_set_ie23a(pframe, _HT_CAPABILITY_IE_,
6504 ie_len,
6505 (u8 *)&pmlmeinfo->HT_caps,
6506 &pattrib->pktlen);
6507 }
6508 }
6509
6510 /* vendor specific IE, such as WPA, WMM, WPS */
6511 for (i = sizeof(struct ndis_802_11_fixed_ies);
6512 i < pmlmeinfo->network.IELength;) {
6513 pIE = (struct ndis_802_11_var_ies *)
6514 (pmlmeinfo->network.IEs + i);
6515
6516 switch (pIE->ElementID)
6517 {
6518 case _VENDOR_SPECIFIC_IE_:
6519 if (!memcmp(pIE->data, RTW_WPA_OUI23A, 4) ||
6520 !memcmp(pIE->data, WMM_OUI23A, 4) ||
6521 !memcmp(pIE->data, WPS_OUI23A, 4)) {
6522 if (!padapter->registrypriv.wifi_spec) {
6523 /* Commented by Kurt 20110629 */
6524 /* In some older APs, WPS handshake */
6525 /* would be fail if we append vender
6526 extensions informations to AP */
6527 if (!memcmp(pIE->data, WPS_OUI23A, 4))
6528 pIE->Length = 14;
6529 }
6530 pframe = rtw_set_ie23a(pframe,
6531 _VENDOR_SPECIFIC_IE_,
6532 pIE->Length, pIE->data,
6533 &pattrib->pktlen);
6534 }
6535 break;
6536
6537 default:
6538 break;
6539 }
6540
6541 i += (pIE->Length + 2);
6542 }
6543
6544 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
6545 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, 6,
6546 REALTEK_96B_IE23A, &pattrib->pktlen);
6547
6548#ifdef CONFIG_8723AU_P2P
6549
6550 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
6551 if (pmlmepriv->p2p_assoc_req_ie &&
6552 pmlmepriv->p2p_assoc_req_ie_len>0) {
6553 memcpy(pframe, pmlmepriv->p2p_assoc_req_ie,
6554 pmlmepriv->p2p_assoc_req_ie_len);
6555 pframe += pmlmepriv->p2p_assoc_req_ie_len;
6556 pattrib->pktlen += pmlmepriv->p2p_assoc_req_ie_len;
6557 }
6558 } else {
6559 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&
6560 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
6561 /* Should add the P2P IE in the association
6562 request frame. */
6563 /* P2P OUI */
6564
6565 p2pielen = 0;
6566 p2pie[p2pielen++] = 0x50;
6567 p2pie[p2pielen++] = 0x6F;
6568 p2pie[p2pielen++] = 0x9A;
6569 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
6570
6571 /* Commented by Albert 20101109 */
6572 /* According to the P2P Specification, the
6573 association request frame should contain
6574 3 P2P attributes */
6575 /* 1. P2P Capability */
6576 /* 2. Extended Listen Timing */
6577 /* 3. Device Info */
6578 /* Commented by Albert 20110516 */
6579 /* 4. P2P Interface */
6580
6581 /* P2P Capability */
6582 /* Type: */
6583 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
6584
6585 /* Length: */
6586 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
6587 p2pielen += 2;
6588
6589 /* Value: */
6590 /* Device Capability Bitmap, 1 byte */
6591 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
6592
6593 /* Group Capability Bitmap, 1 byte */
6594 if (pwdinfo->persistent_supported)
6595 p2pie[p2pielen++] =
6596 P2P_GRPCAP_PERSISTENT_GROUP |
6597 DMP_P2P_GRPCAP_SUPPORT;
6598 else
6599 p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
6600
6601 /* Extended Listen Timing */
6602 /* Type: */
6603 p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
6604
6605 /* Length: */
6606 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0004);
6607 p2pielen += 2;
6608
6609 /* Value: */
6610 /* Availability Period */
6611 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF);
6612 p2pielen += 2;
6613
6614 /* Availability Interval */
6615 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF);
6616 p2pielen += 2;
6617
6618 /* Device Info */
6619 /* Type: */
6620 p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
6621
6622 /* Length: */
6623 /* 21 -> P2P Device Address (6bytes) + Config
6624 Methods (2bytes) + Primary Device
6625 Type (8bytes) */
6626 /* + NumofSecondDevType (1byte) + WPS Device
6627 Name ID field (2bytes) + WPS Device Name
6628 Len field (2bytes) */
6629 *(u16*) (p2pie + p2pielen) =
6630 cpu_to_le16(21 + pwdinfo->device_name_len);
6631 p2pielen += 2;
6632
6633 /* Value: */
6634 /* P2P Device Address */
6635 memcpy(p2pie + p2pielen,
6636 myid(&padapter->eeprompriv), ETH_ALEN);
6637 p2pielen += ETH_ALEN;
6638
6639 /* Config Method */
6640 /* This field should be big endian.
6641 Noted by P2P specification. */
6642 if ((pwdinfo->ui_got_wps_info ==
6643 P2P_GOT_WPSINFO_PEER_DISPLAY_PIN) ||
6644 (pwdinfo->ui_got_wps_info ==
6645 P2P_GOT_WPSINFO_SELF_DISPLAY_PIN))
6646 *(u16*) (p2pie + p2pielen) =
6647 cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
6648 else
6649 *(u16*) (p2pie + p2pielen) =
6650 cpu_to_be16(WPS_CONFIG_METHOD_PBC);
6651
6652 p2pielen += 2;
6653
6654 /* Primary Device Type */
6655 /* Category ID */
6656 *(u16*) (p2pie + p2pielen) =
6657 cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
6658 p2pielen += 2;
6659
6660 /* OUI */
6661 *(u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI);
6662 p2pielen += 4;
6663
6664 /* Sub Category ID */
6665 *(u16*) (p2pie + p2pielen) =
6666 cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
6667 p2pielen += 2;
6668
6669 /* Number of Secondary Device Types */
6670 /* No Secondary Device Type List */
6671 p2pie[p2pielen++] = 0x00;
6672
6673 /* Device Name */
6674 /* Type: */
6675 *(u16*) (p2pie + p2pielen) =
6676 cpu_to_be16(WPS_ATTR_DEVICE_NAME);
6677 p2pielen += 2;
6678
6679 /* Length: */
6680 *(u16*) (p2pie + p2pielen) =
6681 cpu_to_be16(pwdinfo->device_name_len);
6682 p2pielen += 2;
6683
6684 /* Value: */
6685 memcpy(p2pie + p2pielen, pwdinfo->device_name,
6686 pwdinfo->device_name_len);
6687 p2pielen += pwdinfo->device_name_len;
6688
6689 /* P2P Interface */
6690 /* Type: */
6691 p2pie[p2pielen++] = P2P_ATTR_INTERFACE;
6692
6693 /* Length: */
6694 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x000D);
6695 p2pielen += 2;
6696
6697 /* Value: */
6698 memcpy(p2pie + p2pielen, pwdinfo->device_addr,
6699 ETH_ALEN); /* P2P Device Address */
6700 p2pielen += ETH_ALEN;
6701
6702 /* P2P Interface Address Count */
6703 p2pie[p2pielen++] = 1;
6704
6705 memcpy(p2pie + p2pielen, pwdinfo->device_addr,
6706 ETH_ALEN); /* P2P Interface Address List */
6707 p2pielen += ETH_ALEN;
6708
6709 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_,
6710 p2pielen, (unsigned char *)p2pie,
6711 &pattrib->pktlen);
6712
6713 /* wfdielen = build_assoc_req_wfd_ie(pwdinfo, pframe);*/
6714 /* pframe += wfdielen; */
6715 /* pattrib->pktlen += wfdielen; */
6716 }
6717 }
6718
6719 if (true == pwdinfo->wfd_info->wfd_enable) {
6720 wfdielen = build_assoc_req_wfd_ie(pwdinfo, pframe);
6721 pframe += wfdielen;
6722 pattrib->pktlen += wfdielen;
6723 } else if (pmlmepriv->wfd_assoc_req_ie != NULL &&
6724 pmlmepriv->wfd_assoc_req_ie_len > 0) {
6725 /* WFD IE */
6726 memcpy(pframe, pmlmepriv->wfd_assoc_req_ie,
6727 pmlmepriv->wfd_assoc_req_ie_len);
6728 pattrib->pktlen += pmlmepriv->wfd_assoc_req_ie_len;
6729 pframe += pmlmepriv->wfd_assoc_req_ie_len;
6730 }
6731#endif /* CONFIG_8723AU_P2P */
6732
6733 pattrib->last_txcmdsz = pattrib->pktlen;
6734 dump_mgntframe23a(padapter, pmgntframe);
6735
6736 ret = _SUCCESS;
6737
6738exit:
6739 pmlmepriv->assoc_req_len = 0;
6740 if (ret == _SUCCESS) {
6741 kfree(pmlmepriv->assoc_req);
6742 pmlmepriv->assoc_req = kmalloc(pattrib->pktlen, GFP_ATOMIC);
6743 if (pmlmepriv->assoc_req) {
6744 memcpy(pmlmepriv->assoc_req, pwlanhdr,
6745 pattrib->pktlen);
6746 pmlmepriv->assoc_req_len = pattrib->pktlen;
6747 }
6748 } else
6749 kfree(pmlmepriv->assoc_req);
6750
6751 return;
6752}
6753
6754/* when wait_ack is ture, this function shoule be called at process context */
6755static int _issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
6756 unsigned int power_mode, int wait_ack)
6757{
6758 int ret = _FAIL;
6759 struct xmit_frame *pmgntframe;
6760 struct pkt_attrib *pattrib;
6761 unsigned char *pframe;
6762 struct ieee80211_hdr *pwlanhdr;
6763 unsigned short *fctrl;
6764 struct xmit_priv *pxmitpriv;
6765 struct mlme_ext_priv *pmlmeext;
6766 struct mlme_ext_info *pmlmeinfo;
6767
6768 /* DBG_8723A("%s:%d\n", __func__, power_mode); */
6769
6770 if (!padapter)
6771 goto exit;
6772
6773 pxmitpriv = &padapter->xmitpriv;
6774 pmlmeext = &padapter->mlmeextpriv;
6775 pmlmeinfo = &pmlmeext->mlmext_info;
6776
6777 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
6778 goto exit;
6779
6780 /* update attribute */
6781 pattrib = &pmgntframe->attrib;
6782 update_mgntframe_attrib23a(padapter, pattrib);
6783 pattrib->retry_ctrl = false;
6784
6785 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6786
6787 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6788 pwlanhdr = (struct ieee80211_hdr *)pframe;
6789
6790 fctrl = &pwlanhdr->frame_control;
6791 *fctrl = 0;
6792
6793 if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
6794 SetFrDs(fctrl);
6795 else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
6796 SetToDs(fctrl);
6797
6798 if (power_mode)
6799 SetPwrMgt(fctrl);
6800
6801 ether_addr_copy(pwlanhdr->addr1, da);
6802 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
6803 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
6804
6805 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6806 pmlmeext->mgnt_seq++;
6807 SetFrameSubType(pframe, WIFI_DATA_NULL);
6808
6809 pframe += sizeof(struct ieee80211_hdr_3addr);
6810 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
6811
6812 pattrib->last_txcmdsz = pattrib->pktlen;
6813
6814 if (wait_ack)
6815 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
6816 else {
6817 dump_mgntframe23a(padapter, pmgntframe);
6818 ret = _SUCCESS;
6819 }
6820
6821exit:
6822 return ret;
6823}
6824
6825/* when wait_ms >0 , this function shoule be called at process context */
6826/* da == NULL for station mode */
6827int issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
6828 unsigned int power_mode, int try_cnt, int wait_ms)
6829{
6830 int ret;
6831 int i = 0;
6832 unsigned long start = jiffies;
6833 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6834 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6835
6836 /* da == NULL, assum it's null data for sta to ap*/
6837 if (da == NULL)
6838 da = get_my_bssid23a(&pmlmeinfo->network);
6839
6840 do {
6841 ret = _issue_nulldata23a(padapter, da, power_mode,
6842 wait_ms > 0 ? true : false);
6843
6844 i++;
6845
6846 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
6847 break;
6848
6849 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
6850 msleep(wait_ms);
6851
6852 } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
6853
6854 if (ret != _FAIL) {
6855 ret = _SUCCESS;
6856 goto exit;
6857 }
6858
6859 if (try_cnt && wait_ms) {
6860 if (da)
6861 DBG_8723A(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d "
6862 "in %u ms\n", FUNC_ADPT_ARG(padapter),
6863 MAC_ARG(da), rtw_get_oper_ch23a(padapter),
6864 ret == _SUCCESS?", acked":"", i, try_cnt,
6865 jiffies_to_msecs(jiffies - start));
6866 else
6867 DBG_8723A(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
6868 FUNC_ADPT_ARG(padapter),
6869 rtw_get_oper_ch23a(padapter),
6870 ret == _SUCCESS?", acked":"", i, try_cnt,
6871 jiffies_to_msecs(jiffies - start));
6872 }
6873exit:
6874 return ret;
6875}
6876
6877/* when wait_ack is ture, this function shoule be called at process context */
6878static int _issue_qos_nulldata23a(struct rtw_adapter *padapter,
6879 unsigned char *da, u16 tid, int wait_ack)
6880{
6881 int ret = _FAIL;
6882 struct xmit_frame *pmgntframe;
6883 struct pkt_attrib *pattrib;
6884 unsigned char *pframe;
6885 struct ieee80211_hdr *pwlanhdr;
6886 unsigned short *fctrl, *qc;
6887 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
6888 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6889 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6890
6891 DBG_8723A("%s\n", __func__);
6892
6893 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
6894 goto exit;
6895
6896 /* update attribute */
6897 pattrib = &pmgntframe->attrib;
6898 update_mgntframe_attrib23a(padapter, pattrib);
6899
6900 pattrib->hdrlen += 2;
6901 pattrib->qos_en = true;
6902 pattrib->eosp = 1;
6903 pattrib->ack_policy = 0;
6904 pattrib->mdata = 0;
6905
6906 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6907
6908 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6909 pwlanhdr = (struct ieee80211_hdr *)pframe;
6910
6911 fctrl = &pwlanhdr->frame_control;
6912 *fctrl = 0;
6913
6914 if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
6915 SetFrDs(fctrl);
6916 else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
6917 SetToDs(fctrl);
6918
6919 if (pattrib->mdata)
6920 SetMData(fctrl);
6921
6922 qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
6923
6924 SetPriority(qc, tid);
6925
6926 SetEOSP(qc, pattrib->eosp);
6927
6928 SetAckpolicy(qc, pattrib->ack_policy);
6929
6930 ether_addr_copy(pwlanhdr->addr1, da);
6931 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
6932 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
6933
6934 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6935 pmlmeext->mgnt_seq++;
6936 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
6937
6938 pframe += sizeof(struct ieee80211_qos_hdr);
6939 pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
6940
6941 pattrib->last_txcmdsz = pattrib->pktlen;
6942
6943 if (wait_ack)
6944 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
6945 else {
6946 dump_mgntframe23a(padapter, pmgntframe);
6947 ret = _SUCCESS;
6948 }
6949
6950exit:
6951 return ret;
6952}
6953
6954/* when wait_ms >0 , this function shoule be called at process context */
6955/* da == NULL for station mode */
6956int issue_qos_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
6957 u16 tid, int try_cnt, int wait_ms)
6958{
6959 int ret;
6960 int i = 0;
6961 unsigned long start = jiffies;
6962 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6963 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6964
6965 /* da == NULL, assum it's null data for sta to ap*/
6966 if (da == NULL)
6967 da = get_my_bssid23a(&pmlmeinfo->network);
6968
6969 do {
6970 ret = _issue_qos_nulldata23a(padapter, da, tid,
6971 wait_ms > 0 ? true : false);
6972
6973 i++;
6974
6975 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
6976 break;
6977
6978 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
6979 msleep(wait_ms);
6980 } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0)));
6981
6982 if (ret != _FAIL) {
6983 ret = _SUCCESS;
6984 goto exit;
6985 }
6986
6987 if (try_cnt && wait_ms) {
6988 if (da)
6989 DBG_8723A(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d "
6990 "in %u ms\n", FUNC_ADPT_ARG(padapter),
6991 MAC_ARG(da), rtw_get_oper_ch23a(padapter),
6992 ret == _SUCCESS?", acked":"", i, try_cnt,
6993 jiffies_to_msecs(jiffies - start));
6994 else
6995 DBG_8723A(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
6996 FUNC_ADPT_ARG(padapter),
6997 rtw_get_oper_ch23a(padapter),
6998 ret == _SUCCESS?", acked":"", i, try_cnt,
6999 jiffies_to_msecs(jiffies - start));
7000 }
7001exit:
7002 return ret;
7003}
7004
7005static int _issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da,
7006 unsigned short reason, u8 wait_ack)
7007{
7008 struct xmit_frame *pmgntframe;
7009 struct pkt_attrib *pattrib;
7010 unsigned char *pframe;
7011 struct ieee80211_hdr *pwlanhdr;
7012 unsigned short *fctrl;
7013 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
7014 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7015 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7016 int ret = _FAIL;
7017#ifdef CONFIG_8723AU_P2P
7018 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
7019#endif /* CONFIG_8723AU_P2P */
7020
7021 /* DBG_8723A("%s to "MAC_FMT"\n", __func__, MAC_ARG(da)); */
7022
7023#ifdef CONFIG_8723AU_P2P
7024 if (!(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) &&
7025 (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
7026 mod_timer(&pwdinfo->reset_ch_sitesurvey,
7027 jiffies + msecs_to_jiffies(10));
7028 }
7029#endif /* CONFIG_8723AU_P2P */
7030
7031 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
7032 goto exit;
7033
7034 /* update attribute */
7035 pattrib = &pmgntframe->attrib;
7036 update_mgntframe_attrib23a(padapter, pattrib);
7037 pattrib->retry_ctrl = false;
7038
7039 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7040
7041 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7042 pwlanhdr = (struct ieee80211_hdr *)pframe;
7043
7044 fctrl = &pwlanhdr->frame_control;
7045 *fctrl = 0;
7046
7047 ether_addr_copy(pwlanhdr->addr1, da);
7048 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
7049 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
7050
7051 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7052 pmlmeext->mgnt_seq++;
7053 SetFrameSubType(pframe, WIFI_DEAUTH);
7054
7055 pframe += sizeof(struct ieee80211_hdr_3addr);
7056 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
7057
7058 reason = cpu_to_le16(reason);
7059 pframe = rtw_set_fixed_ie23a(pframe, WLAN_REASON_PREV_AUTH_NOT_VALID,
7060 (unsigned char *)&reason,
7061 &pattrib->pktlen);
7062
7063 pattrib->last_txcmdsz = pattrib->pktlen;
7064
7065 if (wait_ack)
7066 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
7067 else {
7068 dump_mgntframe23a(padapter, pmgntframe);
7069 ret = _SUCCESS;
7070 }
7071
7072exit:
7073 return ret;
7074}
7075
7076int issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da,
7077 unsigned short reason)
7078{
7079 DBG_8723A("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));
7080 return _issue_deauth23a(padapter, da, reason, false);
7081}
7082
7083int issue_deauth23a_ex23a(struct rtw_adapter *padapter, u8 *da,
7084 unsigned short reason, int try_cnt, int wait_ms)
7085{
7086 int ret;
7087 int i = 0;
7088 unsigned long start = jiffies;
7089
7090 do {
7091 ret = _issue_deauth23a(padapter, da, reason,
7092 wait_ms >0 ? true : false);
7093
7094 i++;
7095
7096 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
7097 break;
7098
7099 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
7100 msleep(wait_ms);
7101
7102 } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0)));
7103
7104 if (ret != _FAIL) {
7105 ret = _SUCCESS;
7106 goto exit;
7107 }
7108
7109 if (try_cnt && wait_ms) {
7110 if (da)
7111 DBG_8723A(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d "
7112 "in %u ms\n", FUNC_ADPT_ARG(padapter),
7113 MAC_ARG(da), rtw_get_oper_ch23a(padapter),
7114 ret == _SUCCESS?", acked":"", i, try_cnt,
7115 jiffies_to_msecs(jiffies - start));
7116 else
7117 DBG_8723A(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
7118 FUNC_ADPT_ARG(padapter),
7119 rtw_get_oper_ch23a(padapter),
7120 ret == _SUCCESS?", acked":"", i, try_cnt,
7121 jiffies_to_msecs(jiffies - start));
7122 }
7123exit:
7124 return ret;
7125}
7126
7127void issue_action_spct_ch_switch23a(struct rtw_adapter *padapter,
7128 u8 *ra, u8 new_ch, u8 ch_offset)
7129{
7130 struct xmit_frame *pmgntframe;
7131 struct pkt_attrib *pattrib;
7132 unsigned char *pframe;
7133 struct ieee80211_hdr *pwlanhdr;
7134 unsigned short *fctrl;
7135 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
7136 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7137 u8 category, action;
7138
7139 DBG_8723A(FUNC_NDEV_FMT" ra ="MAC_FMT", ch:%u, offset:%u\n",
7140 FUNC_NDEV_ARG(padapter->pnetdev), MAC_ARG(ra),
7141 new_ch, ch_offset);
7142
7143 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
7144 return;
7145
7146 /* update attribute */
7147 pattrib = &pmgntframe->attrib;
7148 update_mgntframe_attrib23a(padapter, pattrib);
7149
7150 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7151
7152 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7153 pwlanhdr = (struct ieee80211_hdr *)pframe;
7154
7155 fctrl = &pwlanhdr->frame_control;
7156 *fctrl = 0;
7157
7158 ether_addr_copy(pwlanhdr->addr1, ra); /* RA */
7159 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv)); /* TA */
7160 ether_addr_copy(pwlanhdr->addr3, ra); /* DA = RA */
7161
7162 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7163 pmlmeext->mgnt_seq++;
7164 SetFrameSubType(pframe, WIFI_ACTION);
7165
7166 pframe += sizeof(struct ieee80211_hdr_3addr);
7167 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
7168
7169 /* category, action */
7170 category = WLAN_CATEGORY_SPECTRUM_MGMT;
7171 action = WLAN_ACTION_SPCT_CHL_SWITCH;
7172
7173 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
7174 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
7175
7176 pframe = rtw_set_ie23a_ch_switch (pframe, &pattrib->pktlen, 0,
7177 new_ch, 0);
7178 pframe = rtw_set_ie23a_secondary_ch_offset(pframe, &pattrib->pktlen,
7179 hal_ch_offset_to_secondary_ch_offset23a(ch_offset));
7180
7181 pattrib->last_txcmdsz = pattrib->pktlen;
7182
7183 dump_mgntframe23a(padapter, pmgntframe);
7184}
7185
7186void issue_action_BA23a(struct rtw_adapter *padapter, unsigned char *raddr,
7187 unsigned char action, unsigned short status)
7188{
7189 u8 category = WLAN_CATEGORY_BACK;
7190 u16 start_seq;
7191 u16 BA_para_set;
7192 u16 reason_code;
7193 u16 BA_timeout_value;
7194 u16 BA_starting_seqctrl;
7195 int max_rx_ampdu_factor;
7196 struct xmit_frame *pmgntframe;
7197 struct pkt_attrib *pattrib;
7198 u8 *pframe;
7199 struct ieee80211_hdr *pwlanhdr;
7200 u16 *fctrl;
7201 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
7202 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7203 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7204 struct sta_info *psta;
7205 struct sta_priv *pstapriv = &padapter->stapriv;
7206 struct registry_priv *pregpriv = &padapter->registrypriv;
7207#ifdef CONFIG_8723AU_BT_COEXIST
7208 u8 tendaAPMac[] = {0xC8, 0x3A, 0x35};
7209#endif
7210
7211 DBG_8723A("%s, category =%d, action =%d, status =%d\n",
7212 __func__, category, action, status);
7213
7214 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
7215 return;
7216
7217 /* update attribute */
7218 pattrib = &pmgntframe->attrib;
7219 update_mgntframe_attrib23a(padapter, pattrib);
7220
7221 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7222
7223 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7224 pwlanhdr = (struct ieee80211_hdr *)pframe;
7225
7226 fctrl = &pwlanhdr->frame_control;
7227 *fctrl = 0;
7228
7229 /* memcpy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN); */
7230 ether_addr_copy(pwlanhdr->addr1, raddr);
7231 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
7232 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
7233
7234 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7235 pmlmeext->mgnt_seq++;
7236 SetFrameSubType(pframe, WIFI_ACTION);
7237
7238 pframe += sizeof(struct ieee80211_hdr_3addr);
7239 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
7240
7241 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
7242 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
7243
7244 status = cpu_to_le16(status);
7245
7246 if (category != 3)
7247 goto out;
7248
7249 switch (action)
7250 {
7251 case 0: /* ADDBA req */
7252 do {
7253 pmlmeinfo->dialogToken++;
7254 } while (pmlmeinfo->dialogToken == 0);
7255 pframe = rtw_set_fixed_ie23a(pframe, 1, &pmlmeinfo->dialogToken,
7256 &pattrib->pktlen);
7257
7258#ifdef CONFIG_8723AU_BT_COEXIST
7259 if ((BT_1Ant(padapter) == true) &&
7260 ((pmlmeinfo->assoc_AP_vendor != broadcomAP) ||
7261 memcmp(raddr, tendaAPMac, 3))) {
7262 /* A-MSDU NOT Supported */
7263 BA_para_set = 0;
7264 /* immediate Block Ack */
7265 BA_para_set |= (1 << 1) &
7266 IEEE80211_ADDBA_PARAM_POLICY_MASK;
7267 /* TID */
7268 BA_para_set |= (status << 2) &
7269 IEEE80211_ADDBA_PARAM_TID_MASK;
7270 /* max buffer size is 8 MSDU */
7271 BA_para_set |= (8 << 6) &
7272 IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
7273 } else
7274#endif
7275 {
7276 /* immediate ack & 64 buffer size */
7277 BA_para_set = (0x1002 | ((status & 0xf) << 2));
7278 }
7279 BA_para_set = cpu_to_le16(BA_para_set);
7280 pframe = rtw_set_fixed_ie23a(pframe, 2,
7281 (unsigned char *)&BA_para_set,
7282 &pattrib->pktlen);
7283
7284 BA_timeout_value = 5000;/* 5ms */
7285 BA_timeout_value = cpu_to_le16(BA_timeout_value);
7286 pframe = rtw_set_fixed_ie23a(pframe, 2, (unsigned char *)
7287 &BA_timeout_value,
7288 &pattrib->pktlen);
7289
7290 /* if ((psta = rtw_get_stainfo23a(pstapriv,
7291 pmlmeinfo->network.MacAddress)) != NULL) */
7292 if ((psta = rtw_get_stainfo23a(pstapriv, raddr))) {
7293 start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1;
7294
7295 DBG_8723A("BA_starting_seqctrl = %d for TID =%d\n",
7296 start_seq, status & 0x07);
7297
7298 psta->BA_starting_seqctrl[status & 0x07] = start_seq;
7299
7300 BA_starting_seqctrl = start_seq << 4;
7301 }
7302
7303 BA_starting_seqctrl = cpu_to_le16(BA_starting_seqctrl);
7304 pframe = rtw_set_fixed_ie23a(pframe, 2, (unsigned char *)&BA_starting_seqctrl, &pattrib->pktlen);
7305 break;
7306
7307 case 1: /* ADDBA rsp */
7308 pframe = rtw_set_fixed_ie23a(pframe, 1, &pmlmeinfo->ADDBA_req.dialog_token, &pattrib->pktlen);
7309 pframe = rtw_set_fixed_ie23a(pframe, 2,
7310 (unsigned char *)&status,
7311 &pattrib->pktlen);
7312 rtw_hal_get_def_var23a(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
7313 &max_rx_ampdu_factor);
7314 if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_64K)
7315 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
7316 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_32K)
7317 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); /* 32 buffer size */
7318 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_16K)
7319 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); /* 16 buffer size */
7320 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_8K)
7321 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); /* 8 buffer size */
7322 else
7323 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
7324
7325#ifdef CONFIG_8723AU_BT_COEXIST
7326 if ((BT_1Ant(padapter) == true) &&
7327 ((pmlmeinfo->assoc_AP_vendor != broadcomAP) ||
7328 memcmp(raddr, tendaAPMac, 3))) {
7329 /* max buffer size is 8 MSDU */
7330 BA_para_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
7331 BA_para_set |= (8 << 6) &
7332 IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
7333 }
7334#endif
7335
7336 if (pregpriv->ampdu_amsdu == 0)/* disabled */
7337 BA_para_set = cpu_to_le16(BA_para_set & ~BIT(0));
7338 else if (pregpriv->ampdu_amsdu == 1)/* enabled */
7339 BA_para_set = cpu_to_le16(BA_para_set | BIT(0));
7340 else /* auto */
7341 BA_para_set = cpu_to_le16(BA_para_set);
7342
7343 pframe = rtw_set_fixed_ie23a(pframe, 2,
7344 (unsigned char *)&BA_para_set,
7345 &pattrib->pktlen);
7346 pframe = rtw_set_fixed_ie23a(pframe, 2, (unsigned char *)&pmlmeinfo->ADDBA_req.BA_timeout_value, &pattrib->pktlen);
7347 break;
7348 case 2:/* DELBA */
7349 BA_para_set = (status & 0x1F) << 3;
7350 BA_para_set = cpu_to_le16(BA_para_set);
7351 pframe = rtw_set_fixed_ie23a(pframe, 2,
7352 (unsigned char *)&BA_para_set,
7353 &pattrib->pktlen);
7354
7355 reason_code = 37;/* Requested from peer STA as it does not
7356 want to use the mechanism */
7357 reason_code = cpu_to_le16(reason_code);
7358 pframe = rtw_set_fixed_ie23a(pframe, 2,
7359 (unsigned char *)&reason_code,
7360 &pattrib->pktlen);
7361 break;
7362 default:
7363 break;
7364 }
7365
7366out:
7367 pattrib->last_txcmdsz = pattrib->pktlen;
7368
7369 dump_mgntframe23a(padapter, pmgntframe);
7370}
7371
7372static void issue_action_BSSCoexistPacket(struct rtw_adapter *padapter)
7373{
7374 struct list_head *plist, *phead, *ptmp;
7375 unsigned char category, action;
7376 struct xmit_frame *pmgntframe;
7377 struct pkt_attrib *pattrib;
7378 unsigned char *pframe;
7379 struct ieee80211_hdr *pwlanhdr;
7380 unsigned short *fctrl;
7381 struct wlan_network *pnetwork = NULL;
7382 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
7383 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
7384 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7385 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7386 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
7387 u8 InfoContent[16] = {0};
7388 u8 ICS[8][15];
7389
7390 if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
7391 return;
7392
7393 if (true == pmlmeinfo->bwmode_updated)
7394 return;
7395
7396 DBG_8723A("%s\n", __func__);
7397
7398 category = WLAN_CATEGORY_PUBLIC;
7399 action = ACT_PUBLIC_BSSCOEXIST;
7400
7401 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
7402 {
7403 return;
7404 }
7405
7406 /* update attribute */
7407 pattrib = &pmgntframe->attrib;
7408 update_mgntframe_attrib23a(padapter, pattrib);
7409
7410 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7411
7412 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7413 pwlanhdr = (struct ieee80211_hdr *)pframe;
7414
7415 fctrl = &pwlanhdr->frame_control;
7416 *fctrl = 0;
7417
7418 ether_addr_copy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network));
7419 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
7420 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
7421
7422 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7423 pmlmeext->mgnt_seq++;
7424 SetFrameSubType(pframe, WIFI_ACTION);
7425
7426 pframe += sizeof(struct ieee80211_hdr_3addr);
7427 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
7428
7429 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
7430 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
7431
7432 /* */
7433 if (pmlmepriv->num_FortyMHzIntolerant>0)
7434 {
7435 u8 iedata = 0;
7436
7437 iedata |= BIT(2);/* 20 MHz BSS Width Request */
7438
7439 pframe = rtw_set_ie23a(pframe, EID_BSSCoexistence, 1, &iedata, &pattrib->pktlen);
7440
7441 }
7442
7443 /* */
7444 memset(ICS, 0, sizeof(ICS));
7445 if (pmlmepriv->num_sta_no_ht>0)
7446 {
7447 int i;
7448
7449 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
7450
7451 phead = get_list_head(queue);
7452 plist = phead->next;
7453
7454 list_for_each_safe(plist, ptmp, phead) {
7455 int len;
7456 u8 *p;
7457 struct wlan_bssid_ex *pbss_network;
7458
7459 pnetwork = container_of(plist, struct wlan_network,
7460 list);
7461
7462 pbss_network = &pnetwork->network;
7463
7464 p = rtw_get_ie23a(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
7465 if ((p == NULL) || (len == 0))/* non-HT */
7466 {
7467 if ((pbss_network->Configuration.DSConfig<= 0) || (pbss_network->Configuration.DSConfig>14))
7468 continue;
7469
7470 ICS[0][pbss_network->Configuration.DSConfig]= 1;
7471
7472 if (ICS[0][0] == 0)
7473 ICS[0][0] = 1;
7474 }
7475
7476 }
7477
7478 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
7479
7480 for (i = 0;i<8;i++)
7481 {
7482 if (ICS[i][0] == 1)
7483 {
7484 int j, k = 0;
7485
7486 InfoContent[k] = i;
7487 /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
7488 k++;
7489
7490 for (j = 1;j<= 14;j++)
7491 {
7492 if (ICS[i][j]== 1)
7493 {
7494 if (k<16)
7495 {
7496 InfoContent[k] = j; /* channel number */
7497 /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
7498 k++;
7499 }
7500 }
7501 }
7502
7503 pframe = rtw_set_ie23a(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &pattrib->pktlen);
7504
7505 }
7506
7507 }
7508
7509 }
7510
7511 pattrib->last_txcmdsz = pattrib->pktlen;
7512
7513 dump_mgntframe23a(padapter, pmgntframe);
7514}
7515
7516unsigned int send_delba23a(struct rtw_adapter *padapter, u8 initiator, u8 *addr)
7517{
7518 struct sta_priv *pstapriv = &padapter->stapriv;
7519 struct sta_info *psta = NULL;
7520 /* struct recv_reorder_ctrl *preorder_ctrl; */
7521 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7522 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7523 u16 tid;
7524
7525 if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
7526 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
7527 return _SUCCESS;
7528
7529 psta = rtw_get_stainfo23a(pstapriv, addr);
7530 if (psta == NULL)
7531 return _SUCCESS;
7532
7533 if (initiator == 0) { /* recipient */
7534 for (tid = 0; tid < MAXTID; tid++) {
7535 if (psta->recvreorder_ctrl[tid].enable == true) {
7536 DBG_8723A("rx agg disable tid(%d)\n", tid);
7537 issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
7538 psta->recvreorder_ctrl[tid].enable = false;
7539 psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
7540 }
7541 }
7542 } else if (initiator == 1) { /* originator */
7543 for (tid = 0; tid < MAXTID; tid++) {
7544 if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
7545 DBG_8723A("tx agg disable tid(%d)\n", tid);
7546 issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
7547 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
7548 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
7549
7550 }
7551 }
7552 }
7553 return _SUCCESS;
7554}
7555
7556unsigned int send_beacon23a(struct rtw_adapter *padapter)
7557{
7558 u8 bxmitok = false;
7559 int issue = 0;
7560 int poll = 0;
7561 unsigned long start = jiffies;
7562
7563 rtw_hal_set_hwreg23a(padapter, HW_VAR_BCN_VALID, NULL);
7564 do {
7565 issue_beacon23a(padapter, 100);
7566 issue++;
7567 do {
7568 yield();
7569 rtw23a_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
7570 poll++;
7571 } while ((poll%10)!= 0 && false == bxmitok &&
7572 !padapter->bSurpriseRemoved &&
7573 !padapter->bDriverStopped);
7574
7575 } while (!bxmitok && issue<100 && !padapter->bSurpriseRemoved &&
7576 !padapter->bDriverStopped);
7577
7578 if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
7579 return _FAIL;
7580
7581 if (!bxmitok) {
7582 DBG_8723A("%s fail! %u ms\n", __func__, rtw_get_passing_time_ms23a(start));
7583 return _FAIL;
7584 } else {
7585 unsigned int passing_time = jiffies_to_msecs(jiffies - start);
7586
7587 if (passing_time > 100 || issue > 3)
7588 DBG_8723A("%s success, issue:%d, poll:%d, %u ms\n",
7589 __func__, issue, poll, passing_time);
7590 return _SUCCESS;
7591 }
7592}
7593
7594/****************************************************************************
7595
7596Following are some utitity fuctions for WiFi MLME
7597
7598*****************************************************************************/
7599
7600bool IsLegal5GChannel(struct rtw_adapter *Adapter, u8 channel)
7601{
7602
7603 int i = 0;
7604 u8 Channel_5G[45] = {36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
7605 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122,
7606 124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
7607 161, 163, 165};
7608 for (i = 0; i < sizeof(Channel_5G); i++)
7609 if (channel == Channel_5G[i])
7610 return true;
7611 return false;
7612}
7613
7614void site_survey23a(struct rtw_adapter *padapter)
7615{
7616 unsigned char survey_channel = 0, val8;
7617 enum rt_scan_type ScanType = SCAN_PASSIVE;
7618 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7619 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7620 u32 initialgain = 0;
7621#ifdef CONFIG_8723AU_P2P
7622 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
7623
7624 if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) ||
7625 (pwdinfo->p2p_info.scan_op_ch_only)) {
7626 if (pwdinfo->rx_invitereq_info.scan_op_ch_only)
7627 survey_channel = pwdinfo->rx_invitereq_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
7628 else
7629 survey_channel = pwdinfo->p2p_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
7630 ScanType = SCAN_ACTIVE;
7631 } else if (rtw_p2p_findphase_ex_is_social(pwdinfo)) {
7632 /* The driver is in the find phase, it should go through the social channel. */
7633 int ch_set_idx;
7634 survey_channel = pwdinfo->social_chan[pmlmeext->sitesurvey_res.channel_idx];
7635 ch_set_idx = rtw_ch_set_search_ch23a(pmlmeext->channel_set, survey_channel);
7636 if (ch_set_idx >= 0)
7637 ScanType = pmlmeext->channel_set[ch_set_idx].ScanType;
7638 else
7639 ScanType = SCAN_ACTIVE;
7640 } else
7641#endif /* CONFIG_8723AU_P2P */
7642 {
7643 struct rtw_ieee80211_channel *ch;
7644 if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
7645 ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
7646 survey_channel = ch->hw_value;
7647 ScanType = (ch->flags & IEEE80211_CHAN_NO_IR) ? SCAN_PASSIVE : SCAN_ACTIVE;
7648}
7649 }
7650
7651 if (survey_channel != 0) {
7652 /* PAUSE 4-AC Queue when site_survey23a */
7653 /* rtw23a_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
7654 /* val8 |= 0x0f; */
7655 /* rtw_hal_set_hwreg23a(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
7656 if (pmlmeext->sitesurvey_res.channel_idx == 0)
7657 set_channel_bwmode23a(padapter, survey_channel,
7658 HAL_PRIME_CHNL_OFFSET_DONT_CARE,
7659 HT_CHANNEL_WIDTH_20);
7660 else
7661 SelectChannel23a(padapter, survey_channel);
7662
7663 if (ScanType == SCAN_ACTIVE) /* obey the channel plan setting... */
7664 {
7665#ifdef CONFIG_8723AU_P2P
7666 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) ||
7667 rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)
7668 )
7669 {
7670 issue23a_probereq_p2p(padapter, NULL);
7671 issue23a_probereq_p2p(padapter, NULL);
7672 issue23a_probereq_p2p(padapter, NULL);
7673 }
7674 else
7675#endif /* CONFIG_8723AU_P2P */
7676 {
7677 int i;
7678 for (i = 0;i<RTW_SSID_SCAN_AMOUNT;i++) {
7679 if (pmlmeext->sitesurvey_res.ssid[i].ssid_len) {
7680 /* todo: to issue two probe req??? */
7681 issue_probereq23a(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
7682 /* msleep(SURVEY_TO>>1); */
7683 issue_probereq23a(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
7684 }
7685 }
7686
7687 if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
7688 /* todo: to issue two probe req??? */
7689 issue_probereq23a(padapter, NULL, NULL);
7690 /* msleep(SURVEY_TO>>1); */
7691 issue_probereq23a(padapter, NULL, NULL);
7692 }
7693 }
7694 }
7695
7696 set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
7697 } else {
7698
7699 /* channel number is 0 or this channel is not valid. */
7700
7701
7702#ifdef CONFIG_8723AU_P2P
7703 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
7704 {
7705 if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) || (pwdinfo->p2p_info.scan_op_ch_only))
7706 {
7707 /* Set the find_phase_state_exchange_cnt to P2P_FINDPHASE_EX_CNT. */
7708 /* This will let the following flow to run the scanning end. */
7709 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
7710 }
7711 }
7712
7713 if (rtw_p2p_findphase_ex_is_needed(pwdinfo))
7714 {
7715 /* Set the P2P State to the listen state of find phase and set the current channel to the listen channel */
7716 set_channel_bwmode23a(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
7717 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_LISTEN);
7718 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
7719
7720 initialgain = 0xff; /* restore RX GAIN */
7721 rtw_hal_set_hwreg23a(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
7722 /* turn on dynamic functions */
7723 Restore_DM_Func_Flag23a(padapter);
7724 /* Switch_DM_Func23a(padapter, DYNAMIC_FUNC_DIG|DYNAMIC_FUNC_HP|DYNAMIC_FUNC_SS, true); */
7725
7726 mod_timer(&pwdinfo->find_phase_timer, jiffies +
7727 msecs_to_jiffies(pwdinfo->listen_dwell * 100));
7728 } else
7729#endif /* CONFIG_8723AU_P2P */
7730 {
7731#ifdef CONFIG_8723AU_P2P
7732 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
7733 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
7734 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
7735#endif /* CONFIG_8723AU_P2P */
7736
7737 pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
7738
7739 /* switch back to the original channel */
7740
7741 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
7742
7743 /* flush 4-AC Queue after site_survey23a */
7744 /* val8 = 0; */
7745 /* rtw_hal_set_hwreg23a(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
7746
7747 /* config MSR */
7748 Set_MSR23a(padapter, (pmlmeinfo->state & 0x3));
7749
7750 initialgain = 0xff; /* restore RX GAIN */
7751 rtw_hal_set_hwreg23a(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
7752 /* turn on dynamic functions */
7753 Restore_DM_Func_Flag23a(padapter);
7754 /* Switch_DM_Func23a(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
7755
7756 if (is_client_associated_to_ap23a(padapter) == true)
7757 {
7758 issue_nulldata23a(padapter, NULL, 0, 3, 500);
7759
7760 }
7761
7762 val8 = 0; /* survey done */
7763 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
7764
7765 report_surveydone_event23a(padapter);
7766
7767 pmlmeext->chan_scan_time = SURVEY_TO;
7768 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
7769
7770 issue_action_BSSCoexistPacket(padapter);
7771 issue_action_BSSCoexistPacket(padapter);
7772 issue_action_BSSCoexistPacket(padapter);
7773
7774 }
7775 }
7776
7777 return;
7778}
7779
7780/* collect bss info from Beacon and Probe request/response frames. */
7781u8 collect_bss_info23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame, struct wlan_bssid_ex *bssid)
7782{
7783 int i;
7784 u32 len;
7785 u8 *p;
7786 u16 val16;
7787 struct sk_buff *skb = precv_frame->pkt;
7788 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
7789 u8 *pframe = skb->data;
7790 u32 packet_len = skb->len;
7791 u8 ie_offset;
7792 struct registry_priv *pregistrypriv = &padapter->registrypriv;
7793 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7794 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7795
7796 len = packet_len - sizeof(struct ieee80211_hdr_3addr);
7797
7798 if (len > MAX_IE_SZ)
7799 {
7800 /* DBG_8723A("IE too long for survey event\n"); */
7801 return _FAIL;
7802 }
7803
7804 memset(bssid, 0, sizeof(struct wlan_bssid_ex));
7805
7806 if (ieee80211_is_beacon(hdr->frame_control)) {
7807 bssid->reserved = 1;
7808 ie_offset = _BEACON_IE_OFFSET_;
7809 } else {
7810 /* FIXME : more type */
7811 if (ieee80211_is_probe_req(hdr->frame_control)) {
7812 ie_offset = _PROBEREQ_IE_OFFSET_;
7813 bssid->reserved = 2;
7814 } else if (ieee80211_is_probe_resp(hdr->frame_control)) {
7815 ie_offset = _PROBERSP_IE_OFFSET_;
7816 bssid->reserved = 3;
7817 } else {
7818 bssid->reserved = 0;
7819 ie_offset = _FIXED_IE_LENGTH_;
7820 }
7821 }
7822
7823 bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
7824
7825 /* below is to copy the information element */
7826 bssid->IELength = len;
7827 memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength);
7828
7829 /* get the signal strength */
7830 bssid->Rssi = precv_frame->attrib.phy_info.RecvSignalPower; /* in dBM.raw data */
7831 bssid->PhyInfo.SignalQuality = precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
7832 bssid->PhyInfo.SignalStrength = precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
7833
7834 /* checking SSID */
7835 if ((p = rtw_get_ie23a(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset)) == NULL)
7836 {
7837 DBG_8723A("marc: cannot find SSID for survey event\n");
7838 return _FAIL;
7839 }
7840
7841 if (*(p + 1)) {
7842 if (len > IEEE80211_MAX_SSID_LEN) {
7843 DBG_8723A("%s()-%d: IE too long (%d) for survey "
7844 "event\n", __func__, __LINE__, len);
7845 return _FAIL;
7846 }
7847 memcpy(bssid->Ssid.ssid, (p + 2), *(p + 1));
7848 bssid->Ssid.ssid_len = *(p + 1);
7849 } else {
7850 bssid->Ssid.ssid_len = 0;
7851 }
7852
7853 memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
7854
7855 /* checking rate info... */
7856 i = 0;
7857 p = rtw_get_ie23a(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
7858 if (p != NULL)
7859 {
7860 if (len > NDIS_802_11_LENGTH_RATES_EX)
7861 {
7862 DBG_8723A("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
7863 return _FAIL;
7864 }
7865 memcpy(bssid->SupportedRates, (p + 2), len);
7866 i = len;
7867 }
7868
7869 p = rtw_get_ie23a(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
7870 if (p != NULL)
7871 {
7872 if (len > (NDIS_802_11_LENGTH_RATES_EX-i))
7873 {
7874 DBG_8723A("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
7875 return _FAIL;
7876 }
7877 memcpy(bssid->SupportedRates + i, (p + 2), len);
7878 }
7879
7880 /* todo: */
7881 {
7882 bssid->NetworkTypeInUse = Ndis802_11OFDM24;
7883 }
7884
7885 if (bssid->IELength < 12)
7886 return _FAIL;
7887
7888 /* Checking for DSConfig */
7889 p = rtw_get_ie23a(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset);
7890
7891 bssid->Configuration.DSConfig = 0;
7892 bssid->Configuration.Length = 0;
7893
7894 if (p)
7895 {
7896 bssid->Configuration.DSConfig = *(p + 2);
7897 }
7898 else
7899 {/* In 5G, some ap do not have DSSET IE */
7900 /* checking HT info for channel */
7901 p = rtw_get_ie23a(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset);
7902 if (p)
7903 {
7904 struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
7905 bssid->Configuration.DSConfig = HT_info->primary_channel;
7906 }
7907 else
7908 { /* use current channel */
7909 bssid->Configuration.DSConfig = rtw_get_oper_ch23a(padapter);
7910 }
7911 }
7912
7913 if (ieee80211_is_probe_req(hdr->frame_control)) {
7914 /* FIXME */
7915 bssid->InfrastructureMode = Ndis802_11Infrastructure;
7916 ether_addr_copy(bssid->MacAddress, hdr->addr2);
7917 bssid->Privacy = 1;
7918 return _SUCCESS;
7919 }
7920
7921 memcpy(&bssid->Configuration.BeaconPeriod, rtw_get_beacon_interval23a_from_ie(bssid->IEs), 2);
7922 bssid->Configuration.BeaconPeriod = le32_to_cpu(bssid->Configuration.BeaconPeriod);
7923
7924 val16 = rtw_get_capability23a(bssid);
7925
7926 if (val16 & BIT(0)) {
7927 bssid->InfrastructureMode = Ndis802_11Infrastructure;
7928 ether_addr_copy(bssid->MacAddress, hdr->addr2);
7929 } else {
7930 bssid->InfrastructureMode = Ndis802_11IBSS;
7931 ether_addr_copy(bssid->MacAddress, hdr->addr3);
7932 }
7933
7934 if (val16 & BIT(4))
7935 bssid->Privacy = 1;
7936 else
7937 bssid->Privacy = 0;
7938
7939 bssid->Configuration.ATIMWindow = 0;
7940
7941 /* 20/40 BSS Coexistence check */
7942 if ((pregistrypriv->wifi_spec == 1) && (false == pmlmeinfo->bwmode_updated))
7943 {
7944 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
7945
7946 p = rtw_get_ie23a(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset);
7947 if (p && len > 0) {
7948 struct HT_caps_element *pHT_caps;
7949 pHT_caps = (struct HT_caps_element *)(p + 2);
7950
7951 if (pHT_caps->u.HT_cap_element.HT_caps_info & BIT(14))
7952 pmlmepriv->num_FortyMHzIntolerant++;
7953 } else
7954 {
7955 pmlmepriv->num_sta_no_ht++;
7956 }
7957 }
7958
7959
7960 /* mark bss info receving from nearby channel as SignalQuality 101 */
7961 if (bssid->Configuration.DSConfig != rtw_get_oper_ch23a(padapter))
7962 bssid->PhyInfo.SignalQuality = 101;
7963
7964 return _SUCCESS;
7965}
7966
7967void start_create_ibss23a(struct rtw_adapter* padapter)
7968{
7969 unsigned short caps;
7970 u8 val8;
7971 u8 join_type;
7972 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7973 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7974 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
7975 pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
7976 pmlmeinfo->bcn_interval = get_beacon_interval23a(pnetwork);
7977
7978 /* update wireless mode */
7979 update_wireless_mode23a(padapter);
7980
7981 /* udpate capability */
7982 caps = rtw_get_capability23a(pnetwork);
7983 update_capinfo23a(padapter, caps);
7984 if (caps&cap_IBSS)/* adhoc master */
7985 {
7986 val8 = 0xcf;
7987 rtw_hal_set_hwreg23a(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
7988
7989 /* switch channel */
7990 /* SelectChannel23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
7991 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
7992
7993 beacon_timing_control23a(padapter);
7994
7995 /* set msr to WIFI_FW_ADHOC_STATE */
7996 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
7997 Set_MSR23a(padapter, (pmlmeinfo->state & 0x3));
7998
7999 /* issue beacon */
8000 if (send_beacon23a(padapter) == _FAIL)
8001 {
8002 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("issuing beacon frame fail....\n"));
8003
8004 report_join_res23a(padapter, -1);
8005 pmlmeinfo->state = WIFI_FW_NULL_STATE;
8006 }
8007 else
8008 {
8009 rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
8010 join_type = 0;
8011 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
8012
8013 report_join_res23a(padapter, 1);
8014 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
8015 }
8016 }
8017 else
8018 {
8019 DBG_8723A("start_create_ibss23a, invalid cap:%x\n", caps);
8020 return;
8021 }
8022}
8023
8024void start_clnt_join23a(struct rtw_adapter* padapter)
8025{
8026 unsigned short caps;
8027 u8 val8;
8028 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8029 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8030 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
8031 int beacon_timeout;
8032
8033 pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
8034 pmlmeinfo->bcn_interval = get_beacon_interval23a(pnetwork);
8035
8036 /* update wireless mode */
8037 update_wireless_mode23a(padapter);
8038
8039 /* udpate capability */
8040 caps = rtw_get_capability23a(pnetwork);
8041 update_capinfo23a(padapter, caps);
8042 if (caps&cap_ESS) {
8043 /* switch channel */
8044 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
8045
8046 Set_MSR23a(padapter, WIFI_FW_STATION_STATE);
8047
8048 val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf;
8049
8050 rtw_hal_set_hwreg23a(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
8051
8052 /* switch channel */
8053 /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
8054
8055 /* here wait for receiving the beacon to start auth */
8056 /* and enable a timer */
8057 beacon_timeout = decide_wait_for_beacon_timeout23a(pmlmeinfo->bcn_interval);
8058 set_link_timer(pmlmeext, beacon_timeout);
8059 mod_timer(&padapter->mlmepriv.assoc_timer, jiffies +
8060 msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout));
8061 pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
8062 }
8063 else if (caps&cap_IBSS) /* adhoc client */
8064 {
8065 Set_MSR23a(padapter, WIFI_FW_ADHOC_STATE);
8066
8067 val8 = 0xcf;
8068 rtw_hal_set_hwreg23a(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
8069
8070 /* switch channel */
8071 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
8072
8073 beacon_timing_control23a(padapter);
8074
8075 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
8076
8077 report_join_res23a(padapter, 1);
8078 }
8079 else
8080 {
8081 /* DBG_8723A("marc: invalid cap:%x\n", caps); */
8082 return;
8083 }
8084}
8085
8086void start_clnt_auth23a(struct rtw_adapter* padapter)
8087{
8088 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8089 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8090
8091 del_timer_sync(&pmlmeext->link_timer);
8092
8093 pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
8094 pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
8095
8096 pmlmeinfo->auth_seq = 1;
8097 pmlmeinfo->reauth_count = 0;
8098 pmlmeinfo->reassoc_count = 0;
8099 pmlmeinfo->link_count = 0;
8100 pmlmeext->retry = 0;
8101
8102 /* Because of AP's not receiving deauth before */
8103 /* AP may: 1)not response auth or 2)deauth us after link is complete */
8104 /* issue deauth before issuing auth to deal with the situation */
8105 /* Commented by Albert 2012/07/21 */
8106 /* For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
8107 issue_deauth23a(padapter, (&pmlmeinfo->network)->MacAddress, WLAN_REASON_DEAUTH_LEAVING);
8108
8109 DBG_8723A_LEVEL(_drv_always_, "start auth\n");
8110 issue_auth23a(padapter, NULL, 0);
8111
8112 set_link_timer(pmlmeext, REAUTH_TO);
8113}
8114
8115void start_clnt_assoc23a(struct rtw_adapter* padapter)
8116{
8117 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8118 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8119
8120 del_timer_sync(&pmlmeext->link_timer);
8121
8122 pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
8123 pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
8124
8125 issue_assocreq23a(padapter);
8126
8127 set_link_timer(pmlmeext, REASSOC_TO);
8128}
8129
8130unsigned int receive_disconnect23a(struct rtw_adapter *padapter, unsigned char *MacAddr, unsigned short reason)
8131{
8132 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8133 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8134
8135 /* check A3 */
8136 if (!ether_addr_equal(MacAddr, get_my_bssid23a(&pmlmeinfo->network)))
8137 return _SUCCESS;
8138
8139 DBG_8723A("%s\n", __func__);
8140
8141 if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
8142 {
8143 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
8144 {
8145 pmlmeinfo->state = WIFI_FW_NULL_STATE;
8146 report_del_sta_event23a(padapter, MacAddr, reason);
8147
8148 }
8149 else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE)
8150 {
8151 pmlmeinfo->state = WIFI_FW_NULL_STATE;
8152 report_join_res23a(padapter, -2);
8153 }
8154 }
8155
8156 return _SUCCESS;
8157}
8158
8159static void process_80211d(struct rtw_adapter *padapter, struct wlan_bssid_ex *bssid)
8160{
8161 struct registry_priv *pregistrypriv;
8162 struct mlme_ext_priv *pmlmeext;
8163 struct rt_channel_info *chplan_new;
8164 u8 channel;
8165 u8 i;
8166
8167 pregistrypriv = &padapter->registrypriv;
8168 pmlmeext = &padapter->mlmeextpriv;
8169
8170 /* Adjust channel plan by AP Country IE */
8171 if (pregistrypriv->enable80211d &&
8172 (!pmlmeext->update_channel_plan_by_ap_done))
8173 {
8174 u8 *ie, *p;
8175 u32 len;
8176 struct rt_channel_plan chplan_ap;
8177 struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
8178 u8 country[4];
8179 u8 fcn; /* first channel number */
8180 u8 noc; /* number of channel */
8181 u8 j, k;
8182
8183 ie = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
8184 if (!ie) return;
8185 if (len < 6) return;
8186
8187 ie += 2;
8188 p = ie;
8189 ie += len;
8190
8191 memset(country, 0, 4);
8192 memcpy(country, p, 3);
8193 p += 3;
8194 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
8195 ("%s: 802.11d country =%s\n", __func__, country));
8196
8197 i = 0;
8198 while ((ie - p) >= 3)
8199 {
8200 fcn = *(p++);
8201 noc = *(p++);
8202 p++;
8203
8204 for (j = 0; j < noc; j++)
8205 {
8206 if (fcn <= 14) channel = fcn + j; /* 2.4 GHz */
8207 else channel = fcn + j*4; /* 5 GHz */
8208
8209 chplan_ap.Channel[i++] = channel;
8210 }
8211 }
8212 chplan_ap.Len = i;
8213
8214 memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
8215 memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
8216 chplan_new = pmlmeext->channel_set;
8217
8218 i = j = k = 0;
8219 if (pregistrypriv->wireless_mode & WIRELESS_11G) {
8220 do {
8221 if ((i == MAX_CHANNEL_NUM) ||
8222 (chplan_sta[i].ChannelNum == 0) ||
8223 (chplan_sta[i].ChannelNum > 14))
8224 break;
8225
8226 if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
8227 break;
8228
8229 if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
8230 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
8231 chplan_new[k].ScanType = SCAN_ACTIVE;
8232 i++;
8233 j++;
8234 k++;
8235 } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
8236 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
8237 chplan_new[k].ScanType = SCAN_PASSIVE;
8238 i++;
8239 k++;
8240 } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
8241 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
8242 chplan_new[k].ScanType = SCAN_ACTIVE;
8243 j++;
8244 k++;
8245 }
8246 } while (1);
8247
8248 /* change AP not support channel to Passive scan */
8249 while ((i < MAX_CHANNEL_NUM) &&
8250 (chplan_sta[i].ChannelNum != 0) &&
8251 (chplan_sta[i].ChannelNum <= 14)) {
8252 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
8253 chplan_new[k].ScanType = SCAN_PASSIVE;
8254 i++;
8255 k++;
8256 }
8257
8258 /* add channel AP supported */
8259 while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
8260 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
8261 chplan_new[k].ScanType = SCAN_ACTIVE;
8262 j++;
8263 k++;
8264 }
8265 } else {
8266 /* keep original STA 2.4G channel plan */
8267 while ((i < MAX_CHANNEL_NUM) &&
8268 (chplan_sta[i].ChannelNum != 0) &&
8269 (chplan_sta[i].ChannelNum <= 14)) {
8270 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
8271 chplan_new[k].ScanType = chplan_sta[i].ScanType;
8272 i++;
8273 k++;
8274 }
8275
8276 /* skip AP 2.4G channel plan */
8277 while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
8278 j++;
8279 }
8280 }
8281
8282 if (pregistrypriv->wireless_mode & WIRELESS_11A) {
8283 do {
8284 if ((i == MAX_CHANNEL_NUM) ||
8285 (chplan_sta[i].ChannelNum == 0))
8286 break;
8287
8288 if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0))
8289 break;
8290
8291 if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j])
8292 {
8293 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
8294 chplan_new[k].ScanType = SCAN_ACTIVE;
8295 i++;
8296 j++;
8297 k++;
8298 }
8299 else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j])
8300 {
8301 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
8302/* chplan_new[k].ScanType = chplan_sta[i].ScanType; */
8303 chplan_new[k].ScanType = SCAN_PASSIVE;
8304 i++;
8305 k++;
8306 }
8307 else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j])
8308 {
8309 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
8310 chplan_new[k].ScanType = SCAN_ACTIVE;
8311 j++;
8312 k++;
8313 }
8314 } while (1);
8315
8316 /* change AP not support channel to Passive scan */
8317 while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
8318 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
8319 chplan_new[k].ScanType = SCAN_PASSIVE;
8320 i++;
8321 k++;
8322 }
8323
8324 /* add channel AP supported */
8325 while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0)) {
8326 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
8327 chplan_new[k].ScanType = SCAN_ACTIVE;
8328 j++;
8329 k++;
8330 }
8331 } else {
8332 /* keep original STA 5G channel plan */
8333 while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
8334 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
8335 chplan_new[k].ScanType = chplan_sta[i].ScanType;
8336 i++;
8337 k++;
8338 }
8339 }
8340 pmlmeext->update_channel_plan_by_ap_done = 1;
8341 }
8342
8343 /* If channel is used by AP, set channel scan type to active */
8344 channel = bssid->Configuration.DSConfig;
8345 chplan_new = pmlmeext->channel_set;
8346 i = 0;
8347 while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
8348 if (chplan_new[i].ChannelNum == channel)
8349 {
8350 if (chplan_new[i].ScanType == SCAN_PASSIVE) {
8351 /* 5G Bnad 2, 3 (DFS) doesn't change to active scan */
8352 if (channel >= 52 && channel <= 144)
8353 break;
8354
8355 chplan_new[i].ScanType = SCAN_ACTIVE;
8356 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
8357 ("%s: change channel %d scan type from passive to active\n",
8358 __func__, channel));
8359 }
8360 break;
8361 }
8362 i++;
8363 }
8364}
8365
8366/****************************************************************************
8367
8368Following are the functions to report events
8369
8370*****************************************************************************/
8371
8372void report_survey_event23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
8373{
8374 struct cmd_obj *pcmd_obj;
8375 u8 *pevtcmd;
8376 u32 cmdsz;
8377 struct survey_event *psurvey_evt;
8378 struct C2HEvent_Header *pc2h_evt_hdr;
8379 struct mlme_ext_priv *pmlmeext;
8380 struct cmd_priv *pcmdpriv;
8381
8382 if (!padapter)
8383 return;
8384
8385 pmlmeext = &padapter->mlmeextpriv;
8386 pcmdpriv = &padapter->cmdpriv;
8387
8388 pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
8389 GFP_ATOMIC);
8390 if (!pcmd_obj)
8391 return;
8392
8393 cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
8394 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
8395 if (!pevtcmd) {
8396 kfree(pcmd_obj);
8397 return;
8398 }
8399
8400 INIT_LIST_HEAD(&pcmd_obj->list);
8401
8402 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
8403 pcmd_obj->cmdsz = cmdsz;
8404 pcmd_obj->parmbuf = pevtcmd;
8405
8406 pcmd_obj->rsp = NULL;
8407 pcmd_obj->rspsz = 0;
8408
8409 pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
8410 pc2h_evt_hdr->len = sizeof(struct survey_event);
8411 pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
8412 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
8413
8414 psurvey_evt = (struct survey_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
8415
8416 if (collect_bss_info23a(padapter, precv_frame, &psurvey_evt->bss) == _FAIL) {
8417 kfree(pcmd_obj);
8418 kfree(pevtcmd);
8419 return;
8420 }
8421
8422 process_80211d(padapter, &psurvey_evt->bss);
8423
8424 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
8425
8426 pmlmeext->sitesurvey_res.bss_cnt++;
8427
8428 return;
8429}
8430
8431void report_surveydone_event23a(struct rtw_adapter *padapter)
8432{
8433 struct cmd_obj *pcmd_obj;
8434 u8 *pevtcmd;
8435 u32 cmdsz;
8436 struct surveydone_event *psurveydone_evt;
8437 struct C2HEvent_Header *pc2h_evt_hdr;
8438 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8439 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
8440
8441 pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
8442 GFP_ATOMIC);
8443 if (!pcmd_obj)
8444 return;
8445
8446 cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
8447 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
8448 if (!pevtcmd) {
8449 kfree(pcmd_obj);
8450 return;
8451 }
8452
8453 INIT_LIST_HEAD(&pcmd_obj->list);
8454
8455 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
8456 pcmd_obj->cmdsz = cmdsz;
8457 pcmd_obj->parmbuf = pevtcmd;
8458
8459 pcmd_obj->rsp = NULL;
8460 pcmd_obj->rspsz = 0;
8461
8462 pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
8463 pc2h_evt_hdr->len = sizeof(struct surveydone_event);
8464 pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
8465 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
8466
8467 psurveydone_evt = (struct surveydone_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
8468 psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
8469
8470 DBG_8723A("survey done event(%x)\n", psurveydone_evt->bss_cnt);
8471
8472 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
8473
8474 return;
8475}
8476
8477void report_join_res23a(struct rtw_adapter *padapter, int res)
8478{
8479 struct cmd_obj *pcmd_obj;
8480 u8 *pevtcmd;
8481 u32 cmdsz;
8482 struct joinbss_event *pjoinbss_evt;
8483 struct C2HEvent_Header *pc2h_evt_hdr;
8484 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8485 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8486 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
8487
8488 pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
8489 GFP_ATOMIC);
8490 if (!pcmd_obj)
8491 return;
8492
8493 cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
8494 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
8495 if (!pevtcmd) {
8496 kfree(pcmd_obj);
8497 return;
8498 }
8499
8500 INIT_LIST_HEAD(&pcmd_obj->list);
8501
8502 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
8503 pcmd_obj->cmdsz = cmdsz;
8504 pcmd_obj->parmbuf = pevtcmd;
8505
8506 pcmd_obj->rsp = NULL;
8507 pcmd_obj->rspsz = 0;
8508
8509 pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
8510 pc2h_evt_hdr->len = sizeof(struct joinbss_event);
8511 pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
8512 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
8513
8514 pjoinbss_evt = (struct joinbss_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
8515 memcpy((unsigned char *)&pjoinbss_evt->network.network,
8516 &pmlmeinfo->network, sizeof(struct wlan_bssid_ex));
8517 pjoinbss_evt->network.join_res = pjoinbss_evt->network.aid = res;
8518
8519 DBG_8723A("report_join_res23a(%d)\n", res);
8520
8521 rtw_joinbss_event_prehandle23a(padapter, (u8 *)&pjoinbss_evt->network);
8522
8523 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
8524
8525 return;
8526}
8527
8528void report_del_sta_event23a(struct rtw_adapter *padapter, unsigned char* MacAddr, unsigned short reason)
8529{
8530 struct cmd_obj *pcmd_obj;
8531 u8 *pevtcmd;
8532 u32 cmdsz;
8533 struct sta_info *psta;
8534 int mac_id;
8535 struct stadel_event *pdel_sta_evt;
8536 struct C2HEvent_Header *pc2h_evt_hdr;
8537 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8538 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
8539
8540 pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
8541 GFP_ATOMIC);
8542 if (!pcmd_obj)
8543 return;
8544
8545 cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
8546 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
8547 if (!pevtcmd) {
8548 kfree(pcmd_obj);
8549 return;
8550 }
8551
8552 INIT_LIST_HEAD(&pcmd_obj->list);
8553
8554 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
8555 pcmd_obj->cmdsz = cmdsz;
8556 pcmd_obj->parmbuf = pevtcmd;
8557
8558 pcmd_obj->rsp = NULL;
8559 pcmd_obj->rspsz = 0;
8560
8561 pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
8562 pc2h_evt_hdr->len = sizeof(struct stadel_event);
8563 pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
8564 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
8565
8566 pdel_sta_evt = (struct stadel_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
8567 ether_addr_copy((unsigned char *)&pdel_sta_evt->macaddr, MacAddr);
8568 memcpy((unsigned char *)pdel_sta_evt->rsvd, (unsigned char *)&reason,
8569 2);
8570
8571 psta = rtw_get_stainfo23a(&padapter->stapriv, MacAddr);
8572 if (psta)
8573 mac_id = (int)psta->mac_id;
8574 else
8575 mac_id = (-1);
8576
8577 pdel_sta_evt->mac_id = mac_id;
8578
8579 DBG_8723A("report_del_sta_event23a: delete STA, mac_id =%d\n", mac_id);
8580
8581 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
8582
8583 return;
8584}
8585
8586void report_add_sta_event23a(struct rtw_adapter *padapter, unsigned char* MacAddr, int cam_idx)
8587{
8588 struct cmd_obj *pcmd_obj;
8589 u8 *pevtcmd;
8590 u32 cmdsz;
8591 struct stassoc_event *padd_sta_evt;
8592 struct C2HEvent_Header *pc2h_evt_hdr;
8593 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8594 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
8595
8596 pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
8597 GFP_ATOMIC);
8598 if (!pcmd_obj)
8599 return;
8600
8601 cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
8602 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
8603 if (!pevtcmd) {
8604 kfree(pcmd_obj);
8605 return;
8606 }
8607
8608 INIT_LIST_HEAD(&pcmd_obj->list);
8609
8610 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
8611 pcmd_obj->cmdsz = cmdsz;
8612 pcmd_obj->parmbuf = pevtcmd;
8613
8614 pcmd_obj->rsp = NULL;
8615 pcmd_obj->rspsz = 0;
8616
8617 pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
8618 pc2h_evt_hdr->len = sizeof(struct stassoc_event);
8619 pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
8620 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
8621
8622 padd_sta_evt = (struct stassoc_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
8623 ether_addr_copy((unsigned char *)&padd_sta_evt->macaddr, MacAddr);
8624 padd_sta_evt->cam_id = cam_idx;
8625
8626 DBG_8723A("report_add_sta_event23a: add STA\n");
8627
8628 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
8629
8630 return;
8631}
8632
8633/****************************************************************************
8634
8635Following are the event callback functions
8636
8637*****************************************************************************/
8638
8639/* for sta/adhoc mode */
8640void update_sta_info23a(struct rtw_adapter *padapter, struct sta_info *psta)
8641{
8642 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
8643 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8644 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8645
8646 /* ERP */
8647 VCS_update23a(padapter, psta);
8648
8649 /* HT */
8650 if (pmlmepriv->htpriv.ht_option)
8651 {
8652 psta->htpriv.ht_option = true;
8653
8654 psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
8655
8656 if (support_short_GI23a(padapter, &pmlmeinfo->HT_caps))
8657 psta->htpriv.sgi = true;
8658
8659 psta->qos_option = true;
8660
8661 }
8662 else
8663 {
8664 psta->htpriv.ht_option = false;
8665
8666 psta->htpriv.ampdu_enable = false;
8667
8668 psta->htpriv.sgi = false;
8669 psta->qos_option = false;
8670
8671 }
8672 psta->htpriv.bwmode = pmlmeext->cur_bwmode;
8673 psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
8674
8675 psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
8676 psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
8677
8678 /* QoS */
8679 if (pmlmepriv->qospriv.qos_option)
8680 psta->qos_option = true;
8681
8682 psta->state = _FW_LINKED;
8683}
8684
8685void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter, int join_res)
8686{
8687 struct sta_info *psta, *psta_bmc;
8688 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8689 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8690 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
8691 struct sta_priv *pstapriv = &padapter->stapriv;
8692 u8 join_type;
8693 u16 media_status;
8694
8695 if (join_res < 0)
8696 {
8697 join_type = 1;
8698 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
8699 rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, null_addr);
8700
8701 /* restore to initial setting. */
8702 update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
8703
8704 goto exit_mlmeext_joinbss_event_callback23a;
8705 }
8706
8707 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
8708 {
8709 /* for bc/mc */
8710 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
8711 if (psta_bmc)
8712 {
8713 pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
8714 update_bmc_sta_support_rate23a(padapter, psta_bmc->mac_id);
8715 Update_RA_Entry23a(padapter, psta_bmc);
8716 }
8717 }
8718
8719 /* turn on dynamic functions */
8720 Switch_DM_Func23a(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
8721
8722 /* update IOT-releated issue */
8723 update_IOT_info23a(padapter);
8724
8725 rtw_hal_set_hwreg23a(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
8726
8727 /* BCN interval */
8728 rtw_hal_set_hwreg23a(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
8729
8730 /* udpate capability */
8731 update_capinfo23a(padapter, pmlmeinfo->capability);
8732
8733 /* WMM, Update EDCA param */
8734 WMMOnAssocRsp23a(padapter);
8735
8736 /* HT */
8737 HTOnAssocRsp23a(padapter);
8738
8739 /* Set cur_channel&cur_bwmode&cur_ch_offset */
8740 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
8741
8742 psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress);
8743 if (psta) /* only for infra. mode */
8744 {
8745 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
8746
8747 /* DBG_8723A("set_sta_rate23a\n"); */
8748
8749 psta->wireless_mode = pmlmeext->cur_wireless_mode;
8750
8751 /* set per sta rate after updating HT cap. */
8752 set_sta_rate23a(padapter, psta);
8753
8754 media_status = (psta->mac_id<<8)|1; /* MACID|OPMODE: 1 means connect */
8755 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
8756 }
8757
8758 join_type = 2;
8759 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
8760
8761 if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
8762 {
8763 /* correcting TSF */
8764 correct_TSF23a(padapter, pmlmeext);
8765
8766 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
8767 }
8768
8769 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_CONNECT, 0);
8770
8771exit_mlmeext_joinbss_event_callback23a:
8772 DBG_8723A("=>%s\n", __func__);
8773}
8774
8775void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter, struct sta_info *psta)
8776{
8777 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8778 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8779 u8 join_type;
8780
8781 DBG_8723A("%s\n", __func__);
8782
8783 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
8784 {
8785 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)/* adhoc master or sta_count>1 */
8786 {
8787 /* nothing to do */
8788 }
8789 else/* adhoc client */
8790 {
8791 /* update TSF Value */
8792 /* update_TSF23a(pmlmeext, pframe, len); */
8793
8794 /* correcting TSF */
8795 correct_TSF23a(padapter, pmlmeext);
8796
8797 /* start beacon */
8798 if (send_beacon23a(padapter) == _FAIL)
8799 {
8800 pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
8801
8802 pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
8803
8804 return;
8805 }
8806
8807 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
8808
8809 }
8810
8811 join_type = 2;
8812 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
8813 }
8814
8815 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
8816
8817 /* rate radaptive */
8818 Update_RA_Entry23a(padapter, psta);
8819
8820 /* update adhoc sta_info */
8821 update_sta_info23a(padapter, psta);
8822}
8823
8824void mlmeext_sta_del_event_callback23a(struct rtw_adapter *padapter)
8825{
8826 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8827 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8828
8829 if (is_client_associated_to_ap23a(padapter) || is_IBSS_empty23a(padapter))
8830 {
8831 /* set_opmode_cmd(padapter, infra_client_with_mlme); */
8832
8833 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_DISCONNECT, NULL);
8834 rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, null_addr);
8835
8836 /* restore to initial setting. */
8837 update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
8838
8839 /* switch to the 20M Hz mode after disconnect */
8840 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
8841 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
8842
8843 /* SelectChannel23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
8844 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
8845
8846 flush_all_cam_entry23a(padapter);
8847
8848 pmlmeinfo->state = WIFI_FW_NULL_STATE;
8849
8850 /* set MSR to no link state -> infra. mode */
8851 Set_MSR23a(padapter, _HW_STATE_STATION_);
8852
8853 del_timer_sync(&pmlmeext->link_timer);
8854 }
8855}
8856
8857/****************************************************************************
8858
8859Following are the functions for the timer handlers
8860
8861*****************************************************************************/
8862void linked23a_rx_sig_stren_disp(struct rtw_adapter *padapter)
8863{
8864 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8865 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8866 u8 mac_id;
8867 int UndecoratedSmoothedPWDB;
8868 if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
8869 mac_id = 0;
8870 else if ((pmlmeinfo->state&0x03) == _HW_STATE_AP_)
8871 mac_id = 2;
8872
8873 rtw_hal_get_def_var23a(padapter, HW_DEF_RA_INFO_DUMP,&mac_id);
8874
8875 rtw_hal_get_def_var23a(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);
8876 DBG_8723A("UndecoratedSmoothedPWDB:%d\n", UndecoratedSmoothedPWDB);
8877}
8878
8879static u8 chk_ap_is_alive(struct rtw_adapter *padapter, struct sta_info *psta)
8880{
8881 u8 ret = false;
8882
8883 if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)) &&
8884 sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) &&
8885 sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
8886 ret = false;
8887 else
8888 ret = true;
8889
8890 sta_update_last_rx_pkts(psta);
8891 return ret;
8892}
8893
8894void linked_status_chk23a(struct rtw_adapter *padapter)
8895{
8896 u32 i;
8897 struct sta_info *psta;
8898 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
8899 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8900 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8901 struct sta_priv *pstapriv = &padapter->stapriv;
8902
8903 if (padapter->bRxRSSIDisplay)
8904 linked23a_rx_sig_stren_disp(padapter);
8905
8906 rtw_hal_sreset_linked_status_check23a(padapter);
8907
8908 if (is_client_associated_to_ap23a(padapter))
8909 {
8910 /* linked infrastructure client mode */
8911
8912 int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
8913 int rx_chk_limit;
8914
8915 rx_chk_limit = 4;
8916
8917 if ((psta = rtw_get_stainfo23a(pstapriv, pmlmeinfo->network.MacAddress)) != NULL)
8918 {
8919 bool is_p2p_enable = false;
8920#ifdef CONFIG_8723AU_P2P
8921 is_p2p_enable = !rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE);
8922#endif
8923
8924 if (chk_ap_is_alive(padapter, psta) == false)
8925 rx_chk = _FAIL;
8926
8927 if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
8928 tx_chk = _FAIL;
8929
8930 if (pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)) {
8931 u8 backup_oper_channel = 0;
8932
8933 /* switch to correct channel of current network before issue keep-alive frames */
8934 if (rtw_get_oper_ch23a(padapter) != pmlmeext->cur_channel) {
8935 backup_oper_channel = rtw_get_oper_ch23a(padapter);
8936 SelectChannel23a(padapter, pmlmeext->cur_channel);
8937 }
8938
8939 if (rx_chk != _SUCCESS)
8940 issue_probereq23a_ex23a(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
8941
8942 if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) || rx_chk != _SUCCESS) {
8943 tx_chk = issue_nulldata23a(padapter, psta->hwaddr, 0, 3, 1);
8944 /* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */
8945 if (tx_chk == _SUCCESS && !is_p2p_enable)
8946 rx_chk = _SUCCESS;
8947 }
8948
8949 /* back to the original operation channel */
8950 if (backup_oper_channel>0)
8951 SelectChannel23a(padapter, backup_oper_channel);
8952
8953 } else {
8954 if (rx_chk != _SUCCESS) {
8955 if (pmlmeext->retry == 0) {
8956 issue_probereq23a(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
8957 issue_probereq23a(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
8958 issue_probereq23a(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
8959 }
8960 }
8961
8962 if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf)
8963 tx_chk = issue_nulldata23a(padapter, NULL, 0, 1, 0);
8964 }
8965
8966 if (rx_chk == _FAIL) {
8967 pmlmeext->retry++;
8968 if (pmlmeext->retry > rx_chk_limit) {
8969 DBG_8723A_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n",
8970 FUNC_ADPT_ARG(padapter));
8971 receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress,
8972 WLAN_REASON_EXPIRATION_CHK);
8973 return;
8974 }
8975 } else {
8976 pmlmeext->retry = 0;
8977 }
8978
8979 if (tx_chk == _FAIL) {
8980 pmlmeinfo->link_count &= 0xf;
8981 } else {
8982 pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
8983 pmlmeinfo->link_count = 0;
8984 }
8985
8986 } /* end of if ((psta = rtw_get_stainfo23a(pstapriv, passoc_res->network.MacAddress)) != NULL) */
8987 }
8988 else if (is_client_associated_to_ibss23a(padapter))
8989 {
8990 /* linked IBSS mode */
8991 /* for each assoc list entry to check the rx pkt counter */
8992 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++)
8993 {
8994 if (pmlmeinfo->FW_sta_info[i].status == 1)
8995 {
8996 psta = pmlmeinfo->FW_sta_info[i].psta;
8997
8998 if (NULL == psta) continue;
8999
9000 if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta))
9001 {
9002
9003 if (pmlmeinfo->FW_sta_info[i].retry<3)
9004 {
9005 pmlmeinfo->FW_sta_info[i].retry++;
9006 }
9007 else
9008 {
9009 pmlmeinfo->FW_sta_info[i].retry = 0;
9010 pmlmeinfo->FW_sta_info[i].status = 0;
9011 report_del_sta_event23a(padapter, psta->hwaddr,
9012 65535/* indicate disconnect caused by no rx */
9013 );
9014 }
9015 }
9016 else
9017 {
9018 pmlmeinfo->FW_sta_info[i].retry = 0;
9019 pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
9020 }
9021 }
9022 }
9023
9024 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
9025
9026 }
9027}
9028
9029static void survey_timer_hdl(unsigned long data)
9030{
9031 struct rtw_adapter *padapter = (struct rtw_adapter *)data;
9032 struct cmd_obj *ph2c;
9033 struct sitesurvey_parm *psurveyPara;
9034 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
9035 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9036#ifdef CONFIG_8723AU_P2P
9037 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
9038#endif
9039
9040 /* issue rtw_sitesurvey_cmd23a */
9041 if (pmlmeext->sitesurvey_res.state > SCAN_START) {
9042 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
9043 pmlmeext->sitesurvey_res.channel_idx++;
9044
9045 if (pmlmeext->scan_abort == true)
9046 {
9047#ifdef CONFIG_8723AU_P2P
9048 if (!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE))
9049 {
9050 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
9051 pmlmeext->sitesurvey_res.channel_idx = 3;
9052 DBG_8723A("%s idx:%d, cnt:%u\n", __func__,
9053 pmlmeext->sitesurvey_res.channel_idx,
9054 pwdinfo->find_phase_state_exchange_cnt);
9055 } else
9056 #endif
9057 {
9058 pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
9059 DBG_8723A("%s idx:%d\n", __func__,
9060 pmlmeext->sitesurvey_res.channel_idx);
9061 }
9062
9063 pmlmeext->scan_abort = false;/* reset */
9064 }
9065
9066 ph2c = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
9067 GFP_ATOMIC);
9068 if (!ph2c)
9069 goto exit_survey_timer_hdl;
9070
9071 psurveyPara = (struct sitesurvey_parm*)
9072 kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC);
9073 if (!psurveyPara) {
9074 kfree(ph2c);
9075 goto exit_survey_timer_hdl;
9076 }
9077
9078 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
9079 rtw_enqueue_cmd23a(pcmdpriv, ph2c);
9080 }
9081
9082exit_survey_timer_hdl:
9083 return;
9084}
9085
9086static void link_timer_hdl(unsigned long data)
9087{
9088 struct rtw_adapter *padapter = (struct rtw_adapter *)data;
9089 /* static unsigned int rx_pkt = 0; */
9090 /* static u64 tx_cnt = 0; */
9091 /* struct xmit_priv *pxmitpriv = &padapter->xmitpriv; */
9092 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9093 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9094 /* struct sta_priv *pstapriv = &padapter->stapriv; */
9095
9096 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL)
9097 {
9098 DBG_8723A("link_timer_hdl:no beacon while connecting\n");
9099 pmlmeinfo->state = WIFI_FW_NULL_STATE;
9100 report_join_res23a(padapter, -3);
9101 }
9102 else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE)
9103 {
9104 /* re-auth timer */
9105 if (++pmlmeinfo->reauth_count > REAUTH_LIMIT)
9106 {
9107 /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */
9108 /* */
9109 pmlmeinfo->state = 0;
9110 report_join_res23a(padapter, -1);
9111 return;
9112 /* */
9113 /* else */
9114 /* */
9115 /* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */
9116 /* pmlmeinfo->reauth_count = 0; */
9117 /* */
9118 }
9119
9120 DBG_8723A("link_timer_hdl: auth timeout and try again\n");
9121 pmlmeinfo->auth_seq = 1;
9122 issue_auth23a(padapter, NULL, 0);
9123 set_link_timer(pmlmeext, REAUTH_TO);
9124 }
9125 else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)
9126 {
9127 /* re-assoc timer */
9128 if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT)
9129 {
9130 pmlmeinfo->state = WIFI_FW_NULL_STATE;
9131 report_join_res23a(padapter, -2);
9132 return;
9133 }
9134
9135 DBG_8723A("link_timer_hdl: assoc timeout and try again\n");
9136 issue_assocreq23a(padapter);
9137 set_link_timer(pmlmeext, REASSOC_TO);
9138 }
9139
9140 return;
9141}
9142
9143static void addba_timer_hdl(unsigned long data)
9144{
9145 struct sta_info *psta = (struct sta_info *)data;
9146 struct ht_priv *phtpriv;
9147
9148 if (!psta)
9149 return;
9150
9151 phtpriv = &psta->htpriv;
9152
9153 if ((phtpriv->ht_option == true) && (phtpriv->ampdu_enable == true))
9154 {
9155 if (phtpriv->candidate_tid_bitmap)
9156 phtpriv->candidate_tid_bitmap = 0x0;
9157
9158 }
9159}
9160
9161void init_addba_retry_timer23a(struct sta_info *psta)
9162{
9163 setup_timer(&psta->addba_retry_timer, addba_timer_hdl,
9164 (unsigned long)psta);
9165}
9166
9167void init_mlme_ext_timer23a(struct rtw_adapter *padapter)
9168{
9169 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9170
9171 setup_timer(&pmlmeext->survey_timer, survey_timer_hdl,
9172 (unsigned long)padapter);
9173
9174 setup_timer(&pmlmeext->link_timer, link_timer_hdl,
9175 (unsigned long)padapter);
9176}
9177
9178u8 NULL_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
9179{
9180 return H2C_SUCCESS;
9181}
9182
9183u8 setopmode_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
9184{
9185 u8 type;
9186 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9187 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9188 struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
9189
9190 if (psetop->mode == Ndis802_11APMode)
9191 {
9192 pmlmeinfo->state = WIFI_FW_AP_STATE;
9193 type = _HW_STATE_AP_;
9194 }
9195 else if (psetop->mode == Ndis802_11Infrastructure)
9196 {
9197 pmlmeinfo->state &= ~(BIT(0)|BIT(1));/* clear state */
9198 pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to STATION_STATE */
9199 type = _HW_STATE_STATION_;
9200 }
9201 else if (psetop->mode == Ndis802_11IBSS)
9202 {
9203 type = _HW_STATE_ADHOC_;
9204 }
9205 else
9206 {
9207 type = _HW_STATE_NOLINK_;
9208 }
9209
9210 rtw_hal_set_hwreg23a(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
9211 /* Set_NETYPE0_MSR(padapter, type); */
9212
9213 return H2C_SUCCESS;
9214}
9215
9216u8 createbss_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
9217{
9218 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9219 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9220 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
9221 struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
9222 /* u32 initialgain; */
9223
9224 if (pparm->InfrastructureMode == Ndis802_11APMode) {
9225#ifdef CONFIG_8723AU_AP_MODE
9226
9227 if (pmlmeinfo->state == WIFI_FW_AP_STATE)
9228 {
9229 /* todo: */
9230 return H2C_SUCCESS;
9231 }
9232#endif
9233 }
9234
9235 /* below is for ad-hoc master */
9236 if (pparm->InfrastructureMode == Ndis802_11IBSS) {
9237 rtw_joinbss_reset23a(padapter);
9238
9239 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
9240 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
9241 pmlmeinfo->ERP_enable = 0;
9242 pmlmeinfo->WMM_enable = 0;
9243 pmlmeinfo->HT_enable = 0;
9244 pmlmeinfo->HT_caps_enable = 0;
9245 pmlmeinfo->HT_info_enable = 0;
9246 pmlmeinfo->agg_enable_bitmap = 0;
9247 pmlmeinfo->candidate_tid_bitmap = 0;
9248
9249 /* disable dynamic functions, such as high power, DIG */
9250 Save_DM_Func_Flag23a(padapter);
9251 Switch_DM_Func23a(padapter, DYNAMIC_FUNC_DISABLE, false);
9252
9253 /* config the initial gain under linking, need to write the BB registers */
9254 /* initialgain = 0x1E; */
9255 /* rtw_hal_set_hwreg23a(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
9256
9257 /* cancel link timer */
9258 del_timer_sync(&pmlmeext->link_timer);
9259
9260 /* clear CAM */
9261 flush_all_cam_entry23a(padapter);
9262
9263 if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
9264 return H2C_PARAMETERS_ERROR;
9265
9266 memcpy(pnetwork, pparm, sizeof(struct wlan_bssid_ex));
9267
9268 start_create_ibss23a(padapter);
9269 }
9270
9271 return H2C_SUCCESS;
9272}
9273
9274u8 join_cmd_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
9275{
9276 u8 join_type;
9277 struct ndis_802_11_var_ies * pIE;
9278 struct registry_priv *pregpriv = &padapter->registrypriv;
9279 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9280 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9281 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
9282 struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
9283 struct HT_info_element *pht_info;
9284 u32 i;
9285 /* u32 initialgain; */
9286 /* u32 acparm; */
9287
9288 /* check already connecting to AP or not */
9289 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
9290 {
9291 if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
9292 issue_deauth23a_ex23a(padapter, pnetwork->MacAddress,
9293 WLAN_REASON_DEAUTH_LEAVING, 5, 100);
9294
9295 pmlmeinfo->state = WIFI_FW_NULL_STATE;
9296
9297 /* clear CAM */
9298 flush_all_cam_entry23a(padapter);
9299
9300 del_timer_sync(&pmlmeext->link_timer);
9301
9302 /* set MSR to nolink -> infra. mode */
9303 /* Set_MSR23a(padapter, _HW_STATE_NOLINK_); */
9304 Set_MSR23a(padapter, _HW_STATE_STATION_);
9305
9306 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_DISCONNECT, NULL);
9307 }
9308
9309 rtw_joinbss_reset23a(padapter);
9310
9311 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
9312 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
9313 pmlmeinfo->ERP_enable = 0;
9314 pmlmeinfo->WMM_enable = 0;
9315 pmlmeinfo->HT_enable = 0;
9316 pmlmeinfo->HT_caps_enable = 0;
9317 pmlmeinfo->HT_info_enable = 0;
9318 pmlmeinfo->agg_enable_bitmap = 0;
9319 pmlmeinfo->candidate_tid_bitmap = 0;
9320 pmlmeinfo->bwmode_updated = false;
9321 /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */
9322
9323 if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
9324 return H2C_PARAMETERS_ERROR;
9325
9326 memcpy(pnetwork, pbuf, sizeof(struct wlan_bssid_ex));
9327
9328 /* Check AP vendor to move rtw_joinbss_cmd23a() */
9329 /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP23a(pnetwork->IEs,
9330 pnetwork->IELength); */
9331
9332 for (i = sizeof(struct ndis_802_11_fixed_ies); i < pnetwork->IELength;)
9333 {
9334 pIE = (struct ndis_802_11_var_ies *)(pnetwork->IEs + i);
9335
9336 switch (pIE->ElementID)
9337 {
9338 case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */
9339 if (!memcmp(pIE->data, WMM_OUI23A, 4))
9340 pmlmeinfo->WMM_enable = 1;
9341 break;
9342
9343 case _HT_CAPABILITY_IE_: /* Get HT Cap IE. */
9344 pmlmeinfo->HT_caps_enable = 1;
9345 break;
9346
9347 case _HT_EXTRA_INFO_IE_: /* Get HT Info IE. */
9348 pmlmeinfo->HT_info_enable = 1;
9349
9350 /* spec case only for cisco's ap because cisco's ap
9351 * issue assoc rsp using mcs rate @40MHz or @20MHz */
9352 pht_info = (struct HT_info_element *)(pIE->data);
9353
9354 if ((pregpriv->cbw40_enable) &&
9355 (pht_info->infos[0] & BIT(2))) {
9356 /* switch to the 40M Hz mode according to AP */
9357 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
9358 switch (pht_info->infos[0] & 0x3)
9359 {
9360 case 1:
9361 pmlmeext->cur_ch_offset =
9362 HAL_PRIME_CHNL_OFFSET_LOWER;
9363 break;
9364
9365 case 3:
9366 pmlmeext->cur_ch_offset =
9367 HAL_PRIME_CHNL_OFFSET_UPPER;
9368 break;
9369
9370 default:
9371 pmlmeext->cur_ch_offset =
9372 HAL_PRIME_CHNL_OFFSET_DONT_CARE;
9373 break;
9374 }
9375
9376 DBG_8723A("set ch/bw before connected\n");
9377 }
9378 break;
9379
9380 default:
9381 break;
9382 }
9383
9384 i += (pIE->Length + 2);
9385 }
9386 /* disable dynamic functions, such as high power, DIG */
9387 /* Switch_DM_Func23a(padapter, DYNAMIC_FUNC_DISABLE, false); */
9388
9389 /* config the initial gain under linking, need to write the BB
9390 registers */
9391 /* initialgain = 0x1E; */
9392 /* rtw_hal_set_hwreg23a(padapter, HW_VAR_INITIAL_GAIN,
9393 (u8 *)(&initialgain)); */
9394
9395 rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID,
9396 pmlmeinfo->network.MacAddress);
9397 join_type = 0;
9398 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
9399
9400 /* cancel link timer */
9401 del_timer_sync(&pmlmeext->link_timer);
9402
9403 start_clnt_join23a(padapter);
9404
9405 return H2C_SUCCESS;
9406}
9407
9408u8 disconnect_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9409{
9410 struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
9411 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9412 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9413 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
9414 u8 val8;
9415
9416 if (is_client_associated_to_ap23a(padapter))
9417 {
9418 issue_deauth23a_ex23a(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
9419 }
9420
9421 /* set_opmode_cmd(padapter, infra_client_with_mlme); */
9422
9423 /* pmlmeinfo->state = WIFI_FW_NULL_STATE; */
9424
9425 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_DISCONNECT, NULL);
9426 rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, null_addr);
9427
9428 /* restore to initial setting. */
9429 update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
9430
9431 if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))
9432 {
9433 /* Stop BCN */
9434 val8 = 0;
9435 rtw_hal_set_hwreg23a(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
9436 }
9437
9438 /* set MSR to no link state -> infra. mode */
9439 Set_MSR23a(padapter, _HW_STATE_STATION_);
9440
9441 pmlmeinfo->state = WIFI_FW_NULL_STATE;
9442
9443 /* switch to the 20M Hz mode after disconnect */
9444 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
9445 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
9446
9447 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
9448
9449 flush_all_cam_entry23a(padapter);
9450
9451 del_timer_sync(&pmlmeext->link_timer);
9452
9453 rtw_free_uc_swdec_pending_queue23a(padapter);
9454
9455 return H2C_SUCCESS;
9456}
9457
9458static int rtw_scan_ch_decision(struct rtw_adapter *padapter, struct rtw_ieee80211_channel *out,
9459 u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
9460{
9461 int i, j;
9462 int scan_ch_num = 0;
9463 int set_idx;
9464 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9465
9466 /* clear out first */
9467 memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
9468
9469 /* acquire channels from in */
9470 j = 0;
9471 for (i = 0;i<in_num;i++) {
9472 if (0)
9473 DBG_8723A(FUNC_ADPT_FMT" "CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(&in[i]));
9474 if (in[i].hw_value && !(in[i].flags & IEEE80211_CHAN_DISABLED)
9475 && (set_idx = rtw_ch_set_search_ch23a(pmlmeext->channel_set, in[i].hw_value)) >= 0
9476 )
9477 {
9478 memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
9479
9480 if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
9481 out[j].flags &= IEEE80211_CHAN_NO_IR;
9482
9483 j++;
9484 }
9485 if (j>= out_num)
9486 break;
9487 }
9488
9489 /* if out is empty, use channel_set as default */
9490 if (j == 0) {
9491 for (i = 0;i<pmlmeext->max_chan_nums;i++) {
9492 out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
9493
9494 if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
9495 out[i].flags &= IEEE80211_CHAN_NO_IR;
9496
9497 j++;
9498 }
9499 }
9500
9501 if (padapter->setband == GHZ_24) { /* 2.4G */
9502 for (i = 0; i < j ; i++) {
9503 if (out[i].hw_value > 35)
9504 memset(&out[i], 0,
9505 sizeof(struct rtw_ieee80211_channel));
9506 else
9507 scan_ch_num++;
9508 }
9509 j = scan_ch_num;
9510 } else if (padapter->setband == GHZ_50) { /* 5G */
9511 for (i = 0; i < j ; i++) {
9512 if (out[i].hw_value > 35) {
9513 memcpy(&out[scan_ch_num++], &out[i], sizeof(struct rtw_ieee80211_channel));
9514 }
9515 }
9516 j = scan_ch_num;
9517 } else
9518 {}
9519
9520 return j;
9521}
9522
9523u8 sitesurvey_cmd_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
9524{
9525 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9526 struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;
9527 u8 bdelayscan = false;
9528 u8 val8;
9529 u32 initialgain;
9530 u32 i;
9531
9532 if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
9533 /* for first time sitesurvey_cmd */
9534 rtw_hal_set_hwreg23a(padapter, HW_VAR_CHECK_TXBUF, NULL);
9535
9536 pmlmeext->sitesurvey_res.state = SCAN_START;
9537 pmlmeext->sitesurvey_res.bss_cnt = 0;
9538 pmlmeext->sitesurvey_res.channel_idx = 0;
9539
9540 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
9541 if (pparm->ssid[i].ssid_len) {
9542 memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid,
9543 pparm->ssid[i].ssid, IW_ESSID_MAX_SIZE);
9544 pmlmeext->sitesurvey_res.ssid[i].ssid_len =
9545 pparm->ssid[i].ssid_len;
9546 } else {
9547 pmlmeext->sitesurvey_res.ssid[i].ssid_len = 0;
9548 }
9549 }
9550
9551 pmlmeext->sitesurvey_res.ch_num =
9552 rtw_scan_ch_decision(padapter,
9553 pmlmeext->sitesurvey_res.ch,
9554 RTW_CHANNEL_SCAN_AMOUNT,
9555 pparm->ch, pparm->ch_num);
9556
9557 pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
9558
9559 /* issue null data if associating to the AP */
9560 if (is_client_associated_to_ap23a(padapter)) {
9561 pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
9562
9563 /* switch to correct channel of current network
9564 before issue keep-alive frames */
9565 if (rtw_get_oper_ch23a(padapter) != pmlmeext->cur_channel)
9566 SelectChannel23a(padapter, pmlmeext->cur_channel);
9567
9568 issue_nulldata23a(padapter, NULL, 1, 3, 500);
9569
9570 bdelayscan = true;
9571 }
9572
9573 if (bdelayscan) {
9574 /* delay 50ms to protect nulldata(1). */
9575 set_survey_timer(pmlmeext, 50);
9576 return H2C_SUCCESS;
9577 }
9578 }
9579
9580 if ((pmlmeext->sitesurvey_res.state == SCAN_START) ||
9581 (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
9582 /* disable dynamic functions, such as high power, DIG */
9583 Save_DM_Func_Flag23a(padapter);
9584 Switch_DM_Func23a(padapter, DYNAMIC_FUNC_DISABLE, false);
9585
9586 /* config the initial gain under scaning, need to
9587 write the BB registers */
9588 if ((wdev_to_priv(padapter->rtw_wdev))->p2p_enabled == true) {
9589 initialgain = 0x30;
9590 } else
9591 initialgain = 0x1E;
9592
9593 rtw_hal_set_hwreg23a(padapter, HW_VAR_INITIAL_GAIN,
9594 (u8 *)(&initialgain));
9595
9596 /* set MSR to no link state */
9597 Set_MSR23a(padapter, _HW_STATE_NOLINK_);
9598
9599 val8 = 1; /* under site survey */
9600 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_SITESURVEY,
9601 (u8 *)(&val8));
9602
9603 pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
9604 }
9605
9606 site_survey23a(padapter);
9607
9608 return H2C_SUCCESS;
9609}
9610
9611u8 setauth_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9612{
9613 struct setauth_parm *pparm = (struct setauth_parm *)pbuf;
9614 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9615 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9616
9617 if (pparm->mode < 4)
9618 {
9619 pmlmeinfo->auth_algo = pparm->mode;
9620 }
9621
9622 return H2C_SUCCESS;
9623}
9624
9625u8 setkey_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
9626{
9627 unsigned short ctrl;
9628 struct setkey_parm *pparm = (struct setkey_parm *)pbuf;
9629 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9630 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9631 unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
9632
9633 /* main tx key for wep. */
9634 if (pparm->set_tx)
9635 pmlmeinfo->key_index = pparm->keyid;
9636
9637 /* write cam */
9638 ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
9639
9640 DBG_8723A_LEVEL(_drv_always_, "set group key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) "
9641 "keyid:%d\n", pparm->algorithm, pparm->keyid);
9642 write_cam23a(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
9643
9644 /* allow multicast packets to driver */
9645 padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr);
9646
9647 return H2C_SUCCESS;
9648}
9649
9650u8 set_stakey_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
9651{
9652 u16 ctrl = 0;
9653 u8 cam_id;/* cam_entry */
9654 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9655 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9656 struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf;
9657
9658 /* cam_entry: */
9659 /* 0~3 for default key */
9660
9661 /* for concurrent mode (ap+sta): */
9662 /* default key is disable, using sw encrypt/decrypt */
9663 /* cam_entry = 4 for sta mode (macid = 0) */
9664 /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */
9665
9666 /* for concurrent mode (sta+sta): */
9667 /* default key is disable, using sw encrypt/decrypt */
9668 /* cam_entry = 4 mapping to macid = 0 */
9669 /* cam_entry = 5 mapping to macid = 2 */
9670
9671 cam_id = 4;
9672
9673 DBG_8723A_LEVEL(_drv_always_, "set pairwise key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) camid:%d\n",
9674 pparm->algorithm, cam_id);
9675 if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
9676 {
9677
9678 struct sta_info *psta;
9679 struct sta_priv *pstapriv = &padapter->stapriv;
9680
9681 if (pparm->algorithm == _NO_PRIVACY_) /* clear cam entry */
9682 {
9683 clear_cam_entry23a(padapter, pparm->id);
9684 return H2C_SUCCESS_RSP;
9685 }
9686
9687 psta = rtw_get_stainfo23a(pstapriv, pparm->addr);
9688 if (psta)
9689 {
9690 ctrl = (BIT(15) | ((pparm->algorithm) << 2));
9691
9692 DBG_8723A("r871x_set_stakey_hdl23a(): enc_algorithm =%d\n", pparm->algorithm);
9693
9694 if ((psta->mac_id<1) || (psta->mac_id>(NUM_STA-4)))
9695 {
9696 DBG_8723A("r871x_set_stakey_hdl23a():set_stakey failed, mac_id(aid) =%d\n", psta->mac_id);
9697 return H2C_REJECTED;
9698 }
9699
9700 cam_id = (psta->mac_id + 3);/* 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
9701
9702 DBG_8723A("Write CAM, mac_addr =%x:%x:%x:%x:%x:%x, cam_entry =%d\n", pparm->addr[0],
9703 pparm->addr[1], pparm->addr[2], pparm->addr[3], pparm->addr[4],
9704 pparm->addr[5], cam_id);
9705
9706 write_cam23a(padapter, cam_id, ctrl, pparm->addr, pparm->key);
9707
9708 return H2C_SUCCESS_RSP;
9709
9710 }
9711 else
9712 {
9713 DBG_8723A("r871x_set_stakey_hdl23a(): sta has been free\n");
9714 return H2C_REJECTED;
9715 }
9716
9717 }
9718
9719 /* below for sta mode */
9720
9721 if (pparm->algorithm == _NO_PRIVACY_) /* clear cam entry */
9722 {
9723 clear_cam_entry23a(padapter, pparm->id);
9724 return H2C_SUCCESS;
9725 }
9726
9727 ctrl = BIT(15) | ((pparm->algorithm) << 2);
9728
9729 write_cam23a(padapter, cam_id, ctrl, pparm->addr, pparm->key);
9730
9731 pmlmeinfo->enc_algo = pparm->algorithm;
9732
9733 return H2C_SUCCESS;
9734}
9735
9736u8 add_ba_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9737{
9738 struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf;
9739 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9740 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9741
9742 struct sta_info *psta = rtw_get_stainfo23a(&padapter->stapriv, pparm->addr);
9743
9744 if (!psta)
9745 return H2C_SUCCESS;
9746
9747 if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
9748 (pmlmeinfo->HT_enable)) ||
9749 ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
9750 issue_action_BA23a(padapter, pparm->addr,
9751 WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
9752 mod_timer(&psta->addba_retry_timer,
9753 jiffies + msecs_to_jiffies(ADDBA_TO));
9754 } else {
9755 psta->htpriv.candidate_tid_bitmap &= ~CHKBIT(pparm->tid);
9756 }
9757 return H2C_SUCCESS;
9758}
9759
9760u8 set_tx_beacon_cmd23a(struct rtw_adapter* padapter)
9761{
9762 struct cmd_obj *ph2c;
9763 struct Tx_Beacon_param *ptxBeacon_parm;
9764 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
9765 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9766 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9767 u8 res = _SUCCESS;
9768 int len_diff = 0;
9769
9770
9771
9772 ph2c = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
9773 if (!ph2c) {
9774 res = _FAIL;
9775 goto exit;
9776 }
9777
9778 ptxBeacon_parm = (struct Tx_Beacon_param *)
9779 kzalloc(sizeof(struct Tx_Beacon_param), GFP_ATOMIC);
9780 if (!ptxBeacon_parm) {
9781 kfree(ph2c);
9782 res = _FAIL;
9783 goto exit;
9784 }
9785
9786 memcpy(&ptxBeacon_parm->network, &pmlmeinfo->network,
9787 sizeof(struct wlan_bssid_ex));
9788
9789 len_diff = update_hidden_ssid(
9790 ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_,
9791 ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_,
9792 pmlmeinfo->hidden_ssid_mode);
9793 ptxBeacon_parm->network.IELength += len_diff;
9794
9795 init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
9796
9797 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
9798
9799exit:
9800
9801
9802
9803 return res;
9804}
9805
9806u8 mlme_evt_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9807{
9808 u8 evt_code, evt_seq;
9809 u16 evt_sz;
9810 uint *peventbuf;
9811 void (*event_callback)(struct rtw_adapter *dev, u8 *pbuf);
9812 struct evt_priv *pevt_priv = &padapter->evtpriv;
9813
9814 peventbuf = (uint*)pbuf;
9815 evt_sz = (u16)(*peventbuf&0xffff);
9816 evt_seq = (u8)((*peventbuf>>24)&0x7f);
9817 evt_code = (u8)((*peventbuf>>16)&0xff);
9818
9819 /* checking if event code is valid */
9820 if (evt_code >= MAX_C2HEVT) {
9821 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent Code(%d) mismatch!\n", evt_code));
9822 goto _abort_event_;
9823 }
9824
9825 /* checking if event size match the event parm size */
9826 if ((wlanevents[evt_code].parmsize != 0) &&
9827 (wlanevents[evt_code].parmsize != evt_sz)) {
9828 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n",
9829 evt_code, wlanevents[evt_code].parmsize, evt_sz));
9830 goto _abort_event_;
9831 }
9832
9833 atomic_inc(&pevt_priv->event_seq);
9834
9835 peventbuf += 2;
9836
9837 if (peventbuf) {
9838 event_callback = wlanevents[evt_code].event_callback;
9839 event_callback(padapter, (u8*)peventbuf);
9840
9841 pevt_priv->evt_done_cnt++;
9842 }
9843
9844_abort_event_:
9845
9846 return H2C_SUCCESS;
9847}
9848
9849u8 h2c_msg_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9850{
9851 if (!pbuf)
9852 return H2C_PARAMETERS_ERROR;
9853
9854 return H2C_SUCCESS;
9855}
9856
9857u8 tx_beacon_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9858{
9859 if (send_beacon23a(padapter) == _FAIL)
9860 {
9861 DBG_8723A("issue_beacon23a, fail!\n");
9862 return H2C_PARAMETERS_ERROR;
9863 }
9864#ifdef CONFIG_8723AU_AP_MODE
9865 else /* tx bc/mc frames after update TIM */
9866 {
9867 struct sta_info *psta_bmc;
9868 struct list_head *plist, *phead, *ptmp;
9869 struct xmit_frame *pxmitframe;
9870 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
9871 struct sta_priv *pstapriv = &padapter->stapriv;
9872
9873 /* for BC/MC Frames */
9874 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
9875 if (!psta_bmc)
9876 return H2C_SUCCESS;
9877
9878 if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len>0))
9879 {
9880 msleep(10);/* 10ms, ATIM(HIQ) Windows */
9881 /* spin_lock_bh(&psta_bmc->sleep_q.lock); */
9882 spin_lock_bh(&pxmitpriv->lock);
9883
9884 phead = get_list_head(&psta_bmc->sleep_q);
9885
9886 list_for_each_safe(plist, ptmp, phead) {
9887 pxmitframe = container_of(plist,
9888 struct xmit_frame,
9889 list);
9890
9891 list_del_init(&pxmitframe->list);
9892
9893 psta_bmc->sleepq_len--;
9894 if (psta_bmc->sleepq_len>0)
9895 pxmitframe->attrib.mdata = 1;
9896 else
9897 pxmitframe->attrib.mdata = 0;
9898
9899 pxmitframe->attrib.triggered = 1;
9900
9901 pxmitframe->attrib.qsel = 0x11;/* HIQ */
9902
9903 rtw_hal_xmit23aframe_enqueue(padapter, pxmitframe);
9904 }
9905
9906 /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
9907 spin_unlock_bh(&pxmitpriv->lock);
9908 }
9909
9910 }
9911#endif
9912
9913 return H2C_SUCCESS;
9914}
9915
9916u8 set_ch_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
9917{
9918 struct set_ch_parm *set_ch_parm;
9919 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9920
9921 if (!pbuf)
9922 return H2C_PARAMETERS_ERROR;
9923
9924 set_ch_parm = (struct set_ch_parm *)pbuf;
9925
9926 DBG_8723A(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
9927 FUNC_NDEV_ARG(padapter->pnetdev),
9928 set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset);
9929
9930 pmlmeext->cur_channel = set_ch_parm->ch;
9931 pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
9932 pmlmeext->cur_bwmode = set_ch_parm->bw;
9933
9934 set_channel_bwmode23a(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
9935
9936 return H2C_SUCCESS;
9937}
9938
9939u8 set_chplan_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9940{
9941 struct SetChannelPlan_param *setChannelPlan_param;
9942 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9943
9944 if (!pbuf)
9945 return H2C_PARAMETERS_ERROR;
9946
9947 setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
9948
9949 pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
9950 init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
9951
9952 return H2C_SUCCESS;
9953}
9954
9955u8 led_blink_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9956{
9957 struct LedBlink_param *ledBlink_param;
9958
9959 if (!pbuf)
9960 return H2C_PARAMETERS_ERROR;
9961
9962 ledBlink_param = (struct LedBlink_param *)pbuf;
9963
9964 return H2C_SUCCESS;
9965}
9966
9967u8 set_csa_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9968{
9969 return H2C_REJECTED;
9970}
9971
9972/* TDLS_WRCR : write RCR DATA BIT */
9973/* TDLS_SD_PTI : issue peer traffic indication */
9974/* TDLS_CS_OFF : go back to the channel linked with AP, terminating channel switch procedure */
9975/* TDLS_INIT_CH_SEN : init channel sensing, receive all data and mgnt frame */
9976/* TDLS_DONE_CH_SEN: channel sensing and report candidate channel */
9977/* TDLS_OFF_CH : first time set channel to off channel */
9978/* TDLS_BASE_CH : go back tp the channel linked with AP when set base channel as target channel */
9979/* TDLS_P_OFF_CH : periodically go to off channel */
9980/* TDLS_P_BASE_CH : periodically go back to base channel */
9981/* TDLS_RS_RCR : restore RCR */
9982/* TDLS_CKALV_PH1 : check alive timer phase1 */
9983/* TDLS_CKALV_PH2 : check alive timer phase2 */
9984/* TDLS_FREE_STA : free tdls sta */
9985u8 tdls_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9986{
9987 return H2C_REJECTED;
9988}
diff --git a/drivers/staging/rtl8723au/core/rtw_p2p.c b/drivers/staging/rtl8723au/core/rtw_p2p.c
new file mode 100644
index 000000000000..becc3feaca1d
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_p2p.c
@@ -0,0 +1,3963 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _RTW_P2P_C_
16
17#include <drv_types.h>
18#include <rtw_p2p.h>
19#include <wifi.h>
20
21#ifdef CONFIG_8723AU_P2P
22
23static int rtw_p2p_is_channel_list_ok(u8 desired_ch, u8* ch_list, u8 ch_cnt)
24{
25 int found = 0, i = 0;
26
27 for (i = 0; i < ch_cnt; i++)
28 {
29 if (ch_list[ i ] == desired_ch)
30 {
31 found = 1;
32 break;
33 }
34 }
35 return found;
36}
37
38static int is_any_client_associated(struct rtw_adapter *padapter)
39{
40 return padapter->stapriv.asoc_list_cnt ? true : false;
41}
42
43static u32 go_add_group_info_attr(struct wifidirect_info *pwdinfo, u8 *pbuf)
44{
45 struct list_head *phead, *plist;
46 u32 len = 0;
47 u16 attr_len = 0;
48 u8 tmplen, *pdata_attr, *pstart, *pcur;
49 struct sta_info *psta;
50 struct rtw_adapter *padapter = pwdinfo->padapter;
51 struct sta_priv *pstapriv = &padapter->stapriv;
52
53 DBG_8723A("%s\n", __func__);
54
55 pdata_attr = kzalloc(MAX_P2P_IE_LEN, GFP_ATOMIC);
56
57 pstart = pdata_attr;
58 pcur = pdata_attr;
59
60 spin_lock_bh(&pstapriv->asoc_list_lock);
61 phead = &pstapriv->asoc_list;
62
63 list_for_each(plist, phead) {
64 psta = container_of(plist, struct sta_info, asoc_list);
65
66 if (psta->is_p2p_device)
67 {
68 tmplen = 0;
69
70 pcur++;
71
72 /* P2P device address */
73 memcpy(pcur, psta->dev_addr, ETH_ALEN);
74 pcur += ETH_ALEN;
75
76 /* P2P interface address */
77 memcpy(pcur, psta->hwaddr, ETH_ALEN);
78 pcur += ETH_ALEN;
79
80 *pcur = psta->dev_cap;
81 pcur++;
82
83 /* u16*)(pcur) = cpu_to_be16(psta->config_methods); */
84 RTW_PUT_BE16(pcur, psta->config_methods);
85 pcur += 2;
86
87 memcpy(pcur, psta->primary_dev_type, 8);
88 pcur += 8;
89
90 *pcur = psta->num_of_secdev_type;
91 pcur++;
92
93 memcpy(pcur, psta->secdev_types_list, psta->num_of_secdev_type*8);
94 pcur += psta->num_of_secdev_type*8;
95
96 if (psta->dev_name_len>0)
97 {
98 /* u16*)(pcur) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
99 RTW_PUT_BE16(pcur, WPS_ATTR_DEVICE_NAME);
100 pcur += 2;
101
102 /* u16*)(pcur) = cpu_to_be16(psta->dev_name_len); */
103 RTW_PUT_BE16(pcur, psta->dev_name_len);
104 pcur += 2;
105
106 memcpy(pcur, psta->dev_name, psta->dev_name_len);
107 pcur += psta->dev_name_len;
108 }
109
110 tmplen = (u8)(pcur-pstart);
111
112 *pstart = (tmplen-1);
113
114 attr_len += tmplen;
115
116 /* pstart += tmplen; */
117 pstart = pcur;
118
119 }
120
121 }
122 spin_unlock_bh(&pstapriv->asoc_list_lock);
123
124 if (attr_len>0)
125 {
126 len = rtw_set_p2p_attr_content23a(pbuf, P2P_ATTR_GROUP_INFO, attr_len, pdata_attr);
127 }
128
129 kfree(pdata_attr);
130
131 return len;
132}
133
134static void issue_group_disc_req(struct wifidirect_info *pwdinfo, u8 *da)
135{
136 struct xmit_frame *pmgntframe;
137 struct pkt_attrib *pattrib;
138 unsigned char *pframe;
139 struct ieee80211_hdr *pwlanhdr;
140 unsigned short *fctrl;
141 struct rtw_adapter *padapter = pwdinfo->padapter;
142 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
143 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
144 unsigned char category = WLAN_CATEGORY_VENDOR_SPECIFIC;/* P2P action frame */
145 u32 p2poui = cpu_to_be32(P2POUI);
146 u8 oui_subtype = P2P_GO_DISC_REQUEST;
147 u8 dialogToken = 0;
148
149 DBG_8723A("[%s]\n", __func__);
150
151 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
152 {
153 return;
154 }
155
156 /* update attribute */
157 pattrib = &pmgntframe->attrib;
158 update_mgntframe_attrib23a(padapter, pattrib);
159
160 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
161
162 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
163 pwlanhdr = (struct ieee80211_hdr *)pframe;
164
165 fctrl = &pwlanhdr->frame_control;
166 *fctrl = 0;
167
168 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
169 memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
170 memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
171
172 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
173 pmlmeext->mgnt_seq++;
174 SetFrameSubType(pframe, WIFI_ACTION);
175
176 pframe += sizeof(struct ieee80211_hdr_3addr);
177 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
178
179 /* Build P2P action frame header */
180 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
181 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
182 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
183 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
184
185 /* there is no IE in this P2P action frame */
186
187 pattrib->last_txcmdsz = pattrib->pktlen;
188
189 dump_mgntframe23a(padapter, pmgntframe);
190}
191
192static void issue_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
193{
194 struct xmit_frame *pmgntframe;
195 struct pkt_attrib *pattrib;
196 unsigned char *pframe;
197 struct ieee80211_hdr *pwlanhdr;
198 unsigned short *fctrl;
199 struct rtw_adapter *padapter = pwdinfo->padapter;
200 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
201 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
202 unsigned char category = WLAN_CATEGORY_PUBLIC;
203 u8 action = P2P_PUB_ACTION_ACTION;
204 u32 p2poui = cpu_to_be32(P2POUI);
205 u8 oui_subtype = P2P_DEVDISC_RESP;
206 u8 p2pie[8] = { 0x00 };
207 u32 p2pielen = 0;
208
209 DBG_8723A("[%s]\n", __func__);
210
211 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
212 {
213 return;
214 }
215
216 /* update attribute */
217 pattrib = &pmgntframe->attrib;
218 update_mgntframe_attrib23a(padapter, pattrib);
219
220 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
221
222 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
223 pwlanhdr = (struct ieee80211_hdr *)pframe;
224
225 fctrl = &pwlanhdr->frame_control;
226 *fctrl = 0;
227
228 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
229 memcpy(pwlanhdr->addr2, pwdinfo->device_addr, ETH_ALEN);
230 memcpy(pwlanhdr->addr3, pwdinfo->device_addr, ETH_ALEN);
231
232 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
233 pmlmeext->mgnt_seq++;
234 SetFrameSubType(pframe, WIFI_ACTION);
235
236 pframe += sizeof(struct ieee80211_hdr_3addr);
237 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
238
239 /* Build P2P public action frame header */
240 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
241 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
242 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *) &p2poui,
243 &pattrib->pktlen);
244 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
245 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
246
247 /* Build P2P IE */
248 /* P2P OUI */
249 p2pielen = 0;
250 p2pie[ p2pielen++ ] = 0x50;
251 p2pie[ p2pielen++ ] = 0x6F;
252 p2pie[ p2pielen++ ] = 0x9A;
253 p2pie[ p2pielen++ ] = 0x09; /* WFA P2P v1.0 */
254
255 /* P2P_ATTR_STATUS */
256 p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
257
258 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &pattrib->pktlen);
259
260 pattrib->last_txcmdsz = pattrib->pktlen;
261
262 dump_mgntframe23a(padapter, pmgntframe);
263}
264
265static void issue_p2p_provision_resp(struct wifidirect_info *pwdinfo, u8* raddr, u8* frame_body, u16 config_method)
266{
267 struct rtw_adapter *padapter = pwdinfo->padapter;
268 unsigned char category = WLAN_CATEGORY_PUBLIC;
269 u8 action = P2P_PUB_ACTION_ACTION;
270 u8 dialogToken = frame_body[7]; /* The Dialog Token of provisioning discovery request frame. */
271 u32 p2poui = cpu_to_be32(P2POUI);
272 u8 oui_subtype = P2P_PROVISION_DISC_RESP;
273 u8 wpsie[ 100 ] = { 0x00 };
274 u8 wpsielen = 0;
275#ifdef CONFIG_8723AU_P2P
276 u32 wfdielen = 0;
277#endif /* CONFIG_8723AU_P2P */
278
279 struct xmit_frame *pmgntframe;
280 struct pkt_attrib *pattrib;
281 unsigned char *pframe;
282 struct ieee80211_hdr *pwlanhdr;
283 unsigned short *fctrl;
284 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
285 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
286
287 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
288 return;
289
290 /* update attribute */
291 pattrib = &pmgntframe->attrib;
292 update_mgntframe_attrib23a(padapter, pattrib);
293
294 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
295
296 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
297 pwlanhdr = (struct ieee80211_hdr *)pframe;
298
299 fctrl = &pwlanhdr->frame_control;
300 *fctrl = 0;
301
302 memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
303 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
304 memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
305
306 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
307 pmlmeext->mgnt_seq++;
308 SetFrameSubType(pframe, WIFI_ACTION);
309
310 pframe += sizeof(struct ieee80211_hdr_3addr);
311 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
312
313 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
314 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
315 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *) &p2poui,
316 &pattrib->pktlen);
317 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
318 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
319
320 wpsielen = 0;
321 /* WPS OUI */
322 /* u32*) (wpsie) = cpu_to_be32(WPSOUI); */
323 RTW_PUT_BE32(wpsie, WPSOUI);
324 wpsielen += 4;
325
326 /* Config Method */
327 /* Type: */
328 /* u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD); */
329 RTW_PUT_BE16(wpsie + wpsielen, WPS_ATTR_CONF_METHOD);
330 wpsielen += 2;
331
332 /* Length: */
333 /* u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002); */
334 RTW_PUT_BE16(wpsie + wpsielen, 0x0002);
335 wpsielen += 2;
336
337 /* Value: */
338 /* u16*) (wpsie + wpsielen) = cpu_to_be16(config_method); */
339 RTW_PUT_BE16(wpsie + wpsielen, config_method);
340 wpsielen += 2;
341
342 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);
343
344#ifdef CONFIG_8723AU_P2P
345 wfdielen = build_provdisc_resp_wfd_ie(pwdinfo, pframe);
346 pframe += wfdielen;
347 pattrib->pktlen += wfdielen;
348#endif /* CONFIG_8723AU_P2P */
349
350 pattrib->last_txcmdsz = pattrib->pktlen;
351
352 dump_mgntframe23a(padapter, pmgntframe);
353
354 return;
355}
356
357static void issue_p2p_presence_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
358{
359 struct xmit_frame *pmgntframe;
360 struct pkt_attrib *pattrib;
361 unsigned char *pframe;
362 struct ieee80211_hdr *pwlanhdr;
363 unsigned short *fctrl;
364 struct rtw_adapter *padapter = pwdinfo->padapter;
365 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
366 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
367 unsigned char category = WLAN_CATEGORY_VENDOR_SPECIFIC;/* P2P action frame */
368 u32 p2poui = cpu_to_be32(P2POUI);
369 u8 oui_subtype = P2P_PRESENCE_RESPONSE;
370 u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
371 u8 noa_attr_content[32] = { 0x00 };
372 u32 p2pielen = 0;
373
374 DBG_8723A("[%s]\n", __func__);
375
376 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
377 {
378 return;
379 }
380
381 /* update attribute */
382 pattrib = &pmgntframe->attrib;
383 update_mgntframe_attrib23a(padapter, pattrib);
384
385 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
386
387 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
388 pwlanhdr = (struct ieee80211_hdr *)pframe;
389
390 fctrl = &pwlanhdr->frame_control;
391 *fctrl = 0;
392
393 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
394 memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
395 memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
396
397 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
398 pmlmeext->mgnt_seq++;
399 SetFrameSubType(pframe, WIFI_ACTION);
400
401 pframe += sizeof(struct ieee80211_hdr_3addr);
402 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
403
404 /* Build P2P action frame header */
405 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
406 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *) &p2poui,
407 &pattrib->pktlen);
408 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
409 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
410
411 /* Add P2P IE header */
412 /* P2P OUI */
413 p2pielen = 0;
414 p2pie[ p2pielen++ ] = 0x50;
415 p2pie[ p2pielen++ ] = 0x6F;
416 p2pie[ p2pielen++ ] = 0x9A;
417 p2pie[ p2pielen++ ] = 0x09; /* WFA P2P v1.0 */
418
419 /* Add Status attribute in P2P IE */
420 p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
421
422 /* Add NoA attribute in P2P IE */
423 noa_attr_content[0] = 0x1;/* index */
424 noa_attr_content[1] = 0x0;/* CTWindow and OppPS Parameters */
425
426 /* todo: Notice of Absence Descriptor(s) */
427
428 p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_NOA, 2, noa_attr_content);
429
430 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie,
431 &pattrib->pktlen);
432
433 pattrib->last_txcmdsz = pattrib->pktlen;
434
435 dump_mgntframe23a(padapter, pmgntframe);
436}
437
438u32 build_beacon_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf)
439{
440 u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
441 u16 capability = 0;
442 u32 len = 0, p2pielen = 0;
443
444 /* P2P OUI */
445 p2pielen = 0;
446 p2pie[ p2pielen++ ] = 0x50;
447 p2pie[ p2pielen++ ] = 0x6F;
448 p2pie[ p2pielen++ ] = 0x9A;
449 p2pie[ p2pielen++ ] = 0x09; /* WFA P2P v1.0 */
450
451 /* According to the P2P Specification, the beacon frame should contain 3 P2P attributes */
452 /* 1. P2P Capability */
453 /* 2. P2P Device ID */
454 /* 3. Notice of Absence (NOA) */
455
456 /* P2P Capability ATTR */
457 /* Type: */
458 /* Length: */
459 /* Value: */
460 /* Device Capability Bitmap, 1 byte */
461 /* Be able to participate in additional P2P Groups and */
462 /* support the P2P Invitation Procedure */
463 /* Group Capability Bitmap, 1 byte */
464 capability = P2P_DEVCAP_INVITATION_PROC|P2P_DEVCAP_CLIENT_DISCOVERABILITY;
465 capability |= ((P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS) << 8);
466 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
467 capability |= (P2P_GRPCAP_GROUP_FORMATION<<8);
468
469 capability = cpu_to_le16(capability);
470
471 p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_CAPABILITY, 2, (u8*)&capability);
472
473 /* P2P Device ID ATTR */
474 p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_DEVICE_ID, ETH_ALEN, pwdinfo->device_addr);
475
476 /* Notice of Absence ATTR */
477 /* Type: */
478 /* Length: */
479 /* Value: */
480
481 /* go_add_noa_attr(pwdinfo); */
482
483 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
484
485 return len;
486}
487
488#ifdef CONFIG_8723AU_P2P
489u32 build_beacon_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
490{
491 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
492 u32 len = 0, wfdielen = 0;
493 struct rtw_adapter *padapter = pwdinfo->padapter;
494 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
495 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
496
497 /* WFD OUI */
498 wfdielen = 0;
499 wfdie[ wfdielen++ ] = 0x50;
500 wfdie[ wfdielen++ ] = 0x6F;
501 wfdie[ wfdielen++ ] = 0x9A;
502 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
503
504 /* Commented by Albert 20110812 */
505 /* According to the WFD Specification, the beacon frame should contain 4 WFD attributes */
506 /* 1. WFD Device Information */
507 /* 2. Associated BSSID */
508 /* 3. Coupled Sink Information */
509
510 /* WFD Device Information ATTR */
511 /* Type: */
512 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
513
514 /* Length: */
515 /* Note: In the WFD specification, the size of length field is 2. */
516 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
517 wfdielen += 2;
518
519 /* Value1: */
520 /* WFD device information */
521
522 if (P2P_ROLE_GO == pwdinfo->role)
523 {
524 if (is_any_client_associated(pwdinfo->padapter))
525 {
526 /* WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) */
527 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD);
528 }
529 else
530 {
531 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
532 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD);
533 }
534
535 }
536 else
537 {
538 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
539 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD);
540 }
541
542 wfdielen += 2;
543
544 /* Value2: */
545 /* Session Management Control Port */
546 /* Default TCP port for RTSP messages is 554 */
547 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
548 wfdielen += 2;
549
550 /* Value3: */
551 /* WFD Device Maximum Throughput */
552 /* 300Mbps is the maximum throughput */
553 RTW_PUT_BE16(wfdie + wfdielen, 300);
554 wfdielen += 2;
555
556 /* Associated BSSID ATTR */
557 /* Type: */
558 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
559
560 /* Length: */
561 /* Note: In the WFD specification, the size of length field is 2. */
562 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
563 wfdielen += 2;
564
565 /* Value: */
566 /* Associated BSSID */
567 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
568 {
569 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
570 }
571 else
572 {
573 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
574 }
575
576 wfdielen += ETH_ALEN;
577
578 /* Coupled Sink Information ATTR */
579 /* Type: */
580 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
581
582 /* Length: */
583 /* Note: In the WFD specification, the size of length field is 2. */
584 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
585 wfdielen += 2;
586
587 /* Value: */
588 /* Coupled Sink Status bitmap */
589 /* Not coupled/available for Coupling */
590 wfdie[ wfdielen++ ] = 0;
591 /* MAC Addr. */
592 wfdie[ wfdielen++ ] = 0;
593 wfdie[ wfdielen++ ] = 0;
594 wfdie[ wfdielen++ ] = 0;
595 wfdie[ wfdielen++ ] = 0;
596 wfdie[ wfdielen++ ] = 0;
597 wfdie[ wfdielen++ ] = 0;
598
599 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
600
601 return len;
602}
603
604u32 build_probe_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
605{
606 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
607 u32 len = 0, wfdielen = 0;
608 struct rtw_adapter *padapter = pwdinfo->padapter;
609 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
610 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
611
612 /* WFD OUI */
613 wfdielen = 0;
614 wfdie[ wfdielen++ ] = 0x50;
615 wfdie[ wfdielen++ ] = 0x6F;
616 wfdie[ wfdielen++ ] = 0x9A;
617 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
618
619 /* Commented by Albert 20110812 */
620 /* According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
621 /* 1. WFD Device Information */
622 /* 2. Associated BSSID */
623 /* 3. Coupled Sink Information */
624
625 /* WFD Device Information ATTR */
626 /* Type: */
627 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
628
629 /* Length: */
630 /* Note: In the WFD specification, the size of length field is 2. */
631 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
632 wfdielen += 2;
633
634 /* Value1: */
635 /* WFD device information */
636
637 if (1 == pwdinfo->wfd_tdls_enable)
638 {
639 /* WFD primary sink + available for WFD session + WiFi TDLS mode + WSC (WFD Service Discovery) */
640 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type |
641 WFD_DEVINFO_SESSION_AVAIL |
642 WFD_DEVINFO_WSD |
643 WFD_DEVINFO_PC_TDLS);
644 }
645 else
646 {
647 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSC (WFD Service Discovery) */
648 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type |
649 WFD_DEVINFO_SESSION_AVAIL |
650 WFD_DEVINFO_WSD);
651 }
652
653 wfdielen += 2;
654
655 /* Value2: */
656 /* Session Management Control Port */
657 /* Default TCP port for RTSP messages is 554 */
658 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
659 wfdielen += 2;
660
661 /* Value3: */
662 /* WFD Device Maximum Throughput */
663 /* 300Mbps is the maximum throughput */
664 RTW_PUT_BE16(wfdie + wfdielen, 300);
665 wfdielen += 2;
666
667 /* Associated BSSID ATTR */
668 /* Type: */
669 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
670
671 /* Length: */
672 /* Note: In the WFD specification, the size of length field is 2. */
673 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
674 wfdielen += 2;
675
676 /* Value: */
677 /* Associated BSSID */
678 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
679 {
680 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
681 }
682 else
683 {
684 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
685 }
686
687 wfdielen += ETH_ALEN;
688
689 /* Coupled Sink Information ATTR */
690 /* Type: */
691 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
692
693 /* Length: */
694 /* Note: In the WFD specification, the size of length field is 2. */
695 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
696 wfdielen += 2;
697
698 /* Value: */
699 /* Coupled Sink Status bitmap */
700 /* Not coupled/available for Coupling */
701 wfdie[ wfdielen++ ] = 0;
702 /* MAC Addr. */
703 wfdie[ wfdielen++ ] = 0;
704 wfdie[ wfdielen++ ] = 0;
705 wfdie[ wfdielen++ ] = 0;
706 wfdie[ wfdielen++ ] = 0;
707 wfdie[ wfdielen++ ] = 0;
708 wfdie[ wfdielen++ ] = 0;
709
710 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
711
712 return len;
713}
714
715u32 build_probe_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 tunneled)
716{
717 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
718 u32 len = 0, wfdielen = 0;
719 struct rtw_adapter *padapter = pwdinfo->padapter;
720 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
721 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
722
723 /* WFD OUI */
724 wfdielen = 0;
725 wfdie[ wfdielen++ ] = 0x50;
726 wfdie[ wfdielen++ ] = 0x6F;
727 wfdie[ wfdielen++ ] = 0x9A;
728 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
729
730 /* Commented by Albert 20110812 */
731 /* According to the WFD Specification, the probe response frame should contain 4 WFD attributes */
732 /* 1. WFD Device Information */
733 /* 2. Associated BSSID */
734 /* 3. Coupled Sink Information */
735 /* 4. WFD Session Information */
736
737 /* WFD Device Information ATTR */
738 /* Type: */
739 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
740
741 /* Length: */
742 /* Note: In the WFD specification, the size of length field is 2. */
743 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
744 wfdielen += 2;
745
746 /* Value1: */
747 /* WFD device information */
748 /* WFD primary sink + available for WFD session + WiFi Direct mode */
749
750 if (true == pwdinfo->session_available)
751 {
752 if (P2P_ROLE_GO == pwdinfo->role)
753 {
754 if (is_any_client_associated(pwdinfo->padapter))
755 {
756 if (pwdinfo->wfd_tdls_enable)
757 {
758 /* TDLS mode + WSD (WFD Service Discovery) */
759 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT);
760 }
761 else
762 {
763 /* WiFi Direct mode + WSD (WFD Service Discovery) */
764 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT);
765 }
766 }
767 else
768 {
769 if (pwdinfo->wfd_tdls_enable)
770 {
771 /* available for WFD session + TDLS mode + WSD (WFD Service Discovery) */
772 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT);
773 }
774 else
775 {
776 /* available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
777 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT);
778 }
779 }
780 }
781 else
782 {
783 if (pwdinfo->wfd_tdls_enable)
784 {
785 /* available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
786 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT);
787 }
788 else
789 {
790
791 /* available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
792 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT);
793 }
794 }
795 }
796 else
797 {
798 if (pwdinfo->wfd_tdls_enable)
799 {
800 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD |WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT);
801 }
802 else
803 {
804 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT);
805 }
806
807 }
808
809 wfdielen += 2;
810
811 /* Value2: */
812 /* Session Management Control Port */
813 /* Default TCP port for RTSP messages is 554 */
814 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
815 wfdielen += 2;
816
817 /* Value3: */
818 /* WFD Device Maximum Throughput */
819 /* 300Mbps is the maximum throughput */
820 RTW_PUT_BE16(wfdie + wfdielen, 300);
821 wfdielen += 2;
822
823 /* Associated BSSID ATTR */
824 /* Type: */
825 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
826
827 /* Length: */
828 /* Note: In the WFD specification, the size of length field is 2. */
829 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
830 wfdielen += 2;
831
832 /* Value: */
833 /* Associated BSSID */
834 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
835 {
836 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
837 }
838 else
839 {
840 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
841 }
842
843 wfdielen += ETH_ALEN;
844
845 /* Coupled Sink Information ATTR */
846 /* Type: */
847 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
848
849 /* Length: */
850 /* Note: In the WFD specification, the size of length field is 2. */
851 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
852 wfdielen += 2;
853
854 /* Value: */
855 /* Coupled Sink Status bitmap */
856 /* Not coupled/available for Coupling */
857 wfdie[ wfdielen++ ] = 0;
858 /* MAC Addr. */
859 wfdie[ wfdielen++ ] = 0;
860 wfdie[ wfdielen++ ] = 0;
861 wfdie[ wfdielen++ ] = 0;
862 wfdie[ wfdielen++ ] = 0;
863 wfdie[ wfdielen++ ] = 0;
864 wfdie[ wfdielen++ ] = 0;
865
866 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
867 {
868 /* WFD Session Information ATTR */
869 /* Type: */
870 wfdie[ wfdielen++ ] = WFD_ATTR_SESSION_INFO;
871
872 /* Length: */
873 /* Note: In the WFD specification, the size of length field is 2. */
874 RTW_PUT_BE16(wfdie + wfdielen, 0x0000);
875 wfdielen += 2;
876
877 /* Todo: to add the list of WFD device info descriptor in WFD group. */
878
879 }
880
881 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
882
883 return len;
884}
885
886u32 build_assoc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
887{
888 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
889 u32 len = 0, wfdielen = 0;
890 struct rtw_adapter *padapter = NULL;
891 struct mlme_priv *pmlmepriv = NULL;
892 struct wifi_display_info *pwfd_info = NULL;
893
894 /* WFD OUI */
895 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
896 {
897 return 0;
898 }
899
900 padapter = pwdinfo->padapter;
901 pmlmepriv = &padapter->mlmepriv;
902 pwfd_info = padapter->wdinfo.wfd_info;
903
904 wfdielen = 0;
905 wfdie[ wfdielen++ ] = 0x50;
906 wfdie[ wfdielen++ ] = 0x6F;
907 wfdie[ wfdielen++ ] = 0x9A;
908 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
909
910 /* Commented by Albert 20110812 */
911 /* According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
912 /* 1. WFD Device Information */
913 /* 2. Associated BSSID */
914 /* 3. Coupled Sink Information */
915
916 /* WFD Device Information ATTR */
917 /* Type: */
918 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
919
920 /* Length: */
921 /* Note: In the WFD specification, the size of length field is 2. */
922 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
923 wfdielen += 2;
924
925 /* Value1: */
926 /* WFD device information */
927 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
928 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD);
929 wfdielen += 2;
930
931 /* Value2: */
932 /* Session Management Control Port */
933 /* Default TCP port for RTSP messages is 554 */
934 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
935 wfdielen += 2;
936
937 /* Value3: */
938 /* WFD Device Maximum Throughput */
939 /* 300Mbps is the maximum throughput */
940 RTW_PUT_BE16(wfdie + wfdielen, 300);
941 wfdielen += 2;
942
943 /* Associated BSSID ATTR */
944 /* Type: */
945 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
946
947 /* Length: */
948 /* Note: In the WFD specification, the size of length field is 2. */
949 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
950 wfdielen += 2;
951
952 /* Value: */
953 /* Associated BSSID */
954 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
955 {
956 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
957 }
958 else
959 {
960 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
961 }
962
963 wfdielen += ETH_ALEN;
964
965 /* Coupled Sink Information ATTR */
966 /* Type: */
967 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
968
969 /* Length: */
970 /* Note: In the WFD specification, the size of length field is 2. */
971 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
972 wfdielen += 2;
973
974 /* Value: */
975 /* Coupled Sink Status bitmap */
976 /* Not coupled/available for Coupling */
977 wfdie[ wfdielen++ ] = 0;
978 /* MAC Addr. */
979 wfdie[ wfdielen++ ] = 0;
980 wfdie[ wfdielen++ ] = 0;
981 wfdie[ wfdielen++ ] = 0;
982 wfdie[ wfdielen++ ] = 0;
983 wfdie[ wfdielen++ ] = 0;
984 wfdie[ wfdielen++ ] = 0;
985
986 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
987
988 return len;
989}
990
991u32 build_assoc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
992{
993 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
994 u32 len = 0, wfdielen = 0;
995 struct rtw_adapter *padapter = pwdinfo->padapter;
996 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
997 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
998
999 /* WFD OUI */
1000 wfdielen = 0;
1001 wfdie[ wfdielen++ ] = 0x50;
1002 wfdie[ wfdielen++ ] = 0x6F;
1003 wfdie[ wfdielen++ ] = 0x9A;
1004 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1005
1006 /* Commented by Albert 20110812 */
1007 /* According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
1008 /* 1. WFD Device Information */
1009 /* 2. Associated BSSID */
1010 /* 3. Coupled Sink Information */
1011
1012 /* WFD Device Information ATTR */
1013 /* Type: */
1014 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1015
1016 /* Length: */
1017 /* Note: In the WFD specification, the size of length field is 2. */
1018 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1019 wfdielen += 2;
1020
1021 /* Value1: */
1022 /* WFD device information */
1023 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
1024 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD);
1025 wfdielen += 2;
1026
1027 /* Value2: */
1028 /* Session Management Control Port */
1029 /* Default TCP port for RTSP messages is 554 */
1030 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1031 wfdielen += 2;
1032
1033 /* Value3: */
1034 /* WFD Device Maximum Throughput */
1035 /* 300Mbps is the maximum throughput */
1036 RTW_PUT_BE16(wfdie + wfdielen, 300);
1037 wfdielen += 2;
1038
1039 /* Associated BSSID ATTR */
1040 /* Type: */
1041 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1042
1043 /* Length: */
1044 /* Note: In the WFD specification, the size of length field is 2. */
1045 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1046 wfdielen += 2;
1047
1048 /* Value: */
1049 /* Associated BSSID */
1050 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1051 {
1052 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1053 }
1054 else
1055 {
1056 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1057 }
1058
1059 wfdielen += ETH_ALEN;
1060
1061 /* Coupled Sink Information ATTR */
1062 /* Type: */
1063 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1064
1065 /* Length: */
1066 /* Note: In the WFD specification, the size of length field is 2. */
1067 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1068 wfdielen += 2;
1069
1070 /* Value: */
1071 /* Coupled Sink Status bitmap */
1072 /* Not coupled/available for Coupling */
1073 wfdie[ wfdielen++ ] = 0;
1074 /* MAC Addr. */
1075 wfdie[ wfdielen++ ] = 0;
1076 wfdie[ wfdielen++ ] = 0;
1077 wfdie[ wfdielen++ ] = 0;
1078 wfdie[ wfdielen++ ] = 0;
1079 wfdie[ wfdielen++ ] = 0;
1080 wfdie[ wfdielen++ ] = 0;
1081
1082 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1083
1084 return len;
1085}
1086
1087u32 build_nego_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1088{
1089 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1090 u32 len = 0, wfdielen = 0;
1091 struct rtw_adapter *padapter = pwdinfo->padapter;
1092 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1093 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1094
1095 /* WFD OUI */
1096 wfdielen = 0;
1097 wfdie[ wfdielen++ ] = 0x50;
1098 wfdie[ wfdielen++ ] = 0x6F;
1099 wfdie[ wfdielen++ ] = 0x9A;
1100 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1101
1102 /* Commented by Albert 20110825 */
1103 /* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
1104 /* 1. WFD Device Information */
1105 /* 2. Associated BSSID (Optional) */
1106 /* 3. Local IP Adress (Optional) */
1107
1108 /* WFD Device Information ATTR */
1109 /* Type: */
1110 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1111
1112 /* Length: */
1113 /* Note: In the WFD specification, the size of length field is 2. */
1114 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1115 wfdielen += 2;
1116
1117 /* Value1: */
1118 /* WFD device information */
1119 /* WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) + WFD Session Available */
1120 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL);
1121 wfdielen += 2;
1122
1123 /* Value2: */
1124 /* Session Management Control Port */
1125 /* Default TCP port for RTSP messages is 554 */
1126 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1127 wfdielen += 2;
1128
1129 /* Value3: */
1130 /* WFD Device Maximum Throughput */
1131 /* 300Mbps is the maximum throughput */
1132 RTW_PUT_BE16(wfdie + wfdielen, 300);
1133 wfdielen += 2;
1134
1135 /* Associated BSSID ATTR */
1136 /* Type: */
1137 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1138
1139 /* Length: */
1140 /* Note: In the WFD specification, the size of length field is 2. */
1141 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1142 wfdielen += 2;
1143
1144 /* Value: */
1145 /* Associated BSSID */
1146 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1147 {
1148 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1149 }
1150 else
1151 {
1152 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1153 }
1154
1155 wfdielen += ETH_ALEN;
1156
1157 /* Coupled Sink Information ATTR */
1158 /* Type: */
1159 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1160
1161 /* Length: */
1162 /* Note: In the WFD specification, the size of length field is 2. */
1163 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1164 wfdielen += 2;
1165
1166 /* Value: */
1167 /* Coupled Sink Status bitmap */
1168 /* Not coupled/available for Coupling */
1169 wfdie[ wfdielen++ ] = 0;
1170 /* MAC Addr. */
1171 wfdie[ wfdielen++ ] = 0;
1172 wfdie[ wfdielen++ ] = 0;
1173 wfdie[ wfdielen++ ] = 0;
1174 wfdie[ wfdielen++ ] = 0;
1175 wfdie[ wfdielen++ ] = 0;
1176 wfdie[ wfdielen++ ] = 0;
1177
1178 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1179
1180 return len;
1181}
1182
1183u32 build_nego_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1184{
1185 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1186 u32 len = 0, wfdielen = 0;
1187 struct rtw_adapter *padapter = pwdinfo->padapter;
1188 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1189 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1190
1191 /* WFD OUI */
1192 wfdielen = 0;
1193 wfdie[ wfdielen++ ] = 0x50;
1194 wfdie[ wfdielen++ ] = 0x6F;
1195 wfdie[ wfdielen++ ] = 0x9A;
1196 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1197
1198 /* Commented by Albert 20110825 */
1199 /* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
1200 /* 1. WFD Device Information */
1201 /* 2. Associated BSSID (Optional) */
1202 /* 3. Local IP Adress (Optional) */
1203
1204 /* WFD Device Information ATTR */
1205 /* Type: */
1206 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1207
1208 /* Length: */
1209 /* Note: In the WFD specification, the size of length field is 2. */
1210 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1211 wfdielen += 2;
1212
1213 /* Value1: */
1214 /* WFD device information */
1215 /* WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) + WFD Session Available */
1216 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL);
1217 wfdielen += 2;
1218
1219 /* Value2: */
1220 /* Session Management Control Port */
1221 /* Default TCP port for RTSP messages is 554 */
1222 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1223 wfdielen += 2;
1224
1225 /* Value3: */
1226 /* WFD Device Maximum Throughput */
1227 /* 300Mbps is the maximum throughput */
1228 RTW_PUT_BE16(wfdie + wfdielen, 300);
1229 wfdielen += 2;
1230
1231 /* Associated BSSID ATTR */
1232 /* Type: */
1233 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1234
1235 /* Length: */
1236 /* Note: In the WFD specification, the size of length field is 2. */
1237 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1238 wfdielen += 2;
1239
1240 /* Value: */
1241 /* Associated BSSID */
1242 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1243 {
1244 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1245 }
1246 else
1247 {
1248 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1249 }
1250
1251 wfdielen += ETH_ALEN;
1252
1253 /* Coupled Sink Information ATTR */
1254 /* Type: */
1255 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1256
1257 /* Length: */
1258 /* Note: In the WFD specification, the size of length field is 2. */
1259 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1260 wfdielen += 2;
1261
1262 /* Value: */
1263 /* Coupled Sink Status bitmap */
1264 /* Not coupled/available for Coupling */
1265 wfdie[ wfdielen++ ] = 0;
1266 /* MAC Addr. */
1267 wfdie[ wfdielen++ ] = 0;
1268 wfdie[ wfdielen++ ] = 0;
1269 wfdie[ wfdielen++ ] = 0;
1270 wfdie[ wfdielen++ ] = 0;
1271 wfdie[ wfdielen++ ] = 0;
1272 wfdie[ wfdielen++ ] = 0;
1273
1274 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1275
1276 return len;
1277}
1278
1279u32 build_nego_confirm_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1280{
1281 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1282 u32 len = 0, wfdielen = 0;
1283 struct rtw_adapter *padapter = pwdinfo->padapter;
1284 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1285 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1286
1287 /* WFD OUI */
1288 wfdielen = 0;
1289 wfdie[ wfdielen++ ] = 0x50;
1290 wfdie[ wfdielen++ ] = 0x6F;
1291 wfdie[ wfdielen++ ] = 0x9A;
1292 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1293
1294 /* Commented by Albert 20110825 */
1295 /* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
1296 /* 1. WFD Device Information */
1297 /* 2. Associated BSSID (Optional) */
1298 /* 3. Local IP Adress (Optional) */
1299
1300 /* WFD Device Information ATTR */
1301 /* Type: */
1302 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1303
1304 /* Length: */
1305 /* Note: In the WFD specification, the size of length field is 2. */
1306 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1307 wfdielen += 2;
1308
1309 /* Value1: */
1310 /* WFD device information */
1311 /* WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) + WFD Session Available */
1312 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL);
1313 wfdielen += 2;
1314
1315 /* Value2: */
1316 /* Session Management Control Port */
1317 /* Default TCP port for RTSP messages is 554 */
1318 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1319 wfdielen += 2;
1320
1321 /* Value3: */
1322 /* WFD Device Maximum Throughput */
1323 /* 300Mbps is the maximum throughput */
1324 RTW_PUT_BE16(wfdie + wfdielen, 300);
1325 wfdielen += 2;
1326
1327 /* Associated BSSID ATTR */
1328 /* Type: */
1329 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1330
1331 /* Length: */
1332 /* Note: In the WFD specification, the size of length field is 2. */
1333 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1334 wfdielen += 2;
1335
1336 /* Value: */
1337 /* Associated BSSID */
1338 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1339 {
1340 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1341 }
1342 else
1343 {
1344 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1345 }
1346
1347 wfdielen += ETH_ALEN;
1348
1349 /* Coupled Sink Information ATTR */
1350 /* Type: */
1351 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1352
1353 /* Length: */
1354 /* Note: In the WFD specification, the size of length field is 2. */
1355 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1356 wfdielen += 2;
1357
1358 /* Value: */
1359 /* Coupled Sink Status bitmap */
1360 /* Not coupled/available for Coupling */
1361 wfdie[ wfdielen++ ] = 0;
1362 /* MAC Addr. */
1363 wfdie[ wfdielen++ ] = 0;
1364 wfdie[ wfdielen++ ] = 0;
1365 wfdie[ wfdielen++ ] = 0;
1366 wfdie[ wfdielen++ ] = 0;
1367 wfdie[ wfdielen++ ] = 0;
1368 wfdie[ wfdielen++ ] = 0;
1369
1370 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1371
1372 return len;
1373}
1374
1375u32 build_invitation_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1376{
1377 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1378 u32 len = 0, wfdielen = 0;
1379 struct rtw_adapter *padapter = pwdinfo->padapter;
1380 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1381 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1382
1383 /* WFD OUI */
1384 wfdielen = 0;
1385 wfdie[ wfdielen++ ] = 0x50;
1386 wfdie[ wfdielen++ ] = 0x6F;
1387 wfdie[ wfdielen++ ] = 0x9A;
1388 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1389
1390 /* Commented by Albert 20110825 */
1391 /* According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
1392 /* 1. WFD Device Information */
1393 /* 2. Associated BSSID (Optional) */
1394 /* 3. Local IP Adress (Optional) */
1395
1396 /* WFD Device Information ATTR */
1397 /* Type: */
1398 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1399
1400 /* Length: */
1401 /* Note: In the WFD specification, the size of length field is 2. */
1402 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1403 wfdielen += 2;
1404
1405 /* Value1: */
1406 /* WFD device information */
1407 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
1408 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD);
1409 wfdielen += 2;
1410
1411 /* Value2: */
1412 /* Session Management Control Port */
1413 /* Default TCP port for RTSP messages is 554 */
1414 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1415 wfdielen += 2;
1416
1417 /* Value3: */
1418 /* WFD Device Maximum Throughput */
1419 /* 300Mbps is the maximum throughput */
1420 RTW_PUT_BE16(wfdie + wfdielen, 300);
1421 wfdielen += 2;
1422
1423 /* Associated BSSID ATTR */
1424 /* Type: */
1425 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1426
1427 /* Length: */
1428 /* Note: In the WFD specification, the size of length field is 2. */
1429 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1430 wfdielen += 2;
1431
1432 /* Value: */
1433 /* Associated BSSID */
1434 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1435 {
1436 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1437 }
1438 else
1439 {
1440 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1441 }
1442
1443 wfdielen += ETH_ALEN;
1444
1445 /* Coupled Sink Information ATTR */
1446 /* Type: */
1447 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1448
1449 /* Length: */
1450 /* Note: In the WFD specification, the size of length field is 2. */
1451 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1452 wfdielen += 2;
1453
1454 /* Value: */
1455 /* Coupled Sink Status bitmap */
1456 /* Not coupled/available for Coupling */
1457 wfdie[ wfdielen++ ] = 0;
1458 /* MAC Addr. */
1459 wfdie[ wfdielen++ ] = 0;
1460 wfdie[ wfdielen++ ] = 0;
1461 wfdie[ wfdielen++ ] = 0;
1462 wfdie[ wfdielen++ ] = 0;
1463 wfdie[ wfdielen++ ] = 0;
1464 wfdie[ wfdielen++ ] = 0;
1465
1466 if (P2P_ROLE_GO == pwdinfo->role)
1467 {
1468 /* WFD Session Information ATTR */
1469 /* Type: */
1470 wfdie[ wfdielen++ ] = WFD_ATTR_SESSION_INFO;
1471
1472 /* Length: */
1473 /* Note: In the WFD specification, the size of length field is 2. */
1474 RTW_PUT_BE16(wfdie + wfdielen, 0x0000);
1475 wfdielen += 2;
1476
1477 /* Todo: to add the list of WFD device info descriptor in WFD group. */
1478
1479 }
1480
1481 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1482
1483 return len;
1484}
1485
1486u32 build_invitation_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1487{
1488 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1489 u32 len = 0, wfdielen = 0;
1490 struct rtw_adapter *padapter = pwdinfo->padapter;
1491 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1492 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1493
1494 /* WFD OUI */
1495 wfdielen = 0;
1496 wfdie[ wfdielen++ ] = 0x50;
1497 wfdie[ wfdielen++ ] = 0x6F;
1498 wfdie[ wfdielen++ ] = 0x9A;
1499 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1500
1501 /* Commented by Albert 20110825 */
1502 /* According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
1503 /* 1. WFD Device Information */
1504 /* 2. Associated BSSID (Optional) */
1505 /* 3. Local IP Adress (Optional) */
1506
1507 /* WFD Device Information ATTR */
1508 /* Type: */
1509 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1510
1511 /* Length: */
1512 /* Note: In the WFD specification, the size of length field is 2. */
1513 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1514 wfdielen += 2;
1515
1516 /* Value1: */
1517 /* WFD device information */
1518 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
1519 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD);
1520 wfdielen += 2;
1521
1522 /* Value2: */
1523 /* Session Management Control Port */
1524 /* Default TCP port for RTSP messages is 554 */
1525 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1526 wfdielen += 2;
1527
1528 /* Value3: */
1529 /* WFD Device Maximum Throughput */
1530 /* 300Mbps is the maximum throughput */
1531 RTW_PUT_BE16(wfdie + wfdielen, 300);
1532 wfdielen += 2;
1533
1534 /* Associated BSSID ATTR */
1535 /* Type: */
1536 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1537
1538 /* Length: */
1539 /* Note: In the WFD specification, the size of length field is 2. */
1540 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1541 wfdielen += 2;
1542
1543 /* Value: */
1544 /* Associated BSSID */
1545 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1546 {
1547 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1548 }
1549 else
1550 {
1551 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1552 }
1553
1554 wfdielen += ETH_ALEN;
1555
1556 /* Coupled Sink Information ATTR */
1557 /* Type: */
1558 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1559
1560 /* Length: */
1561 /* Note: In the WFD specification, the size of length field is 2. */
1562 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1563 wfdielen += 2;
1564
1565 /* Value: */
1566 /* Coupled Sink Status bitmap */
1567 /* Not coupled/available for Coupling */
1568 wfdie[ wfdielen++ ] = 0;
1569 /* MAC Addr. */
1570 wfdie[ wfdielen++ ] = 0;
1571 wfdie[ wfdielen++ ] = 0;
1572 wfdie[ wfdielen++ ] = 0;
1573 wfdie[ wfdielen++ ] = 0;
1574 wfdie[ wfdielen++ ] = 0;
1575 wfdie[ wfdielen++ ] = 0;
1576
1577 if (P2P_ROLE_GO == pwdinfo->role)
1578 {
1579 /* WFD Session Information ATTR */
1580 /* Type: */
1581 wfdie[ wfdielen++ ] = WFD_ATTR_SESSION_INFO;
1582
1583 /* Length: */
1584 /* Note: In the WFD specification, the size of length field is 2. */
1585 RTW_PUT_BE16(wfdie + wfdielen, 0x0000);
1586 wfdielen += 2;
1587
1588 /* Todo: to add the list of WFD device info descriptor in WFD group. */
1589
1590 }
1591
1592 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1593
1594 return len;
1595}
1596
1597u32 build_provdisc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1598{
1599 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1600 u32 len = 0, wfdielen = 0;
1601 struct rtw_adapter *padapter = pwdinfo->padapter;
1602 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1603 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1604
1605 /* WFD OUI */
1606 wfdielen = 0;
1607 wfdie[ wfdielen++ ] = 0x50;
1608 wfdie[ wfdielen++ ] = 0x6F;
1609 wfdie[ wfdielen++ ] = 0x9A;
1610 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1611
1612 /* Commented by Albert 20110825 */
1613 /* According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
1614 /* 1. WFD Device Information */
1615 /* 2. Associated BSSID (Optional) */
1616 /* 3. Local IP Adress (Optional) */
1617
1618 /* WFD Device Information ATTR */
1619 /* Type: */
1620 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1621
1622 /* Length: */
1623 /* Note: In the WFD specification, the size of length field is 2. */
1624 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1625 wfdielen += 2;
1626
1627 /* Value1: */
1628 /* WFD device information */
1629 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
1630 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD);
1631 wfdielen += 2;
1632
1633 /* Value2: */
1634 /* Session Management Control Port */
1635 /* Default TCP port for RTSP messages is 554 */
1636 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1637 wfdielen += 2;
1638
1639 /* Value3: */
1640 /* WFD Device Maximum Throughput */
1641 /* 300Mbps is the maximum throughput */
1642 RTW_PUT_BE16(wfdie + wfdielen, 300);
1643 wfdielen += 2;
1644
1645 /* Associated BSSID ATTR */
1646 /* Type: */
1647 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1648
1649 /* Length: */
1650 /* Note: In the WFD specification, the size of length field is 2. */
1651 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1652 wfdielen += 2;
1653
1654 /* Value: */
1655 /* Associated BSSID */
1656 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1657 {
1658 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1659 }
1660 else
1661 {
1662 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1663 }
1664
1665 wfdielen += ETH_ALEN;
1666
1667 /* Coupled Sink Information ATTR */
1668 /* Type: */
1669 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1670
1671 /* Length: */
1672 /* Note: In the WFD specification, the size of length field is 2. */
1673 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1674 wfdielen += 2;
1675
1676 /* Value: */
1677 /* Coupled Sink Status bitmap */
1678 /* Not coupled/available for Coupling */
1679 wfdie[ wfdielen++ ] = 0;
1680 /* MAC Addr. */
1681 wfdie[ wfdielen++ ] = 0;
1682 wfdie[ wfdielen++ ] = 0;
1683 wfdie[ wfdielen++ ] = 0;
1684 wfdie[ wfdielen++ ] = 0;
1685 wfdie[ wfdielen++ ] = 0;
1686 wfdie[ wfdielen++ ] = 0;
1687
1688 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1689
1690 return len;
1691}
1692
1693u32 build_provdisc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1694{
1695 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1696 u32 len = 0, wfdielen = 0;
1697 struct rtw_adapter *padapter = pwdinfo->padapter;
1698 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1699 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1700
1701 /* WFD OUI */
1702 wfdielen = 0;
1703 wfdie[ wfdielen++ ] = 0x50;
1704 wfdie[ wfdielen++ ] = 0x6F;
1705 wfdie[ wfdielen++ ] = 0x9A;
1706 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1707
1708 /* Commented by Albert 20110825 */
1709 /* According to the WFD Specification, the provision discovery response frame should contain 3 WFD attributes */
1710 /* 1. WFD Device Information */
1711 /* 2. Associated BSSID (Optional) */
1712 /* 3. Local IP Adress (Optional) */
1713
1714 /* WFD Device Information ATTR */
1715 /* Type: */
1716 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1717
1718 /* Length: */
1719 /* Note: In the WFD specification, the size of length field is 2. */
1720 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1721 wfdielen += 2;
1722
1723 /* Value1: */
1724 /* WFD device information */
1725 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
1726 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD);
1727 wfdielen += 2;
1728
1729 /* Value2: */
1730 /* Session Management Control Port */
1731 /* Default TCP port for RTSP messages is 554 */
1732 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1733 wfdielen += 2;
1734
1735 /* Value3: */
1736 /* WFD Device Maximum Throughput */
1737 /* 300Mbps is the maximum throughput */
1738 RTW_PUT_BE16(wfdie + wfdielen, 300);
1739 wfdielen += 2;
1740
1741 /* Associated BSSID ATTR */
1742 /* Type: */
1743 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1744
1745 /* Length: */
1746 /* Note: In the WFD specification, the size of length field is 2. */
1747 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1748 wfdielen += 2;
1749
1750 /* Value: */
1751 /* Associated BSSID */
1752 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1753 {
1754 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1755 }
1756 else
1757 {
1758 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1759 }
1760
1761 wfdielen += ETH_ALEN;
1762
1763 /* Coupled Sink Information ATTR */
1764 /* Type: */
1765 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1766
1767 /* Length: */
1768 /* Note: In the WFD specification, the size of length field is 2. */
1769 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1770 wfdielen += 2;
1771
1772 /* Value: */
1773 /* Coupled Sink Status bitmap */
1774 /* Not coupled/available for Coupling */
1775 wfdie[ wfdielen++ ] = 0;
1776 /* MAC Addr. */
1777 wfdie[ wfdielen++ ] = 0;
1778 wfdie[ wfdielen++ ] = 0;
1779 wfdie[ wfdielen++ ] = 0;
1780 wfdie[ wfdielen++ ] = 0;
1781 wfdie[ wfdielen++ ] = 0;
1782 wfdie[ wfdielen++ ] = 0;
1783
1784 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1785
1786 return len;
1787}
1788
1789#endif /* CONFIG_8723AU_P2P */
1790
1791u32 build_probe_resp_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf)
1792{
1793 u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
1794 u32 len = 0, p2pielen = 0;
1795
1796 /* P2P OUI */
1797 p2pielen = 0;
1798 p2pie[ p2pielen++ ] = 0x50;
1799 p2pie[ p2pielen++ ] = 0x6F;
1800 p2pie[ p2pielen++ ] = 0x9A;
1801 p2pie[ p2pielen++ ] = 0x09; /* WFA P2P v1.0 */
1802
1803 /* Commented by Albert 20100907 */
1804 /* According to the P2P Specification, the probe response frame should contain 5 P2P attributes */
1805 /* 1. P2P Capability */
1806 /* 2. Extended Listen Timing */
1807 /* 3. Notice of Absence (NOA) (Only GO needs this) */
1808 /* 4. Device Info */
1809 /* 5. Group Info (Only GO need this) */
1810
1811 /* P2P Capability ATTR */
1812 /* Type: */
1813 p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
1814
1815 /* Length: */
1816 /* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002); */
1817 RTW_PUT_LE16(p2pie + p2pielen, 0x0002);
1818 p2pielen += 2;
1819
1820 /* Value: */
1821 /* Device Capability Bitmap, 1 byte */
1822 p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
1823
1824 /* Group Capability Bitmap, 1 byte */
1825 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
1826 {
1827 p2pie[ p2pielen ] = (P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS);
1828
1829 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
1830 p2pie[ p2pielen ] |= P2P_GRPCAP_GROUP_FORMATION;
1831
1832 p2pielen++;
1833 }
1834 else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE))
1835 {
1836 /* Group Capability Bitmap, 1 byte */
1837 if (pwdinfo->persistent_supported)
1838 p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
1839 else
1840 p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
1841 }
1842
1843 /* Extended Listen Timing ATTR */
1844 /* Type: */
1845 p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING;
1846
1847 /* Length: */
1848 /* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0004); */
1849 RTW_PUT_LE16(p2pie + p2pielen, 0x0004);
1850 p2pielen += 2;
1851
1852 /* Value: */
1853 /* Availability Period */
1854 /* u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF); */
1855 RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF);
1856 p2pielen += 2;
1857
1858 /* Availability Interval */
1859 /* u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF); */
1860 RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF);
1861 p2pielen += 2;
1862
1863 /* Notice of Absence ATTR */
1864 /* Type: */
1865 /* Length: */
1866 /* Value: */
1867 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
1868 {
1869 /* go_add_noa_attr(pwdinfo); */
1870 }
1871
1872 /* Device Info ATTR */
1873 /* Type: */
1874 p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
1875
1876 /* Length: */
1877 /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
1878 /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
1879 /* u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); */
1880 RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len);
1881 p2pielen += 2;
1882
1883 /* Value: */
1884 /* P2P Device Address */
1885 memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
1886 p2pielen += ETH_ALEN;
1887
1888 /* Config Method */
1889 /* This field should be big endian. Noted by P2P specification. */
1890 /* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm); */
1891 RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->supported_wps_cm);
1892 p2pielen += 2;
1893
1894 /* Primary Device Type */
1895 /* Category ID */
1896 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); */
1897 RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA);
1898 p2pielen += 2;
1899
1900 /* OUI */
1901 /* u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI); */
1902 RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
1903 p2pielen += 4;
1904
1905 /* Sub Category ID */
1906 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); */
1907 RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER);
1908 p2pielen += 2;
1909
1910 /* Number of Secondary Device Types */
1911 p2pie[ p2pielen++ ] = 0x00; /* No Secondary Device Type List */
1912
1913 /* Device Name */
1914 /* Type: */
1915 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
1916 RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME);
1917 p2pielen += 2;
1918
1919 /* Length: */
1920 /* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); */
1921 RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len);
1922 p2pielen += 2;
1923
1924 /* Value: */
1925 memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
1926 p2pielen += pwdinfo->device_name_len;
1927
1928 /* Group Info ATTR */
1929 /* Type: */
1930 /* Length: */
1931 /* Value: */
1932 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
1933 {
1934 p2pielen += go_add_group_info_attr(pwdinfo, p2pie + p2pielen);
1935 }
1936
1937 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
1938
1939 return len;
1940}
1941
1942u32 build_prov_disc_request_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf, u8* pssid, u8 ussidlen, u8* pdev_raddr)
1943{
1944 u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
1945 u32 len = 0, p2pielen = 0;
1946
1947 /* P2P OUI */
1948 p2pielen = 0;
1949 p2pie[ p2pielen++ ] = 0x50;
1950 p2pie[ p2pielen++ ] = 0x6F;
1951 p2pie[ p2pielen++ ] = 0x9A;
1952 p2pie[ p2pielen++ ] = 0x09; /* WFA P2P v1.0 */
1953
1954 /* Commented by Albert 20110301 */
1955 /* According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes */
1956 /* 1. P2P Capability */
1957 /* 2. Device Info */
1958 /* 3. Group ID (When joining an operating P2P Group) */
1959
1960 /* P2P Capability ATTR */
1961 /* Type: */
1962 p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
1963
1964 /* Length: */
1965 /* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002); */
1966 RTW_PUT_LE16(p2pie + p2pielen, 0x0002);
1967 p2pielen += 2;
1968
1969 /* Value: */
1970 /* Device Capability Bitmap, 1 byte */
1971 p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
1972
1973 /* Group Capability Bitmap, 1 byte */
1974 if (pwdinfo->persistent_supported)
1975 p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
1976 else
1977 p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
1978
1979 /* Device Info ATTR */
1980 /* Type: */
1981 p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
1982
1983 /* Length: */
1984 /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
1985 /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
1986 /* u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); */
1987 RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len);
1988 p2pielen += 2;
1989
1990 /* Value: */
1991 /* P2P Device Address */
1992 memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
1993 p2pielen += ETH_ALEN;
1994
1995 /* Config Method */
1996 /* This field should be big endian. Noted by P2P specification. */
1997 if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC)
1998 {
1999 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_PBC); */
2000 RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_PBC);
2001 }
2002 else
2003 {
2004 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY); */
2005 RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_DISPLAY);
2006 }
2007
2008 p2pielen += 2;
2009
2010 /* Primary Device Type */
2011 /* Category ID */
2012 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); */
2013 RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA);
2014 p2pielen += 2;
2015
2016 /* OUI */
2017 /* u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI); */
2018 RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
2019 p2pielen += 4;
2020
2021 /* Sub Category ID */
2022 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); */
2023 RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER);
2024 p2pielen += 2;
2025
2026 /* Number of Secondary Device Types */
2027 p2pie[ p2pielen++ ] = 0x00; /* No Secondary Device Type List */
2028
2029 /* Device Name */
2030 /* Type: */
2031 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
2032 RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME);
2033 p2pielen += 2;
2034
2035 /* Length: */
2036 /* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); */
2037 RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len);
2038 p2pielen += 2;
2039
2040 /* Value: */
2041 memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
2042 p2pielen += pwdinfo->device_name_len;
2043
2044 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT))
2045 {
2046 /* Added by Albert 2011/05/19 */
2047 /* In this case, the pdev_raddr is the device address of the group owner. */
2048
2049 /* P2P Group ID ATTR */
2050 /* Type: */
2051 p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID;
2052
2053 /* Length: */
2054 /* u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + ussidlen); */
2055 RTW_PUT_LE16(p2pie + p2pielen, ETH_ALEN + ussidlen);
2056 p2pielen += 2;
2057
2058 /* Value: */
2059 memcpy(p2pie + p2pielen, pdev_raddr, ETH_ALEN);
2060 p2pielen += ETH_ALEN;
2061
2062 memcpy(p2pie + p2pielen, pssid, ussidlen);
2063 p2pielen += ussidlen;
2064
2065 }
2066
2067 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
2068
2069 return len;
2070}
2071
2072u32 build_assoc_resp_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 status_code)
2073{
2074 u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
2075 u32 len = 0, p2pielen = 0;
2076
2077 /* P2P OUI */
2078 p2pielen = 0;
2079 p2pie[ p2pielen++ ] = 0x50;
2080 p2pie[ p2pielen++ ] = 0x6F;
2081 p2pie[ p2pielen++ ] = 0x9A;
2082 p2pie[ p2pielen++ ] = 0x09; /* WFA P2P v1.0 */
2083
2084 /* According to the P2P Specification, the Association response frame should contain 2 P2P attributes */
2085 /* 1. Status */
2086 /* 2. Extended Listen Timing (optional) */
2087
2088 /* Status ATTR */
2089 p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status_code);
2090
2091 /* Extended Listen Timing ATTR */
2092 /* Type: */
2093 /* Length: */
2094 /* Value: */
2095
2096 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
2097
2098 return len;
2099}
2100
2101u32 build_deauth_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf)
2102{
2103 u32 len = 0;
2104
2105 return len;
2106}
2107
2108u32 process_probe_req_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2109{
2110 u8 *p;
2111 u32 ret = false;
2112 u8 *p2pie;
2113 u32 p2pielen = 0;
2114 int ssid_len = 0, rate_cnt = 0;
2115
2116 p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + _PROBEREQ_IE_OFFSET_, _SUPPORTEDRATES_IE_, (int *)&rate_cnt,
2117 len - sizeof(struct ieee80211_hdr_3addr) - _PROBEREQ_IE_OFFSET_);
2118
2119 if (rate_cnt <= 4)
2120 {
2121 int i, g_rate = 0;
2122
2123 for (i = 0; i < rate_cnt; i++)
2124 {
2125 if (((*(p + 2 + i) & 0xff) != 0x02) &&
2126 ((*(p + 2 + i) & 0xff) != 0x04) &&
2127 ((*(p + 2 + i) & 0xff) != 0x0B) &&
2128 ((*(p + 2 + i) & 0xff) != 0x16))
2129 {
2130 g_rate = 1;
2131 }
2132 }
2133
2134 if (g_rate == 0)
2135 {
2136 /* There is no OFDM rate included in SupportedRates IE of this probe request frame */
2137 /* The driver should response this probe request. */
2138 return ret;
2139 }
2140 }
2141 else
2142 {
2143 /* rate_cnt > 4 means the SupportRates IE contains the OFDM rate because the count of CCK rates are 4. */
2144 /* We should proceed the following check for this probe request. */
2145 }
2146
2147 /* Added comments by Albert 20100906 */
2148 /* There are several items we should check here. */
2149 /* 1. This probe request frame must contain the P2P IE. (Done) */
2150 /* 2. This probe request frame must contain the wildcard SSID. (Done) */
2151 /* 3. Wildcard BSSID. (Todo) */
2152 /* 4. Destination Address. (Done in mgt_dispatcher23a function) */
2153 /* 5. Requested Device Type in WSC IE. (Todo) */
2154 /* 6. Device ID attribute in P2P IE. (Todo) */
2155
2156 p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ssid_len,
2157 len - sizeof(struct ieee80211_hdr_3addr) - _PROBEREQ_IE_OFFSET_);
2158
2159 ssid_len &= 0xff; /* Just last 1 byte is valid for ssid len of the probe request */
2160 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2161 {
2162 if ((p2pie = rtw_get_p2p_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + _PROBEREQ_IE_OFFSET_, len - sizeof(struct ieee80211_hdr_3addr) - _PROBEREQ_IE_OFFSET_, NULL, &p2pielen)))
2163 {
2164 if ((p) && !memcmp((void *)(p+2), (void *)pwdinfo->p2p_wildcard_ssid, 7))
2165 {
2166 /* todo: */
2167 /* Check Requested Device Type attributes in WSC IE. */
2168 /* Check Device ID attribute in P2P IE */
2169
2170 ret = true;
2171 }
2172 else if ((p != NULL) && (ssid_len == 0))
2173 {
2174 ret = true;
2175 }
2176 }
2177 else
2178 {
2179 /* non -p2p device */
2180 }
2181
2182 }
2183
2184 return ret;
2185}
2186
2187u32 process_assoc_req_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len, struct sta_info *psta)
2188{
2189 u8 status_code = P2P_STATUS_SUCCESS;
2190 u8 *pbuf, *pattr_content = NULL;
2191 u32 attr_contentlen = 0;
2192 u16 cap_attr = 0;
2193 unsigned short ie_offset;
2194 u8 * ies;
2195 u32 ies_len;
2196 u8 * p2p_ie;
2197 u32 p2p_ielen = 0;
2198 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)pframe;
2199
2200 if (!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2201 return P2P_STATUS_FAIL_REQUEST_UNABLE;
2202
2203 if (ieee80211_is_assoc_req(hdr->frame_control))
2204 ie_offset = _ASOCREQ_IE_OFFSET_;
2205 else /* WIFI_REASSOCREQ */
2206 ie_offset = _REASOCREQ_IE_OFFSET_;
2207
2208 ies = pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset;
2209 ies_len = len - sizeof(struct ieee80211_hdr_3addr) - ie_offset;
2210
2211 p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
2212
2213 if (!p2p_ie)
2214 {
2215 DBG_8723A("[%s] P2P IE not Found!!\n", __func__);
2216 status_code = P2P_STATUS_FAIL_INVALID_PARAM;
2217 }
2218 else
2219 {
2220 DBG_8723A("[%s] P2P IE Found!!\n", __func__);
2221 }
2222
2223 while (p2p_ie)
2224 {
2225 /* Check P2P Capability ATTR */
2226 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*) &attr_contentlen))
2227 {
2228 DBG_8723A("[%s] Got P2P Capability Attr!!\n", __func__);
2229 cap_attr = le16_to_cpu(cap_attr);
2230 psta->dev_cap = cap_attr&0xff;
2231 }
2232
2233 /* Check Extended Listen Timing ATTR */
2234
2235 /* Check P2P Device Info ATTR */
2236 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, NULL, (uint*)&attr_contentlen))
2237 {
2238 DBG_8723A("[%s] Got P2P DEVICE INFO Attr!!\n", __func__);
2239 pattr_content = pbuf = kzalloc(attr_contentlen,
2240 GFP_ATOMIC);
2241 if (pattr_content) {
2242 u8 num_of_secdev_type;
2243 u16 dev_name_len;
2244
2245 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, pattr_content, (uint*)&attr_contentlen);
2246
2247 memcpy(psta->dev_addr, pattr_content, ETH_ALEN);/* P2P Device Address */
2248
2249 pattr_content += ETH_ALEN;
2250
2251 memcpy(&psta->config_methods, pattr_content, 2);/* Config Methods */
2252 psta->config_methods = be16_to_cpu(psta->config_methods);
2253
2254 pattr_content += 2;
2255
2256 memcpy(psta->primary_dev_type, pattr_content, 8);
2257
2258 pattr_content += 8;
2259
2260 num_of_secdev_type = *pattr_content;
2261 pattr_content += 1;
2262
2263 if (num_of_secdev_type == 0)
2264 {
2265 psta->num_of_secdev_type = 0;
2266 }
2267 else
2268 {
2269 u32 len;
2270
2271 psta->num_of_secdev_type = num_of_secdev_type;
2272
2273 len = (sizeof(psta->secdev_types_list)<(num_of_secdev_type*8)) ? (sizeof(psta->secdev_types_list)) : (num_of_secdev_type*8);
2274
2275 memcpy(psta->secdev_types_list, pattr_content, len);
2276
2277 pattr_content += (num_of_secdev_type*8);
2278 }
2279
2280 /* dev_name_len = attr_contentlen - ETH_ALEN - 2 - 8 - 1 - (num_of_secdev_type*8); */
2281 psta->dev_name_len = 0;
2282 if (WPS_ATTR_DEVICE_NAME == be16_to_cpu(*(u16*)pattr_content))
2283 {
2284 dev_name_len = be16_to_cpu(*(u16*)(pattr_content+2));
2285
2286 psta->dev_name_len = (sizeof(psta->dev_name)<dev_name_len) ? sizeof(psta->dev_name):dev_name_len;
2287
2288 memcpy(psta->dev_name, pattr_content+4, psta->dev_name_len);
2289 }
2290
2291 kfree(pbuf);
2292
2293 }
2294
2295 }
2296
2297 /* Get the next P2P IE */
2298 p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
2299
2300 }
2301
2302 return status_code;
2303}
2304
2305u32 process_p2p_devdisc_req23a(struct wifidirect_info *pwdinfo, u8 *pframe,
2306 uint len)
2307{
2308 u8 *frame_body;
2309 u8 status, dialogToken;
2310 struct sta_info *psta = NULL;
2311 struct rtw_adapter *padapter = pwdinfo->padapter;
2312 struct sta_priv *pstapriv = &padapter->stapriv;
2313 u8 *p2p_ie;
2314 u32 p2p_ielen = 0;
2315 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) pframe;
2316
2317 frame_body = (unsigned char *)
2318 (pframe + sizeof(struct ieee80211_hdr_3addr));
2319
2320 dialogToken = frame_body[7];
2321 status = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
2322
2323 if ((p2p_ie = rtw_get_p2p_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
2324 len - _PUBLIC_ACTION_IE_OFFSET_, NULL,
2325 &p2p_ielen))) {
2326 u8 groupid[38] = { 0x00 };
2327 u8 dev_addr[ETH_ALEN] = { 0x00 };
2328 u32 attr_contentlen = 0;
2329
2330 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen,
2331 P2P_ATTR_GROUP_ID, groupid,
2332 &attr_contentlen)) {
2333 if (!memcmp(pwdinfo->device_addr, groupid, ETH_ALEN) &&
2334 !memcmp(pwdinfo->p2p_group_ssid, groupid + ETH_ALEN,
2335 pwdinfo->p2p_group_ssid_len)) {
2336 attr_contentlen = 0;
2337
2338 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen,
2339 P2P_ATTR_DEVICE_ID,
2340 dev_addr,
2341 &attr_contentlen)) {
2342 struct list_head *phead, *plist, *ptmp;
2343
2344 spin_lock_bh(&pstapriv->asoc_list_lock);
2345 phead = &pstapriv->asoc_list;
2346
2347 list_for_each_safe(plist, ptmp, phead) {
2348 psta = container_of(plist, struct sta_info, asoc_list);
2349
2350 if (psta->is_p2p_device && (psta->dev_cap&P2P_DEVCAP_CLIENT_DISCOVERABILITY) &&
2351 !memcmp(psta->dev_addr, dev_addr, ETH_ALEN))
2352 {
2353 /* spin_unlock_bh(&pstapriv->asoc_list_lock); */
2354 /* issue GO Discoverability Request */
2355 issue_group_disc_req(pwdinfo, psta->hwaddr);
2356 /* spin_lock_bh(&pstapriv->asoc_list_lock); */
2357 status = P2P_STATUS_SUCCESS;
2358 break;
2359 } else {
2360 status = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
2361 }
2362 }
2363 spin_unlock_bh(&pstapriv->asoc_list_lock);
2364 } else {
2365 status = P2P_STATUS_FAIL_INVALID_PARAM;
2366 }
2367 } else {
2368 status = P2P_STATUS_FAIL_INVALID_PARAM;
2369 }
2370 }
2371 }
2372
2373 /* issue Device Discoverability Response */
2374 issue_p2p_devdisc_resp(pwdinfo, hdr->addr2, status, dialogToken);
2375
2376 return (status == P2P_STATUS_SUCCESS) ? true:false;
2377}
2378
2379u32 process_p2p_devdisc_resp23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2380{
2381 return true;
2382}
2383
2384u8 process_p2p_provdisc_req23a(struct wifidirect_info *pwdinfo,
2385 u8 *pframe, uint len)
2386{
2387 u8 *frame_body;
2388 u8 *wpsie;
2389 u8 *ptr = NULL;
2390 uint wps_ielen = 0, attr_contentlen = 0;
2391 u16 uconfig_method = 0;
2392 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)pframe;
2393
2394 frame_body = (pframe + sizeof(struct ieee80211_hdr_3addr));
2395
2396 wpsie = rtw_get_wps_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
2397 len - _PUBLIC_ACTION_IE_OFFSET_, NULL,
2398 &wps_ielen);
2399 if (!wpsie)
2400 goto out;
2401
2402 if (!rtw_get_wps_attr_content23a(wpsie, wps_ielen, WPS_ATTR_CONF_METHOD,
2403 (u8 *)&uconfig_method, &attr_contentlen))
2404 goto out;
2405
2406 uconfig_method = be16_to_cpu(uconfig_method);
2407 ptr = pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req;
2408
2409 switch (uconfig_method)
2410 {
2411 case WPS_CM_DISPLYA:
2412 memcpy(ptr, "dis", 3);
2413 break;
2414
2415 case WPS_CM_LABEL:
2416 memcpy(ptr, "lab", 3);
2417 break;
2418
2419 case WPS_CM_PUSH_BUTTON:
2420 memcpy(ptr, "pbc", 3);
2421 break;
2422
2423 case WPS_CM_KEYPAD:
2424 memcpy(ptr, "pad", 3);
2425 break;
2426 }
2427 issue_p2p_provision_resp(pwdinfo, hdr->addr2, frame_body,
2428 uconfig_method);
2429
2430out:
2431 DBG_8723A("[%s] config method = %s\n", __func__, ptr);
2432
2433 return true;
2434}
2435
2436u8 process_p2p_provdisc_resp23a(struct wifidirect_info *pwdinfo, u8 *pframe)
2437{
2438
2439 return true;
2440}
2441
2442static u8 rtw_p2p_get_peer_ch_list(struct wifidirect_info *pwdinfo, u8 *ch_content, u8 ch_cnt, u8 *peer_ch_list)
2443{
2444 u8 i = 0, j = 0;
2445 u8 temp = 0;
2446 u8 ch_no = 0;
2447 ch_content += 3;
2448 ch_cnt -= 3;
2449
2450 while(ch_cnt > 0)
2451 {
2452 ch_content += 1;
2453 ch_cnt -= 1;
2454 temp = *ch_content;
2455 for (i = 0 ; i < temp ; i++, j++)
2456 {
2457 peer_ch_list[j] = *(ch_content + 1 + i);
2458 }
2459 ch_content += (temp + 1);
2460 ch_cnt -= (temp + 1);
2461 ch_no += temp ;
2462 }
2463
2464 return ch_no;
2465}
2466
2467static u8 rtw_p2p_ch_inclusion(struct mlme_ext_priv *pmlmeext, u8 *peer_ch_list, u8 peer_ch_num, u8 *ch_list_inclusioned)
2468{
2469 int i = 0, j = 0, temp = 0;
2470 u8 ch_no = 0;
2471
2472 for (i = 0; i < peer_ch_num; i++)
2473 {
2474 for (j = temp; j < pmlmeext->max_chan_nums; j++)
2475 {
2476 if (*(peer_ch_list + i) == pmlmeext->channel_set[ j ].ChannelNum)
2477 {
2478 ch_list_inclusioned[ ch_no++ ] = *(peer_ch_list + i);
2479 temp = j;
2480 break;
2481 }
2482 }
2483 }
2484
2485 return ch_no;
2486}
2487
2488u8 process_p2p_group_negotation_req23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2489{
2490 struct rtw_adapter *padapter = pwdinfo->padapter;
2491 u8 result = P2P_STATUS_SUCCESS;
2492 u32 p2p_ielen = 0, wps_ielen = 0;
2493 u8 * ies;
2494 u32 ies_len;
2495 u8 *p2p_ie;
2496 u8 *wpsie;
2497 u16 wps_devicepassword_id = 0x0000;
2498 uint wps_devicepassword_id_len = 0;
2499#ifdef CONFIG_8723AU_P2P
2500 u8 wfd_ie[ 128 ] = { 0x00 };
2501 u32 wfd_ielen = 0;
2502#endif /* CONFIG_8723AU_P2P */
2503
2504 if ((wpsie = rtw_get_wps_ie23a(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen)))
2505 {
2506 /* Commented by Kurt 20120113 */
2507 /* If some device wants to do p2p handshake without sending prov_disc_req */
2508 /* We have to get peer_req_cm from here. */
2509 if (!memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3))
2510 {
2511 rtw_get_wps_attr_content23a(wpsie, wps_ielen, WPS_ATTR_DEVICE_PWID, (u8*) &wps_devicepassword_id, &wps_devicepassword_id_len);
2512 wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id);
2513
2514 if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
2515 {
2516 memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
2517 }
2518 else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
2519 {
2520 memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
2521 }
2522 else
2523 {
2524 memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
2525 }
2526 }
2527 }
2528 else
2529 {
2530 DBG_8723A("[%s] WPS IE not Found!!\n", __func__);
2531 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2532 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2533 return result;
2534 }
2535
2536 if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO)
2537 {
2538 result = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
2539 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INFOR_NOREADY);
2540 return result;
2541 }
2542
2543 ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2544 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2545
2546 p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
2547
2548 if (!p2p_ie)
2549 {
2550 DBG_8723A("[%s] P2P IE not Found!!\n", __func__);
2551 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2552 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2553 }
2554
2555 while (p2p_ie)
2556 {
2557 u8 attr_content = 0x00;
2558 u32 attr_contentlen = 0;
2559 u8 ch_content[50] = { 0x00 };
2560 uint ch_cnt = 0;
2561 u8 peer_ch_list[50] = { 0x00 };
2562 u8 peer_ch_num = 0;
2563 u8 ch_list_inclusioned[50] = { 0x00 };
2564 u8 ch_num_inclusioned = 0;
2565 u16 cap_attr;
2566
2567 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
2568
2569 /* Check P2P Capability ATTR */
2570 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*)&attr_contentlen))
2571 cap_attr = le16_to_cpu(cap_attr);
2572
2573 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, &attr_content, &attr_contentlen))
2574 {
2575 DBG_8723A("[%s] GO Intent = %d, tie = %d\n", __func__, attr_content >> 1, attr_content & 0x01);
2576 pwdinfo->peer_intent = attr_content; /* include both intent and tie breaker values. */
2577
2578 if (pwdinfo->intent == (pwdinfo->peer_intent >> 1))
2579 {
2580 /* Try to match the tie breaker value */
2581 if (pwdinfo->intent == P2P_MAX_INTENT)
2582 {
2583 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2584 result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
2585 }
2586 else
2587 {
2588 if (attr_content & 0x01)
2589 {
2590 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2591 }
2592 else
2593 {
2594 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2595 }
2596 }
2597 }
2598 else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1))
2599 {
2600 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2601 }
2602 else
2603 {
2604 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2605 }
2606
2607 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2608 {
2609 /* Store the group id information. */
2610 memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
2611 memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2612 }
2613 }
2614
2615 attr_contentlen = 0;
2616 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen))
2617 {
2618 if (attr_contentlen != ETH_ALEN)
2619 {
2620 memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
2621 }
2622 }
2623
2624 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, ch_content, &ch_cnt))
2625 {
2626 peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, ch_content, ch_cnt, peer_ch_list);
2627 ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
2628
2629 if (ch_num_inclusioned == 0)
2630 {
2631 DBG_8723A("[%s] No common channel in channel list!\n", __func__);
2632 result = P2P_STATUS_FAIL_NO_COMMON_CH;
2633 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2634 break;
2635 }
2636
2637 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2638 {
2639 if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
2640 ch_list_inclusioned, ch_num_inclusioned))
2641 {
2642 {
2643 u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
2644 attr_contentlen = 0;
2645
2646 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
2647 {
2648 peer_operating_ch = operatingch_info[4];
2649 }
2650
2651 if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
2652 ch_list_inclusioned, ch_num_inclusioned))
2653 {
2654 /**
2655 * Change our operating channel as peer's for compatibility.
2656 */
2657 pwdinfo->operating_channel = peer_operating_ch;
2658 DBG_8723A("[%s] Change op ch to %02x as peer's\n", __func__, pwdinfo->operating_channel);
2659 }
2660 else
2661 {
2662 /* Take first channel of ch_list_inclusioned as operating channel */
2663 pwdinfo->operating_channel = ch_list_inclusioned[0];
2664 DBG_8723A("[%s] Change op ch to %02x\n", __func__, pwdinfo->operating_channel);
2665 }
2666 }
2667
2668 }
2669 }
2670 }
2671
2672 /* Get the next P2P IE */
2673 p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
2674 }
2675
2676#ifdef CONFIG_8723AU_P2P
2677 /* Added by Albert 20110823 */
2678 /* Try to get the TCP port information when receiving the negotiation request. */
2679 if (rtw_get_wfd_ie(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wfd_ie, &wfd_ielen))
2680 {
2681 u8 attr_content[ 10 ] = { 0x00 };
2682 u32 attr_contentlen = 0;
2683
2684 DBG_8723A("[%s] WFD IE Found!!\n", __func__);
2685 rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
2686 if (attr_contentlen)
2687 {
2688 pwdinfo->wfd_info->peer_rtsp_ctrlport = RTW_GET_BE16(attr_content + 2);
2689 DBG_8723A("[%s] Peer PORT NUM = %d\n", __func__, pwdinfo->wfd_info->peer_rtsp_ctrlport);
2690 }
2691 }
2692#endif /* CONFIG_8723AU_P2P */
2693
2694 return result;
2695}
2696
2697u8 process_p2p_group_negotation_resp23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2698{
2699 struct rtw_adapter *padapter = pwdinfo->padapter;
2700 u8 result = P2P_STATUS_SUCCESS;
2701 u32 p2p_ielen, wps_ielen;
2702 u8 * ies;
2703 u32 ies_len;
2704 u8 * p2p_ie;
2705#ifdef CONFIG_8723AU_P2P
2706 u8 wfd_ie[ 128 ] = { 0x00 };
2707 u32 wfd_ielen = 0;
2708#endif /* CONFIG_8723AU_P2P */
2709
2710 ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2711 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2712
2713 /* Be able to know which one is the P2P GO and which one is P2P client. */
2714
2715 if (rtw_get_wps_ie23a(ies, ies_len, NULL, &wps_ielen))
2716 {
2717
2718 }
2719 else
2720 {
2721 DBG_8723A("[%s] WPS IE not Found!!\n", __func__);
2722 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2723 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2724 }
2725
2726 p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
2727 if (!p2p_ie)
2728 {
2729 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2730 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2731 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2732 }
2733 else
2734 {
2735
2736 u8 attr_content = 0x00;
2737 u32 attr_contentlen = 0;
2738 u8 operatingch_info[5] = { 0x00 };
2739 u8 groupid[ 38 ];
2740 u16 cap_attr;
2741 u8 peer_ch_list[50] = { 0x00 };
2742 u8 peer_ch_num = 0;
2743 u8 ch_list_inclusioned[50] = { 0x00 };
2744 u8 ch_num_inclusioned = 0;
2745
2746 while (p2p_ie) /* Found the P2P IE. */
2747 {
2748
2749 /* Check P2P Capability ATTR */
2750 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*)&attr_contentlen))
2751 cap_attr = le16_to_cpu(cap_attr);
2752
2753 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
2754 if (attr_contentlen == 1)
2755 {
2756 DBG_8723A("[%s] Status = %d\n", __func__, attr_content);
2757 if (attr_content == P2P_STATUS_SUCCESS)
2758 {
2759 /* Do nothing. */
2760 }
2761 else
2762 {
2763 if (P2P_STATUS_FAIL_INFO_UNAVAILABLE == attr_content) {
2764 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INFOR_NOREADY);
2765 } else {
2766 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2767 }
2768 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2769 result = attr_content;
2770 break;
2771 }
2772 }
2773
2774 /* Try to get the peer's interface address */
2775 attr_contentlen = 0;
2776 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen))
2777 {
2778 if (attr_contentlen != ETH_ALEN)
2779 {
2780 memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
2781 }
2782 }
2783
2784 /* Try to get the peer's intent and tie breaker value. */
2785 attr_content = 0x00;
2786 attr_contentlen = 0;
2787 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, &attr_content, &attr_contentlen))
2788 {
2789 DBG_8723A("[%s] GO Intent = %d, tie = %d\n", __func__, attr_content >> 1, attr_content & 0x01);
2790 pwdinfo->peer_intent = attr_content; /* include both intent and tie breaker values. */
2791
2792 if (pwdinfo->intent == (pwdinfo->peer_intent >> 1))
2793 {
2794 /* Try to match the tie breaker value */
2795 if (pwdinfo->intent == P2P_MAX_INTENT)
2796 {
2797 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2798 result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
2799 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2800 }
2801 else
2802 {
2803 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2804 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2805 if (attr_content & 0x01)
2806 {
2807 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2808 }
2809 else
2810 {
2811 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2812 }
2813 }
2814 }
2815 else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1))
2816 {
2817 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2818 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2819 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2820 }
2821 else
2822 {
2823 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2824 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2825 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2826 }
2827
2828 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2829 {
2830 /* Store the group id information. */
2831 memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
2832 memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2833
2834 }
2835 }
2836
2837 /* Try to get the operation channel information */
2838
2839 attr_contentlen = 0;
2840 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
2841 {
2842 DBG_8723A("[%s] Peer's operating channel = %d\n", __func__, operatingch_info[4]);
2843 pwdinfo->peer_operating_ch = operatingch_info[4];
2844 }
2845
2846 /* Try to get the channel list information */
2847 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, pwdinfo->channel_list_attr, &pwdinfo->channel_list_attr_len))
2848 {
2849 DBG_8723A("[%s] channel list attribute found, len = %d\n", __func__, pwdinfo->channel_list_attr_len);
2850
2851 peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len, peer_ch_list);
2852 ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
2853
2854 if (ch_num_inclusioned == 0)
2855 {
2856 DBG_8723A("[%s] No common channel in channel list!\n", __func__);
2857 result = P2P_STATUS_FAIL_NO_COMMON_CH;
2858 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2859 break;
2860 }
2861
2862 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2863 {
2864 if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
2865 ch_list_inclusioned, ch_num_inclusioned))
2866 {
2867 {
2868 u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
2869 attr_contentlen = 0;
2870
2871 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
2872 {
2873 peer_operating_ch = operatingch_info[4];
2874 }
2875
2876 if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
2877 ch_list_inclusioned, ch_num_inclusioned))
2878 {
2879 /**
2880 * Change our operating channel as peer's for compatibility.
2881 */
2882 pwdinfo->operating_channel = peer_operating_ch;
2883 DBG_8723A("[%s] Change op ch to %02x as peer's\n", __func__, pwdinfo->operating_channel);
2884 }
2885 else
2886 {
2887 /* Take first channel of ch_list_inclusioned as operating channel */
2888 pwdinfo->operating_channel = ch_list_inclusioned[0];
2889 DBG_8723A("[%s] Change op ch to %02x\n", __func__, pwdinfo->operating_channel);
2890 }
2891 }
2892
2893 }
2894 }
2895
2896 }
2897 else
2898 {
2899 DBG_8723A("[%s] channel list attribute not found!\n", __func__);
2900 }
2901
2902 /* Try to get the group id information if peer is GO */
2903 attr_contentlen = 0;
2904 memset(groupid, 0x00, 38);
2905 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen))
2906 {
2907 memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
2908 memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
2909 }
2910
2911 /* Get the next P2P IE */
2912 p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
2913 }
2914
2915 }
2916
2917#ifdef CONFIG_8723AU_P2P
2918 /* Added by Albert 20111122 */
2919 /* Try to get the TCP port information when receiving the negotiation response. */
2920 if (rtw_get_wfd_ie(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wfd_ie, &wfd_ielen))
2921 {
2922 u8 attr_content[ 10 ] = { 0x00 };
2923 u32 attr_contentlen = 0;
2924
2925 DBG_8723A("[%s] WFD IE Found!!\n", __func__);
2926 rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
2927 if (attr_contentlen)
2928 {
2929 pwdinfo->wfd_info->peer_rtsp_ctrlport = RTW_GET_BE16(attr_content + 2);
2930 DBG_8723A("[%s] Peer PORT NUM = %d\n", __func__, pwdinfo->wfd_info->peer_rtsp_ctrlport);
2931 }
2932 }
2933#endif /* CONFIG_8723AU_P2P */
2934
2935 return result;
2936}
2937
2938u8 process_p2p_group_negotation_confirm23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2939{
2940 u8 * ies;
2941 u32 ies_len;
2942 u8 * p2p_ie;
2943 u32 p2p_ielen = 0;
2944 u8 result = P2P_STATUS_SUCCESS;
2945 ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2946 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2947
2948 p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
2949 while (p2p_ie) /* Found the P2P IE. */
2950 {
2951 u8 attr_content = 0x00, operatingch_info[5] = { 0x00 };
2952 u8 groupid[ 38 ] = { 0x00 };
2953 u32 attr_contentlen = 0;
2954
2955 pwdinfo->negotiation_dialog_token = 1;
2956 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
2957 if (attr_contentlen == 1)
2958 {
2959 DBG_8723A("[%s] Status = %d\n", __func__, attr_content);
2960 result = attr_content;
2961
2962 if (attr_content == P2P_STATUS_SUCCESS)
2963 {
2964 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
2965
2966 /* Commented by Albert 20100911 */
2967 /* Todo: Need to handle the case which both Intents are the same. */
2968 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2969 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2970 if ((pwdinfo->intent) > (pwdinfo->peer_intent >> 1))
2971 {
2972 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2973 }
2974 else if ((pwdinfo->intent) < (pwdinfo->peer_intent >> 1))
2975 {
2976 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2977 }
2978 else
2979 {
2980 /* Have to compare the Tie Breaker */
2981 if (pwdinfo->peer_intent & 0x01)
2982 {
2983 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2984 }
2985 else
2986 {
2987 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2988 }
2989 }
2990 }
2991 else
2992 {
2993 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2994 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2995 break;
2996 }
2997 }
2998
2999 /* Try to get the group id information */
3000 attr_contentlen = 0;
3001 memset(groupid, 0x00, 38);
3002 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen))
3003 {
3004 DBG_8723A("[%s] Ssid = %s, ssidlen = %zu\n", __func__, &groupid[ETH_ALEN], strlen(&groupid[ETH_ALEN]));
3005 memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
3006 memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
3007 }
3008
3009 attr_contentlen = 0;
3010 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
3011 {
3012 DBG_8723A("[%s] Peer's operating channel = %d\n", __func__, operatingch_info[4]);
3013 pwdinfo->peer_operating_ch = operatingch_info[4];
3014 }
3015
3016 /* Get the next P2P IE */
3017 p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
3018
3019 }
3020
3021 return result;
3022}
3023
3024u8 process_p2p_presence_req23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
3025{
3026 u8 *frame_body;
3027 u8 dialogToken = 0;
3028 u8 status = P2P_STATUS_SUCCESS;
3029 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) pframe;
3030
3031 frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
3032
3033 dialogToken = frame_body[6];
3034
3035 /* todo: check NoA attribute */
3036
3037 issue_p2p_presence_resp(pwdinfo, hdr->addr2, status, dialogToken);
3038
3039 return true;
3040}
3041
3042static void find_phase_handler(struct rtw_adapter *padapter)
3043{
3044 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3045 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3046 struct cfg80211_ssid ssid;
3047 u8 _status = 0;
3048
3049
3050
3051 memset((unsigned char*)&ssid, 0, sizeof(struct cfg80211_ssid));
3052 memcpy(ssid.ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
3053 ssid.ssid_len = P2P_WILDCARD_SSID_LEN;
3054
3055 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
3056
3057 spin_lock_bh(&pmlmepriv->lock);
3058 _status = rtw_sitesurvey_cmd23a(padapter, &ssid, 1, NULL, 0);
3059 spin_unlock_bh(&pmlmepriv->lock);
3060
3061
3062}
3063
3064void p2p_concurrent_handler(struct rtw_adapter* padapter);
3065
3066static void restore_p2p_state_handler(struct rtw_adapter *padapter)
3067{
3068 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3069
3070 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
3071 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3072
3073 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3074
3075 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
3076 /* In the P2P client mode, the driver should not switch back to its listen channel */
3077 /* because this P2P client should stay at the operating channel of P2P GO. */
3078 set_channel_bwmode23a(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
3079 }
3080}
3081
3082static void pre_tx_invitereq_handler(struct rtw_adapter *padapter)
3083{
3084 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3085 u8 val8 = 1;
3086
3087 set_channel_bwmode23a(padapter, pwdinfo->invitereq_info.peer_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
3088 padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3089 issue23a_probereq_p2p(padapter, NULL);
3090 mod_timer(&pwdinfo->pre_tx_scan_timer,
3091 jiffies + msecs_to_jiffies(P2P_TX_PRESCAN_TIMEOUT));
3092
3093
3094}
3095
3096static void pre_tx_provdisc_handler(struct rtw_adapter *padapter)
3097{
3098 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3099 u8 val8 = 1;
3100
3101
3102 set_channel_bwmode23a(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
3103 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3104 issue23a_probereq_p2p(padapter, NULL);
3105 mod_timer(&pwdinfo->pre_tx_scan_timer,
3106 jiffies + msecs_to_jiffies(P2P_TX_PRESCAN_TIMEOUT));
3107
3108
3109}
3110
3111static void pre_tx_negoreq_handler(struct rtw_adapter *padapter)
3112{
3113 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3114 u8 val8 = 1;
3115
3116
3117 set_channel_bwmode23a(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
3118 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3119 issue23a_probereq_p2p(padapter, NULL);
3120 mod_timer(&pwdinfo->pre_tx_scan_timer,
3121 jiffies + msecs_to_jiffies(P2P_TX_PRESCAN_TIMEOUT));
3122
3123
3124}
3125
3126static void ro_ch_handler(struct rtw_adapter *padapter)
3127{
3128 struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
3129 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3130 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3131
3132 if (pcfg80211_wdinfo->restore_channel != pmlmeext->cur_channel) {
3133 if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED))
3134 pmlmeext->cur_channel = pcfg80211_wdinfo->restore_channel;
3135
3136 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
3137 HAL_PRIME_CHNL_OFFSET_DONT_CARE,
3138 HT_CHANNEL_WIDTH_20);
3139 }
3140
3141 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3142
3143 pcfg80211_wdinfo->is_ro_ch = false;
3144
3145 DBG_8723A("cfg80211_remain_on_channel_expired\n");
3146
3147 rtw_cfg80211_remain_on_channel_expired(padapter,
3148 pcfg80211_wdinfo->remain_on_ch_cookie,
3149 &pcfg80211_wdinfo->remain_on_ch_channel,
3150 pcfg80211_wdinfo->remain_on_ch_type, GFP_KERNEL);
3151}
3152
3153static void ro_ch_timer_process (unsigned long data)
3154{
3155 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
3156
3157 p2p_protocol_wk_cmd23a(adapter, P2P_RO_CH_WK);
3158}
3159
3160#ifdef CONFIG_8723AU_P2P
3161void rtw_append_wfd_ie(struct rtw_adapter *padapter, u8 *buf, u32* len)
3162{
3163 unsigned char *frame_body;
3164 u8 category, action, OUI_Subtype, dialogToken = 0;
3165 u32 wfdielen = 0;
3166
3167 frame_body = (unsigned char *)(buf + sizeof(struct ieee80211_hdr_3addr));
3168 category = frame_body[0];
3169
3170 if (category == WLAN_CATEGORY_PUBLIC) {
3171 action = frame_body[1];
3172 if (action == ACT_PUBLIC_VENDOR &&
3173 !memcmp(frame_body+2, P2P_OUI23A, 4)) {
3174 OUI_Subtype = frame_body[6];
3175 dialogToken = frame_body[7];
3176 switch (OUI_Subtype)/* OUI Subtype */ {
3177 case P2P_GO_NEGO_REQ:
3178 wfdielen = build_nego_req_wfd_ie(&padapter->wdinfo, buf + (*len));
3179 (*len) += wfdielen;
3180 break;
3181 case P2P_GO_NEGO_RESP:
3182 wfdielen = build_nego_resp_wfd_ie(&padapter->wdinfo, buf + (*len));
3183 (*len) += wfdielen;
3184 break;
3185 case P2P_GO_NEGO_CONF:
3186 wfdielen = build_nego_confirm_wfd_ie(&padapter->wdinfo, buf + (*len));
3187 (*len) += wfdielen;
3188 break;
3189 case P2P_INVIT_REQ:
3190 wfdielen = build_invitation_req_wfd_ie(&padapter->wdinfo, buf + (*len));
3191 (*len) += wfdielen;
3192 break;
3193 case P2P_INVIT_RESP:
3194 wfdielen = build_invitation_resp_wfd_ie(&padapter->wdinfo, buf + (*len));
3195 (*len) += wfdielen;
3196 break;
3197 case P2P_DEVDISC_REQ:
3198 break;
3199 case P2P_DEVDISC_RESP:
3200 break;
3201 case P2P_PROVISION_DISC_REQ:
3202 wfdielen = build_provdisc_req_wfd_ie(&padapter->wdinfo, buf + (*len));
3203 (*len) += wfdielen;
3204 break;
3205 case P2P_PROVISION_DISC_RESP:
3206 wfdielen = build_provdisc_resp_wfd_ie(&padapter->wdinfo, buf + (*len));
3207 (*len) += wfdielen;
3208 break;
3209 default:
3210 break;
3211 }
3212 }
3213 } else if (category == WLAN_CATEGORY_VENDOR_SPECIFIC) {
3214 OUI_Subtype = frame_body[5];
3215 dialogToken = frame_body[6];
3216 } else {
3217 DBG_8723A("%s, action frame category =%d\n", __func__, category);
3218 }
3219}
3220#endif
3221
3222int rtw_p2p_check_frames(struct rtw_adapter *padapter, const u8 *buf, u32 len, u8 tx)
3223{
3224 int is_p2p_frame = (-1);
3225 unsigned char *frame_body;
3226 u8 category, action, OUI_Subtype, dialogToken = 0;
3227 u8 *p2p_ie = NULL;
3228 uint p2p_ielen = 0;
3229 struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
3230
3231 frame_body = (unsigned char *)(buf + sizeof(struct ieee80211_hdr_3addr));
3232 category = frame_body[0];
3233 /* just for check */
3234 if (category == WLAN_CATEGORY_PUBLIC)
3235 {
3236 action = frame_body[1];
3237 if (action == ACT_PUBLIC_VENDOR &&
3238 !memcmp(frame_body+2, P2P_OUI23A, 4)) {
3239 OUI_Subtype = frame_body[6];
3240 dialogToken = frame_body[7];
3241 is_p2p_frame = OUI_Subtype;
3242 p2p_ie = rtw_get_p2p_ie23a(
3243 (u8 *)buf+sizeof(struct ieee80211_hdr_3addr)+_PUBLIC_ACTION_IE_OFFSET_,
3244 len-sizeof(struct ieee80211_hdr_3addr)-_PUBLIC_ACTION_IE_OFFSET_,
3245 NULL, &p2p_ielen);
3246
3247 switch (OUI_Subtype) {/* OUI Subtype */
3248 u8 *cont;
3249 uint cont_len;
3250 case P2P_GO_NEGO_REQ:
3251 DBG_8723A("RTW_%s:P2P_GO_NEGO_REQ, dialogToken =%d\n", (tx == true)?"Tx":"Rx", dialogToken);
3252 break;
3253 case P2P_GO_NEGO_RESP:
3254 cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
3255 DBG_8723A("RTW_%s:P2P_GO_NEGO_RESP, dialogToken =%d, status:%d\n", (tx == true)?"Tx":"Rx", dialogToken, cont?*cont:-1);
3256
3257 if (!tx)
3258 pwdev_priv->provdisc_req_issued = false;
3259 break;
3260 case P2P_GO_NEGO_CONF:
3261 cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
3262 DBG_8723A("RTW_%s:P2P_GO_NEGO_CONF, dialogToken =%d, status:%d\n",
3263 (tx == true)?"Tx":"Rx", dialogToken, cont?*cont:-1);
3264 break;
3265 case P2P_INVIT_REQ:
3266 {
3267 struct rtw_wdev_invit_info* invit_info = &pwdev_priv->invit_info;
3268 int flags = -1;
3269 int op_ch = 0;
3270
3271 if ((cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, NULL, &cont_len)))
3272 flags = *cont;
3273 if ((cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len)))
3274 op_ch = *(cont+4);
3275
3276 if (invit_info->token != dialogToken)
3277 rtw_wdev_invit_info_init(invit_info);
3278
3279 invit_info->token = dialogToken;
3280 invit_info->flags = (flags ==-1) ? 0x0 : flags;
3281 invit_info->req_op_ch = op_ch;
3282
3283 DBG_8723A("RTW_%s:P2P_INVIT_REQ, dialogToken =%d, flags:0x%02x, op_ch:%d\n",
3284 (tx) ? "Tx" : "Rx", dialogToken, flags, op_ch);
3285 break;
3286 }
3287 case P2P_INVIT_RESP:
3288 {
3289 struct rtw_wdev_invit_info* invit_info = &pwdev_priv->invit_info;
3290 int status = -1;
3291 int op_ch = 0;
3292
3293 if ((cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len)))
3294 status = *cont;
3295 if ((cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len)))
3296 op_ch = *(cont+4);
3297
3298 if (invit_info->token != dialogToken) {
3299 rtw_wdev_invit_info_init(invit_info);
3300 } else {
3301 invit_info->token = 0;
3302 invit_info->status = (status ==-1) ? 0xff : status;
3303 invit_info->rsp_op_ch = op_ch;
3304 }
3305
3306 DBG_8723A("RTW_%s:P2P_INVIT_RESP, dialogToken =%d, status:%d, op_ch:%d\n",
3307 (tx == true)?"Tx":"Rx", dialogToken, status, op_ch);
3308 break;
3309 }
3310 case P2P_DEVDISC_REQ:
3311 DBG_8723A("RTW_%s:P2P_DEVDISC_REQ, dialogToken =%d\n", (tx == true)?"Tx":"Rx", dialogToken);
3312 break;
3313 case P2P_DEVDISC_RESP:
3314 cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
3315 DBG_8723A("RTW_%s:P2P_DEVDISC_RESP, dialogToken =%d, status:%d\n", (tx == true)?"Tx":"Rx", dialogToken, cont?*cont:-1);
3316 break;
3317 case P2P_PROVISION_DISC_REQ:
3318 {
3319 size_t frame_body_len = len - sizeof(struct ieee80211_hdr_3addr);
3320 u8 *p2p_ie;
3321 uint p2p_ielen = 0;
3322 uint contentlen = 0;
3323
3324 DBG_8723A("RTW_%s:P2P_PROVISION_DISC_REQ, dialogToken =%d\n", (tx == true)?"Tx":"Rx", dialogToken);
3325
3326 pwdev_priv->provdisc_req_issued = false;
3327
3328 p2p_ie = rtw_get_p2p_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
3329 frame_body_len - _PUBLIC_ACTION_IE_OFFSET_,
3330 NULL, &p2p_ielen);
3331 if (p2p_ie) {
3332 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, NULL, &contentlen))
3333 pwdev_priv->provdisc_req_issued = false;/* case: p2p_client join p2p GO */
3334 else
3335 pwdev_priv->provdisc_req_issued = true;/* case: p2p_devices connection before Nego req. */
3336 }
3337 }
3338 break;
3339 case P2P_PROVISION_DISC_RESP:
3340 DBG_8723A("RTW_%s:P2P_PROVISION_DISC_RESP, dialogToken =%d\n", (tx == true)?"Tx":"Rx", dialogToken);
3341 break;
3342 default:
3343 DBG_8723A("RTW_%s:OUI_Subtype =%d, dialogToken =%d\n", (tx == true)?"Tx":"Rx", OUI_Subtype, dialogToken);
3344 break;
3345 }
3346
3347 }
3348
3349 }
3350 else if (category == WLAN_CATEGORY_VENDOR_SPECIFIC)
3351 {
3352 OUI_Subtype = frame_body[5];
3353 dialogToken = frame_body[6];
3354
3355 is_p2p_frame = OUI_Subtype;
3356
3357 switch (OUI_Subtype) {
3358 case P2P_NOTICE_OF_ABSENCE:
3359 DBG_8723A("RTW_%s:P2P_NOTICE_OF_ABSENCE, dialogToken =%d\n", (tx == true)?"TX":"RX", dialogToken);
3360 break;
3361 case P2P_PRESENCE_REQUEST:
3362 DBG_8723A("RTW_%s:P2P_PRESENCE_REQUEST, dialogToken =%d\n", (tx == true)?"TX":"RX", dialogToken);
3363 break;
3364 case P2P_PRESENCE_RESPONSE:
3365 DBG_8723A("RTW_%s:P2P_PRESENCE_RESPONSE, dialogToken =%d\n", (tx == true)?"TX":"RX", dialogToken);
3366 break;
3367 case P2P_GO_DISC_REQUEST:
3368 DBG_8723A("RTW_%s:P2P_GO_DISC_REQUEST, dialogToken =%d\n", (tx == true)?"TX":"RX", dialogToken);
3369 break;
3370 default:
3371 DBG_8723A("RTW_%s:OUI_Subtype =%d, dialogToken =%d\n", (tx == true)?"TX":"RX", OUI_Subtype, dialogToken);
3372 break;
3373 }
3374
3375 } else {
3376 DBG_8723A("RTW_%s:action frame category =%d\n", (tx == true)?"TX":"RX", category);
3377 }
3378 return is_p2p_frame;
3379}
3380
3381void rtw_init_cfg80211_wifidirect_info(struct rtw_adapter *padapter)
3382{
3383 struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
3384
3385 memset(pcfg80211_wdinfo, 0x00, sizeof(struct cfg80211_wifidirect_info));
3386
3387 setup_timer(&pcfg80211_wdinfo->remain_on_ch_timer,
3388 ro_ch_timer_process, (unsigned long)padapter);
3389}
3390
3391void p2p_protocol_wk_hdl23a(struct rtw_adapter *padapter, int intCmdType)
3392{
3393 switch (intCmdType) {
3394 case P2P_FIND_PHASE_WK:
3395 find_phase_handler(padapter);
3396 break;
3397 case P2P_RESTORE_STATE_WK:
3398 restore_p2p_state_handler(padapter);
3399 break;
3400 case P2P_PRE_TX_PROVDISC_PROCESS_WK:
3401 pre_tx_provdisc_handler(padapter);
3402 break;
3403 case P2P_PRE_TX_INVITEREQ_PROCESS_WK:
3404 pre_tx_invitereq_handler(padapter);
3405 break;
3406 case P2P_PRE_TX_NEGOREQ_PROCESS_WK:
3407 pre_tx_negoreq_handler(padapter);
3408 break;
3409 case P2P_RO_CH_WK:
3410 ro_ch_handler(padapter);
3411 break;
3412 }
3413}
3414
3415#ifdef CONFIG_8723AU_P2P
3416void process_p2p_ps_ie23a(struct rtw_adapter *padapter, u8 *IEs, u32 IELength)
3417{
3418 u8 * ies;
3419 u32 ies_len;
3420 u8 * p2p_ie;
3421 u32 p2p_ielen = 0;
3422 u8 noa_attr[MAX_P2P_IE_LEN] = { 0x00 };/* NoA length should be n*(13) + 2 */
3423 u32 attr_contentlen = 0;
3424
3425 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3426 u8 find_p2p = false, find_p2p_ps = false;
3427 u8 noa_offset, noa_num, noa_index;
3428
3429
3430
3431 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3432 {
3433 return;
3434 }
3435 if (IELength <= _BEACON_IE_OFFSET_)
3436 return;
3437
3438 ies = IEs + _BEACON_IE_OFFSET_;
3439 ies_len = IELength - _BEACON_IE_OFFSET_;
3440
3441 p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
3442
3443 while(p2p_ie)
3444 {
3445 find_p2p = true;
3446 /* Get Notice of Absence IE. */
3447 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_NOA, noa_attr, &attr_contentlen))
3448 {
3449 find_p2p_ps = true;
3450 noa_index = noa_attr[0];
3451
3452 if ((pwdinfo->p2p_ps_mode == P2P_PS_NONE) ||
3453 (noa_index != pwdinfo->noa_index))/* if index change, driver should reconfigure related setting. */
3454 {
3455 pwdinfo->noa_index = noa_index;
3456 pwdinfo->opp_ps = noa_attr[1] >> 7;
3457 pwdinfo->ctwindow = noa_attr[1] & 0x7F;
3458
3459 noa_offset = 2;
3460 noa_num = 0;
3461 /* NoA length should be n*(13) + 2 */
3462 if (attr_contentlen > 2)
3463 {
3464 while(noa_offset < attr_contentlen)
3465 {
3466 /* memcpy(&wifidirect_info->noa_count[noa_num], &noa_attr[noa_offset], 1); */
3467 pwdinfo->noa_count[noa_num] = noa_attr[noa_offset];
3468 noa_offset += 1;
3469
3470 memcpy(&pwdinfo->noa_duration[noa_num], &noa_attr[noa_offset], 4);
3471 noa_offset += 4;
3472
3473 memcpy(&pwdinfo->noa_interval[noa_num], &noa_attr[noa_offset], 4);
3474 noa_offset += 4;
3475
3476 memcpy(&pwdinfo->noa_start_time[noa_num], &noa_attr[noa_offset], 4);
3477 noa_offset += 4;
3478
3479 noa_num++;
3480 }
3481 }
3482 pwdinfo->noa_num = noa_num;
3483
3484 if (pwdinfo->opp_ps == 1)
3485 {
3486 pwdinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
3487 /* driver should wait LPS for entering CTWindow */
3488 if (padapter->pwrctrlpriv.bFwCurrentInPSMode == true)
3489 {
3490 p2p_ps_wk_cmd23a(padapter, P2P_PS_ENABLE, 1);
3491 }
3492 }
3493 else if (pwdinfo->noa_num > 0)
3494 {
3495 pwdinfo->p2p_ps_mode = P2P_PS_NOA;
3496 p2p_ps_wk_cmd23a(padapter, P2P_PS_ENABLE, 1);
3497 }
3498 else if (pwdinfo->p2p_ps_mode > P2P_PS_NONE)
3499 {
3500 p2p_ps_wk_cmd23a(padapter, P2P_PS_DISABLE, 1);
3501 }
3502 }
3503
3504 break; /* find target, just break. */
3505 }
3506
3507 /* Get the next P2P IE */
3508 p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
3509
3510 }
3511
3512 if (find_p2p == true)
3513 {
3514 if ((pwdinfo->p2p_ps_mode > P2P_PS_NONE) && (find_p2p_ps == false))
3515 {
3516 p2p_ps_wk_cmd23a(padapter, P2P_PS_DISABLE, 1);
3517 }
3518 }
3519
3520
3521}
3522
3523void p2p_ps_wk_hdl23a(struct rtw_adapter *padapter, u8 p2p_ps_state)
3524{
3525 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
3526 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3527
3528
3529
3530 /* Pre action for p2p state */
3531 switch (p2p_ps_state)
3532 {
3533 case P2P_PS_DISABLE:
3534 pwdinfo->p2p_ps_state = p2p_ps_state;
3535
3536 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
3537
3538 pwdinfo->noa_index = 0;
3539 pwdinfo->ctwindow = 0;
3540 pwdinfo->opp_ps = 0;
3541 pwdinfo->noa_num = 0;
3542 pwdinfo->p2p_ps_mode = P2P_PS_NONE;
3543 if (padapter->pwrctrlpriv.bFwCurrentInPSMode == true)
3544 {
3545 if (pwrpriv->smart_ps == 0)
3546 {
3547 pwrpriv->smart_ps = 2;
3548 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)&padapter->pwrctrlpriv.pwr_mode);
3549 }
3550 }
3551 break;
3552 case P2P_PS_ENABLE:
3553 if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
3554 pwdinfo->p2p_ps_state = p2p_ps_state;
3555
3556 if (pwdinfo->ctwindow > 0)
3557 {
3558 if (pwrpriv->smart_ps != 0)
3559 {
3560 pwrpriv->smart_ps = 0;
3561 DBG_8723A("%s(): Enter CTW, change SmartPS\n", __func__);
3562 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)&padapter->pwrctrlpriv.pwr_mode);
3563 }
3564 }
3565 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
3566 }
3567 break;
3568 case P2P_PS_SCAN:
3569 case P2P_PS_SCAN_DONE:
3570 case P2P_PS_ALLSTASLEEP:
3571 if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
3572 pwdinfo->p2p_ps_state = p2p_ps_state;
3573 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
3574 }
3575 break;
3576 default:
3577 break;
3578 }
3579
3580
3581}
3582
3583u8 p2p_ps_wk_cmd23a(struct rtw_adapter*padapter, u8 p2p_ps_state, u8 enqueue)
3584{
3585 struct cmd_obj *ph2c;
3586 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3587 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3588 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3589 u8 res = _SUCCESS;
3590
3591
3592
3593 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3594 return res;
3595
3596 if (enqueue) {
3597 ph2c = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
3598 GFP_ATOMIC);
3599 if (!ph2c) {
3600 res = _FAIL;
3601 goto exit;
3602 }
3603
3604 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)
3605 kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
3606 if (pdrvextra_cmd_parm == NULL) {
3607 kfree(ph2c);
3608 res = _FAIL;
3609 goto exit;
3610 }
3611
3612 pdrvextra_cmd_parm->ec_id = P2P_PS_WK_CID;
3613 pdrvextra_cmd_parm->type_size = p2p_ps_state;
3614 pdrvextra_cmd_parm->pbuf = NULL;
3615
3616 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
3617
3618 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
3619 }
3620 else
3621 {
3622 p2p_ps_wk_hdl23a(padapter, p2p_ps_state);
3623 }
3624
3625exit:
3626
3627
3628
3629 return res;
3630}
3631#endif /* CONFIG_8723AU_P2P */
3632
3633static void reset_ch_sitesurvey_timer_process(unsigned long data)
3634{
3635 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
3636 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
3637
3638 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3639 return;
3640
3641 DBG_8723A("[%s] In\n", __func__);
3642 /* Reset the operation channel information */
3643 pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
3644 pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
3645}
3646
3647static void reset_ch_sitesurvey_timer_process2(unsigned long data)
3648{
3649 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
3650 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
3651
3652 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3653 return;
3654
3655 DBG_8723A("[%s] In\n", __func__);
3656 /* Reset the operation channel information */
3657 pwdinfo->p2p_info.operation_ch[0] = 0;
3658 pwdinfo->p2p_info.scan_op_ch_only = 0;
3659}
3660
3661static void restore_p2p_state_timer_process (unsigned long data)
3662{
3663 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
3664 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
3665
3666 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3667 return;
3668
3669 p2p_protocol_wk_cmd23a(adapter, P2P_RESTORE_STATE_WK);
3670}
3671
3672static void pre_tx_scan_timer_process (unsigned long data)
3673{
3674 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
3675 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
3676 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
3677
3678 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3679 return;
3680
3681 spin_lock_bh(&pmlmepriv->lock);
3682
3683 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
3684 {
3685 if (true == pwdinfo->tx_prov_disc_info.benable) /* the provision discovery request frame is trigger to send or not */
3686 {
3687 p2p_protocol_wk_cmd23a(adapter, P2P_PRE_TX_PROVDISC_PROCESS_WK);
3688 /* issue23a_probereq_p2p(adapter, NULL); */
3689 /* _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); */
3690 }
3691 }
3692 else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
3693 {
3694 if (true == pwdinfo->nego_req_info.benable)
3695 {
3696 p2p_protocol_wk_cmd23a(adapter, P2P_PRE_TX_NEGOREQ_PROCESS_WK);
3697 }
3698 }
3699 else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ))
3700 {
3701 if (true == pwdinfo->invitereq_info.benable)
3702 {
3703 p2p_protocol_wk_cmd23a(adapter, P2P_PRE_TX_INVITEREQ_PROCESS_WK);
3704 }
3705 }
3706 else
3707 {
3708 DBG_8723A("[%s] p2p_state is %d, ignore!!\n", __func__, rtw_p2p_state(pwdinfo));
3709 }
3710
3711 spin_unlock_bh(&pmlmepriv->lock);
3712}
3713
3714static void find_phase_timer_process (unsigned long data)
3715{
3716 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
3717 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
3718
3719 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3720 return;
3721
3722 adapter->wdinfo.find_phase_state_exchange_cnt++;
3723
3724 p2p_protocol_wk_cmd23a(adapter, P2P_FIND_PHASE_WK);
3725}
3726
3727void reset_global_wifidirect_info23a(struct rtw_adapter *padapter)
3728{
3729 struct wifidirect_info *pwdinfo;
3730
3731 pwdinfo = &padapter->wdinfo;
3732 pwdinfo->persistent_supported = 0;
3733 pwdinfo->session_available = true;
3734 pwdinfo->wfd_tdls_enable = 0;
3735 pwdinfo->wfd_tdls_weaksec = 0;
3736}
3737
3738#ifdef CONFIG_8723AU_P2P
3739int rtw_init_wifi_display_info(struct rtw_adapter* padapter)
3740{
3741 int res = _SUCCESS;
3742 struct wifi_display_info *pwfd_info = &padapter->wfd_info;
3743
3744 /* Used in P2P and TDLS */
3745 pwfd_info->rtsp_ctrlport = 554;
3746 pwfd_info->peer_rtsp_ctrlport = 0; /* Reset to 0 */
3747 pwfd_info->wfd_enable = false;
3748 pwfd_info->wfd_device_type = WFD_DEVINFO_PSINK;
3749 pwfd_info->scan_result_type = SCAN_RESULT_P2P_ONLY;
3750
3751 /* Used in P2P */
3752 pwfd_info->peer_session_avail = true;
3753 pwfd_info->wfd_pc = false;
3754
3755 /* Used in TDLS */
3756 memset(pwfd_info->ip_address, 0x00, 4);
3757 memset(pwfd_info->peer_ip_address, 0x00, 4);
3758 return res;
3759}
3760#endif /* CONFIG_8723AU_P2P */
3761
3762void rtw_init_wifidirect_timers23a(struct rtw_adapter* padapter)
3763{
3764 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3765
3766 setup_timer(&pwdinfo->find_phase_timer, find_phase_timer_process,
3767 (unsigned long)padapter);
3768 setup_timer(&pwdinfo->restore_p2p_state_timer,
3769 restore_p2p_state_timer_process, (unsigned long)padapter);
3770 setup_timer(&pwdinfo->pre_tx_scan_timer, pre_tx_scan_timer_process,
3771 (unsigned long)padapter);
3772 setup_timer(&pwdinfo->reset_ch_sitesurvey,
3773 reset_ch_sitesurvey_timer_process, (unsigned long)padapter);
3774 setup_timer(&pwdinfo->reset_ch_sitesurvey2,
3775 reset_ch_sitesurvey_timer_process2,
3776 (unsigned long)padapter);
3777}
3778
3779void rtw_init_wifidirect_addrs23a(struct rtw_adapter* padapter, u8 *dev_addr, u8 *iface_addr)
3780{
3781#ifdef CONFIG_8723AU_P2P
3782 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3783
3784 /*init device&interface address */
3785 if (dev_addr) {
3786 memcpy(pwdinfo->device_addr, dev_addr, ETH_ALEN);
3787 }
3788 if (iface_addr) {
3789 memcpy(pwdinfo->interface_addr, iface_addr, ETH_ALEN);
3790 }
3791#endif
3792}
3793
3794void init_wifidirect_info23a(struct rtw_adapter *padapter, enum P2P_ROLE role)
3795{
3796 struct wifidirect_info *pwdinfo;
3797#ifdef CONFIG_8723AU_P2P
3798 struct wifi_display_info *pwfd_info = &padapter->wfd_info;
3799#endif
3800
3801 pwdinfo = &padapter->wdinfo;
3802
3803 pwdinfo->padapter = padapter;
3804
3805 /* 1, 6, 11 are the social channel defined in the WiFi Direct specification. */
3806 pwdinfo->social_chan[0] = 1;
3807 pwdinfo->social_chan[1] = 6;
3808 pwdinfo->social_chan[2] = 11;
3809 pwdinfo->social_chan[3] = 0; /* channel 0 for scanning ending in site survey function. */
3810
3811 /* Use the channel 11 as the listen channel */
3812 pwdinfo->listen_channel = 11;
3813
3814 if (role == P2P_ROLE_DEVICE)
3815 {
3816 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3817 rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
3818 pwdinfo->intent = 1;
3819 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_LISTEN);
3820 }
3821 else if (role == P2P_ROLE_CLIENT)
3822 {
3823 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3824 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
3825 pwdinfo->intent = 1;
3826 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
3827 }
3828 else if (role == P2P_ROLE_GO)
3829 {
3830 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3831 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
3832 pwdinfo->intent = 15;
3833 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
3834 }
3835
3836/* Use the OFDM rate in the P2P probe response frame. (6(B), 9(B), 12, 18, 24, 36, 48, 54) */
3837 pwdinfo->support_rate[0] = 0x8c; /* 6(B) */
3838 pwdinfo->support_rate[1] = 0x92; /* 9(B) */
3839 pwdinfo->support_rate[2] = 0x18; /* 12 */
3840 pwdinfo->support_rate[3] = 0x24; /* 18 */
3841 pwdinfo->support_rate[4] = 0x30; /* 24 */
3842 pwdinfo->support_rate[5] = 0x48; /* 36 */
3843 pwdinfo->support_rate[6] = 0x60; /* 48 */
3844 pwdinfo->support_rate[7] = 0x6c; /* 54 */
3845
3846 memcpy((void*) pwdinfo->p2p_wildcard_ssid, "DIRECT-", 7);
3847
3848 memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
3849 pwdinfo->device_name_len = 0;
3850
3851 memset(&pwdinfo->invitereq_info, 0x00, sizeof(struct tx_invite_req_info));
3852 pwdinfo->invitereq_info.token = 3; /* Token used for P2P invitation request frame. */
3853
3854 memset(&pwdinfo->inviteresp_info, 0x00, sizeof(struct tx_invite_resp_info));
3855 pwdinfo->inviteresp_info.token = 0;
3856
3857 pwdinfo->profileindex = 0;
3858 memset(&pwdinfo->profileinfo[ 0 ], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
3859
3860 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
3861
3862 pwdinfo->listen_dwell = (u8) ((rtw_get_current_time() % 3) + 1);
3863 /* DBG_8723A("[%s] listen_dwell time is %d00ms\n", __func__, pwdinfo->listen_dwell); */
3864
3865 memset(&pwdinfo->tx_prov_disc_info, 0x00, sizeof(struct tx_provdisc_req_info));
3866 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_NONE;
3867
3868 memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
3869
3870 pwdinfo->device_password_id_for_nego = WPS_DPID_PBC;
3871 pwdinfo->negotiation_dialog_token = 1;
3872
3873 memset(pwdinfo->nego_ssid, 0x00, IEEE80211_MAX_SSID_LEN);
3874 pwdinfo->nego_ssidlen = 0;
3875
3876 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
3877#ifdef CONFIG_8723AU_P2P
3878 pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC;
3879 pwdinfo->wfd_info = pwfd_info;
3880#else
3881 pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC | WPS_CONFIG_METHOD_KEYPAD;
3882#endif /* CONFIG_8723AU_P2P */
3883 pwdinfo->channel_list_attr_len = 0;
3884 memset(pwdinfo->channel_list_attr, 0x00, 100);
3885
3886 memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, 0x00, 4);
3887 memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, '0', 3);
3888 memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
3889 pwdinfo->wfd_tdls_enable = 0;
3890 memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
3891 memset(pwdinfo->p2p_peer_device_addr, 0x00, ETH_ALEN);
3892
3893 pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
3894 pwdinfo->rx_invitereq_info.operation_ch[1] = 0; /* Used to indicate the scan end in site survey function */
3895 pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
3896 pwdinfo->p2p_info.operation_ch[0] = 0;
3897 pwdinfo->p2p_info.operation_ch[1] = 0; /* Used to indicate the scan end in site survey function */
3898 pwdinfo->p2p_info.scan_op_ch_only = 0;
3899}
3900
3901int rtw_p2p_enable23a(struct rtw_adapter *padapter, enum P2P_ROLE role)
3902{
3903 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3904 int ret = _SUCCESS;
3905
3906 if (role == P2P_ROLE_DEVICE || role == P2P_ROLE_CLIENT ||
3907 role == P2P_ROLE_GO) {
3908 /* leave IPS/Autosuspend */
3909 if (_FAIL == rtw_pwr_wakeup(padapter)) {
3910 ret = _FAIL;
3911 goto exit;
3912 }
3913
3914 /* Added by Albert 2011/03/22 */
3915 /* In the P2P mode, the driver should not support the b mode. */
3916 /* So, the Tx packet shouldn't use the CCK rate */
3917 update_tx_basic_rate23a(padapter, WIRELESS_11AGN);
3918
3919 /* Enable P2P function */
3920 init_wifidirect_info23a(padapter, role);
3921
3922 rtw_hal_set_odm_var23a(padapter, HAL_ODM_P2P_STATE, NULL, true);
3923 #ifdef CONFIG_8723AU_P2P
3924 rtw_hal_set_odm_var23a(padapter, HAL_ODM_WIFI_DISPLAY_STATE, NULL, true);
3925 #endif
3926
3927 }
3928 else if (role == P2P_ROLE_DISABLE)
3929 {
3930 if (_FAIL == rtw_pwr_wakeup(padapter)) {
3931 ret = _FAIL;
3932 goto exit;
3933 }
3934
3935 /* Disable P2P function */
3936 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3937 {
3938 del_timer_sync(&pwdinfo->find_phase_timer);
3939 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
3940 del_timer_sync(&pwdinfo->pre_tx_scan_timer);
3941 del_timer_sync(&pwdinfo->reset_ch_sitesurvey);
3942 del_timer_sync(&pwdinfo->reset_ch_sitesurvey2);
3943 reset_ch_sitesurvey_timer_process((unsigned long)padapter);
3944 reset_ch_sitesurvey_timer_process2((unsigned long)padapter);
3945 rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
3946 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DISABLE);
3947 memset(&pwdinfo->rx_prov_disc_info, 0x00, sizeof(struct rx_provdisc_req_info));
3948 }
3949
3950 rtw_hal_set_odm_var23a(padapter, HAL_ODM_P2P_STATE, NULL, false);
3951 #ifdef CONFIG_8723AU_P2P
3952 rtw_hal_set_odm_var23a(padapter, HAL_ODM_WIFI_DISPLAY_STATE, NULL, false);
3953 #endif
3954
3955 /* Restore to initial setting. */
3956 update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
3957 }
3958
3959exit:
3960 return ret;
3961}
3962
3963#endif /* CONFIG_8723AU_P2P */
diff --git a/drivers/staging/rtl8723au/core/rtw_pwrctrl.c b/drivers/staging/rtl8723au/core/rtw_pwrctrl.c
new file mode 100644
index 000000000000..354873ca344e
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_pwrctrl.c
@@ -0,0 +1,686 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _RTW_PWRCTRL_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <osdep_intf.h>
20
21#ifdef CONFIG_8723AU_BT_COEXIST
22#include <rtl8723a_hal.h>
23#endif
24
25void ips_enter23a(struct rtw_adapter * padapter)
26{
27 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
28
29 down(&pwrpriv->lock);
30
31 pwrpriv->bips_processing = true;
32
33 /* syn ips_mode with request */
34 pwrpriv->ips_mode = pwrpriv->ips_mode_req;
35
36 pwrpriv->ips_enter23a_cnts++;
37 DBG_8723A("==>ips_enter23a cnts:%d\n", pwrpriv->ips_enter23a_cnts);
38#ifdef CONFIG_8723AU_BT_COEXIST
39 BTDM_TurnOffBtCoexistBeforeEnterIPS(padapter);
40#endif
41 if (rf_off == pwrpriv->change_rfpwrstate)
42 {
43 pwrpriv->bpower_saving = true;
44 DBG_8723A_LEVEL(_drv_always_, "nolinked power save enter\n");
45
46 if (pwrpriv->ips_mode == IPS_LEVEL_2)
47 pwrpriv->bkeepfwalive = true;
48
49 rtw_ips_pwr_down23a(padapter);
50 pwrpriv->rf_pwrstate = rf_off;
51 }
52 pwrpriv->bips_processing = false;
53
54 up(&pwrpriv->lock);
55}
56
57int ips_leave23a(struct rtw_adapter * padapter)
58{
59 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
60 struct security_priv *psecuritypriv = &padapter->securitypriv;
61 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
62 int result = _SUCCESS;
63 int keyid;
64
65 down(&pwrpriv->lock);
66
67 if ((pwrpriv->rf_pwrstate == rf_off) &&!pwrpriv->bips_processing)
68 {
69 pwrpriv->bips_processing = true;
70 pwrpriv->change_rfpwrstate = rf_on;
71 pwrpriv->ips_leave23a_cnts++;
72 DBG_8723A("==>ips_leave23a cnts:%d\n", pwrpriv->ips_leave23a_cnts);
73
74 if ((result = rtw_ips_pwr_up23a(padapter)) == _SUCCESS) {
75 pwrpriv->rf_pwrstate = rf_on;
76 }
77 DBG_8723A_LEVEL(_drv_always_, "nolinked power save leave\n");
78
79 if ((_WEP40_ == psecuritypriv->dot11PrivacyAlgrthm) ||(_WEP104_ == psecuritypriv->dot11PrivacyAlgrthm))
80 {
81 DBG_8723A("==>%s, channel(%d), processing(%x)\n", __func__, padapter->mlmeextpriv.cur_channel, pwrpriv->bips_processing);
82 set_channel_bwmode23a(padapter, padapter->mlmeextpriv.cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
83 for (keyid = 0;keyid<4;keyid++) {
84 if (pmlmepriv->key_mask & CHKBIT(keyid)) {
85 if (keyid == psecuritypriv->dot11PrivacyKeyIndex)
86 result = rtw_set_key23a(padapter, psecuritypriv, keyid, 1);
87 else
88 result = rtw_set_key23a(padapter, psecuritypriv, keyid, 0);
89 }
90 }
91 }
92
93 DBG_8723A("==> ips_leave23a.....LED(0x%08x)...\n", rtw_read32(padapter, 0x4c));
94 pwrpriv->bips_processing = false;
95
96 pwrpriv->bkeepfwalive = false;
97 pwrpriv->bpower_saving = false;
98 }
99
100 up(&pwrpriv->lock);
101
102 return result;
103}
104
105
106static bool rtw_pwr_unassociated_idle(struct rtw_adapter *adapter)
107{
108 struct rtw_adapter *buddy = adapter->pbuddy_adapter;
109 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
110 struct xmit_priv *pxmit_priv = &adapter->xmitpriv;
111#ifdef CONFIG_8723AU_P2P
112 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
113#endif
114
115 bool ret = false;
116
117 if (adapter->pwrctrlpriv.ips_deny_time >= rtw_get_current_time())
118 goto exit;
119
120 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)
121 || check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
122 || check_fwstate(pmlmepriv, WIFI_AP_STATE)
123 || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
124 || !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)
125 ) {
126 goto exit;
127 }
128
129 /* consider buddy, if exist */
130 if (buddy) {
131 struct mlme_priv *b_pmlmepriv = &buddy->mlmepriv;
132#ifdef CONFIG_8723AU_P2P
133 struct wifidirect_info *b_pwdinfo = &buddy->wdinfo;
134#endif
135
136 if (check_fwstate(b_pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)
137 || check_fwstate(b_pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
138 || check_fwstate(b_pmlmepriv, WIFI_AP_STATE)
139 || check_fwstate(b_pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
140 || !rtw_p2p_chk_state(b_pwdinfo, P2P_STATE_NONE)
141 ) {
142 goto exit;
143 }
144 }
145
146 if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF ||
147 pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) {
148 DBG_8723A_LEVEL(_drv_always_, "There are some pkts to transmit\n");
149 DBG_8723A_LEVEL(_drv_info_, "free_xmitbuf_cnt: %d, free_xmit_extbuf_cnt: %d\n",
150 pxmit_priv->free_xmitbuf_cnt, pxmit_priv->free_xmit_extbuf_cnt);
151 goto exit;
152 }
153
154 ret = true;
155
156exit:
157 return ret;
158}
159
160void rtw_ps_processor23a(struct rtw_adapter*padapter)
161{
162 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
163 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
164 enum rt_rf_power_state rfpwrstate;
165
166 pwrpriv->ps_processing = true;
167
168 if (pwrpriv->bips_processing == true)
169 goto exit;
170
171 if (padapter->pwrctrlpriv.bHWPwrPindetect) {
172 rfpwrstate = RfOnOffDetect23a(padapter);
173 DBG_8723A("@@@@- #2 %s ==> rfstate:%s\n", __func__, (rfpwrstate == rf_on)?"rf_on":"rf_off");
174
175 if (rfpwrstate!= pwrpriv->rf_pwrstate) {
176 if (rfpwrstate == rf_off) {
177 pwrpriv->change_rfpwrstate = rf_off;
178 pwrpriv->brfoffbyhw = true;
179 padapter->bCardDisableWOHSM = true;
180 rtw_hw_suspend23a(padapter);
181 } else {
182 pwrpriv->change_rfpwrstate = rf_on;
183 rtw_hw_resume23a(padapter);
184 }
185 DBG_8723A("current rf_pwrstate(%s)\n", (pwrpriv->rf_pwrstate == rf_off)?"rf_off":"rf_on");
186 }
187 pwrpriv->pwr_state_check_cnts ++;
188 }
189
190 if (pwrpriv->ips_mode_req == IPS_NONE)
191 goto exit;
192
193 if (rtw_pwr_unassociated_idle(padapter) == false)
194 goto exit;
195
196 if ((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts%4) == 0))
197 {
198 DBG_8723A("==>%s .fw_state(%x)\n", __func__, get_fwstate(pmlmepriv));
199 pwrpriv->change_rfpwrstate = rf_off;
200 ips_enter23a(padapter);
201 }
202exit:
203 rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
204 pwrpriv->ps_processing = false;
205 return;
206}
207
208static void pwr_state_check_handler(unsigned long data)
209{
210 struct rtw_adapter *padapter = (struct rtw_adapter *)data;
211 rtw_ps_cmd23a(padapter);
212}
213
214/*
215 *
216 * Parameters
217 * padapter
218 * pslv power state level, only could be PS_STATE_S0 ~ PS_STATE_S4
219 *
220 */
221void rtw_set_rpwm23a(struct rtw_adapter *padapter, u8 pslv)
222{
223 u8 rpwm;
224 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
225
226
227
228 pslv = PS_STATE(pslv);
229
230 if (true == pwrpriv->btcoex_rfon)
231 {
232 if (pslv < PS_STATE_S4)
233 pslv = PS_STATE_S3;
234 }
235
236 if (pwrpriv->rpwm == pslv) {
237 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
238 ("%s: Already set rpwm[0x%02X], new = 0x%02X!\n", __func__, pwrpriv->rpwm, pslv));
239 return;
240 }
241
242 if ((padapter->bSurpriseRemoved == true) ||
243 (padapter->hw_init_completed == false)) {
244 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
245 ("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n",
246 __func__, padapter->bSurpriseRemoved, padapter->hw_init_completed));
247
248 pwrpriv->cpwm = PS_STATE_S4;
249
250 return;
251 }
252
253 if (padapter->bDriverStopped == true) {
254 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
255 ("%s: change power state(0x%02X) when DriverStopped\n", __func__, pslv));
256
257 if (pslv < PS_STATE_S2) {
258 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
259 ("%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n", __func__, pslv));
260 return;
261 }
262 }
263
264 rpwm = pslv | pwrpriv->tog;
265 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
266 ("rtw_set_rpwm23a: rpwm = 0x%02x cpwm = 0x%02x\n", rpwm, pwrpriv->cpwm));
267
268 pwrpriv->rpwm = pslv;
269
270 rtw_hal_set_hwreg23a(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm));
271
272 pwrpriv->tog += 0x80;
273 pwrpriv->cpwm = pslv;
274
275
276}
277
278u8 PS_RDY_CHECK(struct rtw_adapter * padapter)
279{
280 unsigned long delta_time;
281 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
282 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
283
284 delta_time = jiffies - pwrpriv->DelayLPSLastTimeStamp;
285
286 if (delta_time < LPS_DELAY_TIME)
287 {
288 return false;
289 }
290
291 if ((check_fwstate(pmlmepriv, _FW_LINKED) == false) ||
292 (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) ||
293 (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) ||
294 (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
295 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true))
296 return false;
297 if (true == pwrpriv->bInSuspend)
298 return false;
299 if ((padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && (padapter->securitypriv.binstallGrpkey == false))
300 {
301 DBG_8723A("Group handshake still in progress !!!\n");
302 return false;
303 }
304 if (!rtw_cfg80211_pwr_mgmt(padapter))
305 return false;
306
307 return true;
308}
309
310void rtw_set_ps_mode23a(struct rtw_adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode)
311{
312 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
313#ifdef CONFIG_8723AU_P2P
314 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
315#endif /* CONFIG_8723AU_P2P */
316
317
318
319 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
320 ("%s: PowerMode =%d Smart_PS =%d\n",
321 __func__, ps_mode, smart_ps));
322
323 if (ps_mode > PM_Card_Disable) {
324 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("ps_mode:%d error\n", ps_mode));
325 return;
326 }
327
328 if (pwrpriv->pwr_mode == ps_mode)
329 {
330 if (PS_MODE_ACTIVE == ps_mode) return;
331
332 if ((pwrpriv->smart_ps == smart_ps) &&
333 (pwrpriv->bcn_ant_mode == bcn_ant_mode))
334 {
335 return;
336 }
337 }
338
339 if (ps_mode == PS_MODE_ACTIVE) {
340#ifdef CONFIG_8723AU_P2P
341 if (pwdinfo->opp_ps == 0)
342#endif /* CONFIG_8723AU_P2P */
343 {
344 DBG_8723A("rtw_set_ps_mode23a: Leave 802.11 power save\n");
345
346 pwrpriv->pwr_mode = ps_mode;
347 rtw_set_rpwm23a(padapter, PS_STATE_S4);
348 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
349 pwrpriv->bFwCurrentInPSMode = false;
350 }
351 }
352 else
353 {
354 if (PS_RDY_CHECK(padapter)
355#ifdef CONFIG_8723AU_BT_COEXIST
356 || (BT_1Ant(padapter) == true)
357#endif
358 )
359 {
360 DBG_8723A("%s: Enter 802.11 power save\n", __func__);
361
362 pwrpriv->bFwCurrentInPSMode = true;
363 pwrpriv->pwr_mode = ps_mode;
364 pwrpriv->smart_ps = smart_ps;
365 pwrpriv->bcn_ant_mode = bcn_ant_mode;
366 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
367
368#ifdef CONFIG_8723AU_P2P
369 /* Set CTWindow after LPS */
370 if (pwdinfo->opp_ps == 1)
371 p2p_ps_wk_cmd23a(padapter, P2P_PS_ENABLE, 0);
372#endif /* CONFIG_8723AU_P2P */
373
374 rtw_set_rpwm23a(padapter, PS_STATE_S2);
375 }
376 }
377
378
379}
380
381/*
382 * Return:
383 * 0: Leave OK
384 * -1: Timeout
385 * -2: Other error
386 */
387s32 LPS_RF_ON_check23a(struct rtw_adapter *padapter, u32 delay_ms)
388{
389 u32 start_time;
390 u8 bAwake = false;
391 s32 err = 0;
392
393 start_time = rtw_get_current_time();
394 while (1)
395 {
396 rtw23a_hal_get_hwreg(padapter, HW_VAR_FWLPS_RF_ON, &bAwake);
397 if (true == bAwake)
398 break;
399
400 if (true == padapter->bSurpriseRemoved)
401 {
402 err = -2;
403 DBG_8723A("%s: device surprise removed!!\n", __func__);
404 break;
405 }
406
407 if (rtw_get_passing_time_ms23a(start_time) > delay_ms)
408 {
409 err = -1;
410 DBG_8723A("%s: Wait for FW LPS leave more than %u ms!!!\n", __func__, delay_ms);
411 break;
412 }
413 udelay(100);
414 }
415
416 return err;
417}
418
419/* Description: */
420/* Enter the leisure power save mode. */
421void LPS_Enter23a(struct rtw_adapter *padapter)
422{
423 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
424
425 if (!PS_RDY_CHECK(padapter))
426 return;
427
428 if (pwrpriv->bLeisurePs) {
429 /* Idle for a while if we connect to AP a while ago. */
430 if (pwrpriv->LpsIdleCount >= 2) { /* 4 Sec */
431 if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) {
432 pwrpriv->bpower_saving = true;
433 DBG_8723A("%s smart_ps:%d\n", __func__, pwrpriv->smart_ps);
434 /* For Tenda W311R IOT issue */
435 rtw_set_ps_mode23a(padapter, pwrpriv->power_mgnt, pwrpriv->smart_ps, 0);
436 }
437 } else {
438 pwrpriv->LpsIdleCount++;
439 }
440 }
441}
442
443/* Description: */
444/* Leave the leisure power save mode. */
445void LPS_Leave23a(struct rtw_adapter *padapter)
446{
447#define LPS_LEAVE_TIMEOUT_MS 100
448
449 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
450
451 if (pwrpriv->bLeisurePs) {
452 if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
453 rtw_set_ps_mode23a(padapter, PS_MODE_ACTIVE, 0, 0);
454
455 if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
456 LPS_RF_ON_check23a(padapter, LPS_LEAVE_TIMEOUT_MS);
457 }
458 }
459
460 pwrpriv->bpower_saving = false;
461}
462
463/* Description: Leave all power save mode: LPS, FwLPS, IPS if needed. */
464/* Move code to function by tynli. 2010.03.26. */
465void LeaveAllPowerSaveMode23a(struct rtw_adapter *Adapter)
466{
467 struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
468 u8 enqueue = 0;
469
470
471
472 /* DBG_8723A("%s.....\n", __func__); */
473 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
474 { /* connect */
475#ifdef CONFIG_8723AU_P2P
476 p2p_ps_wk_cmd23a(Adapter, P2P_PS_DISABLE, enqueue);
477#endif /* CONFIG_8723AU_P2P */
478
479 rtw_lps_ctrl_wk_cmd23a(Adapter, LPS_CTRL_LEAVE, enqueue);
480 }
481
482
483}
484
485void rtw_init_pwrctrl_priv23a(struct rtw_adapter *padapter)
486{
487 struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
488
489 sema_init(&pwrctrlpriv->lock, 1);
490 pwrctrlpriv->rf_pwrstate = rf_on;
491 pwrctrlpriv->ips_enter23a_cnts = 0;
492 pwrctrlpriv->ips_leave23a_cnts = 0;
493 pwrctrlpriv->bips_processing = false;
494
495 pwrctrlpriv->ips_mode = padapter->registrypriv.ips_mode;
496 pwrctrlpriv->ips_mode_req = padapter->registrypriv.ips_mode;
497
498 pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL;
499 pwrctrlpriv->pwr_state_check_cnts = 0;
500 pwrctrlpriv->bInternalAutoSuspend = false;
501 pwrctrlpriv->bInSuspend = false;
502 pwrctrlpriv->bkeepfwalive = false;
503
504 pwrctrlpriv->LpsIdleCount = 0;
505 pwrctrlpriv->power_mgnt = padapter->registrypriv.power_mgnt;/* PS_MODE_MIN; */
506 pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt)?true:false;
507
508 pwrctrlpriv->bFwCurrentInPSMode = false;
509
510 pwrctrlpriv->rpwm = 0;
511 pwrctrlpriv->cpwm = PS_STATE_S4;
512
513 pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE;
514 pwrctrlpriv->smart_ps = padapter->registrypriv.smart_ps;
515 pwrctrlpriv->bcn_ant_mode = 0;
516
517 pwrctrlpriv->tog = 0x80;
518
519 pwrctrlpriv->btcoex_rfon = false;
520
521 setup_timer(&pwrctrlpriv->pwr_state_check_timer,
522 pwr_state_check_handler, (unsigned long)padapter);
523
524
525}
526
527void rtw_free_pwrctrl_priv(struct rtw_adapter *adapter)
528{
529}
530
531u8 rtw_interface_ps_func23a(struct rtw_adapter *padapter, enum hal_intf_ps_func efunc_id, u8* val)
532{
533 u8 bResult = true;
534 rtw_hal_intf_ps_func23a(padapter, efunc_id, val);
535
536 return bResult;
537}
538
539inline void rtw_set_ips_deny23a(struct rtw_adapter *padapter, u32 ms)
540{
541 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
542 pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime23a(ms);
543}
544
545/*
546* rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
547* @adapter: pointer to _adapter structure
548* @ips_deffer_ms: the ms wiil prevent from falling into IPS after wakeup
549* Return _SUCCESS or _FAIL
550*/
551
552int _rtw_pwr_wakeup23a(struct rtw_adapter *padapter, u32 ips_deffer_ms, const char *caller)
553{
554 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
555 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
556 int ret = _SUCCESS;
557 u32 start = rtw_get_current_time();
558
559 if (pwrpriv->ips_deny_time < rtw_get_current_time() + rtw_ms_to_systime23a(ips_deffer_ms))
560 pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime23a(ips_deffer_ms);
561
562 if (pwrpriv->ps_processing) {
563 DBG_8723A("%s wait ps_processing...\n", __func__);
564 while (pwrpriv->ps_processing && rtw_get_passing_time_ms23a(start) <= 3000)
565 msleep(10);
566 if (pwrpriv->ps_processing)
567 DBG_8723A("%s wait ps_processing timeout\n", __func__);
568 else
569 DBG_8723A("%s wait ps_processing done\n", __func__);
570 }
571
572 if (rtw_hal_sreset_inprogress(padapter)) {
573 DBG_8723A("%s wait sreset_inprogress...\n", __func__);
574 while (rtw_hal_sreset_inprogress(padapter) && rtw_get_passing_time_ms23a(start) <= 4000)
575 msleep(10);
576 if (rtw_hal_sreset_inprogress(padapter))
577 DBG_8723A("%s wait sreset_inprogress timeout\n", __func__);
578 else
579 DBG_8723A("%s wait sreset_inprogress done\n", __func__);
580 }
581
582 if (pwrpriv->bInternalAutoSuspend == false && pwrpriv->bInSuspend) {
583 DBG_8723A("%s wait bInSuspend...\n", __func__);
584 while (pwrpriv->bInSuspend &&
585 (rtw_get_passing_time_ms23a(start) <= 3000)) {
586 msleep(10);
587 }
588 if (pwrpriv->bInSuspend)
589 DBG_8723A("%s wait bInSuspend timeout\n", __func__);
590 else
591 DBG_8723A("%s wait bInSuspend done\n", __func__);
592 }
593
594 /* System suspend is not allowed to wakeup */
595 if ((pwrpriv->bInternalAutoSuspend == false) && (true == pwrpriv->bInSuspend)) {
596 ret = _FAIL;
597 goto exit;
598 }
599
600 /* block??? */
601 if ((pwrpriv->bInternalAutoSuspend == true) && (padapter->net_closed == true)) {
602 ret = _FAIL;
603 goto exit;
604 }
605
606 /* I think this should be check in IPS, LPS, autosuspend functions... */
607 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
608 {
609 ret = _SUCCESS;
610 goto exit;
611 }
612
613 if (rf_off == pwrpriv->rf_pwrstate) {
614 DBG_8723A("%s call ips_leave23a....\n", __func__);
615 if (_FAIL == ips_leave23a(padapter)) {
616 DBG_8723A("======> ips_leave23a fail.............\n");
617 ret = _FAIL;
618 goto exit;
619 }
620 }
621
622 /* TODO: the following checking need to be merged... */
623 if (padapter->bDriverStopped || !padapter->bup ||
624 !padapter->hw_init_completed) {
625 DBG_8723A("%s: bDriverStopped =%d, bup =%d, hw_init_completed "
626 "=%u\n", caller, padapter->bDriverStopped,
627 padapter->bup, padapter->hw_init_completed);
628 ret = false;
629 goto exit;
630 }
631
632exit:
633 if (pwrpriv->ips_deny_time < rtw_get_current_time() + rtw_ms_to_systime23a(ips_deffer_ms))
634 pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime23a(ips_deffer_ms);
635 return ret;
636}
637
638int rtw_pm_set_lps23a(struct rtw_adapter *padapter, u8 mode)
639{
640 int ret = 0;
641 struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
642
643 if (mode < PS_MODE_NUM)
644 {
645 if (pwrctrlpriv->power_mgnt != mode)
646 {
647 if (PS_MODE_ACTIVE == mode)
648 {
649 LeaveAllPowerSaveMode23a(padapter);
650 }
651 else
652 {
653 pwrctrlpriv->LpsIdleCount = 2;
654 }
655 pwrctrlpriv->power_mgnt = mode;
656 pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt)?true:false;
657 }
658 }
659 else
660 {
661 ret = -EINVAL;
662 }
663
664 return ret;
665}
666
667int rtw_pm_set_ips23a(struct rtw_adapter *padapter, u8 mode)
668{
669 struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
670
671 if (mode == IPS_NORMAL || mode == IPS_LEVEL_2) {
672 rtw_ips_mode_req(pwrctrlpriv, mode);
673 DBG_8723A("%s %s\n", __func__, mode == IPS_NORMAL?"IPS_NORMAL":"IPS_LEVEL_2");
674 return 0;
675 }
676 else if (mode == IPS_NONE) {
677 rtw_ips_mode_req(pwrctrlpriv, mode);
678 DBG_8723A("%s %s\n", __func__, "IPS_NONE");
679 if ((padapter->bSurpriseRemoved == 0)&&_FAIL == rtw_pwr_wakeup(padapter))
680 return -EFAULT;
681 }
682 else {
683 return -EINVAL;
684 }
685 return 0;
686}
diff --git a/drivers/staging/rtl8723au/core/rtw_recv.c b/drivers/staging/rtl8723au/core/rtw_recv.c
new file mode 100644
index 000000000000..0b2455e4f5b6
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_recv.c
@@ -0,0 +1,2471 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _RTW_RECV_C_
16#include <osdep_service.h>
17#include <drv_types.h>
18#include <recv_osdep.h>
19#include <mlme_osdep.h>
20#include <linux/ip.h>
21#include <linux/if_ether.h>
22#include <ethernet.h>
23#include <usb_ops.h>
24#include <linux/ieee80211.h>
25#include <wifi.h>
26
27void rtw_signal_stat_timer_hdl23a(unsigned long data);
28
29void _rtw_init_sta_recv_priv23a(struct sta_recv_priv *psta_recvpriv)
30{
31
32
33
34 spin_lock_init(&psta_recvpriv->lock);
35
36 /* for (i = 0; i<MAX_RX_NUMBLKS; i++) */
37 /* _rtw_init_queue23a(&psta_recvpriv->blk_strms[i]); */
38
39 _rtw_init_queue23a(&psta_recvpriv->defrag_q);
40
41
42}
43
44int _rtw_init_recv_priv23a(struct recv_priv *precvpriv,
45 struct rtw_adapter *padapter)
46{
47 struct recv_frame *precvframe;
48 int i;
49 int res = _SUCCESS;
50
51
52
53 /* We don't need to memset padapter->XXX to zero, because
54 adapter is allocated by rtw_zvmalloc(). */
55 /* memset((unsigned char *)precvpriv, 0, sizeof (struct recv_priv)); */
56
57 spin_lock_init(&precvpriv->lock);
58
59 _rtw_init_queue23a(&precvpriv->free_recv_queue);
60 _rtw_init_queue23a(&precvpriv->recv_pending_queue);
61 _rtw_init_queue23a(&precvpriv->uc_swdec_pending_queue);
62
63 precvpriv->adapter = padapter;
64
65 precvpriv->free_recvframe_cnt = NR_RECVFRAME;
66
67 precvpriv->pallocated_frame_buf =
68 rtw_zvmalloc(NR_RECVFRAME * sizeof(struct recv_frame));
69
70 if (precvpriv->pallocated_frame_buf == NULL) {
71 res = _FAIL;
72 goto exit;
73 }
74
75 precvframe = precvpriv->pallocated_frame_buf;
76
77 for (i = 0; i < NR_RECVFRAME ; i++) {
78 INIT_LIST_HEAD(&precvframe->list);
79
80 list_add_tail(&precvframe->list,
81 &precvpriv->free_recv_queue.queue);
82
83 res = rtw_os_recv_resource_alloc23a(padapter, precvframe);
84
85 precvframe->adapter = padapter;
86 precvframe++;
87 }
88
89 precvpriv->rx_pending_cnt = 1;
90
91 sema_init(&precvpriv->allrxreturnevt, 0);
92
93 res = rtw_hal_init23a_recv_priv(padapter);
94
95 setup_timer(&precvpriv->signal_stat_timer, rtw_signal_stat_timer_hdl23a,
96 (unsigned long)padapter);
97
98 precvpriv->signal_stat_sampling_interval = 1000; /* ms */
99
100 rtw_set_signal_stat_timer(precvpriv);
101
102exit:
103
104
105
106 return res;
107}
108
109void _rtw_free_recv_priv23a (struct recv_priv *precvpriv)
110{
111 struct rtw_adapter *padapter = precvpriv->adapter;
112
113
114
115 rtw_free_uc_swdec_pending_queue23a(padapter);
116
117 if (precvpriv->pallocated_frame_buf) {
118 rtw_vmfree(precvpriv->pallocated_frame_buf,
119 NR_RECVFRAME * sizeof(struct recv_frame));
120 }
121
122 rtw_hal_free_recv_priv23a(padapter);
123
124
125}
126
127struct recv_frame *rtw_alloc_recvframe23a(struct rtw_queue *pfree_recv_queue)
128{
129 struct recv_frame *pframe;
130 struct list_head *plist, *phead;
131 struct rtw_adapter *padapter;
132 struct recv_priv *precvpriv;
133
134 spin_lock_bh(&pfree_recv_queue->lock);
135
136 if (_rtw_queue_empty23a(pfree_recv_queue) == true)
137 pframe = NULL;
138 else {
139 phead = get_list_head(pfree_recv_queue);
140
141 plist = phead->next;
142
143 pframe = container_of(plist, struct recv_frame, list);
144
145 list_del_init(&pframe->list);
146 padapter = pframe->adapter;
147 if (padapter) {
148 precvpriv = &padapter->recvpriv;
149 if (pfree_recv_queue == &precvpriv->free_recv_queue)
150 precvpriv->free_recvframe_cnt--;
151 }
152 }
153
154 spin_unlock_bh(&pfree_recv_queue->lock);
155
156 return pframe;
157}
158
159int rtw_free_recvframe23a(struct recv_frame *precvframe, struct rtw_queue *pfree_recv_queue)
160{
161 struct rtw_adapter *padapter = precvframe->adapter;
162 struct recv_priv *precvpriv = &padapter->recvpriv;
163
164
165
166 if (precvframe->pkt) {
167 dev_kfree_skb_any(precvframe->pkt);/* free skb by driver */
168 precvframe->pkt = NULL;
169 }
170
171 spin_lock_bh(&pfree_recv_queue->lock);
172
173 list_del_init(&precvframe->list);
174
175 list_add_tail(&precvframe->list, get_list_head(pfree_recv_queue));
176
177 if (padapter) {
178 if (pfree_recv_queue == &precvpriv->free_recv_queue)
179 precvpriv->free_recvframe_cnt++;
180 }
181
182 spin_unlock_bh(&pfree_recv_queue->lock);
183
184
185
186 return _SUCCESS;
187}
188
189int rtw_enqueue_recvframe23a(struct recv_frame *precvframe, struct rtw_queue *queue)
190{
191 struct rtw_adapter *padapter = precvframe->adapter;
192 struct recv_priv *precvpriv = &padapter->recvpriv;
193
194 spin_lock_bh(&queue->lock);
195
196 list_del_init(&precvframe->list);
197
198 list_add_tail(&precvframe->list, get_list_head(queue));
199
200 if (padapter) {
201 if (queue == &precvpriv->free_recv_queue)
202 precvpriv->free_recvframe_cnt++;
203 }
204
205 spin_unlock_bh(&queue->lock);
206
207 return _SUCCESS;
208}
209
210/*
211caller : defrag ; recvframe_chk_defrag23a in recv_thread (passive)
212pframequeue: defrag_queue : will be accessed in recv_thread (passive)
213
214using spinlock to protect
215
216*/
217
218void rtw_free_recvframe23a_queue(struct rtw_queue *pframequeue, struct rtw_queue *pfree_recv_queue)
219{
220 struct recv_frame *hdr;
221 struct list_head *plist, *phead, *ptmp;
222
223
224 spin_lock(&pframequeue->lock);
225
226 phead = get_list_head(pframequeue);
227 plist = phead->next;
228
229 list_for_each_safe(plist, ptmp, phead) {
230 hdr = container_of(plist, struct recv_frame, list);
231 rtw_free_recvframe23a(hdr, pfree_recv_queue);
232 }
233
234 spin_unlock(&pframequeue->lock);
235
236
237}
238
239u32 rtw_free_uc_swdec_pending_queue23a(struct rtw_adapter *adapter)
240{
241 u32 cnt = 0;
242 struct recv_frame *pending_frame;
243 while ((pending_frame = rtw_alloc_recvframe23a(&adapter->recvpriv.uc_swdec_pending_queue))) {
244 rtw_free_recvframe23a(pending_frame,
245 &adapter->recvpriv.free_recv_queue);
246 DBG_8723A("%s: dequeue uc_swdec_pending_queue\n", __func__);
247 cnt++;
248 }
249
250 return cnt;
251}
252
253int rtw_enqueue_recvbuf23a_to_head(struct recv_buf *precvbuf, struct rtw_queue *queue)
254{
255 spin_lock_bh(&queue->lock);
256
257 list_del_init(&precvbuf->list);
258 list_add(&precvbuf->list, get_list_head(queue));
259
260 spin_unlock_bh(&queue->lock);
261
262 return _SUCCESS;
263}
264
265int rtw_enqueue_recvbuf23a(struct recv_buf *precvbuf, struct rtw_queue *queue)
266{
267 unsigned long irqL;
268 spin_lock_irqsave(&queue->lock, irqL);
269
270 list_del_init(&precvbuf->list);
271
272 list_add_tail(&precvbuf->list, get_list_head(queue));
273 spin_unlock_irqrestore(&queue->lock, irqL);
274 return _SUCCESS;
275}
276
277struct recv_buf *rtw_dequeue_recvbuf23a (struct rtw_queue *queue)
278{
279 unsigned long irqL;
280 struct recv_buf *precvbuf;
281 struct list_head *plist, *phead;
282
283 spin_lock_irqsave(&queue->lock, irqL);
284
285 if (_rtw_queue_empty23a(queue) == true) {
286 precvbuf = NULL;
287 } else {
288 phead = get_list_head(queue);
289
290 plist = phead->next;
291
292 precvbuf = container_of(plist, struct recv_buf, list);
293
294 list_del_init(&precvbuf->list);
295 }
296
297 spin_unlock_irqrestore(&queue->lock, irqL);
298
299 return precvbuf;
300}
301
302int recvframe_chkmic(struct rtw_adapter *adapter,
303 struct recv_frame *precvframe);
304int recvframe_chkmic(struct rtw_adapter *adapter,
305 struct recv_frame *precvframe) {
306
307 int i, res = _SUCCESS;
308 u32 datalen;
309 u8 miccode[8];
310 u8 bmic_err = false, brpt_micerror = true;
311 u8 *pframe, *payload,*pframemic;
312 u8 *mickey;
313 /* u8 *iv, rxdata_key_idx = 0; */
314 struct sta_info *stainfo;
315 struct rx_pkt_attrib *prxattrib = &precvframe->attrib;
316 struct security_priv *psecuritypriv = &adapter->securitypriv;
317
318 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
319 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
320
321
322 stainfo = rtw_get_stainfo23a(&adapter->stapriv, &prxattrib->ta[0]);
323
324 if (prxattrib->encrypt == _TKIP_) {
325 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
326 ("\n recvframe_chkmic:prxattrib->encrypt == _TKIP_\n"));
327 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
328 ("\n recvframe_chkmic:da = 0x%02x:0x%02x:0x%02x:0x%02x:"
329 "0x%02x:0x%02x\n", prxattrib->ra[0],
330 prxattrib->ra[1], prxattrib->ra[2], prxattrib->ra[3],
331 prxattrib->ra[4], prxattrib->ra[5]));
332
333 /* calculate mic code */
334 if (stainfo != NULL) {
335 if (is_multicast_ether_addr(prxattrib->ra)) {
336 mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0];
337
338 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
339 ("\n recvframe_chkmic: bcmc key\n"));
340
341 if (psecuritypriv->binstallGrpkey == false) {
342 res = _FAIL;
343 RT_TRACE(_module_rtl871x_recv_c_,
344 _drv_err_,
345 ("\n recvframe_chkmic:didn't "
346 "install group key!!!!!!\n"));
347 DBG_8723A("\n recvframe_chkmic:didn't "
348 "install group key!!!!!!\n");
349 goto exit;
350 }
351 } else {
352 mickey = &stainfo->dot11tkiprxmickey.skey[0];
353 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
354 ("\n recvframe_chkmic: unicast "
355 "key\n"));
356 }
357
358 /* icv_len included the mic code */
359 datalen = precvframe->pkt->len-prxattrib->
360 hdrlen-prxattrib->iv_len-prxattrib->icv_len - 8;
361 pframe = precvframe->pkt->data;
362 payload = pframe + prxattrib->hdrlen +
363 prxattrib->iv_len;
364
365 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
366 ("\n prxattrib->iv_len =%d prxattrib->icv_len ="
367 "%d\n", prxattrib->iv_len,
368 prxattrib->icv_len));
369
370 /* care the length of the data */
371 rtw_seccalctkipmic23a(mickey, pframe, payload,
372 datalen, &miccode[0],
373 (unsigned char)prxattrib->priority);
374
375 pframemic = payload + datalen;
376
377 bmic_err = false;
378
379 for (i = 0; i < 8; i++) {
380 if (miccode[i] != *(pframemic + i)) {
381 RT_TRACE(_module_rtl871x_recv_c_,
382 _drv_err_,
383 ("recvframe_chkmic:miccode"
384 "[%d](%02x) != *(pframemic+"
385 "%d)(%02x) ", i, miccode[i],
386 i, *(pframemic + i)));
387 bmic_err = true;
388 }
389 }
390
391 if (bmic_err == true) {
392 int i;
393 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
394 ("\n *(pframemic-8)-*(pframemic-1) ="
395 "0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:"
396 "0x%02x:0x%02x:0x%02x\n",
397 *(pframemic - 8), *(pframemic - 7),
398 *(pframemic - 6), *(pframemic - 5),
399 *(pframemic - 4), *(pframemic - 3),
400 *(pframemic - 2), *(pframemic - 1)));
401 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
402 ("\n *(pframemic-16)-*(pframemic-9) ="
403 "0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:"
404 "0x%02x:0x%02x:0x%02x\n",
405 *(pframemic - 16), *(pframemic - 15),
406 *(pframemic - 14), *(pframemic - 13),
407 *(pframemic - 12), *(pframemic - 11),
408 *(pframemic - 10), *(pframemic - 9)));
409
410 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
411 ("\n ====== demp packet (len =%d) ======"
412 "\n", precvframe->pkt->len));
413 for (i = 0; i < precvframe->pkt->len; i = i + 8) {
414 RT_TRACE(_module_rtl871x_recv_c_,
415 _drv_err_, ("0x%02x:0x%02x:0x"
416 "%02x:0x%02x:0x%0"
417 "2x:0x%02x:0x%02x"
418 ":0x%02x",
419 *(precvframe->pkt->data+i),*(precvframe->pkt->data+i+1),
420 *(precvframe->pkt->data+i+2),*(precvframe->pkt->data+i+3),
421 *(precvframe->pkt->data+i+4),*(precvframe->pkt->data+i+5),
422 *(precvframe->pkt->data+i+6),*(precvframe->pkt->data+i+7)));
423 }
424 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
425 ("\n ====== demp packet end [len =%d]"
426 "======\n", precvframe->pkt->len));
427 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
428 ("\n hrdlen =%d,\n",
429 prxattrib->hdrlen));
430
431 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
432 ("ra = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%."
433 "2x 0x%.2x psecuritypriv->"
434 "binstallGrpkey =%d ",
435 prxattrib->ra[0], prxattrib->ra[1],
436 prxattrib->ra[2], prxattrib->ra[3],
437 prxattrib->ra[4], prxattrib->ra[5],
438 psecuritypriv->binstallGrpkey));
439
440 /* double check key_index for some timing
441 issue, cannot compare with
442 psecuritypriv->dot118021XGrpKeyid also
443 cause timing issue */
444 if ((is_multicast_ether_addr(prxattrib->ra)) &&
445 (prxattrib->key_index !=
446 pmlmeinfo->key_index))
447 brpt_micerror = false;
448
449 if ((prxattrib->bdecrypted == true) &&
450 (brpt_micerror == true)) {
451 rtw_handle_tkip_mic_err23a(adapter, (u8)is_multicast_ether_addr(prxattrib->ra));
452 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" mic error :prxattrib->bdecrypted =%d ", prxattrib->bdecrypted));
453 DBG_8723A(" mic error :prxattrib->"
454 "bdecrypted =%d\n",
455 prxattrib->bdecrypted);
456 } else {
457 RT_TRACE(_module_rtl871x_recv_c_,
458 _drv_err_,
459 (" mic error :prxattrib->"
460 "bdecrypted =%d ",
461 prxattrib->bdecrypted));
462 DBG_8723A(" mic error :prxattrib->"
463 "bdecrypted =%d\n",
464 prxattrib->bdecrypted);
465 }
466
467 res = _FAIL;
468 } else {
469 /* mic checked ok */
470 if ((psecuritypriv->bcheck_grpkey == false) &&
471 (is_multicast_ether_addr(prxattrib->ra))) {
472 psecuritypriv->bcheck_grpkey = true;
473 RT_TRACE(_module_rtl871x_recv_c_,
474 _drv_err_,
475 ("psecuritypriv->bcheck_grp"
476 "key = true"));
477 }
478 }
479 } else {
480 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
481 ("recvframe_chkmic: rtw_get_stainfo23a =="
482 "NULL!!!\n"));
483 }
484
485 skb_trim(precvframe->pkt, precvframe->pkt->len - 8);
486 }
487
488exit:
489
490
491
492 return res;
493}
494
495/* decrypt and set the ivlen, icvlen of the recv_frame */
496struct recv_frame *decryptor(struct rtw_adapter *padapter,
497 struct recv_frame *precv_frame);
498struct recv_frame *decryptor(struct rtw_adapter *padapter,
499 struct recv_frame *precv_frame)
500{
501 struct rx_pkt_attrib *prxattrib = &precv_frame->attrib;
502 struct security_priv *psecuritypriv = &padapter->securitypriv;
503 struct recv_frame *return_packet = precv_frame;
504 u32 res = _SUCCESS;
505
506
507 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
508 ("prxstat->decrypted =%x prxattrib->encrypt = 0x%03x\n",
509 prxattrib->bdecrypted, prxattrib->encrypt));
510
511 if (prxattrib->encrypt > 0) {
512 u8 *iv = precv_frame->pkt->data + prxattrib->hdrlen;
513 prxattrib->key_index = (((iv[3]) >> 6) & 0x3);
514
515 if (prxattrib->key_index > WEP_KEYS) {
516 DBG_8723A("prxattrib->key_index(%d) > WEP_KEYS\n",
517 prxattrib->key_index);
518
519 switch (prxattrib->encrypt) {
520 case _WEP40_:
521 case _WEP104_:
522 prxattrib->key_index =
523 psecuritypriv->dot11PrivacyKeyIndex;
524 break;
525 case _TKIP_:
526 case _AES_:
527 default:
528 prxattrib->key_index =
529 psecuritypriv->dot118021XGrpKeyid;
530 break;
531 }
532 }
533 }
534
535 if ((prxattrib->encrypt > 0) && ((prxattrib->bdecrypted == 0))) {
536 psecuritypriv->hw_decrypted = false;
537 switch (prxattrib->encrypt) {
538 case _WEP40_:
539 case _WEP104_:
540 rtw_wep_decrypt23a(padapter, precv_frame);
541 break;
542 case _TKIP_:
543 res = rtw_tkip_decrypt23a(padapter, precv_frame);
544 break;
545 case _AES_:
546 res = rtw_aes_decrypt23a(padapter, precv_frame);
547 break;
548 default:
549 break;
550 }
551 } else if (prxattrib->bdecrypted == 1 && prxattrib->encrypt > 0 &&
552 (psecuritypriv->busetkipkey == 1 ||
553 prxattrib->encrypt != _TKIP_)) {
554 psecuritypriv->hw_decrypted = true;
555 }
556
557 if (res == _FAIL) {
558 rtw_free_recvframe23a(return_packet,
559 &padapter->recvpriv.free_recv_queue);
560 return_packet = NULL;
561 }
562
563
564
565 return return_packet;
566}
567
568/* set the security information in the recv_frame */
569static struct recv_frame *portctrl(struct rtw_adapter *adapter,
570 struct recv_frame *precv_frame)
571{
572 u8 *psta_addr = NULL, *ptr;
573 uint auth_alg;
574 struct recv_frame *pfhdr;
575 struct sta_info *psta;
576 struct sta_priv *pstapriv ;
577 struct recv_frame *prtnframe;
578 u16 ether_type = 0;
579 u16 eapol_type = 0x888e;/* for Funia BD's WPA issue */
580 struct rx_pkt_attrib *pattrib;
581
582 pstapriv = &adapter->stapriv;
583 psta = rtw_get_stainfo23a(pstapriv, psta_addr);
584
585 auth_alg = adapter->securitypriv.dot11AuthAlgrthm;
586
587 ptr = precv_frame->pkt->data;
588 pfhdr = precv_frame;
589 pattrib = &pfhdr->attrib;
590 psta_addr = pattrib->ta;
591
592 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
593 ("########portctrl:adapter->securitypriv.dot11AuthAlgrthm ="
594 "%d\n", adapter->securitypriv.dot11AuthAlgrthm));
595
596 if (auth_alg == 2) {
597 if ((psta != NULL) && (psta->ieee8021x_blocked)) {
598 /* blocked */
599 /* only accept EAPOL frame */
600 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
601 ("########portctrl:psta->ieee8021x_blocked =="
602 "1\n"));
603
604 prtnframe = precv_frame;
605
606 /* get ether_type */
607 ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE;
608 memcpy(&ether_type, ptr, 2);
609 ether_type = ntohs((unsigned short)ether_type);
610
611 if (ether_type == eapol_type) {
612 prtnframe = precv_frame;
613 } else {
614 /* free this frame */
615 rtw_free_recvframe23a(precv_frame,
616 &adapter->recvpriv.free_recv_queue);
617 prtnframe = NULL;
618 }
619 } else {
620 /* allowed */
621 /* check decryption status, and decrypt the frame if needed */
622 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
623 ("########portctrl:psta->ieee8021x_blocked =="
624 "0\n"));
625 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
626 ("portctrl:precv_frame->hdr.attrib.privacy ="
627 "%x\n", precv_frame->attrib.privacy));
628
629 if (pattrib->bdecrypted == 0) {
630 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
631 ("portctrl:prxstat->decrypted =%x\n",
632 pattrib->bdecrypted));
633 }
634
635 prtnframe = precv_frame;
636 /* check is the EAPOL frame or not (Rekey) */
637 if (ether_type == eapol_type) {
638 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
639 ("########portctrl:ether_type == "
640 "0x888e\n"));
641 /* check Rekey */
642
643 prtnframe = precv_frame;
644 } else {
645 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
646 ("########portctrl:ether_type = 0x%04x"
647 "\n", ether_type));
648 }
649 }
650 } else {
651 prtnframe = precv_frame;
652 }
653
654
655
656 return prtnframe;
657}
658
659int recv_decache(struct recv_frame *precv_frame, u8 bretry,
660 struct stainfo_rxcache *prxcache);
661int recv_decache(struct recv_frame *precv_frame, u8 bretry,
662 struct stainfo_rxcache *prxcache)
663{
664 int tid = precv_frame->attrib.priority;
665
666 u16 seq_ctrl = ((precv_frame->attrib.seq_num & 0xffff) << 4) |
667 (precv_frame->attrib.frag_num & 0xf);
668
669
670
671 if (tid > 15) {
672 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
673 ("recv_decache, (tid>15)! seq_ctrl = 0x%x, tid = 0x%x\n",
674 seq_ctrl, tid));
675
676 return _FAIL;
677 }
678
679 if (1) { /* if (bretry) */
680 if (seq_ctrl == prxcache->tid_rxseq[tid]) {
681 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
682 ("recv_decache, seq_ctrl = 0x%x, tid = 0x%x, "
683 "tid_rxseq = 0x%x\n",
684 seq_ctrl, tid, prxcache->tid_rxseq[tid]));
685
686 return _FAIL;
687 }
688 }
689
690 prxcache->tid_rxseq[tid] = seq_ctrl;
691
692
693
694 return _SUCCESS;
695}
696
697void process23a_pwrbit_data(struct rtw_adapter *padapter,
698 struct recv_frame *precv_frame);
699void process23a_pwrbit_data(struct rtw_adapter *padapter,
700 struct recv_frame *precv_frame)
701{
702#ifdef CONFIG_8723AU_AP_MODE
703 unsigned char pwrbit;
704 struct sk_buff *skb = precv_frame->pkt;
705 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
706 struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
707 struct sta_priv *pstapriv = &padapter->stapriv;
708 struct sta_info *psta = NULL;
709
710 psta = rtw_get_stainfo23a(pstapriv, pattrib->src);
711
712 if (psta) {
713 pwrbit = ieee80211_has_pm(hdr->frame_control);
714
715 if (pwrbit) {
716 if (!(psta->state & WIFI_SLEEP_STATE))
717 stop_sta_xmit23a(padapter, psta);
718 } else {
719 if (psta->state & WIFI_SLEEP_STATE)
720 wakeup_sta_to_xmit23a(padapter, psta);
721 }
722 }
723
724#endif
725}
726
727void process_wmmps_data(struct rtw_adapter *padapter,
728 struct recv_frame *precv_frame);
729void process_wmmps_data(struct rtw_adapter *padapter,
730 struct recv_frame *precv_frame)
731{
732#ifdef CONFIG_8723AU_AP_MODE
733 struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
734 struct sta_priv *pstapriv = &padapter->stapriv;
735 struct sta_info *psta = NULL;
736
737 psta = rtw_get_stainfo23a(pstapriv, pattrib->src);
738
739 if (!psta)
740 return;
741
742
743 if (!psta->qos_option)
744 return;
745
746 if (!(psta->qos_info & 0xf))
747 return;
748
749 if (psta->state & WIFI_SLEEP_STATE) {
750 u8 wmmps_ac = 0;
751
752 switch (pattrib->priority) {
753 case 1:
754 case 2:
755 wmmps_ac = psta->uapsd_bk & BIT(1);
756 break;
757 case 4:
758 case 5:
759 wmmps_ac = psta->uapsd_vi & BIT(1);
760 break;
761 case 6:
762 case 7:
763 wmmps_ac = psta->uapsd_vo & BIT(1);
764 break;
765 case 0:
766 case 3:
767 default:
768 wmmps_ac = psta->uapsd_be & BIT(1);
769 break;
770 }
771
772 if (wmmps_ac) {
773 if (psta->sleepq_ac_len > 0) {
774 /* process received triggered frame */
775 xmit_delivery_enabled_frames23a(padapter, psta);
776 } else {
777 /* issue one qos null frame with More data bit = 0 and the EOSP bit set (= 1) */
778 issue_qos_nulldata23a(padapter, psta->hwaddr,
779 (u16)pattrib->priority,
780 0, 0);
781 }
782 }
783 }
784
785#endif
786}
787
788static void count_rx_stats(struct rtw_adapter *padapter,
789 struct recv_frame *prframe, struct sta_info *sta)
790{
791 int sz;
792 struct sta_info *psta = NULL;
793 struct stainfo_stats *pstats = NULL;
794 struct rx_pkt_attrib *pattrib = & prframe->attrib;
795 struct recv_priv *precvpriv = &padapter->recvpriv;
796
797 sz = prframe->pkt->len;
798 precvpriv->rx_bytes += sz;
799
800 padapter->mlmepriv.LinkDetectInfo.NumRxOkInPeriod++;
801
802 if ((!is_broadcast_ether_addr(pattrib->dst)) &&
803 (!is_multicast_ether_addr(pattrib->dst)))
804 padapter->mlmepriv.LinkDetectInfo.NumRxUnicastOkInPeriod++;
805
806 if (sta)
807 psta = sta;
808 else
809 psta = prframe->psta;
810
811 if (psta) {
812 pstats = &psta->sta_stats;
813
814 pstats->rx_data_pkts++;
815 pstats->rx_bytes += sz;
816 }
817}
818
819static int sta2sta_data_frame(struct rtw_adapter *adapter,
820 struct recv_frame *precv_frame,
821 struct sta_info**psta)
822{
823 struct sk_buff *skb = precv_frame->pkt;
824 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
825 int ret = _SUCCESS;
826 struct rx_pkt_attrib *pattrib = & precv_frame->attrib;
827 struct sta_priv *pstapriv = &adapter->stapriv;
828 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
829 u8 *mybssid = get_bssid(pmlmepriv);
830 u8 *myhwaddr = myid(&adapter->eeprompriv);
831 u8 *sta_addr = NULL;
832 int bmcast = is_multicast_ether_addr(pattrib->dst);
833
834
835
836 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) ||
837 (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
838
839 /* filter packets that SA is myself or multicast or broadcast */
840 if (ether_addr_equal(myhwaddr, pattrib->src)) {
841 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
842 (" SA == myself\n"));
843 ret = _FAIL;
844 goto exit;
845 }
846
847 if (!ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) {
848 ret = _FAIL;
849 goto exit;
850 }
851
852 if (ether_addr_equal(pattrib->bssid, "\x0\x0\x0\x0\x0\x0") ||
853 ether_addr_equal(mybssid, "\x0\x0\x0\x0\x0\x0") ||
854 !ether_addr_equal(pattrib->bssid, mybssid)) {
855 ret = _FAIL;
856 goto exit;
857 }
858
859 sta_addr = pattrib->src;
860 } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
861 /* For Station mode, sa and bssid should always be BSSID,
862 and DA is my mac-address */
863 if (!ether_addr_equal(pattrib->bssid, pattrib->src)) {
864 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
865 ("bssid != TA under STATION_MODE; drop "
866 "pkt\n"));
867 ret = _FAIL;
868 goto exit;
869 }
870
871 sta_addr = pattrib->bssid;
872
873 } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
874 if (bmcast) {
875 /* For AP mode, if DA == MCAST, then BSSID should be also MCAST */
876 if (!is_multicast_ether_addr(pattrib->bssid)) {
877 ret = _FAIL;
878 goto exit;
879 }
880 } else { /* not mc-frame */
881 /* For AP mode, if DA is non-MCAST, then it must
882 be BSSID, and bssid == BSSID */
883 if (!ether_addr_equal(pattrib->bssid, pattrib->dst)) {
884 ret = _FAIL;
885 goto exit;
886 }
887
888 sta_addr = pattrib->src;
889 }
890 } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) {
891 ether_addr_copy(pattrib->dst, hdr->addr1);
892 ether_addr_copy(pattrib->src, hdr->addr2);
893 ether_addr_copy(pattrib->bssid, hdr->addr3);
894 ether_addr_copy(pattrib->ra, pattrib->dst);
895 ether_addr_copy(pattrib->ta, pattrib->src);
896
897 sta_addr = mybssid;
898 } else {
899 ret = _FAIL;
900 }
901
902 if (bmcast)
903 *psta = rtw_get_bcmc_stainfo23a(adapter);
904 else
905 *psta = rtw_get_stainfo23a(pstapriv, sta_addr); /* get ap_info */
906
907 if (*psta == NULL) {
908 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under sta2sta_data_frame ; drop pkt\n"));
909 ret = _FAIL;
910 goto exit;
911 }
912
913exit:
914
915 return ret;
916}
917
918int ap2sta_data_frame(struct rtw_adapter *adapter,
919 struct recv_frame *precv_frame,
920 struct sta_info **psta);
921int ap2sta_data_frame(struct rtw_adapter *adapter,
922 struct recv_frame *precv_frame,
923 struct sta_info **psta)
924{
925 struct sk_buff *skb = precv_frame->pkt;
926 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
927 struct rx_pkt_attrib *pattrib = & precv_frame->attrib;
928 int ret = _SUCCESS;
929 struct sta_priv *pstapriv = &adapter->stapriv;
930 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
931 u8 *mybssid = get_bssid(pmlmepriv);
932 u8 *myhwaddr = myid(&adapter->eeprompriv);
933 int bmcast = is_multicast_ether_addr(pattrib->dst);
934
935
936
937 if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) &&
938 (check_fwstate(pmlmepriv, _FW_LINKED) == true ||
939 check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)) {
940
941 /* filter packets that SA is myself or multicast or broadcast */
942 if (ether_addr_equal(myhwaddr, pattrib->src)) {
943 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
944 (" SA == myself\n"));
945 ret = _FAIL;
946 goto exit;
947 }
948
949 /* da should be for me */
950 if (!ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) {
951 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
952 (" ap2sta_data_frame: compare DA fail; DA ="
953 MAC_FMT"\n", MAC_ARG(pattrib->dst)));
954 ret = _FAIL;
955 goto exit;
956 }
957
958 /* check BSSID */
959 if (ether_addr_equal(pattrib->bssid, "\x0\x0\x0\x0\x0\x0") ||
960 ether_addr_equal(mybssid, "\x0\x0\x0\x0\x0\x0") ||
961 !ether_addr_equal(pattrib->bssid, mybssid)) {
962 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
963 (" ap2sta_data_frame: compare BSSID fail ; "
964 "BSSID ="MAC_FMT"\n", MAC_ARG(pattrib->bssid)));
965 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
966 ("mybssid ="MAC_FMT"\n", MAC_ARG(mybssid)));
967
968 if (!bmcast) {
969 DBG_8723A("issue_deauth23a to the nonassociated "
970 "ap =" MAC_FMT " for the reason(7)\n",
971 MAC_ARG(pattrib->bssid));
972 issue_deauth23a(adapter, pattrib->bssid,
973 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
974 }
975
976 ret = _FAIL;
977 goto exit;
978 }
979
980 if (bmcast)
981 *psta = rtw_get_bcmc_stainfo23a(adapter);
982 else
983 /* get ap_info */
984 *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid);
985
986 if (*psta == NULL) {
987 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
988 ("ap2sta: can't get psta under STATION_MODE ;"
989 " drop pkt\n"));
990 ret = _FAIL;
991 goto exit;
992 }
993
994 if (ieee80211_is_nullfunc(hdr->frame_control)) {
995 /* No data, will not indicate to upper layer,
996 temporily count it here */
997 count_rx_stats(adapter, precv_frame, *psta);
998 ret = RTW_RX_HANDLED;
999 goto exit;
1000 }
1001
1002 } else if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) &&
1003 (check_fwstate(pmlmepriv, _FW_LINKED) == true)) {
1004 ether_addr_copy(pattrib->dst, hdr->addr1);
1005 ether_addr_copy(pattrib->src, hdr->addr2);
1006 ether_addr_copy(pattrib->bssid, hdr->addr3);
1007 ether_addr_copy(pattrib->ra, pattrib->dst);
1008 ether_addr_copy(pattrib->ta, pattrib->src);
1009
1010 /* */
1011 ether_addr_copy(pattrib->bssid, mybssid);
1012
1013 /* get sta_info */
1014 *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid);
1015 if (*psta == NULL) {
1016 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1017 ("can't get psta under MP_MODE ; drop pkt\n"));
1018 ret = _FAIL;
1019 goto exit;
1020 }
1021 } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
1022 /* Special case */
1023 ret = RTW_RX_HANDLED;
1024 goto exit;
1025 } else {
1026 if (ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) {
1027 *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid);
1028 if (*psta == NULL) {
1029 DBG_8723A("issue_deauth23a to the ap =" MAC_FMT
1030 " for the reason(7)\n",
1031 MAC_ARG(pattrib->bssid));
1032
1033 issue_deauth23a(adapter, pattrib->bssid,
1034 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
1035 }
1036 }
1037
1038 ret = _FAIL;
1039 }
1040
1041exit:
1042
1043
1044
1045 return ret;
1046}
1047
1048int sta2ap_data_frame(struct rtw_adapter *adapter,
1049 struct recv_frame *precv_frame,
1050 struct sta_info **psta);
1051int sta2ap_data_frame(struct rtw_adapter *adapter,
1052 struct recv_frame *precv_frame,
1053 struct sta_info **psta)
1054{
1055 struct sk_buff *skb = precv_frame->pkt;
1056 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1057 struct rx_pkt_attrib *pattrib = & precv_frame->attrib;
1058 struct sta_priv *pstapriv = &adapter->stapriv;
1059 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1060 unsigned char *mybssid = get_bssid(pmlmepriv);
1061 int ret = _SUCCESS;
1062
1063
1064
1065 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
1066 /* For AP mode, RA = BSSID, TX = STA(SRC_ADDR), A3 = DST_ADDR */
1067 if (!ether_addr_equal(pattrib->bssid, mybssid)) {
1068 ret = _FAIL;
1069 goto exit;
1070 }
1071
1072 *psta = rtw_get_stainfo23a(pstapriv, pattrib->src);
1073 if (*psta == NULL) {
1074 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1075 ("can't get psta under AP_MODE; drop pkt\n"));
1076 DBG_8723A("issue_deauth23a to sta =" MAC_FMT
1077 " for the reason(7)\n",
1078 MAC_ARG(pattrib->src));
1079
1080 issue_deauth23a(adapter, pattrib->src,
1081 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
1082
1083 ret = RTW_RX_HANDLED;
1084 goto exit;
1085 }
1086
1087 process23a_pwrbit_data(adapter, precv_frame);
1088
1089 /* We only get here if it's a data frame, so no need to
1090 * confirm data frame type first */
1091 if (ieee80211_is_data_qos(hdr->frame_control))
1092 process_wmmps_data(adapter, precv_frame);
1093
1094 if (ieee80211_is_nullfunc(hdr->frame_control)) {
1095 /* No data, will not indicate to upper layer,
1096 temporily count it here */
1097 count_rx_stats(adapter, precv_frame, *psta);
1098 ret = RTW_RX_HANDLED;
1099 goto exit;
1100 }
1101 } else {
1102 u8 *myhwaddr = myid(&adapter->eeprompriv);
1103 if (!ether_addr_equal(pattrib->ra, myhwaddr)) {
1104 ret = RTW_RX_HANDLED;
1105 goto exit;
1106 }
1107 DBG_8723A("issue_deauth23a to sta =" MAC_FMT " for the reason(7)\n",
1108 MAC_ARG(pattrib->src));
1109 issue_deauth23a(adapter, pattrib->src,
1110 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
1111 ret = RTW_RX_HANDLED;
1112 goto exit;
1113 }
1114
1115exit:
1116
1117
1118
1119 return ret;
1120}
1121
1122int validate_recv_ctrl_frame(struct rtw_adapter *padapter,
1123 struct recv_frame *precv_frame);
1124int validate_recv_ctrl_frame(struct rtw_adapter *padapter,
1125 struct recv_frame *precv_frame)
1126{
1127#ifdef CONFIG_8723AU_AP_MODE
1128 struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
1129 struct sta_priv *pstapriv = &padapter->stapriv;
1130 struct sk_buff *skb = precv_frame->pkt;
1131 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1132 u8 *pframe = skb->data;
1133
1134 if (!ieee80211_is_ctl(hdr->frame_control))
1135 return _FAIL;
1136
1137 /* receive the frames that ra(a1) is my address */
1138 if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv)))
1139 return _FAIL;
1140
1141 /* only handle ps-poll */
1142 if (ieee80211_is_pspoll(hdr->frame_control)) {
1143 u16 aid;
1144 u8 wmmps_ac = 0;
1145 struct sta_info *psta = NULL;
1146
1147 aid = GetAid(pframe);
1148 psta = rtw_get_stainfo23a(pstapriv, hdr->addr2);
1149
1150 if ((!psta) || (psta->aid != aid))
1151 return _FAIL;
1152
1153 /* for rx pkt statistics */
1154 psta->sta_stats.rx_ctrl_pkts++;
1155
1156 switch (pattrib->priority) {
1157 case 1:
1158 case 2:
1159 wmmps_ac = psta->uapsd_bk & BIT(0);
1160 break;
1161 case 4:
1162 case 5:
1163 wmmps_ac = psta->uapsd_vi & BIT(0);
1164 break;
1165 case 6:
1166 case 7:
1167 wmmps_ac = psta->uapsd_vo & BIT(0);
1168 break;
1169 case 0:
1170 case 3:
1171 default:
1172 wmmps_ac = psta->uapsd_be & BIT(0);
1173 break;
1174 }
1175
1176 if (wmmps_ac)
1177 return _FAIL;
1178
1179 if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
1180 DBG_8723A("%s alive check-rx ps-poll\n", __func__);
1181 psta->expire_to = pstapriv->expire_to;
1182 psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
1183 }
1184
1185 if ((psta->state & WIFI_SLEEP_STATE) &&
1186 (pstapriv->sta_dz_bitmap & CHKBIT(psta->aid))) {
1187 struct list_head *xmitframe_plist, *xmitframe_phead;
1188 struct xmit_frame *pxmitframe;
1189 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1190
1191 spin_lock_bh(&pxmitpriv->lock);
1192
1193 xmitframe_phead = get_list_head(&psta->sleep_q);
1194 xmitframe_plist = xmitframe_phead->next;
1195
1196 if (!list_empty(xmitframe_phead)) {
1197 pxmitframe = container_of(xmitframe_plist,
1198 struct xmit_frame,
1199 list);
1200
1201 xmitframe_plist = xmitframe_plist->next;
1202
1203 list_del_init(&pxmitframe->list);
1204
1205 psta->sleepq_len--;
1206
1207 if (psta->sleepq_len>0)
1208 pxmitframe->attrib.mdata = 1;
1209 else
1210 pxmitframe->attrib.mdata = 0;
1211
1212 pxmitframe->attrib.triggered = 1;
1213
1214 /* DBG_8723A("handling ps-poll, q_len =%d, tim =%x\n", psta->sleepq_len, pstapriv->tim_bitmap); */
1215
1216 rtw_hal_xmit23aframe_enqueue(padapter, pxmitframe);
1217
1218 if (psta->sleepq_len == 0) {
1219 pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
1220
1221 /* DBG_8723A("after handling ps-poll, tim =%x\n", pstapriv->tim_bitmap); */
1222
1223 /* upate BCN for TIM IE */
1224 /* update_BCNTIM(padapter); */
1225 update_beacon23a(padapter, _TIM_IE_,
1226 NULL, false);
1227 }
1228
1229 /* spin_unlock_bh(&psta->sleep_q.lock); */
1230 spin_unlock_bh(&pxmitpriv->lock);
1231
1232 } else {
1233 /* spin_unlock_bh(&psta->sleep_q.lock); */
1234 spin_unlock_bh(&pxmitpriv->lock);
1235
1236 /* DBG_8723A("no buffered packets to xmit\n"); */
1237 if (pstapriv->tim_bitmap & CHKBIT(psta->aid)) {
1238 if (psta->sleepq_len == 0) {
1239 DBG_8723A("no buffered packets "
1240 "to xmit\n");
1241
1242 /* issue nulldata with More data bit = 0 to indicate we have no buffered packets */
1243 issue_nulldata23a(padapter,
1244 psta->hwaddr,
1245 0, 0, 0);
1246 } else {
1247 DBG_8723A("error!psta->sleepq"
1248 "_len =%d\n",
1249 psta->sleepq_len);
1250 psta->sleepq_len = 0;
1251 }
1252
1253 pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
1254
1255 /* upate BCN for TIM IE */
1256 /* update_BCNTIM(padapter); */
1257 update_beacon23a(padapter, _TIM_IE_,
1258 NULL, false);
1259 }
1260 }
1261 }
1262 }
1263
1264#endif
1265 return _FAIL;
1266}
1267
1268struct recv_frame* recvframe_chk_defrag23a(struct rtw_adapter *padapter,
1269 struct recv_frame *precv_frame);
1270int validate_recv_mgnt_frame(struct rtw_adapter *padapter,
1271 struct recv_frame *precv_frame);
1272int validate_recv_mgnt_frame(struct rtw_adapter *padapter,
1273 struct recv_frame *precv_frame)
1274{
1275 struct sta_info *psta;
1276 struct sk_buff *skb;
1277 struct ieee80211_hdr *hdr;
1278 /* struct mlme_priv *pmlmepriv = &adapter->mlmepriv; */
1279
1280 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1281 ("+validate_recv_mgnt_frame\n"));
1282
1283 precv_frame = recvframe_chk_defrag23a(padapter, precv_frame);
1284 if (precv_frame == NULL) {
1285 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
1286 ("%s: fragment packet\n", __func__));
1287 return _SUCCESS;
1288 }
1289
1290 skb = precv_frame->pkt;
1291 hdr = (struct ieee80211_hdr *) skb->data;
1292
1293 /* for rx pkt statistics */
1294 psta = rtw_get_stainfo23a(&padapter->stapriv, hdr->addr2);
1295 if (psta) {
1296 psta->sta_stats.rx_mgnt_pkts++;
1297
1298 if (ieee80211_is_beacon(hdr->frame_control))
1299 psta->sta_stats.rx_beacon_pkts++;
1300 else if (ieee80211_is_probe_req(hdr->frame_control))
1301 psta->sta_stats.rx_probereq_pkts++;
1302 else if (ieee80211_is_probe_resp(hdr->frame_control)) {
1303 if (ether_addr_equal(padapter->eeprompriv.mac_addr,
1304 hdr->addr1))
1305 psta->sta_stats.rx_probersp_pkts++;
1306 else if (is_broadcast_ether_addr(hdr->addr1) ||
1307 is_multicast_ether_addr(hdr->addr1))
1308 psta->sta_stats.rx_probersp_bm_pkts++;
1309 else
1310 psta->sta_stats.rx_probersp_uo_pkts++;
1311 }
1312 }
1313
1314 mgt_dispatcher23a(padapter, precv_frame);
1315
1316 return _SUCCESS;
1317}
1318
1319int validate_recv_data_frame(struct rtw_adapter *adapter,
1320 struct recv_frame *precv_frame);
1321int validate_recv_data_frame(struct rtw_adapter *adapter,
1322 struct recv_frame *precv_frame)
1323{
1324 u8 bretry;
1325 u8 *psa, *pda, *pbssid;
1326 struct sta_info *psta = NULL;
1327 u8 *ptr = precv_frame->pkt->data;
1328 struct rx_pkt_attrib *pattrib = & precv_frame->attrib;
1329 struct security_priv *psecuritypriv = &adapter->securitypriv;
1330 int ret = _SUCCESS;
1331 struct sk_buff *skb = precv_frame->pkt;
1332 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1333
1334
1335
1336 bretry = ieee80211_has_retry(hdr->frame_control);
1337 pda = ieee80211_get_DA(hdr);
1338 psa = ieee80211_get_SA(hdr);
1339 pbssid = get_hdr_bssid(ptr);
1340
1341 if (pbssid == NULL) {
1342 ret = _FAIL;
1343 goto exit;
1344 }
1345
1346 ether_addr_copy(pattrib->dst, pda);
1347 ether_addr_copy(pattrib->src, psa);
1348
1349 ether_addr_copy(pattrib->bssid, pbssid);
1350
1351 switch (pattrib->to_fr_ds)
1352 {
1353 case 0:
1354 ether_addr_copy(pattrib->ra, pda);
1355 ether_addr_copy(pattrib->ta, psa);
1356 ret = sta2sta_data_frame(adapter, precv_frame, &psta);
1357 break;
1358
1359 case 1:
1360 ether_addr_copy(pattrib->ra, pda);
1361 ether_addr_copy(pattrib->ta, pbssid);
1362 ret = ap2sta_data_frame(adapter, precv_frame, &psta);
1363 break;
1364
1365 case 2:
1366 ether_addr_copy(pattrib->ra, pbssid);
1367 ether_addr_copy(pattrib->ta, psa);
1368 ret = sta2ap_data_frame(adapter, precv_frame, &psta);
1369 break;
1370
1371 case 3:
1372 ether_addr_copy(pattrib->ra, hdr->addr1);
1373 ether_addr_copy(pattrib->ta, hdr->addr2);
1374 ret = _FAIL;
1375 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" case 3\n"));
1376 break;
1377
1378 default:
1379 ret = _FAIL;
1380 break;
1381 }
1382
1383 if ((ret == _FAIL) || (ret == RTW_RX_HANDLED))
1384 goto exit;
1385
1386 if (!psta) {
1387 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1388 (" after to_fr_ds_chk; psta == NULL\n"));
1389 ret = _FAIL;
1390 goto exit;
1391 }
1392
1393 /* psta->rssi = prxcmd->rssi; */
1394 /* psta->signal_quality = prxcmd->sq; */
1395 precv_frame->psta = psta;
1396
1397 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
1398 if (ieee80211_has_a4(hdr->frame_control))
1399 pattrib->hdrlen += ETH_ALEN;
1400
1401 /* parsing QC field */
1402 if (pattrib->qos == 1) {
1403 __le16 *qptr = (__le16 *)ieee80211_get_qos_ctl(hdr);
1404 u16 qos_ctrl = le16_to_cpu(*qptr);
1405
1406 pattrib->priority = qos_ctrl & IEEE80211_QOS_CTL_TID_MASK;
1407 pattrib->ack_policy = (qos_ctrl >> 5) & 3;
1408 pattrib->amsdu =
1409 (qos_ctrl & IEEE80211_QOS_CTL_A_MSDU_PRESENT) >> 7;
1410 pattrib->hdrlen += IEEE80211_QOS_CTL_LEN;
1411
1412 if (pattrib->priority != 0 && pattrib->priority != 3) {
1413 adapter->recvpriv.bIsAnyNonBEPkts = true;
1414 }
1415 } else {
1416 pattrib->priority = 0;
1417 pattrib->ack_policy = 0;
1418 pattrib->amsdu = 0;
1419 }
1420
1421 if (pattrib->order) { /* HT-CTRL 11n */
1422 pattrib->hdrlen += 4;
1423 }
1424
1425 precv_frame->preorder_ctrl = &psta->recvreorder_ctrl[pattrib->priority];
1426
1427 /* decache, drop duplicate recv packets */
1428 if (recv_decache(precv_frame, bretry, &psta->sta_recvpriv.rxcache) ==
1429 _FAIL) {
1430 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1431 ("decache : drop pkt\n"));
1432 ret = _FAIL;
1433 goto exit;
1434 }
1435
1436 if (pattrib->privacy) {
1437 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1438 ("validate_recv_data_frame:pattrib->privacy =%x\n",
1439 pattrib->privacy));
1440 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1441 ("\n ^^^^^^^^^^^is_multicast_ether_addr"
1442 "(pattrib->ra(0x%02x)) =%d^^^^^^^^^^^^^^^6\n",
1443 pattrib->ra[0],
1444 is_multicast_ether_addr(pattrib->ra)));
1445
1446 GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt,
1447 is_multicast_ether_addr(pattrib->ra));
1448
1449 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1450 ("\n pattrib->encrypt =%d\n", pattrib->encrypt));
1451
1452 switch (pattrib->encrypt)
1453 {
1454 case _WEP40_:
1455 case _WEP104_:
1456 pattrib->iv_len = 4;
1457 pattrib->icv_len = 4;
1458 break;
1459 case _TKIP_:
1460 pattrib->iv_len = 8;
1461 pattrib->icv_len = 4;
1462 break;
1463 case _AES_:
1464 pattrib->iv_len = 8;
1465 pattrib->icv_len = 8;
1466 break;
1467 case _SMS4_:
1468 pattrib->iv_len = 18;
1469 pattrib->icv_len = 16;
1470 break;
1471 default:
1472 pattrib->iv_len = 0;
1473 pattrib->icv_len = 0;
1474 break;
1475 }
1476 } else {
1477 pattrib->encrypt = 0;
1478 pattrib->iv_len = 0;
1479 pattrib->icv_len = 0;
1480 }
1481
1482exit:
1483
1484
1485
1486 return ret;
1487}
1488
1489static void dump_rx_pkt(struct sk_buff *skb, u16 type, int level)
1490{
1491 int i;
1492 u8 *ptr;
1493
1494 if ((level == 1) ||
1495 ((level == 2) && (type == IEEE80211_FTYPE_MGMT)) ||
1496 ((level == 3) && (type == IEEE80211_FTYPE_DATA))) {
1497
1498 ptr = skb->data;
1499
1500 DBG_8723A("#############################\n");
1501
1502 for (i = 0; i < 64; i = i + 8)
1503 DBG_8723A("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n",
1504 *(ptr + i), *(ptr + i + 1), *(ptr + i + 2),
1505 *(ptr + i + 3), *(ptr + i + 4),
1506 *(ptr + i + 5), *(ptr + i + 6),
1507 *(ptr + i + 7));
1508 DBG_8723A("#############################\n");
1509 }
1510}
1511
1512static int validate_recv_frame(struct rtw_adapter *adapter,
1513 struct recv_frame *precv_frame)
1514{
1515 /* shall check frame subtype, to / from ds, da, bssid */
1516
1517 /* then call check if rx seq/frag. duplicated. */
1518 u8 type;
1519 u8 subtype;
1520 int retval = _SUCCESS;
1521 struct rx_pkt_attrib *pattrib = & precv_frame->attrib;
1522 struct sk_buff *skb = precv_frame->pkt;
1523 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1524 u8 ver;
1525 u8 bDumpRxPkt;
1526 u16 seq_ctrl, fctl;
1527
1528 fctl = le16_to_cpu(hdr->frame_control);
1529 ver = fctl & IEEE80211_FCTL_VERS;
1530 type = fctl & IEEE80211_FCTL_FTYPE;
1531 subtype = fctl & IEEE80211_FCTL_STYPE;
1532
1533 /* add version chk */
1534 if (ver != 0) {
1535 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1536 ("validate_recv_data_frame fail! (ver!= 0)\n"));
1537 retval = _FAIL;
1538 goto exit;
1539 }
1540
1541 pattrib->to_fr_ds = get_tofr_ds(hdr->frame_control);
1542
1543 seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
1544 pattrib->frag_num = seq_ctrl & IEEE80211_SCTL_FRAG;
1545 pattrib->seq_num = seq_ctrl >> 4;
1546
1547 pattrib->pw_save = ieee80211_has_pm(hdr->frame_control);
1548 pattrib->mfrag = ieee80211_has_morefrags(hdr->frame_control);
1549 pattrib->mdata = ieee80211_has_moredata(hdr->frame_control);
1550 pattrib->privacy = ieee80211_has_protected(hdr->frame_control);
1551 pattrib->order = ieee80211_has_order(hdr->frame_control);
1552
1553 rtw_hal_get_def_var23a(adapter, HAL_DEF_DBG_DUMP_RXPKT, &bDumpRxPkt);
1554
1555 if (unlikely(bDumpRxPkt == 1))
1556 dump_rx_pkt(skb, type, bDumpRxPkt);
1557
1558 switch (type)
1559 {
1560 case IEEE80211_FTYPE_MGMT:
1561 retval = validate_recv_mgnt_frame(adapter, precv_frame);
1562 if (retval == _FAIL) {
1563 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1564 ("validate_recv_mgnt_frame fail\n"));
1565 }
1566 retval = _FAIL; /* only data frame return _SUCCESS */
1567 break;
1568 case IEEE80211_FTYPE_CTL:
1569 retval = validate_recv_ctrl_frame(adapter, precv_frame);
1570 if (retval == _FAIL) {
1571 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1572 ("validate_recv_ctrl_frame fail\n"));
1573 }
1574 retval = _FAIL; /* only data frame return _SUCCESS */
1575 break;
1576 case IEEE80211_FTYPE_DATA:
1577 rtw_led_control(adapter, LED_CTL_RX);
1578 pattrib->qos = (subtype & IEEE80211_STYPE_QOS_DATA) ? 1 : 0;
1579 retval = validate_recv_data_frame(adapter, precv_frame);
1580 if (retval == _FAIL) {
1581 struct recv_priv *precvpriv = &adapter->recvpriv;
1582 /* RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_data_frame fail\n")); */
1583 precvpriv->rx_drop++;
1584 }
1585 break;
1586 default:
1587 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1588 ("validate_recv_data_frame fail! type = 0x%x\n", type));
1589 retval = _FAIL;
1590 break;
1591 }
1592
1593exit:
1594 return retval;
1595}
1596
1597/* remove the wlanhdr and add the eth_hdr */
1598
1599static int wlanhdr_to_ethhdr (struct recv_frame *precvframe)
1600{
1601 u16 eth_type, len, hdrlen;
1602 u8 bsnaphdr;
1603 u8 *psnap;
1604
1605 int ret = _SUCCESS;
1606 struct rtw_adapter *adapter = precvframe->adapter;
1607 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1608
1609 struct sk_buff *skb = precvframe->pkt;
1610 u8 *ptr;
1611 struct rx_pkt_attrib *pattrib = &precvframe->attrib;
1612
1613
1614
1615 ptr = skb->data;
1616 hdrlen = pattrib->hdrlen;
1617 psnap = ptr + hdrlen;
1618 eth_type = (psnap[6] << 8) | psnap[7];
1619 /* convert hdr + possible LLC headers into Ethernet header */
1620 /* eth_type = (psnap_type[0] << 8) | psnap_type[1]; */
1621 if ((ether_addr_equal(psnap, rfc1042_header) &&
1622 eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) ||
1623 ether_addr_equal(psnap, bridge_tunnel_header)) {
1624 /* remove RFC1042 or Bridge-Tunnel encapsulation
1625 and replace EtherType */
1626 bsnaphdr = true;
1627 hdrlen += SNAP_SIZE;
1628 } else {
1629 /* Leave Ethernet header part of hdr and full payload */
1630 bsnaphdr = false;
1631 eth_type = (psnap[0] << 8) | psnap[1];
1632 }
1633
1634 len = skb->len - hdrlen;
1635
1636 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1637 ("\n === pattrib->hdrlen: %x, pattrib->iv_len:%x ===\n\n",
1638 pattrib->hdrlen, pattrib->iv_len));
1639
1640 pattrib->eth_type = eth_type;
1641 if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)) {
1642 ptr += hdrlen;
1643 *ptr = 0x87;
1644 *(ptr + 1) = 0x12;
1645
1646 eth_type = 0x8712;
1647 /* append rx status for mp test packets */
1648
1649 ptr = skb_pull(skb, (hdrlen - sizeof(struct ethhdr) + 2) - 24);
1650 memcpy(ptr, skb->head, 24);
1651 ptr += 24;
1652 } else {
1653 ptr = skb_pull(skb, (hdrlen - sizeof(struct ethhdr) +
1654 (bsnaphdr ? 2:0)));
1655 }
1656
1657 ether_addr_copy(ptr, pattrib->dst);
1658 ether_addr_copy(ptr + ETH_ALEN, pattrib->src);
1659
1660 if (!bsnaphdr) {
1661 len = htons(len);
1662 memcpy(ptr + 12, &len, 2);
1663 }
1664
1665
1666 return ret;
1667}
1668
1669/* perform defrag */
1670struct recv_frame *recvframe_defrag(struct rtw_adapter *adapter,
1671 struct rtw_queue *defrag_q);
1672struct recv_frame *recvframe_defrag(struct rtw_adapter *adapter,
1673 struct rtw_queue *defrag_q)
1674{
1675 struct list_head *plist, *phead, *ptmp;
1676 u8 *data, wlanhdr_offset;
1677 u8 curfragnum;
1678 struct recv_frame *pnfhdr;
1679 struct recv_frame *prframe, *pnextrframe;
1680 struct rtw_queue *pfree_recv_queue;
1681 struct sk_buff *skb;
1682
1683
1684
1685 curfragnum = 0;
1686 pfree_recv_queue = &adapter->recvpriv.free_recv_queue;
1687
1688 phead = get_list_head(defrag_q);
1689 plist = phead->next;
1690 prframe = container_of(plist, struct recv_frame, list);
1691 list_del_init(&prframe->list);
1692 skb = prframe->pkt;
1693
1694 if (curfragnum != prframe->attrib.frag_num) {
1695 /* the first fragment number must be 0 */
1696 /* free the whole queue */
1697 rtw_free_recvframe23a(prframe, pfree_recv_queue);
1698 rtw_free_recvframe23a_queue(defrag_q, pfree_recv_queue);
1699
1700 return NULL;
1701 }
1702
1703 curfragnum++;
1704
1705 phead = get_list_head(defrag_q);
1706
1707 data = prframe->pkt->data;
1708
1709 list_for_each_safe(plist, ptmp, phead) {
1710 pnfhdr = container_of(plist, struct recv_frame, list);
1711 pnextrframe = (struct recv_frame *)pnfhdr;
1712 /* check the fragment sequence (2nd ~n fragment frame) */
1713
1714 if (curfragnum != pnfhdr->attrib.frag_num) {
1715 /* the fragment number must be increasing
1716 (after decache) */
1717 /* release the defrag_q & prframe */
1718 rtw_free_recvframe23a(prframe, pfree_recv_queue);
1719 rtw_free_recvframe23a_queue(defrag_q, pfree_recv_queue);
1720 return NULL;
1721 }
1722
1723 curfragnum++;
1724
1725 /* copy the 2nd~n fragment frame's payload to the
1726 first fragment */
1727 /* get the 2nd~last fragment frame's payload */
1728
1729 wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len;
1730
1731 skb_pull(pnfhdr->pkt, wlanhdr_offset);
1732
1733 /* append to first fragment frame's tail
1734 (if privacy frame, pull the ICV) */
1735
1736 skb_trim(skb, skb->len - prframe->attrib.icv_len);
1737
1738 memcpy(skb_tail_pointer(skb), pnfhdr->pkt->data,
1739 pnfhdr->pkt->len);
1740
1741 skb_put(skb, pnfhdr->pkt->len);
1742
1743 prframe->attrib.icv_len = pnfhdr->attrib.icv_len;
1744 };
1745
1746 /* free the defrag_q queue and return the prframe */
1747 rtw_free_recvframe23a_queue(defrag_q, pfree_recv_queue);
1748
1749 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1750 ("Performance defrag!!!!!\n"));
1751
1752
1753
1754 return prframe;
1755}
1756
1757/* check if need to defrag, if needed queue the frame to defrag_q */
1758struct recv_frame* recvframe_chk_defrag23a(struct rtw_adapter *padapter,
1759 struct recv_frame *precv_frame)
1760{
1761 u8 ismfrag;
1762 u8 fragnum;
1763 u8 *psta_addr;
1764 struct recv_frame *pfhdr;
1765 struct sta_info *psta;
1766 struct sta_priv *pstapriv;
1767 struct list_head *phead;
1768 struct recv_frame *prtnframe = NULL;
1769 struct rtw_queue *pfree_recv_queue, *pdefrag_q;
1770
1771
1772
1773 pstapriv = &padapter->stapriv;
1774
1775 pfhdr = precv_frame;
1776
1777 pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
1778
1779 /* need to define struct of wlan header frame ctrl */
1780 ismfrag = pfhdr->attrib.mfrag;
1781 fragnum = pfhdr->attrib.frag_num;
1782
1783 psta_addr = pfhdr->attrib.ta;
1784 psta = rtw_get_stainfo23a(pstapriv, psta_addr);
1785 if (!psta) {
1786 struct ieee80211_hdr *hdr =
1787 (struct ieee80211_hdr *) pfhdr->pkt->data;
1788 if (!ieee80211_is_data(hdr->frame_control)) {
1789 psta = rtw_get_bcmc_stainfo23a(padapter);
1790 pdefrag_q = &psta->sta_recvpriv.defrag_q;
1791 } else
1792 pdefrag_q = NULL;
1793 } else
1794 pdefrag_q = &psta->sta_recvpriv.defrag_q;
1795
1796 if ((ismfrag == 0) && (fragnum == 0)) {
1797 prtnframe = precv_frame;/* isn't a fragment frame */
1798 }
1799
1800 if (ismfrag == 1) {
1801 /* 0~(n-1) fragment frame */
1802 /* enqueue to defraf_g */
1803 if (pdefrag_q != NULL) {
1804 if (fragnum == 0) {
1805 /* the first fragment */
1806 if (_rtw_queue_empty23a(pdefrag_q) == false) {
1807 /* free current defrag_q */
1808 rtw_free_recvframe23a_queue(pdefrag_q, pfree_recv_queue);
1809 }
1810 }
1811
1812 /* Then enqueue the 0~(n-1) fragment into the
1813 defrag_q */
1814
1815 /* spin_lock(&pdefrag_q->lock); */
1816 phead = get_list_head(pdefrag_q);
1817 list_add_tail(&pfhdr->list, phead);
1818 /* spin_unlock(&pdefrag_q->lock); */
1819
1820 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1821 ("Enqueuq: ismfrag = %d, fragnum = %d\n",
1822 ismfrag, fragnum));
1823
1824 prtnframe = NULL;
1825
1826 } else {
1827 /* can't find this ta's defrag_queue,
1828 so free this recv_frame */
1829 rtw_free_recvframe23a(precv_frame, pfree_recv_queue);
1830 prtnframe = NULL;
1831 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1832 ("Free because pdefrag_q == NULL: ismfrag = "
1833 "%d, fragnum = %d\n", ismfrag, fragnum));
1834 }
1835 }
1836
1837 if ((ismfrag == 0) && (fragnum != 0)) {
1838 /* the last fragment frame */
1839 /* enqueue the last fragment */
1840 if (pdefrag_q != NULL) {
1841 /* spin_lock(&pdefrag_q->lock); */
1842 phead = get_list_head(pdefrag_q);
1843 list_add_tail(&pfhdr->list, phead);
1844 /* spin_unlock(&pdefrag_q->lock); */
1845
1846 /* call recvframe_defrag to defrag */
1847 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1848 ("defrag: ismfrag = %d, fragnum = %d\n",
1849 ismfrag, fragnum));
1850 precv_frame = recvframe_defrag(padapter, pdefrag_q);
1851 prtnframe = precv_frame;
1852 } else {
1853 /* can't find this ta's defrag_queue,
1854 so free this recv_frame */
1855 rtw_free_recvframe23a(precv_frame, pfree_recv_queue);
1856 prtnframe = NULL;
1857 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1858 ("Free because pdefrag_q == NULL: ismfrag = "
1859 "%d, fragnum = %d\n", ismfrag, fragnum));
1860 }
1861
1862 }
1863
1864 if ((prtnframe != NULL) && (prtnframe->attrib.privacy)) {
1865 /* after defrag we must check tkip mic code */
1866 if (recvframe_chkmic(padapter, prtnframe) == _FAIL) {
1867 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1868 ("recvframe_chkmic(padapter, prtnframe) =="
1869 "_FAIL\n"));
1870 rtw_free_recvframe23a(prtnframe, pfree_recv_queue);
1871 prtnframe = NULL;
1872 }
1873 }
1874
1875
1876
1877 return prtnframe;
1878}
1879
1880int amsdu_to_msdu(struct rtw_adapter *padapter, struct recv_frame *prframe);
1881int amsdu_to_msdu(struct rtw_adapter *padapter, struct recv_frame *prframe)
1882{
1883 struct rx_pkt_attrib *pattrib;
1884 struct sk_buff *skb, *sub_skb;
1885 struct sk_buff_head skb_list;
1886 struct recv_priv *precvpriv = &padapter->recvpriv;
1887 struct rtw_queue *pfree_recv_queue = &precvpriv->free_recv_queue;
1888
1889 pattrib = &prframe->attrib;
1890
1891 skb = prframe->pkt;
1892 skb_pull(skb, prframe->attrib.hdrlen);
1893 __skb_queue_head_init(&skb_list);
1894
1895 ieee80211_amsdu_to_8023s(skb, &skb_list, NULL, 0, 0, false);
1896
1897 while (!skb_queue_empty(&skb_list)) {
1898 sub_skb = __skb_dequeue(&skb_list);
1899
1900 sub_skb->protocol = eth_type_trans(sub_skb, padapter->pnetdev);
1901 sub_skb->dev = padapter->pnetdev;
1902
1903 sub_skb->ip_summed = CHECKSUM_NONE;
1904
1905 netif_rx(sub_skb);
1906 }
1907
1908 prframe->pkt = NULL;
1909 rtw_free_recvframe23a(prframe, pfree_recv_queue);
1910 return _SUCCESS;
1911}
1912
1913int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num);
1914int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num)
1915{
1916 u8 wsize = preorder_ctrl->wsize_b;
1917 u16 wend = (preorder_ctrl->indicate_seq + wsize -1) & 0xFFF;
1918
1919 /* Rx Reorder initialize condition. */
1920 if (preorder_ctrl->indicate_seq == 0xFFFF)
1921 preorder_ctrl->indicate_seq = seq_num;
1922
1923 /* Drop out the packet which SeqNum is smaller than WinStart */
1924 if (SN_LESS(seq_num, preorder_ctrl->indicate_seq))
1925 return false;
1926
1927 /* */
1928 /* Sliding window manipulation. Conditions includes: */
1929 /* 1. Incoming SeqNum is equal to WinStart =>Window shift 1 */
1930 /* 2. Incoming SeqNum is larger than the WinEnd => Window shift N */
1931 /* */
1932 if (SN_EQUAL(seq_num, preorder_ctrl->indicate_seq)) {
1933 preorder_ctrl->indicate_seq =
1934 (preorder_ctrl->indicate_seq + 1) & 0xFFF;
1935 } else if (SN_LESS(wend, seq_num)) {
1936 /* boundary situation, when seq_num cross 0xFFF */
1937 if (seq_num >= (wsize - 1))
1938 preorder_ctrl->indicate_seq = seq_num + 1 -wsize;
1939 else
1940 preorder_ctrl->indicate_seq = 0xFFF - (wsize - (seq_num + 1)) + 1;
1941 }
1942 return true;
1943}
1944
1945int enqueue_reorder_recvframe23a(struct recv_reorder_ctrl *preorder_ctrl,
1946 struct recv_frame *prframe)
1947{
1948 struct rx_pkt_attrib *pattrib = &prframe->attrib;
1949 struct rtw_queue *ppending_recvframe_queue;
1950 struct list_head *phead, *plist, *ptmp;
1951 struct recv_frame *hdr;
1952 struct rx_pkt_attrib *pnextattrib;
1953
1954 ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
1955 /* DbgPrint("+enqueue_reorder_recvframe23a()\n"); */
1956
1957 /* spin_lock_irqsave(&ppending_recvframe_queue->lock); */
1958 /* spin_lock_ex(&ppending_recvframe_queue->lock); */
1959
1960 phead = get_list_head(ppending_recvframe_queue);
1961
1962 list_for_each_safe(plist, ptmp, phead) {
1963 hdr = container_of(plist, struct recv_frame, list);
1964 pnextattrib = &hdr->attrib;
1965
1966 if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num)) {
1967 continue;
1968 } else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num)) {
1969 /* Duplicate entry is found!! Do not insert current entry. */
1970 /* RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum)); */
1971
1972 /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock); */
1973 return false;
1974 } else {
1975 break;
1976 }
1977
1978 /* DbgPrint("enqueue_reorder_recvframe23a():while\n"); */
1979 }
1980
1981 /* spin_lock_irqsave(&ppending_recvframe_queue->lock); */
1982 /* spin_lock_ex(&ppending_recvframe_queue->lock); */
1983
1984 list_del_init(&prframe->list);
1985
1986 list_add_tail(&prframe->list, plist);
1987
1988 /* spin_unlock_ex(&ppending_recvframe_queue->lock); */
1989 /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock); */
1990
1991 /* RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum)); */
1992 return true;
1993}
1994
1995int recv_indicatepkts_in_order(struct rtw_adapter *padapter,
1996 struct recv_reorder_ctrl *preorder_ctrl,
1997 int bforced);
1998int recv_indicatepkts_in_order(struct rtw_adapter *padapter,
1999 struct recv_reorder_ctrl *preorder_ctrl,
2000 int bforced)
2001{
2002 /* u8 bcancelled; */
2003 struct list_head *phead, *plist;
2004 struct recv_frame *prframe;
2005 struct rx_pkt_attrib *pattrib;
2006 /* u8 index = 0; */
2007 int bPktInBuf = false;
2008 struct recv_priv *precvpriv;
2009 struct rtw_queue *ppending_recvframe_queue;
2010
2011 precvpriv = &padapter->recvpriv;
2012 ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
2013 /* DbgPrint("+recv_indicatepkts_in_order\n"); */
2014
2015 /* spin_lock_irqsave(&ppending_recvframe_queue->lock); */
2016 /* spin_lock_ex(&ppending_recvframe_queue->lock); */
2017
2018 phead = get_list_head(ppending_recvframe_queue);
2019 plist = phead->next;
2020
2021 /* Handling some condition for forced indicate case. */
2022 if (bforced) {
2023 if (list_empty(phead)) {
2024 /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock); */
2025 /* spin_unlock_ex(&ppending_recvframe_queue->lock); */
2026 return true;
2027 }
2028
2029 prframe = container_of(plist, struct recv_frame, list);
2030 pattrib = &prframe->attrib;
2031 preorder_ctrl->indicate_seq = pattrib->seq_num;
2032 }
2033
2034 /* Prepare indication list and indication. */
2035 /* Check if there is any packet need indicate. */
2036 while (!list_empty(phead)) {
2037
2038 prframe = container_of(plist, struct recv_frame, list);
2039 pattrib = &prframe->attrib;
2040
2041 if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) {
2042 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2043 ("recv_indicatepkts_in_order: indicate =%d "
2044 "seq =%d amsdu =%d\n",
2045 preorder_ctrl->indicate_seq,
2046 pattrib->seq_num, pattrib->amsdu));
2047
2048 plist = plist->next;
2049 list_del_init(&prframe->list);
2050
2051 if (SN_EQUAL(preorder_ctrl->indicate_seq,
2052 pattrib->seq_num)) {
2053 preorder_ctrl->indicate_seq =
2054 (preorder_ctrl->indicate_seq + 1)&0xFFF;
2055 }
2056
2057 if (!pattrib->amsdu) {
2058 if ((padapter->bDriverStopped == false) &&
2059 (padapter->bSurpriseRemoved == false)) {
2060 rtw_recv_indicatepkt23a(padapter, prframe);
2061 }
2062 } else {
2063 if (amsdu_to_msdu(padapter, prframe) !=
2064 _SUCCESS) {
2065 rtw_free_recvframe23a(prframe,
2066 &precvpriv->free_recv_queue);
2067 }
2068 }
2069
2070 /* Update local variables. */
2071 bPktInBuf = false;
2072
2073 } else {
2074 bPktInBuf = true;
2075 break;
2076 }
2077
2078 /* DbgPrint("recv_indicatepkts_in_order():while\n"); */
2079 }
2080
2081 /* spin_unlock_ex(&ppending_recvframe_queue->lock); */
2082 /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock); */
2083
2084 return bPktInBuf;
2085}
2086
2087int recv_indicatepkt_reorder(struct rtw_adapter *padapter,
2088 struct recv_frame *prframe);
2089int recv_indicatepkt_reorder(struct rtw_adapter *padapter,
2090 struct recv_frame *prframe)
2091{
2092 int retval = _SUCCESS;
2093 struct rx_pkt_attrib *pattrib;
2094 struct recv_reorder_ctrl *preorder_ctrl;
2095 struct rtw_queue *ppending_recvframe_queue;
2096
2097 pattrib = &prframe->attrib;
2098 preorder_ctrl = prframe->preorder_ctrl;
2099 ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
2100
2101 if (!pattrib->amsdu) {
2102 /* s1. */
2103 wlanhdr_to_ethhdr(prframe);
2104
2105 if ((pattrib->qos!= 1) || (pattrib->eth_type == 0x0806) ||
2106 (pattrib->ack_policy != 0)) {
2107 if ((padapter->bDriverStopped == false) &&
2108 (padapter->bSurpriseRemoved == false)) {
2109 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2110 ("@@@@ recv_indicatepkt_reorder -"
2111 "recv_func recv_indicatepkt\n"));
2112
2113 rtw_recv_indicatepkt23a(padapter, prframe);
2114 return _SUCCESS;
2115 }
2116
2117 return _FAIL;
2118 }
2119
2120 if (preorder_ctrl->enable == false) {
2121 /* indicate this recv_frame */
2122 preorder_ctrl->indicate_seq = pattrib->seq_num;
2123 rtw_recv_indicatepkt23a(padapter, prframe);
2124
2125 preorder_ctrl->indicate_seq =
2126 (preorder_ctrl->indicate_seq + 1) % 4096;
2127 return _SUCCESS;
2128 }
2129 } else {
2130 /* temp filter -> means didn't support A-MSDUs in a A-MPDU */
2131 if (preorder_ctrl->enable == false) {
2132 preorder_ctrl->indicate_seq = pattrib->seq_num;
2133 retval = amsdu_to_msdu(padapter, prframe);
2134
2135 preorder_ctrl->indicate_seq =
2136 (preorder_ctrl->indicate_seq + 1) % 4096;
2137 return retval;
2138 }
2139 }
2140
2141 spin_lock_bh(&ppending_recvframe_queue->lock);
2142
2143 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2144 ("recv_indicatepkt_reorder: indicate =%d seq =%d\n",
2145 preorder_ctrl->indicate_seq, pattrib->seq_num));
2146
2147 /* s2. check if winstart_b(indicate_seq) needs to been updated */
2148 if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num)) {
2149 goto _err_exit;
2150 }
2151
2152 /* s3. Insert all packet into Reorder Queue to maintain its ordering. */
2153 if (!enqueue_reorder_recvframe23a(preorder_ctrl, prframe)) {
2154 goto _err_exit;
2155 }
2156
2157 /* s4. */
2158 /* Indication process. */
2159 /* After Packet dropping and Sliding Window shifting as above,
2160 we can now just indicate the packets */
2161 /* with the SeqNum smaller than latest WinStart and buffer
2162 other packets. */
2163 /* */
2164 /* For Rx Reorder condition: */
2165 /* 1. All packets with SeqNum smaller than WinStart => Indicate */
2166 /* 2. All packets with SeqNum larger than or equal to WinStart =>
2167 Buffer it. */
2168 /* */
2169
2170 if (recv_indicatepkts_in_order(padapter, preorder_ctrl, false) == true) {
2171 mod_timer(&preorder_ctrl->reordering_ctrl_timer,
2172 jiffies + msecs_to_jiffies(REORDER_WAIT_TIME));
2173 spin_unlock_bh(&ppending_recvframe_queue->lock);
2174 } else {
2175 spin_unlock_bh(&ppending_recvframe_queue->lock);
2176 del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
2177 }
2178 return _SUCCESS;
2179
2180_err_exit:
2181
2182 spin_unlock_bh(&ppending_recvframe_queue->lock);
2183 return _FAIL;
2184}
2185
2186void rtw_reordering_ctrl_timeout_handler23a(unsigned long pcontext)
2187{
2188 struct recv_reorder_ctrl *preorder_ctrl;
2189 struct rtw_adapter *padapter;
2190 struct rtw_queue *ppending_recvframe_queue;
2191
2192 preorder_ctrl = (struct recv_reorder_ctrl *)pcontext;
2193 padapter = preorder_ctrl->padapter;
2194 ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
2195
2196 if (padapter->bDriverStopped || padapter->bSurpriseRemoved) {
2197 return;
2198 }
2199
2200 /* DBG_8723A("+rtw_reordering_ctrl_timeout_handler23a() =>\n"); */
2201
2202 spin_lock_bh(&ppending_recvframe_queue->lock);
2203
2204 if (recv_indicatepkts_in_order(padapter, preorder_ctrl, true) == true) {
2205 mod_timer(&preorder_ctrl->reordering_ctrl_timer,
2206 jiffies + msecs_to_jiffies(REORDER_WAIT_TIME));
2207 }
2208
2209 spin_unlock_bh(&ppending_recvframe_queue->lock);
2210}
2211
2212int process_recv_indicatepkts(struct rtw_adapter *padapter,
2213 struct recv_frame *prframe);
2214int process_recv_indicatepkts(struct rtw_adapter *padapter,
2215 struct recv_frame *prframe)
2216{
2217 int retval = _SUCCESS;
2218 /* struct recv_priv *precvpriv = &padapter->recvpriv; */
2219 /* struct rx_pkt_attrib *pattrib = &prframe->attrib; */
2220 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2221 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2222
2223 if (phtpriv->ht_option == true) { /* B/G/N Mode */
2224 /* prframe->preorder_ctrl = &precvpriv->recvreorder_ctrl[pattrib->priority]; */
2225
2226 /* including perform A-MPDU Rx Ordering Buffer Control */
2227 if (recv_indicatepkt_reorder(padapter, prframe) != _SUCCESS) {
2228 if ((padapter->bDriverStopped == false) &&
2229 (padapter->bSurpriseRemoved == false)) {
2230 retval = _FAIL;
2231 return retval;
2232 }
2233 }
2234 } else /* B/G mode */
2235 {
2236 retval = wlanhdr_to_ethhdr(prframe);
2237 if (retval != _SUCCESS) {
2238 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
2239 ("wlanhdr_to_ethhdr: drop pkt\n"));
2240 return retval;
2241 }
2242
2243 if ((padapter->bDriverStopped == false) &&
2244 (padapter->bSurpriseRemoved == false)) {
2245 /* indicate this recv_frame */
2246 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2247 ("@@@@ process_recv_indicatepkts- "
2248 "recv_func recv_indicatepkt\n"));
2249 rtw_recv_indicatepkt23a(padapter, prframe);
2250 } else {
2251 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2252 ("@@@@ process_recv_indicatepkts- "
2253 "recv_func free_indicatepkt\n"));
2254
2255 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2256 ("recv_func:bDriverStopped(%d) OR "
2257 "bSurpriseRemoved(%d)",
2258 padapter->bDriverStopped,
2259 padapter->bSurpriseRemoved));
2260 retval = _FAIL;
2261 return retval;
2262 }
2263
2264 }
2265
2266 return retval;
2267}
2268
2269static int recv_func_prehandle(struct rtw_adapter *padapter,
2270 struct recv_frame *rframe)
2271{
2272 struct rtw_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
2273 int ret = _SUCCESS;
2274
2275 /* check the frame crtl field and decache */
2276 ret = validate_recv_frame(padapter, rframe);
2277 if (ret != _SUCCESS) {
2278 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
2279 ("recv_func: validate_recv_frame fail! drop pkt\n"));
2280 rtw_free_recvframe23a(rframe, pfree_recv_queue);
2281 goto exit;
2282 }
2283
2284exit:
2285 return ret;
2286}
2287
2288static int recv_func_posthandle(struct rtw_adapter *padapter,
2289 struct recv_frame *prframe)
2290{
2291 int ret = _SUCCESS;
2292 struct recv_frame *orig_prframe = prframe;
2293 struct recv_priv *precvpriv = &padapter->recvpriv;
2294 struct rtw_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
2295
2296 /* DATA FRAME */
2297 rtw_led_control(padapter, LED_CTL_RX);
2298
2299 prframe = decryptor(padapter, prframe);
2300 if (prframe == NULL) {
2301 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
2302 ("decryptor: drop pkt\n"));
2303 ret = _FAIL;
2304 goto _recv_data_drop;
2305 }
2306
2307 prframe = recvframe_chk_defrag23a(padapter, prframe);
2308 if (!prframe) {
2309 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
2310 ("recvframe_chk_defrag23a: drop pkt\n"));
2311 goto _recv_data_drop;
2312 }
2313
2314 /*
2315 * Pull off crypto headers
2316 */
2317 if (prframe->attrib.iv_len > 0) {
2318 skb_pull(prframe->pkt, prframe->attrib.iv_len);
2319 }
2320
2321 if (prframe->attrib.icv_len > 0) {
2322 skb_trim(prframe->pkt,
2323 prframe->pkt->len - prframe->attrib.icv_len);
2324 }
2325
2326 prframe = portctrl(padapter, prframe);
2327 if (!prframe) {
2328 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
2329 ("portctrl: drop pkt\n"));
2330 ret = _FAIL;
2331 goto _recv_data_drop;
2332 }
2333
2334 count_rx_stats(padapter, prframe, NULL);
2335
2336 ret = process_recv_indicatepkts(padapter, prframe);
2337 if (ret != _SUCCESS) {
2338 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
2339 ("recv_func: process_recv_indicatepkts fail!\n"));
2340 rtw_free_recvframe23a(orig_prframe, pfree_recv_queue);/* free this recv_frame */
2341 goto _recv_data_drop;
2342 }
2343 return ret;
2344
2345_recv_data_drop:
2346 precvpriv->rx_drop++;
2347 return ret;
2348}
2349
2350int rtw_recv_entry23a(struct recv_frame *rframe)
2351{
2352 int ret, r;
2353 struct rtw_adapter *padapter = rframe->adapter;
2354 struct rx_pkt_attrib *prxattrib = &rframe->attrib;
2355 struct recv_priv *recvpriv = &padapter->recvpriv;
2356 struct security_priv *psecuritypriv = &padapter->securitypriv;
2357 struct mlme_priv *mlmepriv = &padapter->mlmepriv;
2358
2359 /* check if need to handle uc_swdec_pending_queue*/
2360 if (check_fwstate(mlmepriv, WIFI_STATION_STATE) &&
2361 psecuritypriv->busetkipkey) {
2362 struct recv_frame *pending_frame;
2363
2364 while ((pending_frame = rtw_alloc_recvframe23a(&padapter->recvpriv.uc_swdec_pending_queue))) {
2365 r = recv_func_posthandle(padapter, pending_frame);
2366 if (r == _SUCCESS)
2367 DBG_8723A("%s: dequeue uc_swdec_pending_queue\n", __func__);
2368 }
2369 }
2370
2371 ret = recv_func_prehandle(padapter, rframe);
2372
2373 if (ret == _SUCCESS) {
2374 /* check if need to enqueue into uc_swdec_pending_queue*/
2375 if (check_fwstate(mlmepriv, WIFI_STATION_STATE) &&
2376 !is_multicast_ether_addr(prxattrib->ra) &&
2377 prxattrib->encrypt > 0 &&
2378 (prxattrib->bdecrypted == 0) &&
2379 !is_wep_enc(psecuritypriv->dot11PrivacyAlgrthm) &&
2380 !psecuritypriv->busetkipkey) {
2381 rtw_enqueue_recvframe23a(rframe, &padapter->recvpriv.uc_swdec_pending_queue);
2382 DBG_8723A("%s: no key, enqueue uc_swdec_pending_queue\n", __func__);
2383 goto exit;
2384 }
2385
2386 ret = recv_func_posthandle(padapter, rframe);
2387
2388 recvpriv->rx_pkts++;
2389 }
2390
2391exit:
2392 return ret;
2393}
2394
2395void rtw_signal_stat_timer_hdl23a(unsigned long data)
2396{
2397 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
2398 struct recv_priv *recvpriv = &adapter->recvpriv;
2399
2400 u32 tmp_s, tmp_q;
2401 u8 avg_signal_strength = 0;
2402 u8 avg_signal_qual = 0;
2403 u32 num_signal_strength = 0;
2404 u32 num_signal_qual = 0;
2405 u8 _alpha = 3; /* this value is based on converging_constant = 5000 */
2406 /* and sampling_interval = 1000 */
2407
2408 if (adapter->recvpriv.is_signal_dbg) {
2409 /* update the user specific value, signal_strength_dbg, */
2410 /* to signal_strength, rssi */
2411 adapter->recvpriv.signal_strength =
2412 adapter->recvpriv.signal_strength_dbg;
2413 adapter->recvpriv.rssi =
2414 (s8)translate_percentage_to_dbm((u8)adapter->recvpriv.signal_strength_dbg);
2415 } else {
2416 if (recvpriv->signal_strength_data.update_req == 0) {
2417 /* update_req is clear, means we got rx */
2418 avg_signal_strength =
2419 recvpriv->signal_strength_data.avg_val;
2420 num_signal_strength =
2421 recvpriv->signal_strength_data.total_num;
2422 /* after avg_vals are accquired, we can re-stat */
2423 /* the signal values */
2424 recvpriv->signal_strength_data.update_req = 1;
2425 }
2426
2427 if (recvpriv->signal_qual_data.update_req == 0) {
2428 /* update_req is clear, means we got rx */
2429 avg_signal_qual = recvpriv->signal_qual_data.avg_val;
2430 num_signal_qual = recvpriv->signal_qual_data.total_num;
2431 /* after avg_vals are accquired, we can re-stat */
2432 /*the signal values */
2433 recvpriv->signal_qual_data.update_req = 1;
2434 }
2435
2436 /* update value of signal_strength, rssi, signal_qual */
2437 if (check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY) ==
2438 false) {
2439 tmp_s = (avg_signal_strength + (_alpha - 1) *
2440 recvpriv->signal_strength);
2441 if (tmp_s %_alpha)
2442 tmp_s = tmp_s / _alpha + 1;
2443 else
2444 tmp_s = tmp_s / _alpha;
2445 if (tmp_s > 100)
2446 tmp_s = 100;
2447
2448 tmp_q = (avg_signal_qual + (_alpha - 1) *
2449 recvpriv->signal_qual);
2450 if (tmp_q %_alpha)
2451 tmp_q = tmp_q / _alpha + 1;
2452 else
2453 tmp_q = tmp_q / _alpha;
2454 if (tmp_q > 100)
2455 tmp_q = 100;
2456
2457 recvpriv->signal_strength = tmp_s;
2458 recvpriv->rssi = (s8)translate_percentage_to_dbm(tmp_s);
2459 recvpriv->signal_qual = tmp_q;
2460
2461 DBG_8723A("%s signal_strength:%3u, rssi:%3d, "
2462 "signal_qual:%3u, num_signal_strength:%u, "
2463 "num_signal_qual:%u\n",
2464 __func__, recvpriv->signal_strength,
2465 recvpriv->rssi, recvpriv->signal_qual,
2466 num_signal_strength, num_signal_qual
2467 );
2468 }
2469 }
2470 rtw_set_signal_stat_timer(recvpriv);
2471}
diff --git a/drivers/staging/rtl8723au/core/rtw_security.c b/drivers/staging/rtl8723au/core/rtw_security.c
new file mode 100644
index 000000000000..0d457144fde7
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_security.c
@@ -0,0 +1,1653 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _RTW_SECURITY_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <wifi.h>
20#include <osdep_intf.h>
21
22/* WEP related ===== */
23
24#define CRC32_POLY 0x04c11db7
25
26struct arc4context
27{
28 u32 x;
29 u32 y;
30 u8 state[256];
31};
32
33static void arcfour_init(struct arc4context *parc4ctx, u8 * key, u32 key_len)
34{
35 u32 t, u;
36 u32 keyindex;
37 u32 stateindex;
38 u8 * state;
39 u32 counter;
40
41 state = parc4ctx->state;
42 parc4ctx->x = 0;
43 parc4ctx->y = 0;
44 for (counter = 0; counter < 256; counter++)
45 state[counter] = (u8)counter;
46 keyindex = 0;
47 stateindex = 0;
48 for (counter = 0; counter < 256; counter++)
49 {
50 t = state[counter];
51 stateindex = (stateindex + key[keyindex] + t) & 0xff;
52 u = state[stateindex];
53 state[stateindex] = (u8)t;
54 state[counter] = (u8)u;
55 if (++keyindex >= key_len)
56 keyindex = 0;
57 }
58
59}
60static u32 arcfour_byte( struct arc4context *parc4ctx)
61{
62 u32 x;
63 u32 y;
64 u32 sx, sy;
65 u8 * state;
66
67 state = parc4ctx->state;
68 x = (parc4ctx->x + 1) & 0xff;
69 sx = state[x];
70 y = (sx + parc4ctx->y) & 0xff;
71 sy = state[y];
72 parc4ctx->x = x;
73 parc4ctx->y = y;
74 state[y] = (u8)sx;
75 state[x] = (u8)sy;
76
77 return state[(sx + sy) & 0xff];
78}
79
80static void arcfour_encrypt( struct arc4context *parc4ctx,
81 u8 * dest,
82 u8 * src,
83 u32 len)
84{
85 u32 i;
86
87 for (i = 0; i < len; i++)
88 dest[i] = src[i] ^ (unsigned char)arcfour_byte(parc4ctx);
89
90}
91
92static int bcrc32initialized = 0;
93static u32 crc32_table[256];
94
95static u8 crc32_reverseBit(u8 data)
96{
97 u8 retval = ((data << 7) & 0x80) | ((data << 5) & 0x40) |
98 ((data << 3) & 0x20) | ((data << 1) & 0x10) |
99 ((data >> 1) & 0x08) | ((data >> 3) & 0x04) |
100 ((data >> 5) & 0x02) | ((data >> 7) & 0x01);
101 return retval;
102}
103
104static void crc32_init(void)
105{
106
107 if (bcrc32initialized == 1)
108 return;
109 else{
110 int i, j;
111 u32 c;
112 u8 *p = (u8 *)&c, *p1;
113 u8 k;
114
115 c = 0x12340000;
116
117 for (i = 0; i < 256; ++i)
118 {
119 k = crc32_reverseBit((u8)i);
120 for (c = ((u32)k) << 24, j = 8; j > 0; --j) {
121 c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1);
122 }
123 p1 = (u8 *)&crc32_table[i];
124
125 p1[0] = crc32_reverseBit(p[3]);
126 p1[1] = crc32_reverseBit(p[2]);
127 p1[2] = crc32_reverseBit(p[1]);
128 p1[3] = crc32_reverseBit(p[0]);
129 }
130 bcrc32initialized = 1;
131 }
132}
133
134static u32 getcrc32(u8 *buf, int len)
135{
136 u8 *p;
137 u32 crc;
138
139 if (bcrc32initialized == 0) crc32_init();
140
141 crc = 0xffffffff; /* preload shift register, per CRC-32 spec */
142
143 for (p = buf; len > 0; ++p, --len)
144 crc = crc32_table[ (crc ^ *p) & 0xff] ^ (crc >> 8);
145
146 return ~crc; /* transmit complement, per CRC-32 spec */
147}
148
149/* Need to consider the fragment situation */
150void rtw_wep_encrypt23a(struct rtw_adapter *padapter,
151 struct xmit_frame *pxmitframe)
152{
153 /* exclude ICV */
154 unsigned char crc[4];
155 struct arc4context mycontext;
156 int curfragnum, length, index;
157 u32 keylength;
158 u8 *pframe, *payload, *iv; /* wepkey */
159 u8 wepkey[16];
160 u8 hw_hdr_offset = 0;
161 struct pkt_attrib *pattrib = &pxmitframe->attrib;
162 struct security_priv *psecuritypriv = &padapter->securitypriv;
163 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
164
165 if (!pxmitframe->buf_addr)
166 return;
167
168 hw_hdr_offset = TXDESC_OFFSET;
169
170 pframe = pxmitframe->buf_addr + hw_hdr_offset;
171
172 /* start to encrypt each fragment */
173 if ((pattrib->encrypt != _WEP40_) && (pattrib->encrypt != _WEP104_))
174 return;
175
176 index = psecuritypriv->dot11PrivacyKeyIndex;
177 keylength = psecuritypriv->dot11DefKeylen[index];
178
179 for (curfragnum = 0; curfragnum < pattrib->nr_frags ; curfragnum++) {
180 iv = pframe + pattrib->hdrlen;
181 memcpy(&wepkey[0], iv, 3);
182 memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[index].skey[0],
183 keylength);
184 payload = pframe + pattrib->iv_len + pattrib->hdrlen;
185
186 if ((curfragnum + 1) == pattrib->nr_frags) {
187 /* the last fragment */
188 length = pattrib->last_txcmdsz - pattrib->hdrlen -
189 pattrib->iv_len- pattrib->icv_len;
190
191 *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));
192
193 arcfour_init(&mycontext, wepkey, 3 + keylength);
194 arcfour_encrypt(&mycontext, payload, payload, length);
195 arcfour_encrypt(&mycontext, payload + length, crc, 4);
196 } else {
197 length = pxmitpriv->frag_len - pattrib->hdrlen -
198 pattrib->iv_len - pattrib->icv_len;
199 *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));
200 arcfour_init(&mycontext, wepkey, 3 + keylength);
201 arcfour_encrypt(&mycontext, payload, payload, length);
202 arcfour_encrypt(&mycontext, payload + length, crc, 4);
203
204 pframe += pxmitpriv->frag_len;
205 pframe = (u8 *)RND4((unsigned long)(pframe));
206 }
207 }
208
209}
210
211void rtw_wep_decrypt23a(struct rtw_adapter *padapter,
212 struct recv_frame *precvframe)
213{
214 /* exclude ICV */
215 u8 crc[4];
216 struct arc4context mycontext;
217 int length;
218 u32 keylength;
219 u8 *pframe, *payload, *iv, wepkey[16];
220 u8 keyindex;
221 struct rx_pkt_attrib *prxattrib = &precvframe->attrib;
222 struct security_priv *psecuritypriv = &padapter->securitypriv;
223 struct sk_buff * skb = precvframe->pkt;
224
225 pframe = skb->data;
226
227 /* start to decrypt recvframe */
228 if ((prxattrib->encrypt =! _WEP40_) && (prxattrib->encrypt != _WEP104_))
229 return;
230
231 iv = pframe + prxattrib->hdrlen;
232 /* keyindex = (iv[3]&0x3); */
233 keyindex = prxattrib->key_index;
234 keylength = psecuritypriv->dot11DefKeylen[keyindex];
235 memcpy(&wepkey[0], iv, 3);
236 /* memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0], keylength); */
237 memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[keyindex].skey[0],
238 keylength);
239 length = skb->len - prxattrib->hdrlen - prxattrib->iv_len;
240
241 payload = pframe + prxattrib->iv_len + prxattrib->hdrlen;
242
243 /* decrypt payload include icv */
244 arcfour_init(&mycontext, wepkey, 3 + keylength);
245 arcfour_encrypt(&mycontext, payload, payload, length);
246
247 /* calculate icv and compare the icv */
248 *((u32 *)crc) = le32_to_cpu(getcrc32(payload, length - 4));
249
250 if (crc[3] != payload[length - 1] || crc[2] != payload[length - 2] ||
251 crc[1] != payload[length - 3] || crc[0] != payload[length - 4]) {
252 RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
253 ("rtw_wep_decrypt23a:icv error crc[3](%x)!= payload"
254 "[length-1](%x) || crc[2](%x)!= payload[length-2](%x)"
255 " || crc[1](%x)!= payload[length-3](%x) || crc[0](%x)"
256 "!= payload[length-4](%x)\n",
257 crc[3], payload[length - 1],
258 crc[2], payload[length - 2],
259 crc[1], payload[length - 3],
260 crc[0], payload[length - 4]));
261 }
262
263 return;
264}
265
266/* 3 ===== TKIP related ===== */
267
268static u32 secmicgetuint32(u8 * p)
269/* Convert from Byte[] to u32 in a portable way */
270{
271 s32 i;
272 u32 res = 0;
273
274 for (i = 0; i<4; i++)
275 {
276 res |= ((u32)(*p++)) << (8*i);
277 }
278
279 return res;
280}
281
282static void secmicputuint32(u8 * p, u32 val)
283/* Convert from long to Byte[] in a portable way */
284{
285 long i;
286
287 for (i = 0; i<4; i++)
288 {
289 *p++ = (u8) (val & 0xff);
290 val >>= 8;
291 }
292
293}
294
295static void secmicclear(struct mic_data *pmicdata)
296{
297/* Reset the state to the empty message. */
298
299 pmicdata->L = pmicdata->K0;
300 pmicdata->R = pmicdata->K1;
301 pmicdata->nBytesInM = 0;
302 pmicdata->M = 0;
303
304}
305
306void rtw_secmicsetkey23a(struct mic_data *pmicdata, u8 * key)
307{
308 /* Set the key */
309
310 pmicdata->K0 = secmicgetuint32(key);
311 pmicdata->K1 = secmicgetuint32(key + 4);
312 /* and reset the message */
313 secmicclear(pmicdata);
314
315}
316
317void rtw_secmicappend23abyte23a(struct mic_data *pmicdata, u8 b)
318{
319
320 /* Append the byte to our word-sized buffer */
321 pmicdata->M |= ((unsigned long)b) << (8*pmicdata->nBytesInM);
322 pmicdata->nBytesInM++;
323 /* Process the word if it is full. */
324 if (pmicdata->nBytesInM >= 4)
325 {
326 pmicdata->L ^= pmicdata->M;
327 pmicdata->R ^= ROL32(pmicdata->L, 17);
328 pmicdata->L += pmicdata->R;
329 pmicdata->R ^= ((pmicdata->L & 0xff00ff00) >> 8) | ((pmicdata->L & 0x00ff00ff) << 8);
330 pmicdata->L += pmicdata->R;
331 pmicdata->R ^= ROL32(pmicdata->L, 3);
332 pmicdata->L += pmicdata->R;
333 pmicdata->R ^= ROR32(pmicdata->L, 2);
334 pmicdata->L += pmicdata->R;
335 /* Clear the buffer */
336 pmicdata->M = 0;
337 pmicdata->nBytesInM = 0;
338 }
339
340}
341
342void rtw_secmicappend23a(struct mic_data *pmicdata, u8 * src, u32 nbytes)
343{
344
345 /* This is simple */
346 while(nbytes > 0)
347 {
348 rtw_secmicappend23abyte23a(pmicdata, *src++);
349 nbytes--;
350 }
351
352}
353
354void rtw_secgetmic23a(struct mic_data *pmicdata, u8 * dst)
355{
356
357 /* Append the minimum padding */
358 rtw_secmicappend23abyte23a(pmicdata, 0x5a);
359 rtw_secmicappend23abyte23a(pmicdata, 0);
360 rtw_secmicappend23abyte23a(pmicdata, 0);
361 rtw_secmicappend23abyte23a(pmicdata, 0);
362 rtw_secmicappend23abyte23a(pmicdata, 0);
363 /* and then zeroes until the length is a multiple of 4 */
364 while(pmicdata->nBytesInM != 0)
365 {
366 rtw_secmicappend23abyte23a(pmicdata, 0);
367 }
368 /* The appendByte function has already computed the result. */
369 secmicputuint32(dst, pmicdata->L);
370 secmicputuint32(dst+4, pmicdata->R);
371 /* Reset to the empty message. */
372 secmicclear(pmicdata);
373
374}
375
376void rtw_seccalctkipmic23a(u8 * key, u8 *header, u8 *data, u32 data_len, u8 *mic_code, u8 pri)
377{
378
379 struct mic_data micdata;
380 u8 priority[4]={0x0, 0x0, 0x0, 0x0};
381
382 rtw_secmicsetkey23a(&micdata, key);
383 priority[0]= pri;
384
385 /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
386 if (header[1]&1) { /* ToDS == 1 */
387 rtw_secmicappend23a(&micdata, &header[16], 6); /* DA */
388 if (header[1]&2) /* From Ds == 1 */
389 rtw_secmicappend23a(&micdata, &header[24], 6);
390 else
391 rtw_secmicappend23a(&micdata, &header[10], 6);
392 }
393 else{ /* ToDS == 0 */
394 rtw_secmicappend23a(&micdata, &header[4], 6); /* DA */
395 if (header[1]&2) /* From Ds == 1 */
396 rtw_secmicappend23a(&micdata, &header[16], 6);
397 else
398 rtw_secmicappend23a(&micdata, &header[10], 6);
399
400 }
401 rtw_secmicappend23a(&micdata, &priority[0], 4);
402
403 rtw_secmicappend23a(&micdata, data, data_len);
404
405 rtw_secgetmic23a(&micdata, mic_code);
406
407}
408
409/* macros for extraction/creation of unsigned char/unsigned short values */
410#define RotR1(v16) ((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15))
411#define Lo8(v16) ((u8)((v16) & 0x00FF))
412#define Hi8(v16) ((u8)(((v16) >> 8) & 0x00FF))
413#define Lo16(v32) ((u16)((v32) & 0xFFFF))
414#define Hi16(v32) ((u16)(((v32) >>16) & 0xFFFF))
415#define Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8))
416
417/* select the Nth 16-bit word of the temporal key unsigned char array TK[] */
418#define TK16(N) Mk16(tk[2*(N)+1], tk[2*(N)])
419
420/* S-box lookup: 16 bits --> 16 bits */
421#define _S_(v16) (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)])
422
423/* fixed algorithm "parameters" */
424#define PHASE1_LOOP_CNT 8 /* this needs to be "big enough" */
425#define TA_SIZE 6 /* 48-bit transmitter address */
426#define TK_SIZE 16 /* 128-bit temporal key */
427#define P1K_SIZE 10 /* 80-bit Phase1 key */
428#define RC4_KEY_SIZE 16 /* 128-bit RC4KEY (104 bits unknown) */
429
430/* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */
431static const unsigned short Sbox1[2][256]= /* Sbox for hash (can be in ROM) */
432{ {
433 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
434 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
435 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
436 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
437 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
438 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
439 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
440 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
441 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
442 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
443 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
444 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
445 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
446 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
447 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
448 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
449 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
450 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
451 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
452 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
453 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
454 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
455 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
456 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
457 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
458 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
459 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
460 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
461 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
462 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
463 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
464 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
465 },
466
467 { /* second half of table is unsigned char-reversed version of first! */
468 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491,
469 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC,
470 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB,
471 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B,
472 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83,
473 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A,
474 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F,
475 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA,
476 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B,
477 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713,
478 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6,
479 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85,
480 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411,
481 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B,
482 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1,
483 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF,
484 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E,
485 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6,
486 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B,
487 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD,
488 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8,
489 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2,
490 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049,
491 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810,
492 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197,
493 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F,
494 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C,
495 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927,
496 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733,
497 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5,
498 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0,
499 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C,
500 }
501};
502
503 /*
504**********************************************************************
505* Routine: Phase 1 -- generate P1K, given TA, TK, IV32
506*
507* Inputs:
508* tk[] = temporal key [128 bits]
509* ta[] = transmitter's MAC address [ 48 bits]
510* iv32 = upper 32 bits of IV [ 32 bits]
511* Output:
512* p1k[] = Phase 1 key [ 80 bits]
513*
514* Note:
515* This function only needs to be called every 2**16 packets,
516* although in theory it could be called every packet.
517*
518**********************************************************************
519*/
520static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32)
521{
522 int i;
523
524 /* Initialize the 80 bits of P1K[] from IV32 and TA[0..5] */
525 p1k[0] = Lo16(iv32);
526 p1k[1] = Hi16(iv32);
527 p1k[2] = Mk16(ta[1], ta[0]); /* use TA[] as little-endian */
528 p1k[3] = Mk16(ta[3], ta[2]);
529 p1k[4] = Mk16(ta[5], ta[4]);
530
531 /* Now compute an unbalanced Feistel cipher with 80-bit block */
532 /* size on the 80-bit block P1K[], using the 128-bit key TK[] */
533 for (i = 0; i < PHASE1_LOOP_CNT ;i++)
534 { /* Each add operation here is mod 2**16 */
535 p1k[0] += _S_(p1k[4] ^ TK16((i&1)+0));
536 p1k[1] += _S_(p1k[0] ^ TK16((i&1)+2));
537 p1k[2] += _S_(p1k[1] ^ TK16((i&1)+4));
538 p1k[3] += _S_(p1k[2] ^ TK16((i&1)+6));
539 p1k[4] += _S_(p1k[3] ^ TK16((i&1)+0));
540 p1k[4] += (unsigned short)i; /* avoid "slide attacks" */
541 }
542
543}
544
545/*
546**********************************************************************
547* Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16
548*
549* Inputs:
550* tk[] = Temporal key [128 bits]
551* p1k[] = Phase 1 output key [ 80 bits]
552* iv16 = low 16 bits of IV counter [ 16 bits]
553* Output:
554* rc4key[] = the key used to encrypt the packet [128 bits]
555*
556* Note:
557* The value {TA, IV32, IV16} for Phase1/Phase2 must be unique
558* across all packets using the same key TK value. Then, for a
559* given value of TK[], this TKIP48 construction guarantees that
560* the final RC4KEY value is unique across all packets.
561*
562* Suggested implementation optimization: if PPK[] is "overlaid"
563* appropriately on RC4KEY[], there is no need for the final
564* for loop below that copies the PPK[] result into RC4KEY[].
565*
566**********************************************************************
567*/
568static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16)
569{
570 int i;
571 u16 PPK[6]; /* temporary key for mixing */
572
573 /* Note: all adds in the PPK[] equations below are mod 2**16 */
574 for (i = 0;i<5;i++) PPK[i]= p1k[i]; /* first, copy P1K to PPK */
575 PPK[5] = p1k[4] +iv16; /* next, add in IV16 */
576
577 /* Bijective non-linear mixing of the 96 bits of PPK[0..5] */
578 PPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each "round" */
579 PPK[1] += _S_(PPK[0] ^ TK16(1));
580 PPK[2] += _S_(PPK[1] ^ TK16(2));
581 PPK[3] += _S_(PPK[2] ^ TK16(3));
582 PPK[4] += _S_(PPK[3] ^ TK16(4));
583 PPK[5] += _S_(PPK[4] ^ TK16(5)); /* Total # S-box lookups == 6 */
584
585 /* Final sweep: bijective, "linear". Rotates kill LSB correlations */
586 PPK[0] += RotR1(PPK[5] ^ TK16(6));
587 PPK[1] += RotR1(PPK[0] ^ TK16(7)); /* Use all of TK[] in Phase2 */
588 PPK[2] += RotR1(PPK[1]);
589 PPK[3] += RotR1(PPK[2]);
590 PPK[4] += RotR1(PPK[3]);
591 PPK[5] += RotR1(PPK[4]);
592 /* Note: At this point, for a given key TK[0..15], the 96-bit output */
593 /* value PPK[0..5] is guaranteed to be unique, as a function */
594 /* of the 96-bit "input" value {TA, IV32, IV16}. That is, P1K */
595 /* is now a keyed permutation of {TA, IV32, IV16}. */
596
597 /* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key */
598 rc4key[0] = Hi8(iv16); /* RC4KEY[0..2] is the WEP IV */
599 rc4key[1] = (Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys */
600 rc4key[2] = Lo8(iv16);
601 rc4key[3] = Lo8((PPK[5] ^ TK16(0)) >> 1);
602
603 /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */
604 for (i = 0;i<6;i++)
605 {
606 rc4key[4+2*i] = Lo8(PPK[i]);
607 rc4key[5+2*i] = Hi8(PPK[i]);
608 }
609
610}
611
612/* The hlen isn't include the IV */
613u32 rtw_tkip_encrypt23a(struct rtw_adapter *padapter,
614 struct xmit_frame *pxmitframe)
615{ /* exclude ICV */
616 u16 pnl;
617 u32 pnh;
618 u8 rc4key[16];
619 u8 ttkey[16];
620 u8 crc[4];
621 u8 hw_hdr_offset = 0;
622 struct arc4context mycontext;
623 int curfragnum, length;
624 u32 prwskeylen;
625
626 u8 *pframe, *payload,*iv,*prwskey;
627 union pn48 dot11txpn;
628 struct sta_info *stainfo;
629 struct pkt_attrib *pattrib = &pxmitframe->attrib;
630 struct security_priv *psecuritypriv = &padapter->securitypriv;
631 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
632 u32 res = _SUCCESS;
633
634 if (!pxmitframe->buf_addr)
635 return _FAIL;
636
637 hw_hdr_offset = TXDESC_OFFSET;
638
639 pframe = pxmitframe->buf_addr + hw_hdr_offset;
640 /* 4 start to encrypt each fragment */
641 if (pattrib->encrypt == _TKIP_) {
642
643 if (pattrib->psta)
644 {
645 stainfo = pattrib->psta;
646 }
647 else
648 {
649 DBG_8723A("%s, call rtw_get_stainfo()\n", __func__);
650 stainfo = rtw_get_stainfo23a(&padapter->stapriv,
651 &pattrib->ra[0]);
652 }
653
654 if (stainfo!= NULL) {
655
656 if (!(stainfo->state &_FW_LINKED))
657 {
658 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, stainfo->state);
659 return _FAIL;
660 }
661
662 RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_encrypt23a: stainfo!= NULL!!!\n"));
663
664 if (is_multicast_ether_addr(pattrib->ra))
665 prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
666 else
667 prwskey = &stainfo->dot118021x_UncstKey.skey[0];
668
669 prwskeylen = 16;
670
671 for (curfragnum = 0;curfragnum<pattrib->nr_frags;curfragnum++) {
672 iv = pframe+pattrib->hdrlen;
673 payload = pframe+pattrib->iv_len+pattrib->hdrlen;
674
675 GET_TKIP_PN(iv, dot11txpn);
676
677 pnl = (u16)(dot11txpn.val);
678 pnh = (u32)(dot11txpn.val>>16);
679
680 phase1((u16 *)&ttkey[0], prwskey,&pattrib->ta[0], pnh);
681
682 phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0], pnl);
683
684 if ((curfragnum+1) == pattrib->nr_frags) { /* 4 the last fragment */
685 length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len- pattrib->icv_len;
686 RT_TRACE(_module_rtl871x_security_c_, _drv_info_, ("pattrib->iv_len =%x, pattrib->icv_len =%x\n", pattrib->iv_len, pattrib->icv_len));
687 *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));/* modified by Amy*/
688
689 arcfour_init(&mycontext, rc4key, 16);
690 arcfour_encrypt(&mycontext, payload, payload, length);
691 arcfour_encrypt(&mycontext, payload+length, crc, 4);
692
693 }
694 else{
695 length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len ;
696 *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));/* modified by Amy*/
697 arcfour_init(&mycontext, rc4key, 16);
698 arcfour_encrypt(&mycontext, payload, payload, length);
699 arcfour_encrypt(&mycontext, payload+length, crc, 4);
700
701 pframe+= pxmitpriv->frag_len;
702 pframe = (u8 *)RND4((unsigned long)(pframe));
703
704 }
705 }
706
707 }
708 else{
709 RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_encrypt23a: stainfo == NULL!!!\n"));
710 DBG_8723A("%s, psta == NUL\n", __func__);
711 res = _FAIL;
712 }
713
714 }
715
716 return res;
717}
718
719/* The hlen isn't include the IV */
720u32 rtw_tkip_decrypt23a(struct rtw_adapter *padapter,
721 struct recv_frame *precvframe)
722{
723 /* exclude ICV */
724 u16 pnl;
725 u32 pnh;
726 u8 rc4key[16];
727 u8 ttkey[16];
728 u8 crc[4];
729 struct arc4context mycontext;
730 int length;
731 u32 prwskeylen;
732 u8 *pframe, *payload,*iv,*prwskey;
733 union pn48 dot11txpn;
734 struct sta_info *stainfo;
735 struct rx_pkt_attrib *prxattrib = &precvframe->attrib;
736 struct security_priv *psecuritypriv = &padapter->securitypriv;
737 struct sk_buff * skb = precvframe->pkt;
738 u32 res = _SUCCESS;
739
740 pframe = skb->data;
741
742 /* 4 start to decrypt recvframe */
743 if (prxattrib->encrypt == _TKIP_) {
744
745 stainfo = rtw_get_stainfo23a(&padapter->stapriv,
746 &prxattrib->ta[0]);
747 if (stainfo!= NULL) {
748
749 if (is_multicast_ether_addr(prxattrib->ra)) {
750 if (psecuritypriv->binstallGrpkey == false) {
751 res = _FAIL;
752 DBG_8723A("%s:rx bc/mc packets, but didn't install group key!!!!!!!!!!\n", __func__);
753 goto exit;
754 }
755 prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
756 prwskeylen = 16;
757 } else {
758 RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_decrypt23a: stainfo!= NULL!!!\n"));
759 prwskey = &stainfo->dot118021x_UncstKey.skey[0];
760 prwskeylen = 16;
761 }
762
763 iv = pframe+prxattrib->hdrlen;
764 payload = pframe+prxattrib->iv_len+prxattrib->hdrlen;
765 length = skb->len - prxattrib->hdrlen-prxattrib->iv_len;
766
767 GET_TKIP_PN(iv, dot11txpn);
768
769 pnl = (u16)(dot11txpn.val);
770 pnh = (u32)(dot11txpn.val>>16);
771
772 phase1((u16 *)&ttkey[0], prwskey,&prxattrib->ta[0], pnh);
773 phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl);
774
775 /* 4 decrypt payload include icv */
776 arcfour_init(&mycontext, rc4key, 16);
777 arcfour_encrypt(&mycontext, payload, payload, length);
778
779 *((u32 *)crc) = le32_to_cpu(getcrc32(payload, length-4));
780
781 if (crc[3]!= payload[length-1] || crc[2]!= payload[length-2] || crc[1]!= payload[length-3] || crc[0]!= payload[length-4])
782 {
783 RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_wep_decrypt23a:icv error crc[3](%x)!= payload[length-1](%x) || crc[2](%x)!= payload[length-2](%x) || crc[1](%x)!= payload[length-3](%x) || crc[0](%x)!= payload[length-4](%x)\n",
784 crc[3], payload[length-1], crc[2], payload[length-2], crc[1], payload[length-3], crc[0], payload[length-4]));
785 res = _FAIL;
786 }
787 } else {
788 RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_decrypt23a: stainfo == NULL!!!\n"));
789 res = _FAIL;
790 }
791 }
792exit:
793 return res;
794}
795
796/* 3 ===== AES related ===== */
797
798#define MAX_MSG_SIZE 2048
799/*****************************/
800/******** SBOX Table *********/
801/*****************************/
802
803static u8 sbox_table[256] = {
804 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
805 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
806 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
807 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
808 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
809 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
810 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
811 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
812 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
813 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
814 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
815 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
816 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
817 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
818 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
819 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
820 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
821 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
822 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
823 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
824 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
825 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
826 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
827 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
828 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
829 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
830 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
831 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
832 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
833 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
834 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
835 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
836};
837
838/*****************************/
839/**** Function Prototypes ****/
840/*****************************/
841
842static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists,
843 int qc_exists);
844
845static void xor_128(u8 *a, u8 *b, u8 *out)
846{
847 int i;
848
849 for (i = 0;i<16; i++)
850 out[i] = a[i] ^ b[i];
851}
852
853static void xor_32(u8 *a, u8 *b, u8 *out)
854{
855 int i;
856
857 for (i = 0; i < 4; i++)
858 out[i] = a[i] ^ b[i];
859}
860
861static u8 sbox(u8 a)
862{
863 return sbox_table[(int)a];
864}
865
866static void next_key(u8 *key, int round)
867{
868 u8 rcon;
869 u8 sbox_key[4];
870 u8 rcon_table[12] =
871 {
872 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
873 0x1b, 0x36, 0x36, 0x36
874 };
875
876 sbox_key[0] = sbox(key[13]);
877 sbox_key[1] = sbox(key[14]);
878 sbox_key[2] = sbox(key[15]);
879 sbox_key[3] = sbox(key[12]);
880
881 rcon = rcon_table[round];
882
883 xor_32(&key[0], sbox_key, &key[0]);
884 key[0] = key[0] ^ rcon;
885
886 xor_32(&key[4], &key[0], &key[4]);
887 xor_32(&key[8], &key[4], &key[8]);
888 xor_32(&key[12], &key[8], &key[12]);
889
890}
891
892static void byte_sub(u8 *in, u8 *out)
893{
894 int i;
895
896 for (i = 0; i< 16; i++)
897 {
898 out[i] = sbox(in[i]);
899 }
900
901}
902
903static void shift_row(u8 *in, u8 *out)
904{
905
906 out[0] = in[0];
907 out[1] = in[5];
908 out[2] = in[10];
909 out[3] = in[15];
910 out[4] = in[4];
911 out[5] = in[9];
912 out[6] = in[14];
913 out[7] = in[3];
914 out[8] = in[8];
915 out[9] = in[13];
916 out[10] = in[2];
917 out[11] = in[7];
918 out[12] = in[12];
919 out[13] = in[1];
920 out[14] = in[6];
921 out[15] = in[11];
922
923}
924
925static void mix_column(u8 *in, u8 *out)
926{
927 int i;
928 u8 add1b[4];
929 u8 add1bf7[4];
930 u8 rotl[4];
931 u8 swap_halfs[4];
932 u8 andf7[4];
933 u8 rotr[4];
934 u8 temp[4];
935 u8 tempb[4];
936
937 for (i = 0 ; i<4; i++)
938 {
939 if ((in[i] & 0x80) == 0x80)
940 add1b[i] = 0x1b;
941 else
942 add1b[i] = 0x00;
943 }
944
945 swap_halfs[0] = in[2]; /* Swap halfs */
946 swap_halfs[1] = in[3];
947 swap_halfs[2] = in[0];
948 swap_halfs[3] = in[1];
949
950 rotl[0] = in[3]; /* Rotate left 8 bits */
951 rotl[1] = in[0];
952 rotl[2] = in[1];
953 rotl[3] = in[2];
954
955 andf7[0] = in[0] & 0x7f;
956 andf7[1] = in[1] & 0x7f;
957 andf7[2] = in[2] & 0x7f;
958 andf7[3] = in[3] & 0x7f;
959
960 for (i = 3; i>0; i--) /* logical shift left 1 bit */
961 {
962 andf7[i] = andf7[i] << 1;
963 if ((andf7[i-1] & 0x80) == 0x80)
964 {
965 andf7[i] = (andf7[i] | 0x01);
966 }
967 }
968 andf7[0] = andf7[0] << 1;
969 andf7[0] = andf7[0] & 0xfe;
970
971 xor_32(add1b, andf7, add1bf7);
972
973 xor_32(in, add1bf7, rotr);
974
975 temp[0] = rotr[0]; /* Rotate right 8 bits */
976 rotr[0] = rotr[1];
977 rotr[1] = rotr[2];
978 rotr[2] = rotr[3];
979 rotr[3] = temp[0];
980
981 xor_32(add1bf7, rotr, temp);
982 xor_32(swap_halfs, rotl, tempb);
983 xor_32(temp, tempb, out);
984
985}
986
987static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext)
988{
989 int round;
990 int i;
991 u8 intermediatea[16];
992 u8 intermediateb[16];
993 u8 round_key[16];
994
995 for (i = 0; i<16; i++) round_key[i] = key[i];
996
997 for (round = 0; round < 11; round++)
998 {
999 if (round == 0)
1000 {
1001 xor_128(round_key, data, ciphertext);
1002 next_key(round_key, round);
1003 }
1004 else if (round == 10)
1005 {
1006 byte_sub(ciphertext, intermediatea);
1007 shift_row(intermediatea, intermediateb);
1008 xor_128(intermediateb, round_key, ciphertext);
1009 }
1010 else /* 1 - 9 */
1011 {
1012 byte_sub(ciphertext, intermediatea);
1013 shift_row(intermediatea, intermediateb);
1014 mix_column(&intermediateb[0], &intermediatea[0]);
1015 mix_column(&intermediateb[4], &intermediatea[4]);
1016 mix_column(&intermediateb[8], &intermediatea[8]);
1017 mix_column(&intermediateb[12], &intermediatea[12]);
1018 xor_128(intermediatea, round_key, ciphertext);
1019 next_key(round_key, round);
1020 }
1021 }
1022
1023}
1024
1025/************************************************/
1026/* construct_mic_iv() */
1027/* Builds the MIC IV from header fields and PN */
1028/************************************************/
1029static void construct_mic_iv(u8 *mic_iv, int qc_exists, int a4_exists, u8 *mpdu,
1030 uint payload_length, u8 *pn_vector)
1031{
1032 int i;
1033
1034 mic_iv[0] = 0x59;
1035 if (qc_exists && a4_exists)
1036 mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */
1037 if (qc_exists && !a4_exists)
1038 mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */
1039 if (!qc_exists)
1040 mic_iv[1] = 0x00;
1041 for (i = 2; i < 8; i++)
1042 mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */
1043 for (i = 8; i < 14; i++)
1044 mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */
1045 mic_iv[14] = (unsigned char)(payload_length / 256);
1046 mic_iv[15] = (unsigned char)(payload_length % 256);
1047}
1048
1049/************************************************/
1050/* construct_mic_header1() */
1051/* Builds the first MIC header block from */
1052/* header fields. */
1053/************************************************/
1054static void construct_mic_header1(u8 *mic_header1, int header_length, u8 *mpdu)
1055{
1056 mic_header1[0] = (u8)((header_length - 2) / 256);
1057 mic_header1[1] = (u8)((header_length - 2) % 256);
1058 mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */
1059 mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */
1060 mic_header1[4] = mpdu[4]; /* A1 */
1061 mic_header1[5] = mpdu[5];
1062 mic_header1[6] = mpdu[6];
1063 mic_header1[7] = mpdu[7];
1064 mic_header1[8] = mpdu[8];
1065 mic_header1[9] = mpdu[9];
1066 mic_header1[10] = mpdu[10]; /* A2 */
1067 mic_header1[11] = mpdu[11];
1068 mic_header1[12] = mpdu[12];
1069 mic_header1[13] = mpdu[13];
1070 mic_header1[14] = mpdu[14];
1071 mic_header1[15] = mpdu[15];
1072
1073}
1074
1075/************************************************/
1076 /* construct_mic_header2() */
1077/* Builds the last MIC header block from */
1078/* header fields. */
1079/************************************************/
1080static void construct_mic_header2(
1081 u8 *mic_header2,
1082 u8 *mpdu,
1083 int a4_exists,
1084 int qc_exists
1085 )
1086{
1087 int i;
1088
1089 for (i = 0; i<16; i++) mic_header2[i]= 0x00;
1090
1091 mic_header2[0] = mpdu[16]; /* A3 */
1092 mic_header2[1] = mpdu[17];
1093 mic_header2[2] = mpdu[18];
1094 mic_header2[3] = mpdu[19];
1095 mic_header2[4] = mpdu[20];
1096 mic_header2[5] = mpdu[21];
1097
1098 mic_header2[6] = 0x00;
1099 mic_header2[7] = 0x00; /* mpdu[23]; */
1100
1101 if (!qc_exists && a4_exists)
1102 {
1103 for (i = 0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */
1104
1105 }
1106
1107 if (qc_exists && !a4_exists)
1108 {
1109 mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */
1110 mic_header2[9] = mpdu[25] & 0x00;
1111 }
1112
1113 if (qc_exists && a4_exists)
1114 {
1115 for (i = 0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */
1116
1117 mic_header2[14] = mpdu[30] & 0x0f;
1118 mic_header2[15] = mpdu[31] & 0x00;
1119 }
1120
1121}
1122
1123/************************************************/
1124/* construct_mic_header2() */
1125/* Builds the last MIC header block from */
1126/* header fields. */
1127/************************************************/
1128static void construct_ctr_preload(u8 *ctr_preload, int a4_exists, int qc_exists,
1129 u8 *mpdu, u8 *pn_vector, int c)
1130{
1131 int i = 0;
1132
1133 for (i = 0; i<16; i++) ctr_preload[i] = 0x00;
1134 i = 0;
1135
1136 ctr_preload[0] = 0x01; /* flag */
1137 if (qc_exists && a4_exists)
1138 ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */
1139 if (qc_exists && !a4_exists)
1140 ctr_preload[1] = mpdu[24] & 0x0f;
1141
1142 for (i = 2; i < 8; i++)
1143 ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */
1144 for (i = 8; i < 14; i++)
1145 ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */
1146 ctr_preload[14] = (unsigned char) (c / 256); /* Ctr */
1147 ctr_preload[15] = (unsigned char) (c % 256);
1148
1149}
1150
1151/************************************/
1152/* bitwise_xor() */
1153/* A 128 bit, bitwise exclusive or */
1154/************************************/
1155static void bitwise_xor(u8 *ina, u8 *inb, u8 *out)
1156{
1157 int i;
1158
1159 for (i = 0; i < 16; i++)
1160 out[i] = ina[i] ^ inb[i];
1161}
1162
1163static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen)
1164{
1165 uint qc_exists, a4_exists, i, j, payload_remainder,
1166 num_blocks, payload_index;
1167 u8 pn_vector[6];
1168 u8 mic_iv[16];
1169 u8 mic_header1[16];
1170 u8 mic_header2[16];
1171 u8 ctr_preload[16];
1172 /* Intermediate Buffers */
1173 u8 chain_buffer[16];
1174 u8 aes_out[16];
1175 u8 padded_buffer[16];
1176 u8 mic[8];
1177 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)pframe;
1178 u16 frsubtype = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE;
1179
1180 memset((void *)mic_iv, 0, 16);
1181 memset((void *)mic_header1, 0, 16);
1182 memset((void *)mic_header2, 0, 16);
1183 memset((void *)ctr_preload, 0, 16);
1184 memset((void *)chain_buffer, 0, 16);
1185 memset((void *)aes_out, 0, 16);
1186 memset((void *)padded_buffer, 0, 16);
1187
1188 if ((hdrlen == sizeof(struct ieee80211_hdr_3addr) ||
1189 (hdrlen == sizeof(struct ieee80211_qos_hdr))))
1190 a4_exists = 0;
1191 else
1192 a4_exists = 1;
1193
1194 if (ieee80211_is_data(hdr->frame_control)) {
1195 if ((frsubtype == IEEE80211_STYPE_DATA_CFACK) ||
1196 (frsubtype == IEEE80211_STYPE_DATA_CFPOLL) ||
1197 (frsubtype == IEEE80211_STYPE_DATA_CFACKPOLL)) {
1198 qc_exists = 1;
1199 if (hdrlen != sizeof(struct ieee80211_qos_hdr))
1200 hdrlen += 2;
1201 } else if ((frsubtype == IEEE80211_STYPE_QOS_DATA) ||
1202 (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACK) ||
1203 (frsubtype == IEEE80211_STYPE_QOS_DATA_CFPOLL) ||
1204 (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACKPOLL)) {
1205 if (hdrlen != sizeof(struct ieee80211_qos_hdr))
1206 hdrlen += 2;
1207 qc_exists = 1;
1208 } else {
1209 qc_exists = 0;
1210 }
1211 } else {
1212 qc_exists = 0;
1213 }
1214 pn_vector[0]= pframe[hdrlen];
1215 pn_vector[1]= pframe[hdrlen+1];
1216 pn_vector[2]= pframe[hdrlen+4];
1217 pn_vector[3]= pframe[hdrlen+5];
1218 pn_vector[4]= pframe[hdrlen+6];
1219 pn_vector[5]= pframe[hdrlen+7];
1220
1221 construct_mic_iv(mic_iv, qc_exists, a4_exists, pframe, plen, pn_vector);
1222
1223 construct_mic_header1(mic_header1, hdrlen, pframe);
1224 construct_mic_header2(mic_header2, pframe, a4_exists, qc_exists);
1225
1226 payload_remainder = plen % 16;
1227 num_blocks = plen / 16;
1228
1229 /* Find start of payload */
1230 payload_index = (hdrlen + 8);
1231
1232 /* Calculate MIC */
1233 aes128k128d(key, mic_iv, aes_out);
1234 bitwise_xor(aes_out, mic_header1, chain_buffer);
1235 aes128k128d(key, chain_buffer, aes_out);
1236 bitwise_xor(aes_out, mic_header2, chain_buffer);
1237 aes128k128d(key, chain_buffer, aes_out);
1238
1239 for (i = 0; i < num_blocks; i++) {
1240 bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
1241
1242 payload_index += 16;
1243 aes128k128d(key, chain_buffer, aes_out);
1244 }
1245
1246 /* Add on the final payload block if it needs padding */
1247 if (payload_remainder > 0) {
1248 for (j = 0; j < 16; j++)
1249 padded_buffer[j] = 0x00;
1250 for (j = 0; j < payload_remainder; j++)
1251 padded_buffer[j] = pframe[payload_index++];
1252 bitwise_xor(aes_out, padded_buffer, chain_buffer);
1253 aes128k128d(key, chain_buffer, aes_out);
1254 }
1255
1256 for (j = 0; j < 8; j++)
1257 mic[j] = aes_out[j];
1258
1259 /* Insert MIC into payload */
1260 for (j = 0; j < 8; j++)
1261 pframe[payload_index+j] = mic[j];
1262
1263 payload_index = hdrlen + 8;
1264 for (i = 0; i < num_blocks; i++) {
1265 construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
1266 pframe, pn_vector, i+1);
1267 aes128k128d(key, ctr_preload, aes_out);
1268 bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
1269 for (j = 0; j < 16; j++)
1270 pframe[payload_index++] = chain_buffer[j];
1271 }
1272
1273 if (payload_remainder > 0) {
1274 /* If there is a short final block, then pad it,
1275 * encrypt it and copy the unpadded part back
1276 */
1277 construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe,
1278 pn_vector, num_blocks+1);
1279
1280 for (j = 0; j < 16; j++)
1281 padded_buffer[j] = 0x00;
1282 for (j = 0; j < payload_remainder; j++)
1283 padded_buffer[j] = pframe[payload_index+j];
1284 aes128k128d(key, ctr_preload, aes_out);
1285 bitwise_xor(aes_out, padded_buffer, chain_buffer);
1286 for (j = 0; j < payload_remainder;j++)
1287 pframe[payload_index++] = chain_buffer[j];
1288 }
1289
1290 /* Encrypt the MIC */
1291 construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe,
1292 pn_vector, 0);
1293
1294 for (j = 0; j < 16; j++)
1295 padded_buffer[j] = 0x00;
1296 for (j = 0; j < 8; j++)
1297 padded_buffer[j] = pframe[j+hdrlen+8+plen];
1298
1299 aes128k128d(key, ctr_preload, aes_out);
1300 bitwise_xor(aes_out, padded_buffer, chain_buffer);
1301 for (j = 0; j < 8;j++)
1302 pframe[payload_index++] = chain_buffer[j];
1303
1304 return _SUCCESS;
1305}
1306
1307u32 rtw_aes_encrypt23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
1308{ /* exclude ICV */
1309 /* Intermediate Buffers */
1310 int curfragnum, length;
1311 u32 prwskeylen;
1312 u8 *pframe, *prwskey; /* *payload,*iv */
1313 u8 hw_hdr_offset = 0;
1314 struct sta_info *stainfo;
1315 struct pkt_attrib *pattrib = &pxmitframe->attrib;
1316 struct security_priv *psecuritypriv = &padapter->securitypriv;
1317 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1318 u32 res = _SUCCESS;
1319
1320 if (!pxmitframe->buf_addr)
1321 return _FAIL;
1322
1323 hw_hdr_offset = TXDESC_OFFSET;
1324
1325 pframe = pxmitframe->buf_addr + hw_hdr_offset;
1326
1327 /* 4 start to encrypt each fragment */
1328 if (pattrib->encrypt != _AES_)
1329 return _FAIL;
1330
1331 if (pattrib->psta) {
1332 stainfo = pattrib->psta;
1333 } else {
1334 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
1335 stainfo = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]);
1336 }
1337
1338 if (!stainfo) {
1339 RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
1340 ("rtw_aes_encrypt23a: stainfo == NULL!!!\n"));
1341 DBG_8723A("%s, psta == NUL\n", __func__);
1342 res = _FAIL;
1343 goto out;
1344 }
1345 if (!(stainfo->state &_FW_LINKED)) {
1346 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n",
1347 __func__, stainfo->state);
1348 return _FAIL;
1349 }
1350 RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
1351 ("rtw_aes_encrypt23a: stainfo!= NULL!!!\n"));
1352
1353 if (is_multicast_ether_addr(pattrib->ra))
1354 prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
1355 else
1356 prwskey = &stainfo->dot118021x_UncstKey.skey[0];
1357
1358 prwskeylen = 16;
1359
1360 for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
1361 /* 4 the last fragment */
1362 if ((curfragnum + 1) == pattrib->nr_frags) {
1363 length = pattrib->last_txcmdsz -
1364 pattrib->hdrlen-pattrib->iv_len -
1365 pattrib->icv_len;
1366
1367 aes_cipher(prwskey, pattrib->hdrlen, pframe, length);
1368 } else {
1369 length = pxmitpriv->frag_len-pattrib->hdrlen -
1370 pattrib->iv_len - pattrib->icv_len;
1371
1372 aes_cipher(prwskey, pattrib->hdrlen, pframe, length);
1373 pframe += pxmitpriv->frag_len;
1374 pframe = (u8*)RND4((unsigned long)pframe);
1375 }
1376 }
1377out:
1378 return res;
1379}
1380
1381static int aes_decipher(u8 *key, uint hdrlen,
1382 u8 *pframe, uint plen)
1383{
1384 static u8 message[MAX_MSG_SIZE];
1385 uint qc_exists, a4_exists, i, j, payload_remainder,
1386 num_blocks, payload_index;
1387 int res = _SUCCESS;
1388 u8 pn_vector[6];
1389 u8 mic_iv[16];
1390 u8 mic_header1[16];
1391 u8 mic_header2[16];
1392 u8 ctr_preload[16];
1393 /* Intermediate Buffers */
1394 u8 chain_buffer[16];
1395 u8 aes_out[16];
1396 u8 padded_buffer[16];
1397 u8 mic[8];
1398 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)pframe;
1399 u16 frsubtype = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE;
1400
1401 memset((void *)mic_iv, 0, 16);
1402 memset((void *)mic_header1, 0, 16);
1403 memset((void *)mic_header2, 0, 16);
1404 memset((void *)ctr_preload, 0, 16);
1405 memset((void *)chain_buffer, 0, 16);
1406 memset((void *)aes_out, 0, 16);
1407 memset((void *)padded_buffer, 0, 16);
1408
1409 /* start to decrypt the payload */
1410
1411 num_blocks = (plen-8) / 16; /* plen including llc, payload_length and mic) */
1412
1413 payload_remainder = (plen-8) % 16;
1414
1415 pn_vector[0] = pframe[hdrlen];
1416 pn_vector[1] = pframe[hdrlen+1];
1417 pn_vector[2] = pframe[hdrlen+4];
1418 pn_vector[3] = pframe[hdrlen+5];
1419 pn_vector[4] = pframe[hdrlen+6];
1420 pn_vector[5] = pframe[hdrlen+7];
1421
1422 if ((hdrlen == sizeof(struct ieee80211_hdr_3addr) ||
1423 (hdrlen == sizeof(struct ieee80211_qos_hdr))))
1424 a4_exists = 0;
1425 else
1426 a4_exists = 1;
1427
1428 if (ieee80211_is_data(hdr->frame_control)) {
1429 if ((frsubtype == IEEE80211_STYPE_DATA_CFACK) ||
1430 (frsubtype == IEEE80211_STYPE_DATA_CFPOLL) ||
1431 (frsubtype == IEEE80211_STYPE_DATA_CFACKPOLL)) {
1432 qc_exists = 1;
1433 if (hdrlen != sizeof(struct ieee80211_hdr_3addr))
1434 hdrlen += 2;
1435 } else if ((frsubtype == IEEE80211_STYPE_QOS_DATA) ||
1436 (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACK) ||
1437 (frsubtype == IEEE80211_STYPE_QOS_DATA_CFPOLL) ||
1438 (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACKPOLL)) {
1439 if (hdrlen != sizeof(struct ieee80211_hdr_3addr))
1440 hdrlen += 2;
1441 qc_exists = 1;
1442 } else {
1443 qc_exists = 0;
1444 }
1445 } else {
1446 qc_exists = 0;
1447 }
1448
1449 /* now, decrypt pframe with hdrlen offset and plen long */
1450
1451 payload_index = hdrlen + 8; /* 8 is for extiv */
1452
1453 for (i = 0; i < num_blocks; i++) {
1454 construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
1455 pframe, pn_vector, i+1);
1456
1457 aes128k128d(key, ctr_preload, aes_out);
1458 bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
1459
1460 for (j = 0; j < 16; j++)
1461 pframe[payload_index++] = chain_buffer[j];
1462 }
1463
1464 if (payload_remainder > 0) {
1465 /* If there is a short final block, then pad it,
1466 * encrypt it and copy the unpadded part back
1467 */
1468 construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe,
1469 pn_vector, num_blocks+1);
1470
1471 for (j = 0; j < 16; j++)
1472 padded_buffer[j] = 0x00;
1473 for (j = 0; j < payload_remainder; j++)
1474 padded_buffer[j] = pframe[payload_index+j];
1475 aes128k128d(key, ctr_preload, aes_out);
1476 bitwise_xor(aes_out, padded_buffer, chain_buffer);
1477 for (j = 0; j < payload_remainder; j++)
1478 pframe[payload_index++] = chain_buffer[j];
1479 }
1480
1481 /* start to calculate the mic */
1482 if ((hdrlen +plen+8) <= MAX_MSG_SIZE)
1483 memcpy(message, pframe, (hdrlen+plen+8)); /* 8 is for ext iv len */
1484
1485 pn_vector[0] = pframe[hdrlen];
1486 pn_vector[1] = pframe[hdrlen+1];
1487 pn_vector[2] = pframe[hdrlen+4];
1488 pn_vector[3] = pframe[hdrlen+5];
1489 pn_vector[4] = pframe[hdrlen+6];
1490 pn_vector[5] = pframe[hdrlen+7];
1491
1492 construct_mic_iv(mic_iv, qc_exists, a4_exists, message,
1493 plen-8, pn_vector);
1494
1495 construct_mic_header1(mic_header1, hdrlen, message);
1496 construct_mic_header2(mic_header2, message, a4_exists, qc_exists);
1497
1498 payload_remainder = (plen-8) % 16;
1499 num_blocks = (plen-8) / 16;
1500
1501 /* Find start of payload */
1502 payload_index = (hdrlen + 8);
1503
1504 /* Calculate MIC */
1505 aes128k128d(key, mic_iv, aes_out);
1506 bitwise_xor(aes_out, mic_header1, chain_buffer);
1507 aes128k128d(key, chain_buffer, aes_out);
1508 bitwise_xor(aes_out, mic_header2, chain_buffer);
1509 aes128k128d(key, chain_buffer, aes_out);
1510
1511 for (i = 0; i < num_blocks; i++) {
1512 bitwise_xor(aes_out, &message[payload_index], chain_buffer);
1513
1514 payload_index += 16;
1515 aes128k128d(key, chain_buffer, aes_out);
1516 }
1517
1518 /* Add on the final payload block if it needs padding */
1519 if (payload_remainder > 0) {
1520 for (j = 0; j < 16; j++)
1521 padded_buffer[j] = 0x00;
1522 for (j = 0; j < payload_remainder; j++)
1523 padded_buffer[j] = message[payload_index++];
1524 bitwise_xor(aes_out, padded_buffer, chain_buffer);
1525 aes128k128d(key, chain_buffer, aes_out);
1526 }
1527
1528 for (j = 0 ; j < 8; j++)
1529 mic[j] = aes_out[j];
1530
1531 /* Insert MIC into payload */
1532 for (j = 0; j < 8; j++)
1533 message[payload_index+j] = mic[j];
1534
1535 payload_index = hdrlen + 8;
1536 for (i = 0; i< num_blocks; i++) {
1537 construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
1538 message, pn_vector, i+1);
1539 aes128k128d(key, ctr_preload, aes_out);
1540 bitwise_xor(aes_out, &message[payload_index], chain_buffer);
1541 for (j = 0; j < 16; j++)
1542 message[payload_index++] = chain_buffer[j];
1543 }
1544
1545 if (payload_remainder > 0) {
1546 /* If there is a short final block, then pad it,
1547 * encrypt it and copy the unpadded part back
1548 */
1549 construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
1550 message, pn_vector, num_blocks+1);
1551
1552 for (j = 0; j < 16; j++)
1553 padded_buffer[j] = 0x00;
1554 for (j = 0; j < payload_remainder; j++)
1555 padded_buffer[j] = message[payload_index+j];
1556 aes128k128d(key, ctr_preload, aes_out);
1557 bitwise_xor(aes_out, padded_buffer, chain_buffer);
1558 for (j = 0; j < payload_remainder; j++)
1559 message[payload_index++] = chain_buffer[j];
1560 }
1561
1562 /* Encrypt the MIC */
1563 construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message,
1564 pn_vector, 0);
1565
1566 for (j = 0; j < 16; j++)
1567 padded_buffer[j] = 0x00;
1568 for (j = 0; j < 8; j++)
1569 padded_buffer[j] = message[j+hdrlen+8+plen-8];
1570
1571 aes128k128d(key, ctr_preload, aes_out);
1572 bitwise_xor(aes_out, padded_buffer, chain_buffer);
1573 for (j = 0; j < 8; j++)
1574 message[payload_index++] = chain_buffer[j];
1575
1576 /* compare the mic */
1577 for (i = 0; i < 8; i++) {
1578 if (pframe[hdrlen+8+plen-8+i] != message[hdrlen+8+plen-8+i]) {
1579 RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
1580 ("aes_decipher:mic check error mic[%d]: pframe(%x) != message(%x)\n",
1581 i, pframe[hdrlen+8+plen-8+i], message[hdrlen+8+plen-8+i]));
1582 DBG_8723A("aes_decipher:mic check error mic[%d]: pframe(%x) != message(%x)\n",
1583 i, pframe[hdrlen+8+plen-8+i], message[hdrlen+8+plen-8+i]);
1584 res = _FAIL;
1585 }
1586 }
1587 return res;
1588}
1589
1590u32 rtw_aes_decrypt23a(struct rtw_adapter *padapter, struct recv_frame *precvframe)
1591{ /* exclude ICV */
1592 struct sta_info *stainfo;
1593 struct rx_pkt_attrib *prxattrib = &precvframe->attrib;
1594 struct security_priv *psecuritypriv = &padapter->securitypriv;
1595 struct sk_buff *skb = precvframe->pkt;
1596 int length;
1597 u8 *pframe, *prwskey; /* *payload,*iv */
1598 u32 res = _SUCCESS;
1599
1600 pframe = skb->data;
1601 /* 4 start to encrypt each fragment */
1602 if (!prxattrib->encrypt != _AES_)
1603 return _FAIL;
1604
1605 stainfo = rtw_get_stainfo23a(&padapter->stapriv, &prxattrib->ta[0]);
1606 if (!stainfo) {
1607 RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
1608 ("rtw_aes_encrypt23a: stainfo == NULL!!!\n"));
1609 res = _FAIL;
1610 goto exit;
1611 }
1612
1613 RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
1614 ("rtw_aes_decrypt23a: stainfo!= NULL!!!\n"));
1615
1616 if (is_multicast_ether_addr(prxattrib->ra)) {
1617 /* in concurrent we should use sw decrypt in group key,
1618 so we remove this message */
1619 if (!psecuritypriv->binstallGrpkey) {
1620 res = _FAIL;
1621 DBG_8723A("%s:rx bc/mc packets, but didn't install "
1622 "group key!!!!!!!!!!\n", __func__);
1623 goto exit;
1624 }
1625 prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
1626 if (psecuritypriv->dot118021XGrpKeyid != prxattrib->key_index) {
1627 DBG_8723A("not match packet_index =%d, install_index ="
1628 "%d\n", prxattrib->key_index,
1629 psecuritypriv->dot118021XGrpKeyid);
1630 res = _FAIL;
1631 goto exit;
1632 }
1633 } else {
1634 prwskey = &stainfo->dot118021x_UncstKey.skey[0];
1635 }
1636
1637 length = skb->len - prxattrib->hdrlen - prxattrib->iv_len;
1638
1639 res = aes_decipher(prwskey, prxattrib->hdrlen, pframe, length);
1640exit:
1641 return res;
1642}
1643
1644void rtw_use_tkipkey_handler23a(void *FunctionContext)
1645{
1646 struct rtw_adapter *padapter = (struct rtw_adapter *)FunctionContext;
1647
1648 RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("^^^rtw_use_tkipkey_handler23a ^^^\n"));
1649 padapter->securitypriv.busetkipkey = true;
1650 RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
1651 ("^^^rtw_use_tkipkey_handler23a padapter->securitypriv.busetkipkey =%d^^^\n",
1652 padapter->securitypriv.busetkipkey));
1653}
diff --git a/drivers/staging/rtl8723au/core/rtw_sreset.c b/drivers/staging/rtl8723au/core/rtw_sreset.c
new file mode 100644
index 000000000000..8d1a6fe168ac
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_sreset.c
@@ -0,0 +1,253 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15
16#include<rtw_sreset.h>
17
18void sreset_init_value23a(struct rtw_adapter *padapter)
19{
20 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
21 struct sreset_priv *psrtpriv = &pHalData->srestpriv;
22
23 mutex_init(&psrtpriv->silentreset_mutex);
24 psrtpriv->silent_reset_inprogress = false;
25 psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
26 psrtpriv->last_tx_time = 0;
27 psrtpriv->last_tx_complete_time = 0;
28}
29void sreset_reset_value23a(struct rtw_adapter *padapter)
30{
31 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
32 struct sreset_priv *psrtpriv = &pHalData->srestpriv;
33
34 psrtpriv->silent_reset_inprogress = false;
35 psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
36 psrtpriv->last_tx_time = 0;
37 psrtpriv->last_tx_complete_time = 0;
38}
39
40u8 sreset_get_wifi_status23a(struct rtw_adapter *padapter)
41{
42 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
43 struct sreset_priv *psrtpriv = &pHalData->srestpriv;
44 u8 status = WIFI_STATUS_SUCCESS;
45 u32 val32 = 0;
46
47 if (psrtpriv->silent_reset_inprogress)
48 return status;
49 val32 = rtw_read32(padapter, REG_TXDMA_STATUS);
50 if (val32 == 0xeaeaeaea) {
51 psrtpriv->Wifi_Error_Status = WIFI_IF_NOT_EXIST;
52 } else if (val32 != 0) {
53 DBG_8723A("txdmastatu(%x)\n", val32);
54 psrtpriv->Wifi_Error_Status = WIFI_MAC_TXDMA_ERROR;
55 }
56
57 if (WIFI_STATUS_SUCCESS != psrtpriv->Wifi_Error_Status) {
58 DBG_8723A("==>%s error_status(0x%x)\n", __func__, psrtpriv->Wifi_Error_Status);
59 status = (psrtpriv->Wifi_Error_Status &~(USB_READ_PORT_FAIL|USB_WRITE_PORT_FAIL));
60 }
61 DBG_8723A("==> %s wifi_status(0x%x)\n", __func__, status);
62
63 /* status restore */
64 psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
65
66 return status;
67}
68
69void sreset_set_wifi_error_status23a(struct rtw_adapter *padapter, u32 status)
70{
71 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
72
73 pHalData->srestpriv.Wifi_Error_Status = status;
74}
75
76void sreset_set_trigger_point(struct rtw_adapter *padapter, s32 tgp)
77{
78 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
79
80 pHalData->srestpriv.dbg_trigger_point = tgp;
81}
82
83bool sreset_inprogress(struct rtw_adapter *padapter)
84{
85 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
86
87 return pHalData->srestpriv.silent_reset_inprogress;
88}
89
90static void sreset_restore_security_station(struct rtw_adapter *padapter)
91{
92 struct mlme_priv *mlmepriv = &padapter->mlmepriv;
93 struct sta_priv *pstapriv = &padapter->stapriv;
94 struct sta_info *psta;
95 struct mlme_ext_info *pmlmeinfo = &padapter->mlmeextpriv.mlmext_info;
96 u8 val8;
97
98 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X)
99 val8 = 0xcc;
100 else
101 val8 = 0xcf;
102 rtw_hal_set_hwreg23a(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
103
104 if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
105 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) {
106 psta = rtw_get_stainfo23a(pstapriv, get_bssid(mlmepriv));
107 if (psta == NULL) {
108 /* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
109 } else {
110 /* pairwise key */
111 rtw_setstakey_cmd23a(padapter, (unsigned char *)psta, true);
112 /* group key */
113 rtw_set_key23a(padapter,&padapter->securitypriv, padapter->securitypriv.dot118021XGrpKeyid, 0);
114 }
115 }
116}
117
118static void sreset_restore_network_station(struct rtw_adapter *padapter)
119{
120 struct mlme_priv *mlmepriv = &padapter->mlmepriv;
121 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
122 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
123 u8 threshold;
124
125 rtw_setopmode_cmd23a(padapter, Ndis802_11Infrastructure);
126
127 /* TH = 1 => means that invalidate usb rx aggregation */
128 /* TH = 0 => means that validate usb rx aggregation, use init value. */
129 if (mlmepriv->htpriv.ht_option) {
130 if (padapter->registrypriv.wifi_spec == 1)
131 threshold = 1;
132 else
133 threshold = 0;
134 rtw_hal_set_hwreg23a(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
135 } else {
136 threshold = 1;
137 rtw_hal_set_hwreg23a(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
138 }
139
140 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
141
142 /* disable dynamic functions, such as high power, DIG */
143 /* Switch_DM_Func23a(padapter, DYNAMIC_FUNC_DISABLE, false); */
144
145 rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
146
147 {
148 u8 join_type = 0;
149 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
150 }
151
152 Set_MSR23a(padapter, (pmlmeinfo->state & 0x3));
153
154 mlmeext_joinbss_event_callback23a(padapter, 1);
155 /* restore Sequence No. */
156 rtw_write8(padapter, 0x4dc, padapter->xmitpriv.nqos_ssn);
157
158 sreset_restore_security_station(padapter);
159}
160
161static void sreset_restore_network_status(struct rtw_adapter *padapter)
162{
163 struct mlme_priv *mlmepriv = &padapter->mlmepriv;
164
165 if (check_fwstate(mlmepriv, WIFI_STATION_STATE)) {
166 DBG_8723A(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_STATION_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
167 sreset_restore_network_station(padapter);
168 } else if (check_fwstate(mlmepriv, WIFI_AP_STATE)) {
169 DBG_8723A(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_AP_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
170 rtw_ap_restore_network(padapter);
171 } else if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE)) {
172 DBG_8723A(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_ADHOC_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
173 } else {
174 DBG_8723A(FUNC_ADPT_FMT" fwstate:0x%08x - ???\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
175 }
176}
177
178static void sreset_stop_adapter(struct rtw_adapter *padapter)
179{
180 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
181 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
182
183 if (padapter == NULL)
184 return;
185
186 DBG_8723A(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
187
188 if (!rtw_netif_queue_stopped(padapter->pnetdev))
189 netif_tx_stop_all_queues(padapter->pnetdev);
190
191 rtw_cancel_all_timer23a(padapter);
192
193 /* TODO: OS and HCI independent */
194 tasklet_kill(&pxmitpriv->xmit_tasklet);
195
196 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
197 rtw_scan_abort23a(padapter);
198
199 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
200 rtw23a_join_to_handler((unsigned long)padapter);
201}
202
203static void sreset_start_adapter(struct rtw_adapter *padapter)
204{
205 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
206 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
207
208 if (padapter == NULL)
209 return;
210
211 DBG_8723A(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
212
213 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
214 sreset_restore_network_status(padapter);
215 }
216
217 /* TODO: OS and HCI independent */
218 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
219
220 mod_timer(&padapter->mlmepriv.dynamic_chk_timer,
221 jiffies + msecs_to_jiffies(2000));
222
223 if (rtw_netif_queue_stopped(padapter->pnetdev))
224 netif_tx_wake_all_queues(padapter->pnetdev);
225}
226
227void sreset_reset(struct rtw_adapter *padapter)
228{
229 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
230 struct sreset_priv *psrtpriv = &pHalData->srestpriv;
231 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
232 unsigned long start = jiffies;
233
234 DBG_8723A("%s\n", __func__);
235
236 psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
237
238 mutex_lock(&psrtpriv->silentreset_mutex);
239 psrtpriv->silent_reset_inprogress = true;
240 pwrpriv->change_rfpwrstate = rf_off;
241
242 sreset_stop_adapter(padapter);
243
244 ips_enter23a(padapter);
245 ips_leave23a(padapter);
246
247 sreset_start_adapter(padapter);
248 psrtpriv->silent_reset_inprogress = false;
249 mutex_unlock(&psrtpriv->silentreset_mutex);
250
251 DBG_8723A("%s done in %d ms\n", __func__,
252 jiffies_to_msecs(jiffies - start));
253}
diff --git a/drivers/staging/rtl8723au/core/rtw_sta_mgt.c b/drivers/staging/rtl8723au/core/rtw_sta_mgt.c
new file mode 100644
index 000000000000..451b58f47287
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_sta_mgt.c
@@ -0,0 +1,509 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _RTW_STA_MGT_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <recv_osdep.h>
20#include <xmit_osdep.h>
21#include <mlme_osdep.h>
22#include <sta_info.h>
23
24void _rtw_init_stainfo(struct sta_info *psta)
25{
26 memset((u8 *)psta, 0, sizeof (struct sta_info));
27 spin_lock_init(&psta->lock);
28 INIT_LIST_HEAD(&psta->list);
29 INIT_LIST_HEAD(&psta->hash_list);
30 _rtw_init_queue23a(&psta->sleep_q);
31 psta->sleepq_len = 0;
32 _rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv);
33 _rtw_init_sta_recv_priv23a(&psta->sta_recvpriv);
34#ifdef CONFIG_8723AU_AP_MODE
35 INIT_LIST_HEAD(&psta->asoc_list);
36 INIT_LIST_HEAD(&psta->auth_list);
37 psta->expire_to = 0;
38 psta->flags = 0;
39 psta->capability = 0;
40 psta->bpairwise_key_installed = false;
41 psta->nonerp_set = 0;
42 psta->no_short_slot_time_set = 0;
43 psta->no_short_preamble_set = 0;
44 psta->no_ht_gf_set = 0;
45 psta->no_ht_set = 0;
46 psta->ht_20mhz_set = 0;
47 psta->keep_alive_trycnt = 0;
48#endif /* CONFIG_8723AU_AP_MODE */
49}
50
51u32 _rtw_init_sta_priv23a(struct sta_priv *pstapriv)
52{
53 struct sta_info *psta;
54 s32 i;
55
56 pstapriv->pallocated_stainfo_buf = rtw_zvmalloc(sizeof(struct sta_info) * NUM_STA+ 4);
57
58 if (!pstapriv->pallocated_stainfo_buf)
59 return _FAIL;
60
61 pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 -
62 ((unsigned long)(pstapriv->pallocated_stainfo_buf) & 3);
63 _rtw_init_queue23a(&pstapriv->free_sta_queue);
64 spin_lock_init(&pstapriv->sta_hash_lock);
65 pstapriv->asoc_sta_count = 0;
66 _rtw_init_queue23a(&pstapriv->sleep_q);
67 _rtw_init_queue23a(&pstapriv->wakeup_q);
68 psta = (struct sta_info *)(pstapriv->pstainfo_buf);
69
70 for (i = 0; i < NUM_STA; i++) {
71 _rtw_init_stainfo(psta);
72 INIT_LIST_HEAD(&pstapriv->sta_hash[i]);
73 list_add_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
74 psta++;
75 }
76#ifdef CONFIG_8723AU_AP_MODE
77 pstapriv->sta_dz_bitmap = 0;
78 pstapriv->tim_bitmap = 0;
79 INIT_LIST_HEAD(&pstapriv->asoc_list);
80 INIT_LIST_HEAD(&pstapriv->auth_list);
81 spin_lock_init(&pstapriv->asoc_list_lock);
82 spin_lock_init(&pstapriv->auth_list_lock);
83 pstapriv->asoc_list_cnt = 0;
84 pstapriv->auth_list_cnt = 0;
85 pstapriv->auth_to = 3; /* 3*2 = 6 sec */
86 pstapriv->assoc_to = 3;
87 /* pstapriv->expire_to = 900; 900*2 = 1800 sec = 30 min, expire after no any traffic. */
88 /* pstapriv->expire_to = 30; 30*2 = 60 sec = 1 min, expire after no any traffic. */
89 pstapriv->expire_to = 3; /* 3*2 = 6 sec */
90 pstapriv->max_num_sta = NUM_STA;
91#endif
92 return _SUCCESS;
93}
94
95inline int rtw_stainfo_offset23a(struct sta_priv *stapriv, struct sta_info *sta)
96{
97 int offset = (((u8 *)sta) - stapriv->pstainfo_buf)/sizeof(struct sta_info);
98
99 if (!stainfo_offset_valid(offset))
100 DBG_8723A("%s invalid offset(%d), out of range!!!", __func__, offset);
101 return offset;
102}
103
104inline struct sta_info *rtw_get_stainfo23a_by_offset23a(struct sta_priv *stapriv, int offset)
105{
106 if (!stainfo_offset_valid(offset))
107 DBG_8723A("%s invalid offset(%d), out of range!!!", __func__, offset);
108 return (struct sta_info *)(stapriv->pstainfo_buf + offset * sizeof(struct sta_info));
109}
110
111/* this function is used to free the memory of lock || sema for all stainfos */
112void rtw_mfree_all_stainfo(struct sta_priv *pstapriv)
113{
114 struct list_head *plist, *phead;
115 struct sta_info *psta;
116
117 spin_lock_bh(&pstapriv->sta_hash_lock);
118
119 phead = get_list_head(&pstapriv->free_sta_queue);
120
121 /* we really achieve a lot in this loop .... */
122 list_for_each(plist, phead)
123 psta = container_of(plist, struct sta_info, list);
124 spin_unlock_bh(&pstapriv->sta_hash_lock);
125}
126
127void rtw_mfree_sta_priv_lock(struct sta_priv *pstapriv)
128{
129 rtw_mfree_all_stainfo(pstapriv); /* be done before free sta_hash_lock */
130}
131
132u32 _rtw_free_sta_priv23a(struct sta_priv *pstapriv)
133{
134 struct list_head *phead, *plist, *ptmp;
135 struct sta_info *psta;
136 struct recv_reorder_ctrl *preorder_ctrl;
137 int index;
138
139 if (pstapriv) {
140 /* delete all reordering_ctrl_timer */
141 spin_lock_bh(&pstapriv->sta_hash_lock);
142 for (index = 0; index < NUM_STA; index++) {
143 phead = &pstapriv->sta_hash[index];
144
145 list_for_each_safe(plist, ptmp, phead) {
146 int i;
147 psta = container_of(plist, struct sta_info,
148 hash_list);
149 for (i = 0; i < 16 ; i++) {
150 preorder_ctrl = &psta->recvreorder_ctrl[i];
151 del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
152 }
153 }
154 }
155 spin_unlock_bh(&pstapriv->sta_hash_lock);
156 /*===============================*/
157
158 rtw_mfree_sta_priv_lock(pstapriv);
159
160 if (pstapriv->pallocated_stainfo_buf)
161 rtw_vmfree(pstapriv->pallocated_stainfo_buf, sizeof(struct sta_info)*NUM_STA+4);
162 }
163 return _SUCCESS;
164}
165
166struct sta_info *rtw_alloc_stainfo23a(struct sta_priv *pstapriv, u8 *hwaddr)
167{
168 struct list_head *phash_list;
169 struct sta_info *psta;
170 struct rtw_queue *pfree_sta_queue;
171 struct recv_reorder_ctrl *preorder_ctrl;
172 uint tmp_aid;
173 s32 index;
174 int i = 0;
175 u16 wRxSeqInitialValue = 0xffff;
176
177 pfree_sta_queue = &pstapriv->free_sta_queue;
178
179 spin_lock_bh(&pstapriv->sta_hash_lock);
180
181 if (_rtw_queue_empty23a(pfree_sta_queue)) {
182 spin_unlock_bh(&pstapriv->sta_hash_lock);
183 return NULL;
184 }
185 psta = container_of((&pfree_sta_queue->queue)->next, struct sta_info, list);
186
187 list_del_init(&psta->list);
188
189 tmp_aid = psta->aid;
190
191 _rtw_init_stainfo(psta);
192
193 psta->padapter = pstapriv->padapter;
194
195 memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
196
197 index = wifi_mac_hash(hwaddr);
198
199 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
200 ("rtw_alloc_stainfo23a: index = %x", index));
201 if (index >= NUM_STA) {
202 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
203 ("ERROR => rtw_alloc_stainfo23a: index >= NUM_STA"));
204 psta = NULL;
205 goto exit;
206 }
207 phash_list = &pstapriv->sta_hash[index];
208
209 list_add_tail(&psta->hash_list, phash_list);
210
211 pstapriv->asoc_sta_count ++ ;
212
213/* For the SMC router, the sequence number of first packet of WPS handshake will be 0. */
214/* In this case, this packet will be dropped by recv_decache function if we use the 0x00 as the default value for tid_rxseq variable. */
215/* So, we initialize the tid_rxseq variable as the 0xffff. */
216
217 for (i = 0; i < 16; i++)
218 memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], &wRxSeqInitialValue, 2);
219
220 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
221 ("alloc number_%d stainfo with hwaddr = %pM\n",
222 pstapriv->asoc_sta_count, hwaddr));
223
224 init_addba_retry_timer23a(psta);
225
226 /* for A-MPDU Rx reordering buffer control */
227 for (i = 0; i < 16; i++) {
228 preorder_ctrl = &psta->recvreorder_ctrl[i];
229
230 preorder_ctrl->padapter = pstapriv->padapter;
231
232 preorder_ctrl->enable = false;
233
234 preorder_ctrl->indicate_seq = 0xffff;
235 preorder_ctrl->wend_b = 0xffff;
236 /* preorder_ctrl->wsize_b = (NR_RECVBUFF-2); */
237 preorder_ctrl->wsize_b = 64;/* 64; */
238
239 _rtw_init_queue23a(&preorder_ctrl->pending_recvframe_queue);
240
241 rtw_init_recv_timer23a(preorder_ctrl);
242 }
243 /* init for DM */
244 psta->rssi_stat.UndecoratedSmoothedPWDB = (-1);
245 psta->rssi_stat.UndecoratedSmoothedCCK = (-1);
246
247 /* init for the sequence number of received management frame */
248 psta->RxMgmtFrameSeqNum = 0xffff;
249exit:
250 spin_unlock_bh(&pstapriv->sta_hash_lock);
251 return psta;
252}
253
254/* using pstapriv->sta_hash_lock to protect */
255u32 rtw_free_stainfo23a(struct rtw_adapter *padapter, struct sta_info *psta)
256{
257 struct rtw_queue *pfree_sta_queue;
258 struct recv_reorder_ctrl *preorder_ctrl;
259 struct sta_xmit_priv *pstaxmitpriv;
260 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
261 struct sta_priv *pstapriv = &padapter->stapriv;
262 struct hw_xmit *phwxmit;
263 int i;
264
265 if (psta == NULL)
266 goto exit;
267
268 spin_lock_bh(&psta->lock);
269 psta->state &= ~_FW_LINKED;
270 spin_unlock_bh(&psta->lock);
271
272 pfree_sta_queue = &pstapriv->free_sta_queue;
273
274 pstaxmitpriv = &psta->sta_xmitpriv;
275
276 spin_lock_bh(&pxmitpriv->lock);
277
278 rtw_free_xmitframe_queue23a(pxmitpriv, &psta->sleep_q);
279 psta->sleepq_len = 0;
280
281 /* vo */
282 rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
283 list_del_init(&pstaxmitpriv->vo_q.tx_pending);
284 phwxmit = pxmitpriv->hwxmits;
285 phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt;
286 pstaxmitpriv->vo_q.qcnt = 0;
287
288 /* vi */
289 rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
290 list_del_init(&pstaxmitpriv->vi_q.tx_pending);
291 phwxmit = pxmitpriv->hwxmits+1;
292 phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt;
293 pstaxmitpriv->vi_q.qcnt = 0;
294
295 /* be */
296 rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
297 list_del_init(&pstaxmitpriv->be_q.tx_pending);
298 phwxmit = pxmitpriv->hwxmits+2;
299 phwxmit->accnt -= pstaxmitpriv->be_q.qcnt;
300 pstaxmitpriv->be_q.qcnt = 0;
301
302 /* bk */
303 rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
304 list_del_init(&pstaxmitpriv->bk_q.tx_pending);
305 phwxmit = pxmitpriv->hwxmits+3;
306 phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt;
307 pstaxmitpriv->bk_q.qcnt = 0;
308
309 spin_unlock_bh(&pxmitpriv->lock);
310
311 list_del_init(&psta->hash_list);
312 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("\n free number_%d stainfo with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x \n", pstapriv->asoc_sta_count, psta->hwaddr[0], psta->hwaddr[1], psta->hwaddr[2], psta->hwaddr[3], psta->hwaddr[4], psta->hwaddr[5]));
313 pstapriv->asoc_sta_count --;
314
315 /* re-init sta_info; 20061114 will be init in alloc_stainfo */
316 /* _rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv); */
317 /* _rtw_init_sta_recv_priv23a(&psta->sta_recvpriv); */
318
319 del_timer_sync(&psta->addba_retry_timer);
320
321 /* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */
322 for (i = 0; i < 16; i++) {
323 struct list_head *phead, *plist;
324 struct recv_frame *prframe;
325 struct rtw_queue *ppending_recvframe_queue;
326 struct rtw_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
327
328 preorder_ctrl = &psta->recvreorder_ctrl[i];
329
330 del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
331
332 ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
333
334 spin_lock_bh(&ppending_recvframe_queue->lock);
335 phead = get_list_head(ppending_recvframe_queue);
336 plist = phead->next;
337
338 while (!list_empty(phead)) {
339 prframe = container_of(plist, struct recv_frame, list);
340 plist = plist->next;
341 list_del_init(&prframe->list);
342 rtw_free_recvframe23a(prframe, pfree_recv_queue);
343 }
344 spin_unlock_bh(&ppending_recvframe_queue->lock);
345 }
346 if (!(psta->state & WIFI_AP_STATE))
347 rtw_hal_set_odm_var23a(padapter, HAL_ODM_STA_INFO, psta, false);
348#ifdef CONFIG_8723AU_AP_MODE
349 spin_lock_bh(&pstapriv->auth_list_lock);
350 if (!list_empty(&psta->auth_list)) {
351 list_del_init(&psta->auth_list);
352 pstapriv->auth_list_cnt--;
353 }
354 spin_unlock_bh(&pstapriv->auth_list_lock);
355
356 psta->expire_to = 0;
357
358 psta->sleepq_ac_len = 0;
359 psta->qos_info = 0;
360
361 psta->max_sp_len = 0;
362 psta->uapsd_bk = 0;
363 psta->uapsd_be = 0;
364 psta->uapsd_vi = 0;
365 psta->uapsd_vo = 0;
366
367 psta->has_legacy_ac = 0;
368
369 pstapriv->sta_dz_bitmap &= ~CHKBIT(psta->aid);
370 pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
371
372 if ((psta->aid >0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) {
373 pstapriv->sta_aid[psta->aid - 1] = NULL;
374 psta->aid = 0;
375 }
376#endif /* CONFIG_8723AU_AP_MODE */
377 list_add_tail(&psta->list, get_list_head(pfree_sta_queue));
378exit:
379 return _SUCCESS;
380}
381
382/* free all stainfo which in sta_hash[all] */
383void rtw_free_all_stainfo23a(struct rtw_adapter *padapter)
384{
385 struct list_head *plist, *phead, *ptmp;
386 struct sta_info *psta;
387 struct sta_priv *pstapriv = &padapter->stapriv;
388 struct sta_info* pbcmc_stainfo = rtw_get_bcmc_stainfo23a(padapter);
389 s32 index; if (pstapriv->asoc_sta_count == 1)
390 return;
391
392 spin_lock_bh(&pstapriv->sta_hash_lock);
393
394 for (index = 0; index < NUM_STA; index++) {
395 phead = &pstapriv->sta_hash[index];
396
397 list_for_each_safe(plist, ptmp, phead) {
398 psta = container_of(plist, struct sta_info, hash_list);
399
400 if (pbcmc_stainfo!= psta)
401 rtw_free_stainfo23a(padapter, psta);
402 }
403 }
404 spin_unlock_bh(&pstapriv->sta_hash_lock);
405}
406
407/* any station allocated can be searched by hash list */
408struct sta_info *rtw_get_stainfo23a(struct sta_priv *pstapriv, u8 *hwaddr)
409{
410 struct list_head *plist, *phead;
411 struct sta_info *psta = NULL;
412 u32 index;
413 u8 *addr;
414 u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
415
416 if (hwaddr == NULL)
417 return NULL;
418
419 if (is_multicast_ether_addr(hwaddr))
420 addr = bc_addr;
421 else
422 addr = hwaddr;
423
424 index = wifi_mac_hash(addr);
425
426 spin_lock_bh(&pstapriv->sta_hash_lock);
427
428 phead = &pstapriv->sta_hash[index];
429
430 list_for_each(plist, phead) {
431 psta = container_of(plist, struct sta_info, hash_list);
432
433 if (!memcmp(psta->hwaddr, addr, ETH_ALEN)) {
434 /* if found the matched address */
435 break;
436 }
437 psta = NULL;
438 }
439 spin_unlock_bh(&pstapriv->sta_hash_lock);
440 return psta;
441}
442
443u32 rtw_init_bcmc_stainfo23a(struct rtw_adapter* padapter)
444{
445 struct sta_priv *pstapriv = &padapter->stapriv;
446 struct sta_info *psta;
447 struct tx_servq *ptxservq;
448 u32 res = _SUCCESS;
449 unsigned char bcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
450
451 psta = rtw_alloc_stainfo23a(pstapriv, bcast_addr);
452 if (psta == NULL) {
453 res = _FAIL;
454 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
455 ("rtw_alloc_stainfo23a fail"));
456 return res;
457 }
458 /* default broadcast & multicast use macid 1 */
459 psta->mac_id = 1;
460
461 ptxservq = &psta->sta_xmitpriv.be_q;
462 return _SUCCESS;
463}
464
465struct sta_info *rtw_get_bcmc_stainfo23a(struct rtw_adapter *padapter)
466{
467 struct sta_info *psta;
468 struct sta_priv *pstapriv = &padapter->stapriv;
469 u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
470
471 psta = rtw_get_stainfo23a(pstapriv, bc_addr);
472 return psta;
473}
474
475u8 rtw_access_ctrl23a(struct rtw_adapter *padapter, u8 *mac_addr)
476{
477 u8 res = true;
478#ifdef CONFIG_8723AU_AP_MODE
479 struct list_head *plist, *phead;
480 struct rtw_wlan_acl_node *paclnode;
481 u8 match = false;
482 struct sta_priv *pstapriv = &padapter->stapriv;
483 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
484 struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q;
485
486 spin_lock_bh(&pacl_node_q->lock);
487 phead = get_list_head(pacl_node_q);
488
489 list_for_each(plist, phead) {
490 paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
491
492 if (!memcmp(paclnode->addr, mac_addr, ETH_ALEN)) {
493 if (paclnode->valid) {
494 match = true;
495 break;
496 }
497 }
498 }
499 spin_unlock_bh(&pacl_node_q->lock);
500
501 if (pacl_list->mode == 1)/* accept unless in deny list */
502 res = (match) ? false : true;
503 else if (pacl_list->mode == 2)/* deny unless in accept list */
504 res = (match) ? true : false;
505 else
506 res = true;
507#endif
508 return res;
509}
diff --git a/drivers/staging/rtl8723au/core/rtw_wlan_util.c b/drivers/staging/rtl8723au/core/rtw_wlan_util.c
new file mode 100644
index 000000000000..76d2f240656e
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_wlan_util.c
@@ -0,0 +1,1760 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _RTW_WLAN_UTIL_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <linux/ieee80211.h>
20#include <wifi.h>
21
22static unsigned char ARTHEROS_OUI1[] = {0x00, 0x03, 0x7f};
23static unsigned char ARTHEROS_OUI2[] = {0x00, 0x13, 0x74};
24
25static unsigned char BROADCOM_OUI1[] = {0x00, 0x10, 0x18};
26static unsigned char BROADCOM_OUI2[] = {0x00, 0x0a, 0xf7};
27
28static unsigned char CISCO_OUI[] = {0x00, 0x40, 0x96};
29static unsigned char MARVELL_OUI[] = {0x00, 0x50, 0x43};
30static unsigned char RALINK_OUI[] = {0x00, 0x0c, 0x43};
31static unsigned char REALTEK_OUI[] = {0x00, 0xe0, 0x4c};
32static unsigned char AIRGOCAP_OUI[] = {0x00, 0x0a, 0xf5};
33static unsigned char EPIGRAM_OUI[] = {0x00, 0x90, 0x4c};
34
35unsigned char REALTEK_96B_IE23A[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
36
37#define R2T_PHY_DELAY (0)
38
39/* define WAIT_FOR_BCN_TO_MIN (3000) */
40#define WAIT_FOR_BCN_TO_MIN (6000)
41#define WAIT_FOR_BCN_TO_MAX (20000)
42
43static u8 rtw_basic_rate_cck[4] = {
44 IEEE80211_CCK_RATE_1MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_2MB|IEEE80211_BASIC_RATE_MASK,
45 IEEE80211_CCK_RATE_5MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_11MB|IEEE80211_BASIC_RATE_MASK
46};
47
48static u8 rtw_basic_rate_ofdm[3] = {
49 IEEE80211_OFDM_RATE_6MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_OFDM_RATE_12MB|IEEE80211_BASIC_RATE_MASK,
50 IEEE80211_OFDM_RATE_24MB|IEEE80211_BASIC_RATE_MASK
51};
52
53static u8 rtw_basic_rate_mix[7] = {
54 IEEE80211_CCK_RATE_1MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_2MB|IEEE80211_BASIC_RATE_MASK,
55 IEEE80211_CCK_RATE_5MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_11MB|IEEE80211_BASIC_RATE_MASK,
56 IEEE80211_OFDM_RATE_6MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_OFDM_RATE_12MB|IEEE80211_BASIC_RATE_MASK,
57 IEEE80211_OFDM_RATE_24MB|IEEE80211_BASIC_RATE_MASK
58};
59
60int cckrates_included23a(unsigned char *rate, int ratelen)
61{
62 int i;
63
64 for (i = 0; i < ratelen; i++) {
65 if ((((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) ||
66 (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22))
67 return true;
68 }
69
70 return false;
71}
72
73int cckratesonly_included23a(unsigned char *rate, int ratelen)
74{
75 int i;
76
77 for (i = 0; i < ratelen; i++) {
78 if ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
79 (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22))
80 return false;
81 }
82
83 return true;
84}
85
86unsigned char networktype_to_raid23a(unsigned char network_type)
87{
88 unsigned char raid;
89
90 switch (network_type) {
91 case WIRELESS_11B:
92 raid = RATR_INX_WIRELESS_B;
93 break;
94 case WIRELESS_11A:
95 case WIRELESS_11G:
96 raid = RATR_INX_WIRELESS_G;
97 break;
98 case WIRELESS_11BG:
99 raid = RATR_INX_WIRELESS_GB;
100 break;
101 case WIRELESS_11_24N:
102 case WIRELESS_11_5N:
103 raid = RATR_INX_WIRELESS_N;
104 break;
105 case WIRELESS_11A_5N:
106 case WIRELESS_11G_24N:
107 raid = RATR_INX_WIRELESS_NG;
108 break;
109 case WIRELESS_11BG_24N:
110 raid = RATR_INX_WIRELESS_NGB;
111 break;
112 default:
113 raid = RATR_INX_WIRELESS_GB;
114 break;
115 }
116 return raid;
117}
118
119u8 judge_network_type23a(struct rtw_adapter *padapter, unsigned char *rate, int ratelen)
120{
121 u8 network_type = 0;
122 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
123 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
124
125 if (pmlmeext->cur_channel > 14) {
126 if (pmlmeinfo->HT_enable)
127 network_type = WIRELESS_11_5N;
128 network_type |= WIRELESS_11A;
129 } else {
130 if (pmlmeinfo->HT_enable)
131 network_type = WIRELESS_11_24N;
132
133 if ((cckratesonly_included23a(rate, ratelen)) == true)
134 network_type |= WIRELESS_11B;
135 else if ((cckrates_included23a(rate, ratelen)) == true)
136 network_type |= WIRELESS_11BG;
137 else
138 network_type |= WIRELESS_11G;
139 }
140 return network_type;
141}
142
143unsigned char ratetbl_val_2wifirate(unsigned char rate)
144{
145 unsigned char val = 0;
146
147 switch (rate & 0x7f) {
148 case 0:
149 val = IEEE80211_CCK_RATE_1MB;
150 break;
151 case 1:
152 val = IEEE80211_CCK_RATE_2MB;
153 break;
154 case 2:
155 val = IEEE80211_CCK_RATE_5MB;
156 break;
157 case 3:
158 val = IEEE80211_CCK_RATE_11MB;
159 break;
160 case 4:
161 val = IEEE80211_OFDM_RATE_6MB;
162 break;
163 case 5:
164 val = IEEE80211_OFDM_RATE_9MB;
165 break;
166 case 6:
167 val = IEEE80211_OFDM_RATE_12MB;
168 break;
169 case 7:
170 val = IEEE80211_OFDM_RATE_18MB;
171 break;
172 case 8:
173 val = IEEE80211_OFDM_RATE_24MB;
174 break;
175 case 9:
176 val = IEEE80211_OFDM_RATE_36MB;
177 break;
178 case 10:
179 val = IEEE80211_OFDM_RATE_48MB;
180 break;
181 case 11:
182 val = IEEE80211_OFDM_RATE_54MB;
183 break;
184 }
185 return val;
186}
187
188int is_basicrate(struct rtw_adapter *padapter, unsigned char rate)
189{
190 int i;
191 unsigned char val;
192 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
193
194 for (i = 0; i < NumRates; i++) {
195 val = pmlmeext->basicrate[i];
196
197 if ((val != 0xff) && (val != 0xfe)) {
198 if (rate == ratetbl_val_2wifirate(val))
199 return true;
200 }
201 }
202
203 return false;
204}
205
206unsigned int ratetbl2rateset(struct rtw_adapter *padapter, unsigned char *rateset)
207{
208 int i;
209 unsigned char rate;
210 unsigned int len = 0;
211 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
212
213 for (i = 0; i < NumRates; i++) {
214 rate = pmlmeext->datarate[i];
215
216 switch (rate) {
217 case 0xff:
218 return len;
219 case 0xfe:
220 continue;
221 default:
222 rate = ratetbl_val_2wifirate(rate);
223
224 if (is_basicrate(padapter, rate) == true)
225 rate |= IEEE80211_BASIC_RATE_MASK;
226
227 rateset[len] = rate;
228 len++;
229 break;
230 }
231 }
232 return len;
233}
234
235void get_rate_set23a(struct rtw_adapter *padapter, unsigned char *pbssrate, int *bssrate_len)
236{
237 unsigned char supportedrates[NumRates];
238
239 memset(supportedrates, 0, NumRates);
240 *bssrate_len = ratetbl2rateset(padapter, supportedrates);
241 memcpy(pbssrate, supportedrates, *bssrate_len);
242}
243
244void UpdateBrateTbl23a(struct rtw_adapter *Adapter, u8 *mBratesOS)
245{
246 u8 i;
247 u8 rate;
248
249 /* 1M, 2M, 5.5M, 11M, 6M, 12M, 24M are mandatory. */
250 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
251 rate = mBratesOS[i] & 0x7f;
252 switch (rate) {
253 case IEEE80211_CCK_RATE_1MB:
254 case IEEE80211_CCK_RATE_2MB:
255 case IEEE80211_CCK_RATE_5MB:
256 case IEEE80211_CCK_RATE_11MB:
257 case IEEE80211_OFDM_RATE_6MB:
258 case IEEE80211_OFDM_RATE_12MB:
259 case IEEE80211_OFDM_RATE_24MB:
260 mBratesOS[i] |= IEEE80211_BASIC_RATE_MASK;
261 break;
262 default:
263 break;
264 }
265 }
266}
267
268void Update23aTblForSoftAP(u8 *bssrateset, u32 bssratelen)
269{
270 u8 i;
271 u8 rate;
272
273 for (i = 0; i < bssratelen; i++) {
274 rate = bssrateset[i] & 0x7f;
275 switch (rate) {
276 case IEEE80211_CCK_RATE_1MB:
277 case IEEE80211_CCK_RATE_2MB:
278 case IEEE80211_CCK_RATE_5MB:
279 case IEEE80211_CCK_RATE_11MB:
280 bssrateset[i] |= IEEE80211_BASIC_RATE_MASK;
281 break;
282 }
283 }
284}
285
286void Save_DM_Func_Flag23a(struct rtw_adapter *padapter)
287{
288 u8 bSaveFlag = true;
289
290 rtw_hal_set_hwreg23a(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&bSaveFlag));
291}
292
293void Restore_DM_Func_Flag23a(struct rtw_adapter *padapter)
294{
295 u8 bSaveFlag = false;
296 rtw_hal_set_hwreg23a(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&bSaveFlag));
297}
298
299void Switch_DM_Func23a(struct rtw_adapter *padapter, unsigned long mode, u8 enable)
300{
301 if (enable == true)
302 rtw_hal_set_hwreg23a(padapter, HW_VAR_DM_FUNC_SET, (u8 *)(&mode));
303 else
304 rtw_hal_set_hwreg23a(padapter, HW_VAR_DM_FUNC_CLR, (u8 *)(&mode));
305}
306
307static void Set_NETYPE0_MSR(struct rtw_adapter *padapter, u8 type)
308{
309 rtw_hal_set_hwreg23a(padapter, HW_VAR_MEDIA_STATUS, (u8 *)(&type));
310}
311
312void Set_MSR23a(struct rtw_adapter *padapter, u8 type)
313{
314 Set_NETYPE0_MSR(padapter, type);
315}
316
317inline u8 rtw_get_oper_ch23a(struct rtw_adapter *adapter)
318{
319 return adapter_to_dvobj(adapter)->oper_channel;
320}
321
322inline void rtw_set_oper_ch23a(struct rtw_adapter *adapter, u8 ch)
323{
324 adapter_to_dvobj(adapter)->oper_channel = ch;
325}
326
327inline u8 rtw_get_oper_bw23a(struct rtw_adapter *adapter)
328{
329 return adapter_to_dvobj(adapter)->oper_bwmode;
330}
331
332inline void rtw_set_oper_bw23a(struct rtw_adapter *adapter, u8 bw)
333{
334 adapter_to_dvobj(adapter)->oper_bwmode = bw;
335}
336
337inline u8 rtw_get_oper_ch23aoffset(struct rtw_adapter *adapter)
338{
339 return adapter_to_dvobj(adapter)->oper_ch_offset;
340}
341
342inline void rtw_set_oper_ch23aoffset23a(struct rtw_adapter *adapter, u8 offset)
343{
344 adapter_to_dvobj(adapter)->oper_ch_offset = offset;
345}
346
347void SelectChannel23a(struct rtw_adapter *padapter, unsigned char channel)
348{
349 mutex_lock(&adapter_to_dvobj(padapter)->setch_mutex);
350
351 /* saved channel info */
352 rtw_set_oper_ch23a(padapter, channel);
353
354 rtw_hal_set_chan23a(padapter, channel);
355
356 mutex_unlock(&adapter_to_dvobj(padapter)->setch_mutex);
357}
358
359void SetBWMode23a(struct rtw_adapter *padapter, unsigned short bwmode, unsigned char channel_offset)
360{
361 mutex_lock(&adapter_to_dvobj(padapter)->setbw_mutex);
362
363 /* saved bw info */
364 rtw_set_oper_bw23a(padapter, bwmode);
365 rtw_set_oper_ch23aoffset23a(padapter, channel_offset);
366
367 rtw_hal_set_bwmode23a(padapter, (enum ht_channel_width)bwmode,
368 channel_offset);
369
370 mutex_unlock(&adapter_to_dvobj(padapter)->setbw_mutex);
371}
372
373void set_channel_bwmode23a(struct rtw_adapter *padapter, unsigned char channel,
374 unsigned char channel_offset, unsigned short bwmode)
375{
376 u8 center_ch;
377
378 if (padapter->bNotifyChannelChange)
379 DBG_8723A("[%s] ch = %d, offset = %d, bwmode = %d\n", __func__, channel, channel_offset, bwmode);
380
381 if ((bwmode == HT_CHANNEL_WIDTH_20) ||
382 (channel_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)) {
383 /* SelectChannel23a(padapter, channel); */
384 center_ch = channel;
385 } else {
386 /* switch to the proper channel */
387 if (channel_offset == HAL_PRIME_CHNL_OFFSET_LOWER) {
388 /* SelectChannel23a(padapter, channel + 2); */
389 center_ch = channel + 2;
390 } else {
391 /* SelectChannel23a(padapter, channel - 2); */
392 center_ch = channel - 2;
393 }
394 }
395
396 /* set Channel */
397 mutex_lock(&adapter_to_dvobj(padapter)->setch_mutex);
398
399 /* saved channel/bw info */
400 rtw_set_oper_ch23a(padapter, channel);
401 rtw_set_oper_bw23a(padapter, bwmode);
402 rtw_set_oper_ch23aoffset23a(padapter, channel_offset);
403
404 rtw_hal_set_chan23a(padapter, center_ch); /* set center channel */
405
406 mutex_unlock(&adapter_to_dvobj(padapter)->setch_mutex);
407
408 SetBWMode23a(padapter, bwmode, channel_offset);
409}
410
411int get_bsstype23a(unsigned short capability)
412{
413 if (capability & BIT(0))
414 return WIFI_FW_AP_STATE;
415 else if (capability & BIT(1))
416 return WIFI_FW_ADHOC_STATE;
417 return 0;
418}
419
420inline u8 *get_my_bssid23a(struct wlan_bssid_ex *pnetwork)
421{
422 return pnetwork->MacAddress;
423}
424
425u16 get_beacon_interval23a(struct wlan_bssid_ex *bss)
426{
427 unsigned short val;
428 memcpy((unsigned char *)&val, rtw_get_beacon_interval23a_from_ie(bss->IEs), 2);
429
430 return le16_to_cpu(val);
431}
432
433int is_client_associated_to_ap23a(struct rtw_adapter *padapter)
434{
435 struct mlme_ext_priv *pmlmeext;
436 struct mlme_ext_info *pmlmeinfo;
437
438 if (!padapter)
439 return _FAIL;
440
441 pmlmeext = &padapter->mlmeextpriv;
442 pmlmeinfo = &pmlmeext->mlmext_info;
443
444 if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE))
445 return true;
446 else
447 return _FAIL;
448}
449
450int is_client_associated_to_ibss23a(struct rtw_adapter *padapter)
451{
452 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
453 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
454
455 if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
456 ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE))
457 return true;
458 else
459 return _FAIL;
460}
461
462int is_IBSS_empty23a(struct rtw_adapter *padapter)
463{
464 unsigned int i;
465 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
466 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
467
468 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
469 if (pmlmeinfo->FW_sta_info[i].status == 1)
470 return _FAIL;
471 }
472
473 return true;
474}
475
476unsigned int decide_wait_for_beacon_timeout23a(unsigned int bcn_interval)
477{
478 if ((bcn_interval << 2) < WAIT_FOR_BCN_TO_MIN)
479 return WAIT_FOR_BCN_TO_MIN;
480 else if ((bcn_interval << 2) > WAIT_FOR_BCN_TO_MAX)
481 return WAIT_FOR_BCN_TO_MAX;
482 else
483 return bcn_interval << 2;
484}
485
486void CAM_empty_entry23a(struct rtw_adapter *Adapter, u8 ucIndex)
487{
488 rtw_hal_set_hwreg23a(Adapter, HW_VAR_CAM_EMPTY_ENTRY, (u8 *)(&ucIndex));
489}
490
491void invalidate_cam_all23a(struct rtw_adapter *padapter)
492{
493 rtw_hal_set_hwreg23a(padapter, HW_VAR_CAM_INVALID_ALL, NULL);
494}
495
496void write_cam23a(struct rtw_adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key)
497{
498 unsigned int i, val, addr;
499 int j;
500 u32 cam_val[2];
501
502 addr = entry << 3;
503
504 for (j = 5; j >= 0; j--) {
505 switch (j) {
506 case 0:
507 val = (ctrl | (mac[0] << 16) | (mac[1] << 24));
508 break;
509 case 1:
510 val = (mac[2] | (mac[3] << 8) | (mac[4] << 16) | (mac[5] << 24));
511 break;
512 default:
513 i = (j - 2) << 2;
514 val = (key[i] | (key[i+1] << 8) | (key[i+2] << 16) | (key[i+3] << 24));
515 break;
516 }
517
518 cam_val[0] = val;
519 cam_val[1] = addr + (unsigned int)j;
520
521 rtw_hal_set_hwreg23a(padapter, HW_VAR_CAM_WRITE, (u8 *)cam_val);
522
523 /* rtw_write32(padapter, WCAMI, val); */
524
525 /* cmd = CAM_POLLINIG | CAM_WRITE | (addr + j); */
526 /* rtw_write32(padapter, RWCAM, cmd); */
527
528 /* DBG_8723A("%s => cam write: %x, %x\n", __func__, cmd, val); */
529
530 }
531}
532
533void clear_cam_entry23a(struct rtw_adapter *padapter, u8 entry)
534{
535 unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
536
537 unsigned char null_key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
538
539 write_cam23a(padapter, entry, 0, null_sta, null_key);
540}
541
542int allocate_fw_sta_entry23a(struct rtw_adapter *padapter)
543{
544 unsigned int mac_id;
545 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
546 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
547
548 for (mac_id = IBSS_START_MAC_ID; mac_id < NUM_STA; mac_id++) {
549 if (pmlmeinfo->FW_sta_info[mac_id].status == 0) {
550 pmlmeinfo->FW_sta_info[mac_id].status = 1;
551 pmlmeinfo->FW_sta_info[mac_id].retry = 0;
552 break;
553 }
554 }
555
556 return mac_id;
557}
558
559void flush_all_cam_entry23a(struct rtw_adapter *padapter)
560{
561 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
562 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
563
564 rtw_hal_set_hwreg23a(padapter, HW_VAR_CAM_INVALID_ALL, NULL);
565
566 memset((u8 *)(pmlmeinfo->FW_sta_info), 0, sizeof(pmlmeinfo->FW_sta_info));
567}
568
569#if defined(CONFIG_8723AU_P2P) && defined(CONFIG_8723AU_P2P)
570int WFD_info_handler(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
571{
572 struct wifidirect_info *pwdinfo;
573 u8 wfd_ie[128] = {0x00};
574 u32 wfd_ielen = 0;
575
576 pwdinfo = &padapter->wdinfo;
577 if (rtw_get_wfd_ie((u8 *) pIE, pIE->Length, wfd_ie, &wfd_ielen)) {
578 u8 attr_content[ 10 ] = { 0x00 };
579 u32 attr_contentlen = 0;
580
581 DBG_8723A("[%s] Found WFD IE\n", __func__);
582 rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
583 if (attr_contentlen) {
584 pwdinfo->wfd_info->peer_rtsp_ctrlport = RTW_GET_BE16(attr_content + 2);
585 DBG_8723A("[%s] Peer PORT NUM = %d\n", __func__, pwdinfo->wfd_info->peer_rtsp_ctrlport);
586 return true;
587 }
588 } else {
589 DBG_8723A("[%s] NO WFD IE\n", __func__);
590 }
591 return _FAIL;
592}
593#endif
594
595int WMM_param_handler23a(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
596{
597 /* struct registry_priv *pregpriv = &padapter->registrypriv; */
598 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
599 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
600 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
601
602 if (pmlmepriv->qospriv.qos_option == 0) {
603 pmlmeinfo->WMM_enable = 0;
604 return _FAIL;
605 }
606
607 pmlmeinfo->WMM_enable = 1;
608 memcpy(&pmlmeinfo->WMM_param, (pIE->data + 6),
609 sizeof(struct WMM_para_element));
610 return true;
611}
612
613void WMMOnAssocRsp23a(struct rtw_adapter *padapter)
614{
615 u8 ACI, ACM, AIFS, ECWMin, ECWMax, aSifsTime;
616 u8 acm_mask;
617 u16 TXOP;
618 u32 acParm, i;
619 u32 edca[4], inx[4];
620 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
621 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
622 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
623 struct registry_priv *pregpriv = &padapter->registrypriv;
624
625 if (pmlmeinfo->WMM_enable == 0) {
626 padapter->mlmepriv.acm_mask = 0;
627 return;
628 }
629
630 acm_mask = 0;
631
632 if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
633 aSifsTime = 10;
634 else
635 aSifsTime = 16;
636
637 for (i = 0; i < 4; i++) {
638 ACI = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 5) & 0x03;
639 ACM = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 4) & 0x01;
640
641 /* AIFS = AIFSN * slot time + SIFS - r2t phy delay */
642 AIFS = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN & 0x0f) * pmlmeinfo->slotTime + aSifsTime;
643
644 ECWMin = (pmlmeinfo->WMM_param.ac_param[i].CW & 0x0f);
645 ECWMax = (pmlmeinfo->WMM_param.ac_param[i].CW & 0xf0) >> 4;
646 TXOP = le16_to_cpu(pmlmeinfo->WMM_param.ac_param[i].TXOP_limit);
647
648 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
649
650 switch (ACI) {
651 case 0x0:
652 rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));
653 acm_mask |= (ACM? BIT(1):0);
654 edca[XMIT_BE_QUEUE] = acParm;
655 break;
656 case 0x1:
657 rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));
658 /* acm_mask |= (ACM? BIT(0):0); */
659 edca[XMIT_BK_QUEUE] = acParm;
660 break;
661 case 0x2:
662 rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));
663 acm_mask |= (ACM? BIT(2):0);
664 edca[XMIT_VI_QUEUE] = acParm;
665 break;
666 case 0x3:
667 rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));
668 acm_mask |= (ACM? BIT(3):0);
669 edca[XMIT_VO_QUEUE] = acParm;
670 break;
671 }
672
673 DBG_8723A("WMM(%x): %x, %x\n", ACI, ACM, acParm);
674 }
675
676 if (padapter->registrypriv.acm_method == 1)
677 rtw_hal_set_hwreg23a(padapter, HW_VAR_ACM_CTRL, (u8 *)(&acm_mask));
678 else
679 padapter->mlmepriv.acm_mask = acm_mask;
680
681 inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
682
683 if (pregpriv->wifi_spec == 1) {
684 u32 j, tmp, change_inx;
685
686 /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */
687 for (i = 0; i < 4; i++) {
688 for (j = i+1; j < 4; j++) {
689 /* compare CW and AIFS */
690 if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF)) {
691 change_inx = true;
692 } else if ((edca[j] & 0xFFFF) == (edca[i] & 0xFFFF)) {
693 /* compare TXOP */
694 if ((edca[j] >> 16) > (edca[i] >> 16))
695 change_inx = true;
696 }
697
698 if (change_inx) {
699 tmp = edca[i];
700 edca[i] = edca[j];
701 edca[j] = tmp;
702
703 tmp = inx[i];
704 inx[i] = inx[j];
705 inx[j] = tmp;
706
707 change_inx = false;
708 }
709 }
710 }
711 }
712
713 for (i = 0; i<4; i++) {
714 pxmitpriv->wmm_para_seq[i] = inx[i];
715 DBG_8723A("wmm_para_seq(%d): %d\n", i, pxmitpriv->wmm_para_seq[i]);
716 }
717
718 return;
719}
720
721static void bwmode_update_check(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
722{
723 struct HT_info_element *pHT_info;
724 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
725 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
726 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
727 struct registry_priv *pregistrypriv = &padapter->registrypriv;
728 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
729 unsigned char new_bwmode;
730 unsigned char new_ch_offset;
731
732 if (!pIE)
733 return;
734 if (!phtpriv->ht_option)
735 return;
736 if (pIE->Length > sizeof(struct HT_info_element))
737 return;
738
739 pHT_info = (struct HT_info_element *)pIE->data;
740
741 if ((pHT_info->infos[0] & BIT(2)) && pregistrypriv->cbw40_enable) {
742 new_bwmode = HT_CHANNEL_WIDTH_40;
743
744 switch (pHT_info->infos[0] & 0x3) {
745 case 1:
746 new_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
747 break;
748 case 3:
749 new_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
750 break;
751 default:
752 new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
753 break;
754 }
755 } else {
756 new_bwmode = HT_CHANNEL_WIDTH_20;
757 new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
758 }
759
760 if ((new_bwmode!= pmlmeext->cur_bwmode) ||
761 (new_ch_offset!= pmlmeext->cur_ch_offset)) {
762 pmlmeinfo->bwmode_updated = true;
763
764 pmlmeext->cur_bwmode = new_bwmode;
765 pmlmeext->cur_ch_offset = new_ch_offset;
766
767 /* update HT info also */
768 HT_info_handler23a(padapter, pIE);
769 } else {
770 pmlmeinfo->bwmode_updated = false;
771 }
772
773 if (pmlmeinfo->bwmode_updated) {
774 struct sta_info *psta;
775 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
776 struct sta_priv *pstapriv = &padapter->stapriv;
777
778 /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
779
780 /* update ap's stainfo */
781 psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress);
782 if (psta) {
783 struct ht_priv *phtpriv_sta = &psta->htpriv;
784
785 if (phtpriv_sta->ht_option) {
786 /* bwmode */
787 phtpriv_sta->bwmode = pmlmeext->cur_bwmode;
788 phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
789 } else {
790 phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20;
791 phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
792 }
793
794 }
795 }
796}
797
798void HT_caps_handler23a(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
799{
800 unsigned int i;
801 u8 rf_type;
802 u8 max_AMPDU_len, min_MPDU_spacing;
803 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
804 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
805 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
806 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
807
808 if (pIE == NULL) return;
809
810 if (phtpriv->ht_option == false) return;
811
812 pmlmeinfo->HT_caps_enable = 1;
813
814 for (i = 0; i < (pIE->Length); i++) {
815 if (i != 2) {
816 /* Commented by Albert 2010/07/12 */
817 /* Got the endian issue here. */
818 pmlmeinfo->HT_caps.u.HT_cap[i] &= (pIE->data[i]);
819 } else {
820 /* modify from fw by Thomas 2010/11/17 */
821 if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3) > (pIE->data[i] & 0x3))
822 max_AMPDU_len = (pIE->data[i] & 0x3);
823 else
824 max_AMPDU_len = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3);
825
826 if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) > (pIE->data[i] & 0x1c))
827 min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c);
828 else
829 min_MPDU_spacing = (pIE->data[i] & 0x1c);
830
831 pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para = max_AMPDU_len | min_MPDU_spacing;
832 }
833 }
834
835 /* Commented by Albert 2010/07/12 */
836 /* Have to handle the endian issue after copying. */
837 /* HT_ext_caps didn't be used yet. */
838 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info = le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info);
839 pmlmeinfo->HT_caps.u.HT_cap_element.HT_ext_caps = le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_ext_caps);
840
841 rtw23a_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
842
843 /* update the MCS rates */
844 for (i = 0; i < 16; i++) {
845 if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R))
846 pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_1R23A[i];
847 else
848 pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_2R23A[i];
849 }
850 return;
851}
852
853void HT_info_handler23a(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
854{
855 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
856 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
857 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
858 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
859
860 if (pIE == NULL) return;
861
862 if (phtpriv->ht_option == false) return;
863
864 if (pIE->Length > sizeof(struct HT_info_element))
865 return;
866
867 pmlmeinfo->HT_info_enable = 1;
868 memcpy(&pmlmeinfo->HT_info, pIE->data, pIE->Length);
869 return;
870}
871
872void HTOnAssocRsp23a(struct rtw_adapter *padapter)
873{
874 unsigned char max_AMPDU_len;
875 unsigned char min_MPDU_spacing;
876 /* struct registry_priv *pregpriv = &padapter->registrypriv; */
877 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
878 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
879
880 DBG_8723A("%s\n", __func__);
881
882 if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable)) {
883 pmlmeinfo->HT_enable = 1;
884 } else {
885 pmlmeinfo->HT_enable = 0;
886 /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
887 return;
888 }
889
890 /* handle A-MPDU parameter field */
891 /*
892 AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
893 AMPDU_para [4:2]:Min MPDU Start Spacing
894 */
895 max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
896
897 min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
898
899 rtw_hal_set_hwreg23a(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
900
901 rtw_hal_set_hwreg23a(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
902}
903
904void ERP_IE_handler23a(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
905{
906 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
907 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
908
909 if (pIE->Length>1)
910 return;
911
912 pmlmeinfo->ERP_enable = 1;
913 memcpy(&pmlmeinfo->ERP_IE, pIE->data, pIE->Length);
914}
915
916void VCS_update23a(struct rtw_adapter *padapter, struct sta_info *psta)
917{
918 struct registry_priv *pregpriv = &padapter->registrypriv;
919 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
920 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
921
922 switch (pregpriv->vrtl_carrier_sense) { /* 0:off 1:on 2:auto */
923 case 0: /* off */
924 psta->rtsen = 0;
925 psta->cts2self = 0;
926 break;
927 case 1: /* on */
928 if (pregpriv->vcs_type == 1) { /* 1:RTS/CTS 2:CTS to self */
929 psta->rtsen = 1;
930 psta->cts2self = 0;
931 } else {
932 psta->rtsen = 0;
933 psta->cts2self = 1;
934 }
935 break;
936 case 2: /* auto */
937 default:
938 if ((pmlmeinfo->ERP_enable) && (pmlmeinfo->ERP_IE & BIT(1))) {
939 if (pregpriv->vcs_type == 1) {
940 psta->rtsen = 1;
941 psta->cts2self = 0;
942 } else {
943 psta->rtsen = 0;
944 psta->cts2self = 1;
945 }
946 } else {
947 psta->rtsen = 0;
948 psta->cts2self = 0;
949 }
950 break;
951 }
952}
953
954int rtw_check_bcn_info23a(struct rtw_adapter *Adapter, u8 *pframe, u32 packet_len)
955{
956 unsigned int len;
957 unsigned char *p;
958 unsigned short val16;
959 struct wlan_network *cur_network = &Adapter->mlmepriv.cur_network;
960 u16 wpa_len = 0, rsn_len = 0;
961 u8 encryp_protocol = 0;
962 struct wlan_bssid_ex *bssid;
963 int group_cipher = 0, pairwise_cipher = 0, is_8021x = 0;
964 unsigned char *pbuf;
965 u32 wpa_ielen = 0;
966 u32 hidden_ssid = 0;
967 struct HT_info_element *pht_info = NULL;
968 struct ieee80211_ht_cap *pht_cap = NULL;
969 u32 bcn_channel;
970 unsigned short ht_cap_info;
971 unsigned char ht_info_infos_0;
972 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) pframe;
973 u8 *pbssid = hdr->addr3;
974
975 if (is_client_associated_to_ap23a(Adapter) == false)
976 return true;
977
978 len = packet_len - sizeof(struct ieee80211_hdr_3addr);
979
980 if (len > MAX_IE_SZ) {
981 DBG_8723A("%s IE too long for survey event\n", __func__);
982 return _FAIL;
983 }
984
985 if (memcmp(cur_network->network.MacAddress, pbssid, 6)) {
986 DBG_8723A("Oops: rtw_check_network_encrypt linked but recv other bssid bcn\n" MAC_FMT MAC_FMT,
987 MAC_ARG(pbssid), MAC_ARG(cur_network->network.MacAddress));
988 return true;
989 }
990
991 bssid = (struct wlan_bssid_ex *)kzalloc(sizeof(struct wlan_bssid_ex),
992 GFP_ATOMIC);
993
994 if (ieee80211_is_beacon(hdr->frame_control))
995 bssid->reserved = 1;
996
997 bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
998
999 /* below is to copy the information element */
1000 bssid->IELength = len;
1001 memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength);
1002
1003 /* check bw and channel offset */
1004 /* parsing HT_CAP_IE */
1005 p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
1006 if (p && len>0) {
1007 pht_cap = (struct ieee80211_ht_cap *)(p + 2);
1008 ht_cap_info = pht_cap->cap_info;
1009 } else {
1010 ht_cap_info = 0;
1011 }
1012 /* parsing HT_INFO_IE */
1013 p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
1014 if (p && len>0) {
1015 pht_info = (struct HT_info_element *)(p + 2);
1016 ht_info_infos_0 = pht_info->infos[0];
1017 } else {
1018 ht_info_infos_0 = 0;
1019 }
1020 if (ht_cap_info != cur_network->BcnInfo.ht_cap_info ||
1021 ((ht_info_infos_0&0x03) != (cur_network->BcnInfo.ht_info_infos_0&0x03))) {
1022 DBG_8723A("%s bcn now: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
1023 ht_cap_info, ht_info_infos_0);
1024 DBG_8723A("%s bcn link: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
1025 cur_network->BcnInfo.ht_cap_info, cur_network->BcnInfo.ht_info_infos_0);
1026 DBG_8723A("%s bw mode change, disconnect\n", __func__);
1027 /* bcn_info_update */
1028 cur_network->BcnInfo.ht_cap_info = ht_cap_info;
1029 cur_network->BcnInfo.ht_info_infos_0 = ht_info_infos_0;
1030 /* to do : need to check that whether modify related register of BB or not */
1031 }
1032
1033 /* Checking for channel */
1034 p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _DSSET_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
1035 if (p) {
1036 bcn_channel = *(p + 2);
1037 } else {/* In 5G, some ap do not have DSSET IE checking HT info for channel */
1038 p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
1039 if (pht_info) {
1040 bcn_channel = pht_info->primary_channel;
1041 } else { /* we don't find channel IE, so don't check it */
1042 DBG_8723A("Oops: %s we don't find channel IE, so don't check it\n", __func__);
1043 bcn_channel = Adapter->mlmeextpriv.cur_channel;
1044 }
1045 }
1046 if (bcn_channel != Adapter->mlmeextpriv.cur_channel) {
1047 DBG_8723A("%s beacon channel:%d cur channel:%d disconnect\n", __func__,
1048 bcn_channel, Adapter->mlmeextpriv.cur_channel);
1049 goto _mismatch;
1050 }
1051
1052 /* checking SSID */
1053 if ((p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _SSID_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_)) == NULL) {
1054 DBG_8723A("%s marc: cannot find SSID for survey event\n", __func__);
1055 hidden_ssid = true;
1056 } else {
1057 hidden_ssid = false;
1058 }
1059
1060 if ((NULL != p) && (false == hidden_ssid && (*(p + 1)))) {
1061 memcpy(bssid->Ssid.ssid, (p + 2), *(p + 1));
1062 bssid->Ssid.ssid_len = *(p + 1);
1063 } else {
1064 bssid->Ssid.ssid_len = 0;
1065 bssid->Ssid.ssid[0] = '\0';
1066 }
1067
1068 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1069 ("%s bssid.Ssid.Ssid:%s bssid.Ssid.SsidLength:%d "
1070 "cur_network->network.Ssid.Ssid:%s len:%d\n", __func__,
1071 bssid->Ssid.ssid, bssid->Ssid.ssid_len,
1072 cur_network->network.Ssid.ssid,
1073 cur_network->network.Ssid.ssid_len));
1074
1075 if (memcmp(bssid->Ssid.ssid, cur_network->network.Ssid.ssid, 32) ||
1076 bssid->Ssid.ssid_len != cur_network->network.Ssid.ssid_len) {
1077 if (bssid->Ssid.ssid[0] != '\0' &&
1078 bssid->Ssid.ssid_len != 0) { /* not hidden ssid */
1079 DBG_8723A("%s(), SSID is not match return FAIL\n",
1080 __func__);
1081 goto _mismatch;
1082 }
1083 }
1084
1085 /* check encryption info */
1086 val16 = rtw_get_capability23a((struct wlan_bssid_ex *)bssid);
1087
1088 if (val16 & BIT(4))
1089 bssid->Privacy = 1;
1090 else
1091 bssid->Privacy = 0;
1092
1093 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1094 ("%s(): cur_network->network.Privacy is %d, bssid.Privacy is %d\n",
1095 __func__, cur_network->network.Privacy, bssid->Privacy));
1096 if (cur_network->network.Privacy != bssid->Privacy) {
1097 DBG_8723A("%s(), privacy is not match return FAIL\n", __func__);
1098 goto _mismatch;
1099 }
1100
1101 rtw_get_sec_ie23a(bssid->IEs, bssid->IELength, NULL,&rsn_len, NULL,&wpa_len);
1102
1103 if (rsn_len > 0) {
1104 encryp_protocol = ENCRYP_PROTOCOL_WPA2;
1105 } else if (wpa_len > 0) {
1106 encryp_protocol = ENCRYP_PROTOCOL_WPA;
1107 } else {
1108 if (bssid->Privacy)
1109 encryp_protocol = ENCRYP_PROTOCOL_WEP;
1110 }
1111
1112 if (cur_network->BcnInfo.encryp_protocol != encryp_protocol) {
1113 DBG_8723A("%s(): enctyp is not match , return FAIL\n", __func__);
1114 goto _mismatch;
1115 }
1116
1117 if (encryp_protocol == ENCRYP_PROTOCOL_WPA || encryp_protocol == ENCRYP_PROTOCOL_WPA2) {
1118 pbuf = rtw_get_wpa_ie23a(&bssid->IEs[12], &wpa_ielen, bssid->IELength-12);
1119 if (pbuf && (wpa_ielen>0)) {
1120 if (_SUCCESS == rtw_parse_wpa_ie23a(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is_8021x)) {
1121 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1122 ("%s pnetwork->pairwise_cipher: %d, group_cipher is %d, is_8021x is %d\n", __func__,
1123 pairwise_cipher, group_cipher, is_8021x));
1124 }
1125 } else {
1126 pbuf = rtw_get_wpa2_ie23a(&bssid->IEs[12], &wpa_ielen, bssid->IELength-12);
1127
1128 if (pbuf && (wpa_ielen>0)) {
1129 if (_SUCCESS == rtw_parse_wpa2_ie23a(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is_8021x)) {
1130 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1131 ("%s pnetwork->pairwise_cipher: %d, pnetwork->group_cipher is %d, is_802x is %d\n",
1132 __func__, pairwise_cipher, group_cipher, is_8021x));
1133 }
1134 }
1135 }
1136
1137 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1138 ("%s cur_network->group_cipher is %d: %d\n", __func__, cur_network->BcnInfo.group_cipher, group_cipher));
1139 if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher || group_cipher != cur_network->BcnInfo.group_cipher) {
1140 DBG_8723A("%s pairwise_cipher(%x:%x) or group_cipher(%x:%x) is not match , return FAIL\n", __func__,
1141 pairwise_cipher, cur_network->BcnInfo.pairwise_cipher,
1142 group_cipher, cur_network->BcnInfo.group_cipher);
1143 goto _mismatch;
1144 }
1145
1146 if (is_8021x != cur_network->BcnInfo.is_8021x) {
1147 DBG_8723A("%s authentication is not match , return FAIL\n", __func__);
1148 goto _mismatch;
1149 }
1150 }
1151
1152 kfree(bssid);
1153 return _SUCCESS;
1154
1155_mismatch:
1156 kfree(bssid);
1157
1158 return _FAIL;
1159}
1160
1161void update_beacon23a_info(struct rtw_adapter *padapter, u8 *pframe, uint pkt_len, struct sta_info *psta)
1162{
1163 unsigned int i;
1164 unsigned int len;
1165 struct ndis_802_11_var_ies * pIE;
1166
1167 len = pkt_len -
1168 (_BEACON_IE_OFFSET_ + sizeof(struct ieee80211_hdr_3addr));
1169
1170 for (i = 0; i < len;) {
1171 pIE = (struct ndis_802_11_var_ies *)(pframe + (_BEACON_IE_OFFSET_ + sizeof(struct ieee80211_hdr_3addr)) + i);
1172
1173 switch (pIE->ElementID) {
1174 case _HT_EXTRA_INFO_IE_: /* HT info */
1175 /* HT_info_handler23a(padapter, pIE); */
1176 bwmode_update_check(padapter, pIE);
1177 break;
1178 case _ERPINFO_IE_:
1179 ERP_IE_handler23a(padapter, pIE);
1180 VCS_update23a(padapter, psta);
1181 break;
1182 default:
1183 break;
1184 }
1185 i += (pIE->Length + 2);
1186 }
1187}
1188
1189unsigned int is_ap_in_tkip23a(struct rtw_adapter *padapter)
1190{
1191 u32 i;
1192 struct ndis_802_11_var_ies * pIE;
1193 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1194 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1195 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
1196
1197 if (rtw_get_capability23a((struct wlan_bssid_ex *)cur_network) & WLAN_CAPABILITY_PRIVACY) {
1198 for (i = sizeof(struct ndis_802_11_fixed_ies); i < pmlmeinfo->network.IELength;) {
1199 pIE = (struct ndis_802_11_var_ies *)(pmlmeinfo->network.IEs + i);
1200
1201 switch (pIE->ElementID) {
1202 case _VENDOR_SPECIFIC_IE_:
1203 if ((!memcmp(pIE->data, RTW_WPA_OUI23A, 4)) && (!memcmp((pIE->data + 12), WPA_TKIP_CIPHER23A, 4)))
1204 return true;
1205 break;
1206 case _RSN_IE_2_:
1207 if (!memcmp((pIE->data + 8), RSN_TKIP_CIPHER23A, 4))
1208 return true;
1209 break;
1210 default:
1211 break;
1212 }
1213 i += (pIE->Length + 2);
1214 }
1215 return false;
1216 } else {
1217 return false;
1218 }
1219}
1220
1221unsigned int should_forbid_n_rate23a(struct rtw_adapter * padapter)
1222{
1223 u32 i;
1224 struct ndis_802_11_var_ies * pIE;
1225 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1226 struct wlan_bssid_ex *cur_network = &pmlmepriv->cur_network.network;
1227
1228 if (rtw_get_capability23a((struct wlan_bssid_ex *)cur_network) & WLAN_CAPABILITY_PRIVACY) {
1229 for (i = sizeof(struct ndis_802_11_fixed_ies); i < cur_network->IELength;) {
1230 pIE = (struct ndis_802_11_var_ies *)(cur_network->IEs + i);
1231
1232 switch (pIE->ElementID) {
1233 case _VENDOR_SPECIFIC_IE_:
1234 if (!memcmp(pIE->data, RTW_WPA_OUI23A, 4) &&
1235 ((!memcmp((pIE->data + 12), WPA_CIPHER_SUITE_CCMP23A, 4)) ||
1236 (!memcmp((pIE->data + 16), WPA_CIPHER_SUITE_CCMP23A, 4))))
1237 return false;
1238 break;
1239 case _RSN_IE_2_:
1240 if ((!memcmp((pIE->data + 8), RSN_CIPHER_SUITE_CCMP23A, 4)) ||
1241 (!memcmp((pIE->data + 12), RSN_CIPHER_SUITE_CCMP23A, 4)))
1242 return false;
1243 default:
1244 break;
1245 }
1246
1247 i += (pIE->Length + 2);
1248 }
1249 return true;
1250 } else {
1251 return false;
1252 }
1253}
1254
1255unsigned int is_ap_in_wep23a(struct rtw_adapter *padapter)
1256{
1257 u32 i;
1258 struct ndis_802_11_var_ies * pIE;
1259 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1260 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1261 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
1262
1263 if (rtw_get_capability23a((struct wlan_bssid_ex *)cur_network) & WLAN_CAPABILITY_PRIVACY) {
1264 for (i = sizeof(struct ndis_802_11_fixed_ies); i < pmlmeinfo->network.IELength;) {
1265 pIE = (struct ndis_802_11_var_ies *)(pmlmeinfo->network.IEs + i);
1266
1267 switch (pIE->ElementID) {
1268 case _VENDOR_SPECIFIC_IE_:
1269 if (!memcmp(pIE->data, RTW_WPA_OUI23A, 4))
1270 return false;
1271 break;
1272 case _RSN_IE_2_:
1273 return false;
1274
1275 default:
1276 break;
1277 }
1278
1279 i += (pIE->Length + 2);
1280 }
1281
1282 return true;
1283 } else {
1284 return false;
1285 }
1286}
1287
1288int wifirate2_ratetbl_inx23a(unsigned char rate)
1289{
1290 int inx = 0;
1291 rate = rate & 0x7f;
1292
1293 switch (rate) {
1294 case 54*2:
1295 inx = 11;
1296 break;
1297 case 48*2:
1298 inx = 10;
1299 break;
1300 case 36*2:
1301 inx = 9;
1302 break;
1303 case 24*2:
1304 inx = 8;
1305 break;
1306 case 18*2:
1307 inx = 7;
1308 break;
1309 case 12*2:
1310 inx = 6;
1311 break;
1312 case 9*2:
1313 inx = 5;
1314 break;
1315 case 6*2:
1316 inx = 4;
1317 break;
1318 case 11*2:
1319 inx = 3;
1320 break;
1321 case 11:
1322 inx = 2;
1323 break;
1324 case 2*2:
1325 inx = 1;
1326 break;
1327 case 1*2:
1328 inx = 0;
1329 break;
1330 }
1331 return inx;
1332}
1333
1334unsigned int update_basic_rate23a(unsigned char *ptn, unsigned int ptn_sz)
1335{
1336 unsigned int i, num_of_rate;
1337 unsigned int mask = 0;
1338
1339 num_of_rate = (ptn_sz > NumRates)? NumRates: ptn_sz;
1340
1341 for (i = 0; i < num_of_rate; i++) {
1342 if ((*(ptn + i)) & 0x80)
1343 mask |= 0x1 << wifirate2_ratetbl_inx23a(*(ptn + i));
1344 }
1345 return mask;
1346}
1347
1348unsigned int update_supported_rate23a(unsigned char *ptn, unsigned int ptn_sz)
1349{
1350 unsigned int i, num_of_rate;
1351 unsigned int mask = 0;
1352
1353 num_of_rate = (ptn_sz > NumRates)? NumRates: ptn_sz;
1354
1355 for (i = 0; i < num_of_rate; i++)
1356 mask |= 0x1 << wifirate2_ratetbl_inx23a(*(ptn + i));
1357 return mask;
1358}
1359
1360unsigned int update_MSC_rate23a(struct HT_caps_element *pHT_caps)
1361{
1362 unsigned int mask = 0;
1363
1364 mask = ((pHT_caps->u.HT_cap_element.MCS_rate[0] << 12) | (pHT_caps->u.HT_cap_element.MCS_rate[1] << 20));
1365
1366 return mask;
1367}
1368
1369int support_short_GI23a(struct rtw_adapter *padapter,
1370 struct HT_caps_element *pHT_caps)
1371{
1372 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1373 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1374 unsigned char bit_offset;
1375
1376 if (!(pmlmeinfo->HT_enable))
1377 return _FAIL;
1378 if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK))
1379 return _FAIL;
1380 bit_offset = (pmlmeext->cur_bwmode & HT_CHANNEL_WIDTH_40)? 6: 5;
1381
1382 if (pHT_caps->u.HT_cap_element.HT_caps_info & (0x1 << bit_offset))
1383 return _SUCCESS;
1384 else
1385 return _FAIL;
1386}
1387
1388unsigned char get_highest_rate_idx23a(u32 mask)
1389{
1390 int i;
1391 unsigned char rate_idx = 0;
1392
1393 for (i = 27; i >= 0; i--) {
1394 if (mask & BIT(i)) {
1395 rate_idx = i;
1396 break;
1397 }
1398 }
1399 return rate_idx;
1400}
1401
1402unsigned char get_highest_mcs_rate(struct HT_caps_element *pHT_caps)
1403{
1404 int i, mcs_rate;
1405
1406 mcs_rate = (pHT_caps->u.HT_cap_element.MCS_rate[0] | (pHT_caps->u.HT_cap_element.MCS_rate[1] << 8));
1407
1408 for (i = 15; i >= 0; i--) {
1409 if (mcs_rate & (0x1 << i))
1410 break;
1411 }
1412 return i;
1413}
1414
1415void Update_RA_Entry23a(struct rtw_adapter *padapter, struct sta_info *psta)
1416{
1417 rtw_hal_update_ra_mask23a(psta, 0);
1418}
1419
1420void enable_rate_adaptive(struct rtw_adapter *padapter, struct sta_info *psta)
1421{
1422 Update_RA_Entry23a(padapter, psta);
1423}
1424
1425void set_sta_rate23a(struct rtw_adapter *padapter, struct sta_info *psta)
1426{
1427 /* rate adaptive */
1428 enable_rate_adaptive(padapter, psta);
1429}
1430
1431/* Update RRSR and Rate for USERATE */
1432void update_tx_basic_rate23a(struct rtw_adapter *padapter, u8 wirelessmode)
1433{
1434 unsigned char supported_rates[NDIS_802_11_LENGTH_RATES_EX];
1435#ifdef CONFIG_8723AU_P2P
1436 struct wifidirect_info* pwdinfo = &padapter->wdinfo;
1437
1438 /* Added by Albert 2011/03/22 */
1439 /* In the P2P mode, the driver should not support the b mode. */
1440 /* So, the Tx packet shouldn't use the CCK rate */
1441 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1442 return;
1443#endif /* CONFIG_8723AU_P2P */
1444
1445 memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
1446
1447 if ((wirelessmode & WIRELESS_11B) && (wirelessmode == WIRELESS_11B)) {
1448 memcpy(supported_rates, rtw_basic_rate_cck, 4);
1449 } else if (wirelessmode & WIRELESS_11B) {
1450 memcpy(supported_rates, rtw_basic_rate_mix, 7);
1451 } else {
1452 memcpy(supported_rates, rtw_basic_rate_ofdm, 3);
1453 }
1454
1455 if (wirelessmode & WIRELESS_11B)
1456 update_mgnt_tx_rate23a(padapter, IEEE80211_CCK_RATE_1MB);
1457 else
1458 update_mgnt_tx_rate23a(padapter, IEEE80211_OFDM_RATE_6MB);
1459
1460 rtw_hal_set_hwreg23a(padapter, HW_VAR_BASIC_RATE, supported_rates);
1461}
1462
1463unsigned char check_assoc_AP23a(u8 *pframe, uint len)
1464{
1465 unsigned int i;
1466 struct ndis_802_11_var_ies * pIE;
1467 u8 epigram_vendor_flag;
1468 u8 ralink_vendor_flag;
1469 epigram_vendor_flag = 0;
1470 ralink_vendor_flag = 0;
1471
1472 for (i = sizeof(struct ndis_802_11_fixed_ies); i < len;) {
1473 pIE = (struct ndis_802_11_var_ies *)(pframe + i);
1474
1475 switch (pIE->ElementID) {
1476 case _VENDOR_SPECIFIC_IE_:
1477 if ((!memcmp(pIE->data, ARTHEROS_OUI1, 3)) ||
1478 (!memcmp(pIE->data, ARTHEROS_OUI2, 3))) {
1479 DBG_8723A("link to Artheros AP\n");
1480 return HT_IOT_PEER_ATHEROS;
1481 } else if ((!memcmp(pIE->data, BROADCOM_OUI1, 3)) ||
1482 !memcmp(pIE->data, BROADCOM_OUI2, 3) ||
1483 !memcmp(pIE->data, BROADCOM_OUI2, 3)) {
1484 DBG_8723A("link to Broadcom AP\n");
1485 return HT_IOT_PEER_BROADCOM;
1486 } else if (!memcmp(pIE->data, MARVELL_OUI, 3)) {
1487 DBG_8723A("link to Marvell AP\n");
1488 return HT_IOT_PEER_MARVELL;
1489 } else if (!memcmp(pIE->data, RALINK_OUI, 3)) {
1490 if (!ralink_vendor_flag) {
1491 ralink_vendor_flag = 1;
1492 } else {
1493 DBG_8723A("link to Ralink AP\n");
1494 return HT_IOT_PEER_RALINK;
1495 }
1496 } else if (!memcmp(pIE->data, CISCO_OUI, 3)) {
1497 DBG_8723A("link to Cisco AP\n");
1498 return HT_IOT_PEER_CISCO;
1499 } else if (!memcmp(pIE->data, REALTEK_OUI, 3)) {
1500 DBG_8723A("link to Realtek 96B\n");
1501 return HT_IOT_PEER_REALTEK;
1502 } else if (!memcmp(pIE->data, AIRGOCAP_OUI, 3)) {
1503 DBG_8723A("link to Airgo Cap\n");
1504 return HT_IOT_PEER_AIRGO;
1505 } else if (!memcmp(pIE->data, EPIGRAM_OUI, 3)) {
1506 epigram_vendor_flag = 1;
1507 if (ralink_vendor_flag) {
1508 DBG_8723A("link to Tenda W311R AP\n");
1509 return HT_IOT_PEER_TENDA;
1510 } else {
1511 DBG_8723A("Capture EPIGRAM_OUI\n");
1512 }
1513 } else {
1514 break;
1515 }
1516 default:
1517 break;
1518 }
1519
1520 i += (pIE->Length + 2);
1521 }
1522
1523 if (ralink_vendor_flag && !epigram_vendor_flag) {
1524 DBG_8723A("link to Ralink AP\n");
1525 return HT_IOT_PEER_RALINK;
1526 } else if (ralink_vendor_flag && epigram_vendor_flag) {
1527 DBG_8723A("link to Tenda W311R AP\n");
1528 return HT_IOT_PEER_TENDA;
1529 } else {
1530 DBG_8723A("link to new AP\n");
1531 return HT_IOT_PEER_UNKNOWN;
1532 }
1533}
1534
1535void update_IOT_info23a(struct rtw_adapter *padapter)
1536{
1537 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1538 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1539
1540 switch (pmlmeinfo->assoc_AP_vendor) {
1541 case HT_IOT_PEER_MARVELL:
1542 pmlmeinfo->turboMode_cts2self = 1;
1543 pmlmeinfo->turboMode_rtsen = 0;
1544 break;
1545 case HT_IOT_PEER_RALINK:
1546 pmlmeinfo->turboMode_cts2self = 0;
1547 pmlmeinfo->turboMode_rtsen = 1;
1548 /* disable high power */
1549 Switch_DM_Func23a(padapter, ~DYNAMIC_BB_DYNAMIC_TXPWR,
1550 false);
1551 break;
1552 case HT_IOT_PEER_REALTEK:
1553 /* rtw_write16(padapter, 0x4cc, 0xffff); */
1554 /* rtw_write16(padapter, 0x546, 0x01c0); */
1555 /* disable high power */
1556 Switch_DM_Func23a(padapter, ~DYNAMIC_BB_DYNAMIC_TXPWR,
1557 false);
1558 break;
1559 default:
1560 pmlmeinfo->turboMode_cts2self = 0;
1561 pmlmeinfo->turboMode_rtsen = 1;
1562 break;
1563 }
1564}
1565
1566void update_capinfo23a(struct rtw_adapter *Adapter, u16 updateCap)
1567{
1568 struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
1569 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1570 bool ShortPreamble;
1571
1572 if (updateCap & cShortPreamble) {
1573 /* Short Preamble */
1574 if (pmlmeinfo->preamble_mode != PREAMBLE_SHORT) {
1575 /* PREAMBLE_LONG or PREAMBLE_AUTO */
1576 ShortPreamble = true;
1577 pmlmeinfo->preamble_mode = PREAMBLE_SHORT;
1578 rtw_hal_set_hwreg23a(Adapter, HW_VAR_ACK_PREAMBLE, (u8 *)&ShortPreamble);
1579 }
1580 } else { /* Long Preamble */
1581 if (pmlmeinfo->preamble_mode != PREAMBLE_LONG) {
1582 /* PREAMBLE_SHORT or PREAMBLE_AUTO */
1583 ShortPreamble = false;
1584 pmlmeinfo->preamble_mode = PREAMBLE_LONG;
1585 rtw_hal_set_hwreg23a(Adapter, HW_VAR_ACK_PREAMBLE, (u8 *)&ShortPreamble);
1586 }
1587 }
1588 if (updateCap & cIBSS) {
1589 /* Filen: See 802.11-2007 p.91 */
1590 pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1591 } else {
1592 /* Filen: See 802.11-2007 p.90 */
1593 if (pmlmeext->cur_wireless_mode & (WIRELESS_11G | WIRELESS_11_24N)) {
1594 if (updateCap & cShortSlotTime) { /* Short Slot Time */
1595 if (pmlmeinfo->slotTime != SHORT_SLOT_TIME)
1596 pmlmeinfo->slotTime = SHORT_SLOT_TIME;
1597 } else { /* Long Slot Time */
1598 if (pmlmeinfo->slotTime != NON_SHORT_SLOT_TIME)
1599 pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1600 }
1601 } else if (pmlmeext->cur_wireless_mode & (WIRELESS_11A | WIRELESS_11_5N)) {
1602 pmlmeinfo->slotTime = SHORT_SLOT_TIME;
1603 } else {
1604 /* B Mode */
1605 pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1606 }
1607 }
1608 rtw_hal_set_hwreg23a(Adapter, HW_VAR_SLOT_TIME, &pmlmeinfo->slotTime);
1609}
1610
1611void update_wireless_mode23a(struct rtw_adapter *padapter)
1612{
1613 int ratelen, network_type = 0;
1614 u32 SIFS_Timer;
1615 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1616 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1617 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
1618 unsigned char *rate = cur_network->SupportedRates;
1619
1620 ratelen = rtw_get_rateset_len23a(cur_network->SupportedRates);
1621
1622 if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable))
1623 pmlmeinfo->HT_enable = 1;
1624
1625 if (pmlmeext->cur_channel > 14) {
1626 if (pmlmeinfo->HT_enable)
1627 network_type = WIRELESS_11_5N;
1628 network_type |= WIRELESS_11A;
1629 } else {
1630 if (pmlmeinfo->HT_enable)
1631 network_type = WIRELESS_11_24N;
1632
1633 if ((cckratesonly_included23a(rate, ratelen)) == true)
1634 network_type |= WIRELESS_11B;
1635 else if ((cckrates_included23a(rate, ratelen)) == true)
1636 network_type |= WIRELESS_11BG;
1637 else
1638 network_type |= WIRELESS_11G;
1639 }
1640
1641 pmlmeext->cur_wireless_mode = network_type & padapter->registrypriv.wireless_mode;
1642
1643 SIFS_Timer = 0x0a0a0808; /* 0x0808 -> for CCK, 0x0a0a -> for OFDM */
1644 /* change this value if having IOT issues. */
1645
1646 padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_RESP_SIFS, (u8 *)&SIFS_Timer);
1647
1648 if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
1649 update_mgnt_tx_rate23a(padapter, IEEE80211_CCK_RATE_1MB);
1650 else
1651 update_mgnt_tx_rate23a(padapter, IEEE80211_OFDM_RATE_6MB);
1652}
1653
1654void update_bmc_sta_support_rate23a(struct rtw_adapter *padapter, u32 mac_id)
1655{
1656 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1657 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1658
1659 if (pmlmeext->cur_wireless_mode & WIRELESS_11B) {
1660 /* Only B, B/G, and B/G/N AP could use CCK rate */
1661 memcpy((pmlmeinfo->FW_sta_info[mac_id].SupportedRates), rtw_basic_rate_cck, 4);
1662 } else {
1663 memcpy((pmlmeinfo->FW_sta_info[mac_id].SupportedRates), rtw_basic_rate_ofdm, 4);
1664 }
1665}
1666
1667int update_sta_support_rate23a(struct rtw_adapter *padapter, u8 *pvar_ie, uint var_ie_len, int cam_idx)
1668{
1669 unsigned int ie_len;
1670 struct ndis_802_11_var_ies *pIE;
1671 int supportRateNum = 0;
1672 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1673 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1674
1675 pIE = (struct ndis_802_11_var_ies *)rtw_get_ie23a(pvar_ie, _SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
1676 if (pIE == NULL)
1677 return _FAIL;
1678
1679 memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, pIE->data, ie_len);
1680 supportRateNum = ie_len;
1681
1682 pIE = (struct ndis_802_11_var_ies *)rtw_get_ie23a(pvar_ie, _EXT_SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
1683 if (pIE)
1684 memcpy((pmlmeinfo->FW_sta_info[cam_idx].SupportedRates + supportRateNum), pIE->data, ie_len);
1685 return _SUCCESS;
1686}
1687
1688void process_addba_req23a(struct rtw_adapter *padapter, u8 *paddba_req, u8 *addr)
1689{
1690 struct sta_info *psta;
1691 u16 tid, start_seq, param;
1692 struct recv_reorder_ctrl *preorder_ctrl;
1693 struct sta_priv *pstapriv = &padapter->stapriv;
1694 struct ADDBA_request *preq = (struct ADDBA_request*)paddba_req;
1695 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1696 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1697
1698 psta = rtw_get_stainfo23a(pstapriv, addr);
1699
1700 if (psta) {
1701 start_seq = le16_to_cpu(preq->BA_starting_seqctrl) >> 4;
1702
1703 param = le16_to_cpu(preq->BA_para_set);
1704 tid = (param>>2)&0x0f;
1705
1706 preorder_ctrl = &psta->recvreorder_ctrl[tid];
1707
1708 preorder_ctrl->indicate_seq = 0xffff;
1709
1710 preorder_ctrl->enable = (pmlmeinfo->bAcceptAddbaReq == true)? true :false;
1711 }
1712}
1713
1714void update_TSF23a(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len)
1715{
1716 u8 *pIE;
1717 u32 *pbuf;
1718
1719 pIE = pframe + sizeof(struct ieee80211_hdr_3addr);
1720 pbuf = (u32 *)pIE;
1721
1722 pmlmeext->TSFValue = le32_to_cpu(*(pbuf+1));
1723
1724 pmlmeext->TSFValue = pmlmeext->TSFValue << 32;
1725
1726 pmlmeext->TSFValue |= le32_to_cpu(*pbuf);
1727}
1728
1729void correct_TSF23a(struct rtw_adapter *padapter, struct mlme_ext_priv *pmlmeext)
1730{
1731 rtw_hal_set_hwreg23a(padapter, HW_VAR_CORRECT_TSF, NULL);
1732}
1733
1734void beacon_timing_control23a(struct rtw_adapter *padapter)
1735{
1736 rtw_hal_bcn_related_reg_setting23a(padapter);
1737}
1738
1739static struct rtw_adapter *pbuddy_padapter;
1740
1741int rtw_handle_dualmac23a(struct rtw_adapter *adapter, bool init)
1742{
1743 int status = _SUCCESS;
1744
1745 if (init) {
1746 if (pbuddy_padapter == NULL) {
1747 pbuddy_padapter = adapter;
1748 DBG_8723A("%s(): pbuddy_padapter == NULL, Set pbuddy_padapter\n", __func__);
1749 } else {
1750 adapter->pbuddy_adapter = pbuddy_padapter;
1751 pbuddy_padapter->pbuddy_adapter = adapter;
1752 /* clear global value */
1753 pbuddy_padapter = NULL;
1754 DBG_8723A("%s(): pbuddy_padapter exist, Exchange Information\n", __func__);
1755 }
1756 } else {
1757 pbuddy_padapter = NULL;
1758 }
1759 return status;
1760}
diff --git a/drivers/staging/rtl8723au/core/rtw_xmit.c b/drivers/staging/rtl8723au/core/rtw_xmit.c
new file mode 100644
index 000000000000..a1abba053944
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_xmit.c
@@ -0,0 +1,2463 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _RTW_XMIT_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <wifi.h>
20#include <osdep_intf.h>
21#include <linux/ip.h>
22#include <usb_ops.h>
23
24static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
25static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
26
27static void _init_txservq(struct tx_servq *ptxservq)
28{
29
30 INIT_LIST_HEAD(&ptxservq->tx_pending);
31 _rtw_init_queue23a(&ptxservq->sta_pending);
32 ptxservq->qcnt = 0;
33
34}
35
36void _rtw_init_sta_xmit_priv23a(struct sta_xmit_priv *psta_xmitpriv)
37{
38
39 spin_lock_init(&psta_xmitpriv->lock);
40
41 /* for (i = 0 ; i < MAX_NUMBLKS; i++) */
42 /* _init_txservq(&psta_xmitpriv->blk_q[i]); */
43
44 _init_txservq(&psta_xmitpriv->be_q);
45 _init_txservq(&psta_xmitpriv->bk_q);
46 _init_txservq(&psta_xmitpriv->vi_q);
47 _init_txservq(&psta_xmitpriv->vo_q);
48 INIT_LIST_HEAD(&psta_xmitpriv->legacy_dz);
49 INIT_LIST_HEAD(&psta_xmitpriv->apsd);
50
51}
52
53s32 _rtw_init_xmit_priv23a(struct xmit_priv *pxmitpriv, struct rtw_adapter *padapter)
54{
55 int i;
56 struct xmit_buf *pxmitbuf;
57 struct xmit_frame *pxframe;
58 int res = _SUCCESS;
59 u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
60 u32 num_xmit_extbuf = NR_XMIT_EXTBUFF;
61
62 /* We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc(). */
63 /* memset((unsigned char *)pxmitpriv, 0, sizeof(struct xmit_priv)); */
64
65 spin_lock_init(&pxmitpriv->lock);
66 spin_lock_init(&pxmitpriv->lock_sctx);
67 sema_init(&pxmitpriv->xmit_sema, 0);
68 sema_init(&pxmitpriv->terminate_xmitthread_sema, 0);
69
70 /*
71 Please insert all the queue initializaiton using _rtw_init_queue23a below
72 */
73
74 pxmitpriv->adapter = padapter;
75
76 _rtw_init_queue23a(&pxmitpriv->be_pending);
77 _rtw_init_queue23a(&pxmitpriv->bk_pending);
78 _rtw_init_queue23a(&pxmitpriv->vi_pending);
79 _rtw_init_queue23a(&pxmitpriv->vo_pending);
80 _rtw_init_queue23a(&pxmitpriv->bm_pending);
81
82 _rtw_init_queue23a(&pxmitpriv->free_xmit_queue);
83
84 /*
85 Please allocate memory with the sz = (struct xmit_frame) * NR_XMITFRAME,
86 and initialize free_xmit_frame below.
87 Please also apply free_txobj to link_up all the xmit_frames...
88 */
89
90 pxmitpriv->pallocated_frame_buf = rtw_zvmalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4);
91
92 if (pxmitpriv->pallocated_frame_buf == NULL) {
93 pxmitpriv->pxmit_frame_buf = NULL;
94 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_frame fail!\n"));
95 res = _FAIL;
96 goto exit;
97 }
98 pxmitpriv->pxmit_frame_buf = PTR_ALIGN(pxmitpriv->pallocated_frame_buf, 4);
99
100 pxframe = (struct xmit_frame*) pxmitpriv->pxmit_frame_buf;
101
102 for (i = 0; i < NR_XMITFRAME; i++) {
103 INIT_LIST_HEAD(&pxframe->list);
104
105 pxframe->padapter = padapter;
106 pxframe->frame_tag = NULL_FRAMETAG;
107
108 pxframe->pkt = NULL;
109
110 pxframe->buf_addr = NULL;
111 pxframe->pxmitbuf = NULL;
112
113 list_add_tail(&pxframe->list,
114 &pxmitpriv->free_xmit_queue.queue);
115
116 pxframe++;
117 }
118
119 pxmitpriv->free_xmitframe_cnt = NR_XMITFRAME;
120
121 pxmitpriv->frag_len = MAX_FRAG_THRESHOLD;
122
123 /* init xmit_buf */
124 _rtw_init_queue23a(&pxmitpriv->free_xmitbuf_queue);
125 INIT_LIST_HEAD(&pxmitpriv->xmitbuf_list);
126 _rtw_init_queue23a(&pxmitpriv->pending_xmitbuf_queue);
127
128 for (i = 0; i < NR_XMITBUFF; i++) {
129 pxmitbuf = kzalloc(sizeof(struct xmit_buf), GFP_KERNEL);
130 if (!pxmitbuf)
131 goto fail;
132 INIT_LIST_HEAD(&pxmitbuf->list);
133 INIT_LIST_HEAD(&pxmitbuf->list2);
134
135 pxmitbuf->padapter = padapter;
136
137 /* Tx buf allocation may fail sometimes, so sleep and retry. */
138 res = rtw_os_xmit_resource_alloc23a(padapter, pxmitbuf,
139 (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ));
140 if (res == _FAIL) {
141 goto fail;
142 }
143
144 list_add_tail(&pxmitbuf->list,
145 &pxmitpriv->free_xmitbuf_queue.queue);
146 list_add_tail(&pxmitbuf->list2,
147 &pxmitpriv->xmitbuf_list);
148 }
149
150 pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF;
151
152 /* init xframe_ext queue, the same count as extbuf */
153 _rtw_init_queue23a(&pxmitpriv->free_xframe_ext_queue);
154
155 pxmitpriv->xframe_ext_alloc_addr = rtw_zvmalloc(num_xmit_extbuf * sizeof(struct xmit_frame) + 4);
156
157 if (pxmitpriv->xframe_ext_alloc_addr == NULL) {
158 pxmitpriv->xframe_ext = NULL;
159 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xframe_ext fail!\n"));
160 res = _FAIL;
161 goto exit;
162 }
163 pxmitpriv->xframe_ext = PTR_ALIGN(pxmitpriv->xframe_ext_alloc_addr, 4);
164 pxframe = (struct xmit_frame*)pxmitpriv->xframe_ext;
165
166 for (i = 0; i < num_xmit_extbuf; i++) {
167 INIT_LIST_HEAD(&pxframe->list);
168
169 pxframe->padapter = padapter;
170 pxframe->frame_tag = NULL_FRAMETAG;
171
172 pxframe->pkt = NULL;
173
174 pxframe->buf_addr = NULL;
175 pxframe->pxmitbuf = NULL;
176
177 pxframe->ext_tag = 1;
178
179 list_add_tail(&pxframe->list,
180 &pxmitpriv->free_xframe_ext_queue.queue);
181
182 pxframe++;
183 }
184 pxmitpriv->free_xframe_ext_cnt = num_xmit_extbuf;
185
186 /* Init xmit extension buff */
187 _rtw_init_queue23a(&pxmitpriv->free_xmit_extbuf_queue);
188 INIT_LIST_HEAD(&pxmitpriv->xmitextbuf_list);
189
190 for (i = 0; i < num_xmit_extbuf; i++) {
191 pxmitbuf = kzalloc(sizeof(struct xmit_buf), GFP_KERNEL);
192 if (!pxmitbuf)
193 goto fail;
194 INIT_LIST_HEAD(&pxmitbuf->list);
195 INIT_LIST_HEAD(&pxmitbuf->list2);
196
197 pxmitbuf->padapter = padapter;
198
199 /* Tx buf allocation may fail sometimes, so sleep and retry. */
200 res = rtw_os_xmit_resource_alloc23a(padapter, pxmitbuf,
201 max_xmit_extbuf_size + XMITBUF_ALIGN_SZ);
202 if (res == _FAIL) {
203 goto exit;
204 }
205
206 list_add_tail(&pxmitbuf->list,
207 &pxmitpriv->free_xmit_extbuf_queue.queue);
208 list_add_tail(&pxmitbuf->list2,
209 &pxmitpriv->xmitextbuf_list);
210 }
211
212 pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf;
213
214 rtw_alloc_hwxmits23a(padapter);
215 rtw_init_hwxmits23a(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
216
217 for (i = 0; i < 4; i ++)
218 pxmitpriv->wmm_para_seq[i] = i;
219
220 pxmitpriv->txirp_cnt = 1;
221
222 sema_init(&pxmitpriv->tx_retevt, 0);
223
224 /* per AC pending irp */
225 pxmitpriv->beq_cnt = 0;
226 pxmitpriv->bkq_cnt = 0;
227 pxmitpriv->viq_cnt = 0;
228 pxmitpriv->voq_cnt = 0;
229
230 pxmitpriv->ack_tx = false;
231 mutex_init(&pxmitpriv->ack_tx_mutex);
232 rtw_sctx_init23a(&pxmitpriv->ack_tx_ops, 0);
233 rtw_hal_init23a_xmit_priv(padapter);
234
235exit:
236
237 return res;
238fail:
239 goto exit;
240}
241
242void _rtw_free_xmit_priv23a (struct xmit_priv *pxmitpriv)
243{
244 struct rtw_adapter *padapter = pxmitpriv->adapter;
245 struct xmit_frame *pxmitframe = (struct xmit_frame*) pxmitpriv->pxmit_frame_buf;
246 struct xmit_buf *pxmitbuf;
247 struct list_head *plist, *ptmp;
248 u32 num_xmit_extbuf = NR_XMIT_EXTBUFF;
249 int i;
250
251 rtw_hal_free_xmit_priv23a(padapter);
252
253 if (pxmitpriv->pxmit_frame_buf == NULL)
254 return;
255 for (i = 0; i < NR_XMITFRAME; i++) {
256 rtw_os_xmit_complete23a(padapter, pxmitframe);
257 pxmitframe++;
258 }
259
260 list_for_each_safe(plist, ptmp, &pxmitpriv->xmitbuf_list) {
261 pxmitbuf = container_of(plist, struct xmit_buf, list2);
262 list_del_init(&pxmitbuf->list2);
263 rtw_os_xmit_resource_free23a(padapter, pxmitbuf);
264 kfree(pxmitbuf);
265 }
266
267 if (pxmitpriv->pallocated_frame_buf) {
268 rtw_vmfree(pxmitpriv->pallocated_frame_buf, NR_XMITFRAME * sizeof(struct xmit_frame) + 4);
269 }
270
271 /* free xframe_ext queue, the same count as extbuf */
272 if ((pxmitframe = (struct xmit_frame*)pxmitpriv->xframe_ext)) {
273 for (i = 0; i<num_xmit_extbuf; i++) {
274 rtw_os_xmit_complete23a(padapter, pxmitframe);
275 pxmitframe++;
276 }
277 }
278 if (pxmitpriv->xframe_ext_alloc_addr)
279 rtw_vmfree(pxmitpriv->xframe_ext_alloc_addr, num_xmit_extbuf * sizeof(struct xmit_frame) + 4);
280
281 /* free xmit extension buff */
282 list_for_each_safe(plist, ptmp, &pxmitpriv->xmitextbuf_list) {
283 pxmitbuf = container_of(plist, struct xmit_buf, list2);
284 list_del_init(&pxmitbuf->list2);
285 rtw_os_xmit_resource_free23a(padapter, pxmitbuf);
286 kfree(pxmitbuf);
287 }
288
289 rtw_free_hwxmits23a(padapter);
290 mutex_destroy(&pxmitpriv->ack_tx_mutex);
291}
292
293static void update_attrib_vcs_info(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
294{
295 u32 sz;
296 struct pkt_attrib *pattrib = &pxmitframe->attrib;
297 struct sta_info *psta = pattrib->psta;
298 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
299 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
300
301 if (pattrib->psta) {
302 psta = pattrib->psta;
303 } else {
304 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
305 psta = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]);
306 }
307
308 if (psta == NULL) {
309 DBG_8723A("%s, psta == NUL\n", __func__);
310 return;
311 }
312
313 if (!(psta->state &_FW_LINKED)) {
314 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
315 return;
316 }
317
318 if (pattrib->nr_frags != 1)
319 sz = padapter->xmitpriv.frag_len;
320 else /* no frag */
321 sz = pattrib->last_txcmdsz;
322
323 /* (1) RTS_Threshold is compared to the MPDU, not MSDU. */
324 /* (2) If there are more than one frag in this MSDU, only the first frag uses protection frame. */
325 /* Other fragments are protected by previous fragment. */
326 /* So we only need to check the length of first fragment. */
327 if (pmlmeext->cur_wireless_mode < WIRELESS_11_24N || padapter->registrypriv.wifi_spec) {
328 if (sz > padapter->registrypriv.rts_thresh) {
329 pattrib->vcs_mode = RTS_CTS;
330 } else {
331 if (psta->rtsen)
332 pattrib->vcs_mode = RTS_CTS;
333 else if (psta->cts2self)
334 pattrib->vcs_mode = CTS_TO_SELF;
335 else
336 pattrib->vcs_mode = NONE_VCS;
337 }
338 } else {
339 while (true) {
340 /* IOT action */
341 if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS) &&
342 (pattrib->ampdu_en) &&
343 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) {
344 pattrib->vcs_mode = CTS_TO_SELF;
345 break;
346 }
347
348 /* check ERP protection */
349 if (psta->rtsen || psta->cts2self) {
350 if (psta->rtsen)
351 pattrib->vcs_mode = RTS_CTS;
352 else if (psta->cts2self)
353 pattrib->vcs_mode = CTS_TO_SELF;
354
355 break;
356 }
357
358 /* check HT op mode */
359 if (pattrib->ht_en) {
360 u8 HTOpMode = pmlmeinfo->HT_protection;
361 if ((pmlmeext->cur_bwmode && (HTOpMode == 2 || HTOpMode == 3)) ||
362 (!pmlmeext->cur_bwmode && HTOpMode == 3)) {
363 pattrib->vcs_mode = RTS_CTS;
364 break;
365 }
366 }
367
368 /* check rts */
369 if (sz > padapter->registrypriv.rts_thresh) {
370 pattrib->vcs_mode = RTS_CTS;
371 break;
372 }
373
374 /* to do list: check MIMO power save condition. */
375
376 /* check AMPDU aggregation for TXOP */
377 if (pattrib->ampdu_en) {
378 pattrib->vcs_mode = RTS_CTS;
379 break;
380 }
381
382 pattrib->vcs_mode = NONE_VCS;
383 break;
384 }
385 }
386}
387
388static void update_attrib_phy_info(struct pkt_attrib *pattrib, struct sta_info *psta)
389{
390 /*if (psta->rtsen)
391 pattrib->vcs_mode = RTS_CTS;
392 else if (psta->cts2self)
393 pattrib->vcs_mode = CTS_TO_SELF;
394 else
395 pattrib->vcs_mode = NONE_VCS;*/
396
397 pattrib->mdata = 0;
398 pattrib->eosp = 0;
399 pattrib->triggered = 0;
400
401 /* qos_en, ht_en, init rate, , bw, ch_offset, sgi */
402 pattrib->qos_en = psta->qos_option;
403
404 pattrib->raid = psta->raid;
405 pattrib->ht_en = psta->htpriv.ht_option;
406 pattrib->bwmode = psta->htpriv.bwmode;
407 pattrib->ch_offset = psta->htpriv.ch_offset;
408 pattrib->sgi = psta->htpriv.sgi;
409 pattrib->ampdu_en = false;
410
411 pattrib->retry_ctrl = false;
412}
413
414u8 qos_acm23a(u8 acm_mask, u8 priority)
415{
416 u8 change_priority = priority;
417
418 switch (priority) {
419 case 0:
420 case 3:
421 if (acm_mask & BIT(1))
422 change_priority = 1;
423 break;
424 case 1:
425 case 2:
426 break;
427 case 4:
428 case 5:
429 if (acm_mask & BIT(2))
430 change_priority = 0;
431 break;
432 case 6:
433 case 7:
434 if (acm_mask & BIT(3))
435 change_priority = 5;
436 break;
437 default:
438 DBG_8723A("qos_acm23a(): invalid pattrib->priority: %d!!!\n",
439 priority);
440 break;
441 }
442
443 return change_priority;
444}
445
446static void set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib)
447{
448 struct ethhdr etherhdr;
449 struct iphdr ip_hdr;
450 s32 UserPriority = 0;
451
452 _rtw_open_pktfile23a(ppktfile->pkt, ppktfile);
453 _rtw_pktfile_read23a(ppktfile, (unsigned char*)&etherhdr, ETH_HLEN);
454
455 /* get UserPriority from IP hdr */
456 if (pattrib->ether_type == 0x0800) {
457 _rtw_pktfile_read23a(ppktfile, (u8*)&ip_hdr, sizeof(ip_hdr));
458/* UserPriority = (ntohs(ip_hdr.tos) >> 5) & 0x3; */
459 UserPriority = ip_hdr.tos >> 5;
460 } else if (pattrib->ether_type == 0x888e) {
461 /* "When priority processing of data frames is supported, */
462 /* a STA's SME should send EAPOL-Key frames at the highest
463 priority." */
464 UserPriority = 7;
465 }
466
467 pattrib->priority = UserPriority;
468 pattrib->hdrlen = sizeof(struct ieee80211_qos_hdr);
469 pattrib->subtype = WIFI_QOS_DATA_TYPE;
470}
471
472static s32 update_attrib(struct rtw_adapter *padapter,
473 struct sk_buff *pkt, struct pkt_attrib *pattrib)
474{
475 uint i;
476 struct pkt_file pktfile;
477 struct sta_info *psta = NULL;
478 struct ethhdr etherhdr;
479
480 int bmcast;
481 struct sta_priv *pstapriv = &padapter->stapriv;
482 struct security_priv *psecuritypriv = &padapter->securitypriv;
483 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
484 struct qos_priv *pqospriv = &pmlmepriv->qospriv;
485 int res = _SUCCESS;
486
487 _rtw_open_pktfile23a(pkt, &pktfile);
488 i = _rtw_pktfile_read23a(&pktfile, (u8*)&etherhdr, ETH_HLEN);
489
490 pattrib->ether_type = ntohs(etherhdr.h_proto);
491
492 memcpy(pattrib->dst, &etherhdr.h_dest, ETH_ALEN);
493 memcpy(pattrib->src, &etherhdr.h_source, ETH_ALEN);
494
495 pattrib->pctrl = 0;
496
497 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) ||
498 (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
499 memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
500 memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
501 }
502 else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
503 memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
504 memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
505 }
506 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
507 memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
508 memcpy(pattrib->ta, get_bssid(pmlmepriv), ETH_ALEN);
509 }
510
511 pattrib->pktlen = pktfile.pkt_len;
512
513 if (pattrib->ether_type == ETH_P_IP) {
514 /* The following is for DHCP and ARP packet, we use cck1M
515 to tx these packets and let LPS awake some time */
516 /* to prevent DHCP protocol fail */
517 u8 tmp[24];
518 _rtw_pktfile_read23a(&pktfile, &tmp[0], 24);
519 pattrib->dhcp_pkt = 0;
520 if (pktfile.pkt_len > 282) {/* MINIMUM_DHCP_PACKET_SIZE) { */
521 if (ETH_P_IP == pattrib->ether_type) {/* IP header */
522 if (((tmp[21] == 68) && (tmp[23] == 67)) ||
523 ((tmp[21] == 67) && (tmp[23] == 68))) {
524 /* 68 : UDP BOOTP client */
525 /* 67 : UDP BOOTP server */
526 RT_TRACE(_module_rtl871x_xmit_c_,
527 _drv_err_,
528 ("======================"
529 "update_attrib: get DHCP "
530 "Packet\n"));
531 pattrib->dhcp_pkt = 1;
532 }
533 }
534 }
535 } else if (0x888e == pattrib->ether_type) {
536 DBG_8723A_LEVEL(_drv_always_, "send eapol packet\n");
537 }
538
539 if ((pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1)) {
540 rtw_set_scan_deny(padapter, 3000);
541 }
542
543 /* If EAPOL , ARP , OR DHCP packet, driver must be in active mode. */
544 if ((pattrib->ether_type == 0x0806) ||
545 (pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1)) {
546 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_SPECIAL_PACKET, 1);
547 }
548
549 bmcast = is_multicast_ether_addr(pattrib->ra);
550
551 /* get sta_info */
552 if (bmcast) {
553 psta = rtw_get_bcmc_stainfo23a(padapter);
554 } else {
555 psta = rtw_get_stainfo23a(pstapriv, pattrib->ra);
556 if (psta == NULL) { /* if we cannot get psta => drrp the pkt */
557 RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_,
558 ("\nupdate_attrib => get sta_info fail, ra:"
559 MAC_FMT"\n", MAC_ARG(pattrib->ra)));
560 res = _FAIL;
561 goto exit;
562 } else if ((check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) &&
563 (!(psta->state & _FW_LINKED))) {
564 res = _FAIL;
565 goto exit;
566 }
567 }
568
569 if (psta) {
570 pattrib->mac_id = psta->mac_id;
571 /* DBG_8723A("%s ==> mac_id(%d)\n", __func__, pattrib->mac_id); */
572 pattrib->psta = psta;
573 } else {
574 /* if we cannot get psta => drop the pkt */
575 RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_,
576 ("\nupdate_attrib => get sta_info fail, ra:" MAC_FMT
577 "\n", MAC_ARG(pattrib->ra)));
578 res = _FAIL;
579 goto exit;
580 }
581
582 pattrib->ack_policy = 0;
583 /* get ether_hdr_len */
584
585 /* pattrib->ether_type == 0x8100) ? (14 + 4): 14; vlan tag */
586 pattrib->pkt_hdrlen = ETH_HLEN;
587
588 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
589 pattrib->subtype = WIFI_DATA_TYPE;
590 pattrib->priority = 0;
591
592 if (check_fwstate(pmlmepriv, WIFI_AP_STATE | WIFI_ADHOC_STATE |
593 WIFI_ADHOC_MASTER_STATE)) {
594 if (psta->qos_option)
595 set_qos(&pktfile, pattrib);
596 } else {
597 if (pqospriv->qos_option) {
598 set_qos(&pktfile, pattrib);
599
600 if (pmlmepriv->acm_mask != 0) {
601 pattrib->priority = qos_acm23a(pmlmepriv->acm_mask,
602 pattrib->priority);
603 }
604 }
605 }
606
607 if (psta->ieee8021x_blocked == true) {
608 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
609 ("\n psta->ieee8021x_blocked == true\n"));
610
611 pattrib->encrypt = 0;
612
613 if ((pattrib->ether_type != 0x888e) &&
614 (check_fwstate(pmlmepriv, WIFI_MP_STATE) == false)) {
615 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
616 ("\npsta->ieee8021x_blocked == true, "
617 "pattrib->ether_type(%.4x) != 0x888e\n",
618 pattrib->ether_type));
619 res = _FAIL;
620 goto exit;
621 }
622 } else {
623 GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast);
624
625 switch (psecuritypriv->dot11AuthAlgrthm) {
626 case dot11AuthAlgrthm_Open:
627 case dot11AuthAlgrthm_Shared:
628 case dot11AuthAlgrthm_Auto:
629 pattrib->key_idx =
630 (u8)psecuritypriv->dot11PrivacyKeyIndex;
631 break;
632 case dot11AuthAlgrthm_8021X:
633 if (bmcast)
634 pattrib->key_idx =
635 (u8)psecuritypriv->dot118021XGrpKeyid;
636 else
637 pattrib->key_idx = 0;
638 break;
639 default:
640 pattrib->key_idx = 0;
641 break;
642 }
643
644 }
645
646 switch (pattrib->encrypt) {
647 case _WEP40_:
648 case _WEP104_:
649 pattrib->iv_len = 4;
650 pattrib->icv_len = 4;
651 break;
652
653 case _TKIP_:
654 pattrib->iv_len = 8;
655 pattrib->icv_len = 4;
656
657 if (padapter->securitypriv.busetkipkey == _FAIL) {
658 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
659 ("\npadapter->securitypriv.busetkip"
660 "key(%d) == _FAIL drop packet\n",
661 padapter->securitypriv.busetkipkey));
662 res = _FAIL;
663 goto exit;
664 }
665
666 break;
667 case _AES_:
668 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
669 ("pattrib->encrypt =%d (_AES_)\n", pattrib->encrypt));
670 pattrib->iv_len = 8;
671 pattrib->icv_len = 8;
672 break;
673
674 default:
675 pattrib->iv_len = 0;
676 pattrib->icv_len = 0;
677 break;
678 }
679
680 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
681 ("update_attrib: encrypt =%d\n", pattrib->encrypt));
682
683 if (pattrib->encrypt && psecuritypriv->hw_decrypted == false) {
684 pattrib->bswenc = true;
685 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
686 ("update_attrib: encrypt =%d bswenc = true\n",
687 pattrib->encrypt));
688 } else {
689 pattrib->bswenc = false;
690 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
691 ("update_attrib: bswenc = false\n"));
692 }
693 update_attrib_phy_info(pattrib, psta);
694
695exit:
696
697 return res;
698}
699
700static s32 xmitframe_addmic(struct rtw_adapter *padapter,
701 struct xmit_frame *pxmitframe) {
702 struct mic_data micdata;
703 struct sta_info *stainfo;
704 struct pkt_attrib *pattrib = &pxmitframe->attrib;
705 struct security_priv *psecuritypriv = &padapter->securitypriv;
706 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
707 int curfragnum, length;
708 u8 *pframe, *payload, mic[8];
709 u8 priority[4]= {0x0, 0x0, 0x0, 0x0};
710 u8 hw_hdr_offset = 0;
711 int bmcst = is_multicast_ether_addr(pattrib->ra);
712
713 if (pattrib->psta) {
714 stainfo = pattrib->psta;
715 } else {
716 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
717 stainfo = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]);
718 }
719
720 if (!stainfo) {
721 DBG_8723A("%s, psta == NUL\n", __func__);
722 return _FAIL;
723 }
724
725 if (!(stainfo->state &_FW_LINKED)) {
726 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n",
727 __func__, stainfo->state);
728 return _FAIL;
729 }
730
731 hw_hdr_offset = TXDESC_OFFSET;
732
733 if (pattrib->encrypt == _TKIP_) {
734 /* encode mic code */
735 if (stainfo) {
736 u8 null_key[16]={0x0, 0x0, 0x0, 0x0,
737 0x0, 0x0, 0x0, 0x0,
738 0x0, 0x0, 0x0, 0x0,
739 0x0, 0x0, 0x0, 0x0};
740
741 pframe = pxmitframe->buf_addr + hw_hdr_offset;
742
743 if (bmcst) {
744 if (!memcmp(psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey, null_key, 16)) {
745 return _FAIL;
746 }
747 /* start to calculate the mic code */
748 rtw_secmicsetkey23a(&micdata, psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey);
749 } else {
750 if (!memcmp(&stainfo->dot11tkiptxmickey.skey[0],
751 null_key, 16)) {
752 return _FAIL;
753 }
754 /* start to calculate the mic code */
755 rtw_secmicsetkey23a(&micdata, &stainfo->dot11tkiptxmickey.skey[0]);
756 }
757
758 if (pframe[1] & 1) { /* ToDS == 1 */
759 /* DA */
760 rtw_secmicappend23a(&micdata, &pframe[16], 6);
761 if (pframe[1] & 2) /* From Ds == 1 */
762 rtw_secmicappend23a(&micdata,
763 &pframe[24], 6);
764 else
765 rtw_secmicappend23a(&micdata,
766 &pframe[10], 6);
767 } else { /* ToDS == 0 */
768 /* DA */
769 rtw_secmicappend23a(&micdata, &pframe[4], 6);
770 if (pframe[1] & 2) /* From Ds == 1 */
771 rtw_secmicappend23a(&micdata,
772 &pframe[16], 6);
773 else
774 rtw_secmicappend23a(&micdata,
775 &pframe[10], 6);
776 }
777
778 /* if (pqospriv->qos_option == 1) */
779 if (pattrib->qos_en)
780 priority[0] = (u8)pxmitframe->attrib.priority;
781
782 rtw_secmicappend23a(&micdata, &priority[0], 4);
783
784 payload = pframe;
785
786 for (curfragnum = 0; curfragnum < pattrib->nr_frags;
787 curfragnum++) {
788 payload = (u8 *)RND4((unsigned long)payload);
789 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
790 ("=== curfragnum =%d, pframe = 0x%.2x, "
791 "0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x"
792 "%.2x, 0x%.2x, 0x%.2x,!!!\n",
793 curfragnum, *payload, *(payload + 1),
794 *(payload + 2), *(payload + 3),
795 *(payload + 4), *(payload + 5),
796 *(payload + 6), *(payload + 7)));
797
798 payload = payload + pattrib->hdrlen +
799 pattrib->iv_len;
800 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
801 ("curfragnum =%d pattrib->hdrlen =%d "
802 "pattrib->iv_len =%d", curfragnum,
803 pattrib->hdrlen, pattrib->iv_len));
804 if ((curfragnum + 1) == pattrib->nr_frags) {
805 length = pattrib->last_txcmdsz -
806 pattrib->hdrlen -
807 pattrib->iv_len -
808 ((pattrib->bswenc) ?
809 pattrib->icv_len : 0);
810 rtw_secmicappend23a(&micdata, payload,
811 length);
812 payload = payload + length;
813 } else {
814 length = pxmitpriv->frag_len -
815 pattrib->hdrlen -
816 pattrib->iv_len -
817 ((pattrib->bswenc) ?
818 pattrib->icv_len : 0);
819 rtw_secmicappend23a(&micdata, payload,
820 length);
821 payload = payload + length +
822 pattrib->icv_len;
823 RT_TRACE(_module_rtl871x_xmit_c_,
824 _drv_err_,
825 ("curfragnum =%d length =%d "
826 "pattrib->icv_len =%d",
827 curfragnum, length,
828 pattrib->icv_len));
829 }
830 }
831 rtw_secgetmic23a(&micdata, &mic[0]);
832 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
833 ("xmitframe_addmic: before add mic code!!\n"));
834 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
835 ("xmitframe_addmic: pattrib->last_txcmdsz ="
836 "%d!!!\n", pattrib->last_txcmdsz));
837 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
838 ("xmitframe_addmic: mic[0]= 0x%.2x , mic[1]="
839 "0x%.2x , mic[2]= 0x%.2x , mic[3]= 0x%.2x\n"
840 "mic[4]= 0x%.2x , mic[5]= 0x%.2x , mic[6]= 0x%.2x "
841 ", mic[7]= 0x%.2x !!!!\n", mic[0], mic[1],
842 mic[2], mic[3], mic[4], mic[5], mic[6],
843 mic[7]));
844 /* add mic code and add the mic code length
845 in last_txcmdsz */
846
847 memcpy(payload, &mic[0], 8);
848 pattrib->last_txcmdsz += 8;
849
850 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
851 ("\n ======== last pkt ========\n"));
852 payload = payload - pattrib->last_txcmdsz + 8;
853 for (curfragnum = 0; curfragnum < pattrib->last_txcmdsz;
854 curfragnum = curfragnum + 8)
855 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
856 (" %.2x, %.2x, %.2x, %.2x, %.2x, "
857 " %.2x, %.2x, %.2x ",
858 *(payload + curfragnum),
859 *(payload + curfragnum + 1),
860 *(payload + curfragnum + 2),
861 *(payload + curfragnum + 3),
862 *(payload + curfragnum + 4),
863 *(payload + curfragnum + 5),
864 *(payload + curfragnum + 6),
865 *(payload + curfragnum + 7)));
866 } else {
867 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
868 ("xmitframe_addmic: rtw_get_stainfo23a =="
869 "NULL!!!\n"));
870 }
871 }
872
873 return _SUCCESS;
874}
875
876static s32 xmitframe_swencrypt(struct rtw_adapter *padapter,
877 struct xmit_frame *pxmitframe)
878{
879 struct pkt_attrib *pattrib = &pxmitframe->attrib;
880
881 /* if ((psecuritypriv->sw_encrypt)||(pattrib->bswenc)) */
882 if (pattrib->bswenc) {
883 /* DBG_8723A("start xmitframe_swencrypt\n"); */
884 RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_,
885 ("### xmitframe_swencrypt\n"));
886 switch (pattrib->encrypt) {
887 case _WEP40_:
888 case _WEP104_:
889 rtw_wep_encrypt23a(padapter, pxmitframe);
890 break;
891 case _TKIP_:
892 rtw_tkip_encrypt23a(padapter, pxmitframe);
893 break;
894 case _AES_:
895 rtw_aes_encrypt23a(padapter, pxmitframe);
896 break;
897 default:
898 break;
899 }
900
901 } else {
902 RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_,
903 ("### xmitframe_hwencrypt\n"));
904 }
905
906 return _SUCCESS;
907}
908
909s32 rtw_make_wlanhdr23a(struct rtw_adapter *padapter, u8 *hdr,
910 struct pkt_attrib *pattrib)
911{
912 u16 *qc;
913
914 struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr;
915 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
916 struct qos_priv *pqospriv = &pmlmepriv->qospriv;
917 u8 qos_option = false;
918 int res = _SUCCESS;
919 u16 *fctrl = &pwlanhdr->frame_control;
920
921 struct sta_info *psta;
922
923 int bmcst = is_multicast_ether_addr(pattrib->ra);
924
925 if (pattrib->psta) {
926 psta = pattrib->psta;
927 } else {
928 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
929 if (bmcst) {
930 psta = rtw_get_bcmc_stainfo23a(padapter);
931 } else {
932 psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra);
933 }
934 }
935
936 if (psta == NULL) {
937 DBG_8723A("%s, psta == NUL\n", __func__);
938 return _FAIL;
939 }
940
941 if (!(psta->state &_FW_LINKED)) {
942 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
943 return _FAIL;
944 }
945
946 memset(hdr, 0, WLANHDR_OFFSET);
947
948 SetFrameSubType(fctrl, pattrib->subtype);
949
950 if (pattrib->subtype & WIFI_DATA_TYPE) {
951 if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)) {
952 /* to_ds = 1, fr_ds = 0; */
953 /* Data transfer to AP */
954 SetToDs(fctrl);
955 memcpy(pwlanhdr->addr1, get_bssid(pmlmepriv), ETH_ALEN);
956 memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
957 memcpy(pwlanhdr->addr3, pattrib->dst, ETH_ALEN);
958
959 if (pqospriv->qos_option)
960 qos_option = true;
961
962 }
963 else if ((check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)) {
964 /* to_ds = 0, fr_ds = 1; */
965 SetFrDs(fctrl);
966 memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
967 memcpy(pwlanhdr->addr2, get_bssid(pmlmepriv), ETH_ALEN);
968 memcpy(pwlanhdr->addr3, pattrib->src, ETH_ALEN);
969
970 if (psta->qos_option)
971 qos_option = true;
972 }
973 else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) ||
974 (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
975 memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
976 memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
977 memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN);
978
979 if (psta->qos_option)
980 qos_option = true;
981 }
982 else {
983 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("fw_state:%x is not allowed to xmit frame\n", get_fwstate(pmlmepriv)));
984 res = _FAIL;
985 goto exit;
986 }
987 if (pattrib->mdata)
988 SetMData(fctrl);
989 if (pattrib->encrypt)
990 SetPrivacy(fctrl);
991 if (qos_option) {
992 qc = (unsigned short *)(hdr + pattrib->hdrlen - 2);
993 if (pattrib->priority)
994 SetPriority(qc, pattrib->priority);
995 SetEOSP(qc, pattrib->eosp);
996 SetAckpolicy(qc, pattrib->ack_policy);
997 }
998 /* TODO: fill HT Control Field */
999
1000 /* Update Seq Num will be handled by f/w */
1001 if (psta) {
1002 psta->sta_xmitpriv.txseq_tid[pattrib->priority]++;
1003 psta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF;
1004 pattrib->seqnum = psta->sta_xmitpriv.txseq_tid[pattrib->priority];
1005 SetSeqNum(hdr, pattrib->seqnum);
1006 /* check if enable ampdu */
1007 if (pattrib->ht_en && psta->htpriv.ampdu_enable) {
1008 if (psta->htpriv.agg_enable_bitmap & CHKBIT(pattrib->priority))
1009 pattrib->ampdu_en = true;
1010 }
1011 /* re-check if enable ampdu by BA_starting_seqctrl */
1012 if (pattrib->ampdu_en) {
1013 u16 tx_seq;
1014
1015 tx_seq = psta->BA_starting_seqctrl[pattrib->priority & 0x0f];
1016
1017 /* check BA_starting_seqctrl */
1018 if (SN_LESS(pattrib->seqnum, tx_seq)) {
1019 /* DBG_8723A("tx ampdu seqnum(%d) < tx_seq(%d)\n", pattrib->seqnum, tx_seq); */
1020 pattrib->ampdu_en = false;/* AGG BK */
1021 } else if (SN_EQUAL(pattrib->seqnum, tx_seq)) {
1022 psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (tx_seq+1)&0xfff;
1023 pattrib->ampdu_en = true;/* AGG EN */
1024 } else {
1025 /* DBG_8723A("tx ampdu over run\n"); */
1026 psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (pattrib->seqnum+1)&0xfff;
1027 pattrib->ampdu_en = true;/* AGG EN */
1028 }
1029 }
1030 }
1031 }
1032exit:
1033 return res;
1034}
1035
1036s32 rtw_txframes_pending23a(struct rtw_adapter *padapter)
1037{
1038 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1039
1040 return (!_rtw_queue_empty23a(&pxmitpriv->be_pending)) ||
1041 (!_rtw_queue_empty23a(&pxmitpriv->bk_pending)) ||
1042 (!_rtw_queue_empty23a(&pxmitpriv->vi_pending)) ||
1043 (!_rtw_queue_empty23a(&pxmitpriv->vo_pending));
1044}
1045
1046s32 rtw_txframes_sta_ac_pending23a(struct rtw_adapter *padapter,
1047 struct pkt_attrib *pattrib)
1048{
1049 struct sta_info *psta;
1050 struct tx_servq *ptxservq;
1051 int priority = pattrib->priority;
1052
1053 if (pattrib->psta) {
1054 psta = pattrib->psta;
1055 } else {
1056 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
1057 psta = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]);
1058 }
1059 if (psta == NULL) {
1060 DBG_8723A("%s, psta == NUL\n", __func__);
1061 return 0;
1062 }
1063 if (!(psta->state &_FW_LINKED)) {
1064 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__,
1065 psta->state);
1066 return 0;
1067 }
1068 switch (priority) {
1069 case 1:
1070 case 2:
1071 ptxservq = &psta->sta_xmitpriv.bk_q;
1072 break;
1073 case 4:
1074 case 5:
1075 ptxservq = &psta->sta_xmitpriv.vi_q;
1076 break;
1077 case 6:
1078 case 7:
1079 ptxservq = &psta->sta_xmitpriv.vo_q;
1080 break;
1081 case 0:
1082 case 3:
1083 default:
1084 ptxservq = &psta->sta_xmitpriv.be_q;
1085 break;
1086 }
1087 return ptxservq->qcnt;
1088}
1089
1090/*
1091 * Calculate wlan 802.11 packet MAX size from pkt_attrib
1092 * This function doesn't consider fragment case
1093 */
1094u32 rtw_calculate_wlan_pkt_size_by_attribue23a(struct pkt_attrib *pattrib)
1095{
1096 u32 len = 0;
1097
1098 len = pattrib->hdrlen + pattrib->iv_len; /* WLAN Header and IV */
1099 len += SNAP_SIZE + sizeof(u16); /* LLC */
1100 len += pattrib->pktlen;
1101 if (pattrib->encrypt == _TKIP_) len += 8; /* MIC */
1102 len += ((pattrib->bswenc) ? pattrib->icv_len : 0); /* ICV */
1103
1104 return len;
1105}
1106
1107/*
1108
1109This sub-routine will perform all the following:
1110
11111. remove 802.3 header.
11122. create wlan_header, based on the info in pxmitframe
11133. append sta's iv/ext-iv
11144. append LLC
11155. move frag chunk from pframe to pxmitframe->mem
11166. apply sw-encrypt, if necessary.
1117
1118*/
1119s32 rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *pkt,
1120 struct xmit_frame *pxmitframe)
1121{
1122 struct pkt_file pktfile;
1123 struct sta_info *psta;
1124 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1125 struct pkt_attrib *pattrib = &pxmitframe->attrib;
1126 s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz;
1127 unsigned long addr;
1128 u8 *pframe, *mem_start;
1129 u8 hw_hdr_offset;
1130 u8 *pbuf_start;
1131
1132 s32 bmcst = is_multicast_ether_addr(pattrib->ra);
1133 s32 res = _SUCCESS;
1134
1135 if (pattrib->psta) {
1136 psta = pattrib->psta;
1137 } else {
1138 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
1139 psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra);
1140 }
1141
1142 if (psta == NULL) {
1143 DBG_8723A("%s, psta == NUL\n", __func__);
1144 return _FAIL;
1145 }
1146
1147 if (!(psta->state &_FW_LINKED)) {
1148 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
1149 return _FAIL;
1150 }
1151
1152 if (pxmitframe->buf_addr == NULL) {
1153 DBG_8723A("==> %s buf_addr == NULL\n", __func__);
1154 return _FAIL;
1155 }
1156
1157 pbuf_start = pxmitframe->buf_addr;
1158
1159 hw_hdr_offset = TXDESC_OFFSET;
1160
1161 mem_start = pbuf_start + hw_hdr_offset;
1162
1163 if (rtw_make_wlanhdr23a(padapter, mem_start, pattrib) == _FAIL) {
1164 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
1165 ("rtw_xmitframe_coalesce23a: rtw_make_wlanhdr23a "
1166 "fail; drop pkt\n"));
1167 res = _FAIL;
1168 goto exit;
1169 }
1170
1171 _rtw_open_pktfile23a(pkt, &pktfile);
1172 _rtw_pktfile_read23a(&pktfile, NULL, pattrib->pkt_hdrlen);
1173
1174 frg_inx = 0;
1175 frg_len = pxmitpriv->frag_len - 4;/* 2346-4 = 2342 */
1176
1177 while (1) {
1178 llc_sz = 0;
1179
1180 mpdu_len = frg_len;
1181
1182 pframe = mem_start;
1183
1184 SetMFrag(mem_start);
1185
1186 pframe += pattrib->hdrlen;
1187 mpdu_len -= pattrib->hdrlen;
1188
1189 /* adding icv, if necessary... */
1190 if (pattrib->iv_len) {
1191 if (psta != NULL) {
1192 switch (pattrib->encrypt) {
1193 case _WEP40_:
1194 case _WEP104_:
1195 WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
1196 break;
1197 case _TKIP_:
1198 if (bmcst)
1199 TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
1200 else
1201 TKIP_IV(pattrib->iv, psta->dot11txpn, 0);
1202 break;
1203 case _AES_:
1204 if (bmcst)
1205 AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
1206 else
1207 AES_IV(pattrib->iv, psta->dot11txpn, 0);
1208 break;
1209 }
1210 }
1211
1212 memcpy(pframe, pattrib->iv, pattrib->iv_len);
1213
1214 RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_,
1215 ("rtw_xmiaframe_coalesce23a: keyid =%d pattrib"
1216 "->iv[3]=%.2x pframe =%.2x %.2x %.2x %.2x\n",
1217 padapter->securitypriv.dot11PrivacyKeyIndex,
1218 pattrib->iv[3], *pframe, *(pframe+1),
1219 *(pframe+2), *(pframe+3)));
1220 pframe += pattrib->iv_len;
1221 mpdu_len -= pattrib->iv_len;
1222 }
1223 if (frg_inx == 0) {
1224 llc_sz = rtw_put_snap23a(pframe, pattrib->ether_type);
1225 pframe += llc_sz;
1226 mpdu_len -= llc_sz;
1227 }
1228
1229 if ((pattrib->icv_len >0) && (pattrib->bswenc))
1230 mpdu_len -= pattrib->icv_len;
1231
1232 if (bmcst) {
1233 /* don't do fragment to broadcat/multicast packets */
1234 mem_sz = _rtw_pktfile_read23a(&pktfile, pframe, pattrib->pktlen);
1235 } else {
1236 mem_sz = _rtw_pktfile_read23a(&pktfile, pframe, mpdu_len);
1237 }
1238 pframe += mem_sz;
1239
1240 if ((pattrib->icv_len >0) && (pattrib->bswenc)) {
1241 memcpy(pframe, pattrib->icv, pattrib->icv_len);
1242 pframe += pattrib->icv_len;
1243 }
1244
1245 frg_inx++;
1246
1247 if (bmcst || (rtw_endofpktfile23a(&pktfile))) {
1248 pattrib->nr_frags = frg_inx;
1249
1250 pattrib->last_txcmdsz = pattrib->hdrlen +
1251 pattrib->iv_len +
1252 ((pattrib->nr_frags == 1) ?
1253 llc_sz : 0) +
1254 ((pattrib->bswenc) ?
1255 pattrib->icv_len : 0) + mem_sz;
1256
1257 ClearMFrag(mem_start);
1258
1259 break;
1260 } else {
1261 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: There're still something in packet!\n", __func__));
1262 }
1263
1264 addr = (unsigned long)pframe;
1265
1266 mem_start = (unsigned char *)RND4(addr) + hw_hdr_offset;
1267 memcpy(mem_start, pbuf_start + hw_hdr_offset, pattrib->hdrlen);
1268
1269 }
1270
1271 if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) {
1272 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n"));
1273 DBG_8723A("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n");
1274 res = _FAIL;
1275 goto exit;
1276 }
1277
1278 xmitframe_swencrypt(padapter, pxmitframe);
1279
1280 if (bmcst == false)
1281 update_attrib_vcs_info(padapter, pxmitframe);
1282 else
1283 pattrib->vcs_mode = NONE_VCS;
1284
1285exit:
1286 return res;
1287}
1288
1289/* Logical Link Control(LLC) SubNetwork Attachment Point(SNAP) header
1290 * IEEE LLC/SNAP header contains 8 octets
1291 * First 3 octets comprise the LLC portion
1292 * SNAP portion, 5 octets, is divided into two fields:
1293 * Organizationally Unique Identifier(OUI), 3 octets,
1294 * type, defined by that organization, 2 octets.
1295 */
1296s32 rtw_put_snap23a(u8 *data, u16 h_proto)
1297{
1298 struct ieee80211_snap_hdr *snap;
1299 u8 *oui;
1300
1301 snap = (struct ieee80211_snap_hdr *)data;
1302 snap->dsap = 0xaa;
1303 snap->ssap = 0xaa;
1304 snap->ctrl = 0x03;
1305
1306 if (h_proto == 0x8137 || h_proto == 0x80f3)
1307 oui = P802_1H_OUI;
1308 else
1309 oui = RFC1042_OUI;
1310 snap->oui[0] = oui[0];
1311 snap->oui[1] = oui[1];
1312 snap->oui[2] = oui[2];
1313 *(u16 *)(data + SNAP_SIZE) = htons(h_proto);
1314 return SNAP_SIZE + sizeof(u16);
1315}
1316
1317void rtw_update_protection23a(struct rtw_adapter *padapter, u8 *ie, uint ie_len)
1318{
1319 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1320 struct registry_priv *pregistrypriv = &padapter->registrypriv;
1321 uint protection;
1322 u8 *perp;
1323 int erp_len;
1324
1325 switch (pxmitpriv->vcs_setting) {
1326 case DISABLE_VCS:
1327 pxmitpriv->vcs = NONE_VCS;
1328 break;
1329 case ENABLE_VCS:
1330 break;
1331 case AUTO_VCS:
1332 default:
1333 perp = rtw_get_ie23a(ie, _ERPINFO_IE_, &erp_len, ie_len);
1334 if (perp == NULL) {
1335 pxmitpriv->vcs = NONE_VCS;
1336 } else {
1337 protection = (*(perp + 2)) & BIT(1);
1338 if (protection) {
1339 if (pregistrypriv->vcs_type == RTS_CTS)
1340 pxmitpriv->vcs = RTS_CTS;
1341 else
1342 pxmitpriv->vcs = CTS_TO_SELF;
1343 } else {
1344 pxmitpriv->vcs = NONE_VCS;
1345 }
1346 }
1347 break;
1348 }
1349}
1350
1351void rtw_count_tx_stats23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe, int sz)
1352{
1353 struct sta_info *psta = NULL;
1354 struct stainfo_stats *pstats = NULL;
1355 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1356 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1357
1358 if ((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG) {
1359 pxmitpriv->tx_bytes += sz;
1360 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod++;
1361
1362 psta = pxmitframe->attrib.psta;
1363 if (psta) {
1364 pstats = &psta->sta_stats;
1365 pstats->tx_pkts++;
1366 pstats->tx_bytes += sz;
1367 }
1368 }
1369}
1370
1371struct xmit_buf *rtw_alloc_xmitbuf23a_ext(struct xmit_priv *pxmitpriv)
1372{
1373 unsigned long irqL;
1374 struct xmit_buf *pxmitbuf = NULL;
1375 struct list_head *phead;
1376 struct rtw_queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;
1377
1378 spin_lock_irqsave(&pfree_queue->lock, irqL);
1379
1380 phead = get_list_head(pfree_queue);
1381
1382 if (!list_empty(phead)) {
1383 pxmitbuf = list_first_entry(phead, struct xmit_buf, list);
1384
1385 list_del_init(&pxmitbuf->list);
1386
1387 pxmitpriv->free_xmit_extbuf_cnt--;
1388 pxmitbuf->priv_data = NULL;
1389 pxmitbuf->ext_tag = true;
1390
1391 if (pxmitbuf->sctx) {
1392 DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__);
1393 rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);
1394 }
1395 }
1396
1397 spin_unlock_irqrestore(&pfree_queue->lock, irqL);
1398
1399 return pxmitbuf;
1400}
1401
1402s32 rtw_free_xmitbuf_ext23a(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
1403{
1404 unsigned long irqL;
1405 struct rtw_queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;
1406
1407 if (pxmitbuf == NULL)
1408 return _FAIL;
1409
1410 spin_lock_irqsave(&pfree_queue->lock, irqL);
1411
1412 list_del_init(&pxmitbuf->list);
1413
1414 list_add_tail(&pxmitbuf->list, get_list_head(pfree_queue));
1415 pxmitpriv->free_xmit_extbuf_cnt++;
1416
1417 spin_unlock_irqrestore(&pfree_queue->lock, irqL);
1418
1419 return _SUCCESS;
1420}
1421
1422struct xmit_buf *rtw_alloc_xmitbuf23a(struct xmit_priv *pxmitpriv)
1423{
1424 unsigned long irqL;
1425 struct xmit_buf *pxmitbuf = NULL;
1426 struct list_head *phead;
1427 struct rtw_queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
1428
1429 /* DBG_8723A("+rtw_alloc_xmitbuf23a\n"); */
1430
1431 spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
1432
1433 phead = get_list_head(pfree_xmitbuf_queue);
1434
1435 if (!list_empty(phead)) {
1436 pxmitbuf = list_first_entry(phead, struct xmit_buf, list);
1437
1438 list_del_init(&pxmitbuf->list);
1439
1440 pxmitpriv->free_xmitbuf_cnt--;
1441 pxmitbuf->priv_data = NULL;
1442 pxmitbuf->ext_tag = false;
1443 pxmitbuf->flags = XMIT_VO_QUEUE;
1444
1445 if (pxmitbuf->sctx) {
1446 DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__);
1447 rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);
1448 }
1449 }
1450
1451 spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
1452
1453 return pxmitbuf;
1454}
1455
1456s32 rtw_free_xmitbuf23a(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
1457{
1458 unsigned long irqL;
1459 struct rtw_queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
1460
1461 /* DBG_8723A("+rtw_free_xmitbuf23a\n"); */
1462
1463 if (pxmitbuf == NULL)
1464 return _FAIL;
1465
1466 if (pxmitbuf->sctx) {
1467 DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__);
1468 rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_FREE);
1469 }
1470
1471 if (pxmitbuf->ext_tag) {
1472 rtw_free_xmitbuf_ext23a(pxmitpriv, pxmitbuf);
1473 } else {
1474 spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
1475
1476 list_del_init(&pxmitbuf->list);
1477
1478 list_add_tail(&pxmitbuf->list,
1479 get_list_head(pfree_xmitbuf_queue));
1480
1481 pxmitpriv->free_xmitbuf_cnt++;
1482 spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
1483 }
1484
1485 return _SUCCESS;
1486}
1487
1488static void rtw_init_xmitframe(struct xmit_frame *pxframe)
1489{
1490 if (pxframe != NULL) {
1491 /* default value setting */
1492 pxframe->buf_addr = NULL;
1493 pxframe->pxmitbuf = NULL;
1494
1495 memset(&pxframe->attrib, 0, sizeof(struct pkt_attrib));
1496 /* pxframe->attrib.psta = NULL; */
1497
1498 pxframe->frame_tag = DATA_FRAMETAG;
1499
1500 pxframe->pkt = NULL;
1501 pxframe->pkt_offset = 1;/* default use pkt_offset to fill tx desc */
1502
1503 pxframe->ack_report = 0;
1504 }
1505}
1506
1507/*
1508Calling context:
15091. OS_TXENTRY
15102. RXENTRY (rx_thread or RX_ISR/RX_CallBack)
1511
1512If we turn on USE_RXTHREAD, then, no need for critical section.
1513Otherwise, we must use _enter/_exit critical to protect free_xmit_queue...
1514
1515Must be very very cautious...
1516
1517*/
1518struct xmit_frame *rtw_alloc_xmitframe23a(struct xmit_priv *pxmitpriv)/* _queue *pfree_xmit_queue) */
1519{
1520 /*
1521 Please remember to use all the osdep_service api,
1522 and lock/unlock or _enter/_exit critical to protect
1523 pfree_xmit_queue
1524 */
1525
1526 struct xmit_frame *pxframe = NULL;
1527 struct list_head *plist, *phead;
1528 struct rtw_queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
1529
1530 spin_lock_bh(&pfree_xmit_queue->lock);
1531
1532 if (_rtw_queue_empty23a(pfree_xmit_queue) == true) {
1533 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe23a:%d\n", pxmitpriv->free_xmitframe_cnt));
1534 pxframe = NULL;
1535 } else {
1536 phead = get_list_head(pfree_xmit_queue);
1537
1538 plist = phead->next;
1539
1540 pxframe = container_of(plist, struct xmit_frame, list);
1541
1542 list_del_init(&pxframe->list);
1543 pxmitpriv->free_xmitframe_cnt--;
1544 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe23a():free_xmitframe_cnt =%d\n", pxmitpriv->free_xmitframe_cnt));
1545 }
1546
1547 spin_unlock_bh(&pfree_xmit_queue->lock);
1548
1549 rtw_init_xmitframe(pxframe);
1550
1551 return pxframe;
1552}
1553
1554struct xmit_frame *rtw_alloc_xmitframe23a_ext(struct xmit_priv *pxmitpriv)
1555{
1556 struct xmit_frame *pxframe = NULL;
1557 struct list_head *plist, *phead;
1558 struct rtw_queue *queue = &pxmitpriv->free_xframe_ext_queue;
1559
1560 spin_lock_bh(&queue->lock);
1561
1562 if (_rtw_queue_empty23a(queue) == true) {
1563 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe23a_ext:%d\n", pxmitpriv->free_xframe_ext_cnt));
1564 pxframe = NULL;
1565 } else {
1566 phead = get_list_head(queue);
1567 plist = phead->next;
1568 pxframe = container_of(plist, struct xmit_frame, list);
1569
1570 list_del_init(&pxframe->list);
1571 pxmitpriv->free_xframe_ext_cnt--;
1572 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe23a_ext():free_xmitframe_cnt =%d\n", pxmitpriv->free_xframe_ext_cnt));
1573 }
1574
1575 spin_unlock_bh(&queue->lock);
1576
1577 rtw_init_xmitframe(pxframe);
1578
1579 return pxframe;
1580}
1581
1582s32 rtw_free_xmitframe23a(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitframe)
1583{
1584 struct rtw_queue *queue = NULL;
1585 struct rtw_adapter *padapter = pxmitpriv->adapter;
1586 struct sk_buff *pndis_pkt = NULL;
1587
1588 if (pxmitframe == NULL) {
1589 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("====== rtw_free_xmitframe23a():pxmitframe == NULL!!!!!!!!!!\n"));
1590 goto exit;
1591 }
1592
1593 if (pxmitframe->pkt) {
1594 pndis_pkt = pxmitframe->pkt;
1595 pxmitframe->pkt = NULL;
1596 }
1597
1598 if (pxmitframe->ext_tag == 0)
1599 queue = &pxmitpriv->free_xmit_queue;
1600 else if (pxmitframe->ext_tag == 1)
1601 queue = &pxmitpriv->free_xframe_ext_queue;
1602
1603 if (!queue)
1604 goto check_pkt_complete;
1605 spin_lock_bh(&queue->lock);
1606
1607 list_del_init(&pxmitframe->list);
1608 list_add_tail(&pxmitframe->list, get_list_head(queue));
1609 if (pxmitframe->ext_tag == 0) {
1610 pxmitpriv->free_xmitframe_cnt++;
1611 RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, ("rtw_free_xmitframe23a():free_xmitframe_cnt =%d\n", pxmitpriv->free_xmitframe_cnt));
1612 } else if (pxmitframe->ext_tag == 1) {
1613 pxmitpriv->free_xframe_ext_cnt++;
1614 RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, ("rtw_free_xmitframe23a():free_xframe_ext_cnt =%d\n", pxmitpriv->free_xframe_ext_cnt));
1615 }
1616
1617 spin_unlock_bh(&queue->lock);
1618
1619check_pkt_complete:
1620
1621 if (pndis_pkt)
1622 rtw_os_pkt_complete23a(padapter, pndis_pkt);
1623
1624exit:
1625
1626 return _SUCCESS;
1627}
1628
1629void rtw_free_xmitframe_queue23a(struct xmit_priv *pxmitpriv,
1630 struct rtw_queue *pframequeue)
1631{
1632 struct list_head *plist, *phead, *ptmp;
1633 struct xmit_frame *pxmitframe;
1634
1635 spin_lock_bh(&pframequeue->lock);
1636
1637 phead = get_list_head(pframequeue);
1638
1639 list_for_each_safe(plist, ptmp, phead) {
1640 pxmitframe = container_of(plist, struct xmit_frame, list);
1641
1642 rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
1643 }
1644 spin_unlock_bh(&pframequeue->lock);
1645
1646}
1647
1648s32 rtw_xmitframe_enqueue23a(struct rtw_adapter *padapter,
1649 struct xmit_frame *pxmitframe)
1650{
1651 if (rtw_xmit23a_classifier(padapter, pxmitframe) == _FAIL) {
1652 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
1653 ("rtw_xmitframe_enqueue23a: drop xmit pkt for "
1654 "classifier fail\n"));
1655 return _FAIL;
1656 }
1657
1658 return _SUCCESS;
1659}
1660
1661static struct xmit_frame *
1662dequeue_one_xmitframe(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit,
1663 struct tx_servq *ptxservq, struct rtw_queue *pframe_queue)
1664{
1665 struct list_head *phead;
1666 struct xmit_frame *pxmitframe = NULL;
1667
1668 phead = get_list_head(pframe_queue);
1669
1670 if (!list_empty(phead)) {
1671 pxmitframe = list_first_entry(phead, struct xmit_frame, list);
1672 list_del_init(&pxmitframe->list);
1673 ptxservq->qcnt--;
1674 }
1675 return pxmitframe;
1676}
1677
1678struct xmit_frame *
1679rtw_dequeue_xframe23a(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit_i,
1680 int entry)
1681{
1682 struct list_head *sta_plist, *sta_phead, *ptmp;
1683 struct hw_xmit *phwxmit;
1684 struct tx_servq *ptxservq = NULL;
1685 struct rtw_queue *pframe_queue = NULL;
1686 struct xmit_frame *pxmitframe = NULL;
1687 struct rtw_adapter *padapter = pxmitpriv->adapter;
1688 struct registry_priv *pregpriv = &padapter->registrypriv;
1689 int i, inx[4];
1690
1691 inx[0] = 0;
1692 inx[1] = 1;
1693 inx[2] = 2;
1694 inx[3] = 3;
1695 if (pregpriv->wifi_spec == 1) {
1696 int j;
1697
1698 for (j = 0; j < 4; j++)
1699 inx[j] = pxmitpriv->wmm_para_seq[j];
1700 }
1701
1702 spin_lock_bh(&pxmitpriv->lock);
1703
1704 for (i = 0; i < entry; i++) {
1705 phwxmit = phwxmit_i + inx[i];
1706
1707 sta_phead = get_list_head(phwxmit->sta_queue);
1708
1709 list_for_each_safe(sta_plist, ptmp, sta_phead) {
1710 ptxservq = container_of(sta_plist, struct tx_servq,
1711 tx_pending);
1712
1713 pframe_queue = &ptxservq->sta_pending;
1714
1715 pxmitframe = dequeue_one_xmitframe(pxmitpriv, phwxmit, ptxservq, pframe_queue);
1716
1717 if (pxmitframe) {
1718 phwxmit->accnt--;
1719
1720 /* Remove sta node when there is no pending packets. */
1721 if (_rtw_queue_empty23a(pframe_queue)) /* must be done after get_next and before break */
1722 list_del_init(&ptxservq->tx_pending);
1723 goto exit;
1724 }
1725 }
1726 }
1727exit:
1728 spin_unlock_bh(&pxmitpriv->lock);
1729 return pxmitframe;
1730}
1731
1732struct tx_servq *rtw_get_sta_pending23a(struct rtw_adapter *padapter, struct sta_info *psta, int up, u8 *ac)
1733{
1734 struct tx_servq *ptxservq = NULL;
1735
1736 switch (up) {
1737 case 1:
1738 case 2:
1739 ptxservq = &psta->sta_xmitpriv.bk_q;
1740 *(ac) = 3;
1741 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending23a : BK\n"));
1742 break;
1743 case 4:
1744 case 5:
1745 ptxservq = &psta->sta_xmitpriv.vi_q;
1746 *(ac) = 1;
1747 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending23a : VI\n"));
1748 break;
1749 case 6:
1750 case 7:
1751 ptxservq = &psta->sta_xmitpriv.vo_q;
1752 *(ac) = 0;
1753 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending23a : VO\n"));
1754 break;
1755 case 0:
1756 case 3:
1757 default:
1758 ptxservq = &psta->sta_xmitpriv.be_q;
1759 *(ac) = 2;
1760 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending23a : BE\n"));
1761 break;
1762 }
1763 return ptxservq;
1764}
1765
1766/*
1767 * Will enqueue pxmitframe to the proper queue,
1768 * and indicate it to xx_pending list.....
1769 */
1770s32 rtw_xmit23a_classifier(struct rtw_adapter *padapter,
1771 struct xmit_frame *pxmitframe)
1772{
1773 struct sta_info *psta;
1774 struct tx_servq *ptxservq;
1775 struct pkt_attrib *pattrib = &pxmitframe->attrib;
1776 struct sta_priv *pstapriv = &padapter->stapriv;
1777 struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;
1778 u8 ac_index;
1779 int res = _SUCCESS;
1780
1781 if (pattrib->psta) {
1782 psta = pattrib->psta;
1783 } else {
1784 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
1785 psta = rtw_get_stainfo23a(pstapriv, pattrib->ra);
1786 }
1787 if (psta == NULL) {
1788 res = _FAIL;
1789 DBG_8723A("rtw_xmit23a_classifier: psta == NULL\n");
1790 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
1791 ("rtw_xmit23a_classifier: psta == NULL\n"));
1792 goto exit;
1793 }
1794 if (!(psta->state & _FW_LINKED)) {
1795 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__,
1796 psta->state);
1797 return _FAIL;
1798 }
1799 ptxservq = rtw_get_sta_pending23a(padapter, psta, pattrib->priority,
1800 (u8 *)(&ac_index));
1801
1802 if (list_empty(&ptxservq->tx_pending)) {
1803 list_add_tail(&ptxservq->tx_pending,
1804 get_list_head(phwxmits[ac_index].sta_queue));
1805 }
1806
1807 list_add_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending));
1808 ptxservq->qcnt++;
1809 phwxmits[ac_index].accnt++;
1810exit:
1811 return res;
1812}
1813
1814void rtw_alloc_hwxmits23a(struct rtw_adapter *padapter)
1815{
1816 struct hw_xmit *hwxmits;
1817 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1818 int size;
1819
1820 pxmitpriv->hwxmit_entry = HWXMIT_ENTRY;
1821
1822 size = sizeof(struct hw_xmit) * (pxmitpriv->hwxmit_entry + 1);
1823 pxmitpriv->hwxmits = kzalloc(size, GFP_KERNEL);
1824
1825 hwxmits = pxmitpriv->hwxmits;
1826
1827 if (pxmitpriv->hwxmit_entry == 5) {
1828 /* pxmitpriv->bmc_txqueue.head = 0; */
1829 /* hwxmits[0] .phwtxqueue = &pxmitpriv->bmc_txqueue; */
1830 hwxmits[0] .sta_queue = &pxmitpriv->bm_pending;
1831
1832 /* pxmitpriv->vo_txqueue.head = 0; */
1833 /* hwxmits[1] .phwtxqueue = &pxmitpriv->vo_txqueue; */
1834 hwxmits[1] .sta_queue = &pxmitpriv->vo_pending;
1835
1836 /* pxmitpriv->vi_txqueue.head = 0; */
1837 /* hwxmits[2] .phwtxqueue = &pxmitpriv->vi_txqueue; */
1838 hwxmits[2] .sta_queue = &pxmitpriv->vi_pending;
1839
1840 /* pxmitpriv->bk_txqueue.head = 0; */
1841 /* hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; */
1842 hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
1843
1844 /* pxmitpriv->be_txqueue.head = 0; */
1845 /* hwxmits[4] .phwtxqueue = &pxmitpriv->be_txqueue; */
1846 hwxmits[4] .sta_queue = &pxmitpriv->be_pending;
1847
1848 } else if (pxmitpriv->hwxmit_entry == 4) {
1849
1850 /* pxmitpriv->vo_txqueue.head = 0; */
1851 /* hwxmits[0] .phwtxqueue = &pxmitpriv->vo_txqueue; */
1852 hwxmits[0] .sta_queue = &pxmitpriv->vo_pending;
1853
1854 /* pxmitpriv->vi_txqueue.head = 0; */
1855 /* hwxmits[1] .phwtxqueue = &pxmitpriv->vi_txqueue; */
1856 hwxmits[1] .sta_queue = &pxmitpriv->vi_pending;
1857
1858 /* pxmitpriv->be_txqueue.head = 0; */
1859 /* hwxmits[2] .phwtxqueue = &pxmitpriv->be_txqueue; */
1860 hwxmits[2] .sta_queue = &pxmitpriv->be_pending;
1861
1862 /* pxmitpriv->bk_txqueue.head = 0; */
1863 /* hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; */
1864 hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
1865 } else {
1866
1867 }
1868}
1869
1870void rtw_free_hwxmits23a(struct rtw_adapter *padapter)
1871{
1872 struct hw_xmit *hwxmits;
1873 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1874
1875 hwxmits = pxmitpriv->hwxmits;
1876 kfree(hwxmits);
1877}
1878
1879void rtw_init_hwxmits23a(struct hw_xmit *phwxmit, int entry)
1880{
1881 int i;
1882
1883 for (i = 0; i < entry; i++, phwxmit++)
1884 phwxmit->accnt = 0;
1885}
1886
1887u32 rtw_get_ff_hwaddr23a(struct xmit_frame *pxmitframe)
1888{
1889 u32 addr;
1890 struct pkt_attrib *pattrib = &pxmitframe->attrib;
1891
1892 switch (pattrib->qsel) {
1893 case 0:
1894 case 3:
1895 addr = BE_QUEUE_INX;
1896 break;
1897 case 1:
1898 case 2:
1899 addr = BK_QUEUE_INX;
1900 break;
1901 case 4:
1902 case 5:
1903 addr = VI_QUEUE_INX;
1904 break;
1905 case 6:
1906 case 7:
1907 addr = VO_QUEUE_INX;
1908 break;
1909 case 0x10:
1910 addr = BCN_QUEUE_INX;
1911 break;
1912 case 0x11:/* BC/MC in PS (HIQ) */
1913 addr = HIGH_QUEUE_INX;
1914 break;
1915 case 0x12:
1916 default:
1917 addr = MGT_QUEUE_INX;
1918 break;
1919 }
1920
1921 return addr;
1922}
1923
1924static void do_queue_select(struct rtw_adapter *padapter, struct pkt_attrib *pattrib)
1925{
1926 u8 qsel;
1927
1928 qsel = pattrib->priority;
1929 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
1930 ("### do_queue_select priority =%d , qsel = %d\n",
1931 pattrib->priority, qsel));
1932
1933 pattrib->qsel = qsel;
1934}
1935
1936/*
1937 * The main transmit(tx) entry
1938 *
1939 * Return
1940 * 1 enqueue
1941 * 0 success, hardware will handle this xmit frame(packet)
1942 * <0 fail
1943 */
1944int rtw_xmit23a(struct rtw_adapter *padapter, struct sk_buff *skb)
1945{
1946 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1947 struct xmit_frame *pxmitframe = NULL;
1948 s32 res;
1949
1950 pxmitframe = rtw_alloc_xmitframe23a(pxmitpriv);
1951
1952 if (pxmitframe == NULL) {
1953 RT_TRACE(_module_xmit_osdep_c_, _drv_err_,
1954 ("rtw_xmit23a: no more pxmitframe\n"));
1955 return -1;
1956 }
1957
1958 res = update_attrib(padapter, skb, &pxmitframe->attrib);
1959
1960 if (res == _FAIL) {
1961 RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("rtw_xmit23a: update attrib fail\n"));
1962 rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
1963 return -1;
1964 }
1965 pxmitframe->pkt = skb;
1966
1967 rtw_led_control(padapter, LED_CTL_TX);
1968
1969 do_queue_select(padapter, &pxmitframe->attrib);
1970
1971#ifdef CONFIG_8723AU_AP_MODE
1972 spin_lock_bh(&pxmitpriv->lock);
1973 if (xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe)) {
1974 spin_unlock_bh(&pxmitpriv->lock);
1975 return 1;
1976 }
1977 spin_unlock_bh(&pxmitpriv->lock);
1978#endif
1979
1980 if (rtw_hal_xmit23a(padapter, pxmitframe) == false)
1981 return 1;
1982
1983 return 0;
1984}
1985
1986#if defined(CONFIG_8723AU_AP_MODE)
1987
1988int xmitframe_enqueue_for_sleeping_sta23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
1989{
1990 int ret = false;
1991 struct sta_info *psta = NULL;
1992 struct sta_priv *pstapriv = &padapter->stapriv;
1993 struct pkt_attrib *pattrib = &pxmitframe->attrib;
1994 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1995 int bmcst = is_multicast_ether_addr(pattrib->ra);
1996
1997 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == false)
1998 return ret;
1999
2000 if (pattrib->psta) {
2001 psta = pattrib->psta;
2002 } else {
2003 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
2004 psta = rtw_get_stainfo23a(pstapriv, pattrib->ra);
2005 }
2006
2007 if (psta == NULL) {
2008 DBG_8723A("%s, psta == NUL\n", __func__);
2009 return false;
2010 }
2011
2012 if (!(psta->state & _FW_LINKED)) {
2013 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__,
2014 psta->state);
2015 return false;
2016 }
2017
2018 if (pattrib->triggered == 1) {
2019 if (bmcst)
2020 pattrib->qsel = 0x11;/* HIQ */
2021 return ret;
2022 }
2023
2024 if (bmcst) {
2025 spin_lock_bh(&psta->sleep_q.lock);
2026
2027 if (pstapriv->sta_dz_bitmap) {
2028 /* if anyone sta is in ps mode */
2029 list_del_init(&pxmitframe->list);
2030
2031 /* spin_lock_bh(&psta->sleep_q.lock); */
2032
2033 list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
2034
2035 psta->sleepq_len++;
2036
2037 pstapriv->tim_bitmap |= BIT(0);/* */
2038 pstapriv->sta_dz_bitmap |= BIT(0);
2039
2040 /* DBG_8723A("enqueue, sq_len =%d, tim =%x\n", psta->sleepq_len, pstapriv->tim_bitmap); */
2041
2042 update_beacon23a(padapter, _TIM_IE_, NULL, false);/* tx bc/mc packets after upate bcn */
2043
2044 /* spin_unlock_bh(&psta->sleep_q.lock); */
2045
2046 ret = true;
2047
2048 }
2049
2050 spin_unlock_bh(&psta->sleep_q.lock);
2051
2052 return ret;
2053
2054 }
2055
2056 spin_lock_bh(&psta->sleep_q.lock);
2057
2058 if (psta->state&WIFI_SLEEP_STATE) {
2059 u8 wmmps_ac = 0;
2060
2061 if (pstapriv->sta_dz_bitmap & CHKBIT(psta->aid)) {
2062 list_del_init(&pxmitframe->list);
2063
2064 /* spin_lock_bh(&psta->sleep_q.lock); */
2065
2066 list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
2067
2068 psta->sleepq_len++;
2069
2070 switch (pattrib->priority) {
2071 case 1:
2072 case 2:
2073 wmmps_ac = psta->uapsd_bk & BIT(0);
2074 break;
2075 case 4:
2076 case 5:
2077 wmmps_ac = psta->uapsd_vi & BIT(0);
2078 break;
2079 case 6:
2080 case 7:
2081 wmmps_ac = psta->uapsd_vo & BIT(0);
2082 break;
2083 case 0:
2084 case 3:
2085 default:
2086 wmmps_ac = psta->uapsd_be & BIT(0);
2087 break;
2088 }
2089
2090 if (wmmps_ac)
2091 psta->sleepq_ac_len++;
2092
2093 if (((psta->has_legacy_ac) && (!wmmps_ac)) ||
2094 ((!psta->has_legacy_ac) && (wmmps_ac))) {
2095 pstapriv->tim_bitmap |= CHKBIT(psta->aid);
2096
2097 if (psta->sleepq_len == 1) {
2098 /* upate BCN for TIM IE */
2099 update_beacon23a(padapter, _TIM_IE_, NULL, false);
2100 }
2101 }
2102
2103 /* spin_unlock_bh(&psta->sleep_q.lock); */
2104
2105 /* if (psta->sleepq_len > (NR_XMITFRAME>>3)) */
2106 /* */
2107 /* wakeup_sta_to_xmit23a(padapter, psta); */
2108 /* */
2109
2110 ret = true;
2111
2112 }
2113
2114 }
2115
2116 spin_unlock_bh(&psta->sleep_q.lock);
2117
2118 return ret;
2119}
2120
2121static void
2122dequeue_xmitframes_to_sleeping_queue(struct rtw_adapter *padapter,
2123 struct sta_info *psta,
2124 struct rtw_queue *pframequeue)
2125{
2126 int ret;
2127 struct list_head *plist, *phead, *ptmp;
2128 u8 ac_index;
2129 struct tx_servq *ptxservq;
2130 struct pkt_attrib *pattrib;
2131 struct xmit_frame *pxmitframe;
2132 struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;
2133
2134 phead = get_list_head(pframequeue);
2135
2136 list_for_each_safe(plist, ptmp, phead) {
2137 pxmitframe = container_of(plist, struct xmit_frame, list);
2138
2139 ret = xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe);
2140
2141 if (ret == true) {
2142 pattrib = &pxmitframe->attrib;
2143
2144 ptxservq = rtw_get_sta_pending23a(padapter, psta, pattrib->priority, (u8 *)(&ac_index));
2145
2146 ptxservq->qcnt--;
2147 phwxmits[ac_index].accnt--;
2148 } else {
2149 /* DBG_8723A("xmitframe_enqueue_for_sleeping_sta23a return false\n"); */
2150 }
2151 }
2152}
2153
2154void stop_sta_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta)
2155{
2156 struct sta_info *psta_bmc;
2157 struct sta_xmit_priv *pstaxmitpriv;
2158 struct sta_priv *pstapriv = &padapter->stapriv;
2159 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2160
2161 pstaxmitpriv = &psta->sta_xmitpriv;
2162
2163 /* for BC/MC Frames */
2164 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
2165
2166 spin_lock_bh(&pxmitpriv->lock);
2167
2168 psta->state |= WIFI_SLEEP_STATE;
2169
2170 pstapriv->sta_dz_bitmap |= CHKBIT(psta->aid);
2171
2172 dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vo_q.sta_pending);
2173 list_del_init(&pstaxmitpriv->vo_q.tx_pending);
2174
2175 dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vi_q.sta_pending);
2176 list_del_init(&pstaxmitpriv->vi_q.tx_pending);
2177
2178 dequeue_xmitframes_to_sleeping_queue(padapter, psta,
2179 &pstaxmitpriv->be_q.sta_pending);
2180 list_del_init(&pstaxmitpriv->be_q.tx_pending);
2181
2182 dequeue_xmitframes_to_sleeping_queue(padapter, psta,
2183 &pstaxmitpriv->bk_q.sta_pending);
2184 list_del_init(&pstaxmitpriv->bk_q.tx_pending);
2185
2186 /* for BC/MC Frames */
2187 pstaxmitpriv = &psta_bmc->sta_xmitpriv;
2188 dequeue_xmitframes_to_sleeping_queue(padapter, psta_bmc,
2189 &pstaxmitpriv->be_q.sta_pending);
2190 list_del_init(&pstaxmitpriv->be_q.tx_pending);
2191
2192 spin_unlock_bh(&pxmitpriv->lock);
2193}
2194
2195void wakeup_sta_to_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta)
2196{
2197 u8 update_mask = 0, wmmps_ac = 0;
2198 struct sta_info *psta_bmc;
2199 struct list_head *plist, *phead, *ptmp;
2200 struct xmit_frame *pxmitframe = NULL;
2201 struct sta_priv *pstapriv = &padapter->stapriv;
2202 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2203
2204 spin_lock_bh(&pxmitpriv->lock);
2205
2206 phead = get_list_head(&psta->sleep_q);
2207
2208 list_for_each_safe(plist, ptmp, phead) {
2209 pxmitframe = container_of(plist, struct xmit_frame, list);
2210 list_del_init(&pxmitframe->list);
2211
2212 switch (pxmitframe->attrib.priority) {
2213 case 1:
2214 case 2:
2215 wmmps_ac = psta->uapsd_bk & BIT(1);
2216 break;
2217 case 4:
2218 case 5:
2219 wmmps_ac = psta->uapsd_vi & BIT(1);
2220 break;
2221 case 6:
2222 case 7:
2223 wmmps_ac = psta->uapsd_vo & BIT(1);
2224 break;
2225 case 0:
2226 case 3:
2227 default:
2228 wmmps_ac = psta->uapsd_be & BIT(1);
2229 break;
2230 }
2231
2232 psta->sleepq_len--;
2233 if (psta->sleepq_len > 0)
2234 pxmitframe->attrib.mdata = 1;
2235 else
2236 pxmitframe->attrib.mdata = 0;
2237
2238 if (wmmps_ac) {
2239 psta->sleepq_ac_len--;
2240 if (psta->sleepq_ac_len > 0) {
2241 pxmitframe->attrib.mdata = 1;
2242 pxmitframe->attrib.eosp = 0;
2243 } else {
2244 pxmitframe->attrib.mdata = 0;
2245 pxmitframe->attrib.eosp = 1;
2246 }
2247 }
2248
2249 pxmitframe->attrib.triggered = 1;
2250 rtw_hal_xmit23aframe_enqueue(padapter, pxmitframe);
2251 }
2252
2253 if (psta->sleepq_len == 0) {
2254 pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
2255
2256 /* upate BCN for TIM IE */
2257 update_mask = BIT(0);
2258
2259 if (psta->state&WIFI_SLEEP_STATE)
2260 psta->state ^= WIFI_SLEEP_STATE;
2261
2262 if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
2263 psta->expire_to = pstapriv->expire_to;
2264 psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
2265 }
2266
2267 pstapriv->sta_dz_bitmap &= ~CHKBIT(psta->aid);
2268 }
2269
2270 /* spin_unlock_bh(&psta->sleep_q.lock); */
2271 spin_unlock_bh(&pxmitpriv->lock);
2272
2273 /* for BC/MC Frames */
2274 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
2275 if (!psta_bmc)
2276 return;
2277
2278 if ((pstapriv->sta_dz_bitmap&0xfffe) == 0x0) {
2279 /* no any sta in ps mode */
2280 spin_lock_bh(&pxmitpriv->lock);
2281
2282 phead = get_list_head(&psta_bmc->sleep_q);
2283
2284 list_for_each_safe(plist, ptmp, phead) {
2285 pxmitframe = container_of(plist, struct xmit_frame,
2286 list);
2287
2288 list_del_init(&pxmitframe->list);
2289
2290 psta_bmc->sleepq_len--;
2291 if (psta_bmc->sleepq_len > 0)
2292 pxmitframe->attrib.mdata = 1;
2293 else
2294 pxmitframe->attrib.mdata = 0;
2295
2296 pxmitframe->attrib.triggered = 1;
2297 rtw_hal_xmit23aframe_enqueue(padapter, pxmitframe);
2298 }
2299 if (psta_bmc->sleepq_len == 0) {
2300 pstapriv->tim_bitmap &= ~BIT(0);
2301 pstapriv->sta_dz_bitmap &= ~BIT(0);
2302
2303 /* upate BCN for TIM IE */
2304 /* update_BCNTIM(padapter); */
2305 update_mask |= BIT(1);
2306 }
2307
2308 /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
2309 spin_unlock_bh(&pxmitpriv->lock);
2310 }
2311
2312 if (update_mask)
2313 update_beacon23a(padapter, _TIM_IE_, NULL, false);
2314}
2315
2316void xmit_delivery_enabled_frames23a(struct rtw_adapter *padapter,
2317 struct sta_info *psta)
2318{
2319 u8 wmmps_ac = 0;
2320 struct list_head *plist, *phead, *ptmp;
2321 struct xmit_frame *pxmitframe;
2322 struct sta_priv *pstapriv = &padapter->stapriv;
2323 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2324
2325 /* spin_lock_bh(&psta->sleep_q.lock); */
2326 spin_lock_bh(&pxmitpriv->lock);
2327
2328 phead = get_list_head(&psta->sleep_q);
2329
2330 list_for_each_safe(plist, ptmp, phead) {
2331 pxmitframe = container_of(plist, struct xmit_frame, list);
2332
2333 switch (pxmitframe->attrib.priority) {
2334 case 1:
2335 case 2:
2336 wmmps_ac = psta->uapsd_bk & BIT(1);
2337 break;
2338 case 4:
2339 case 5:
2340 wmmps_ac = psta->uapsd_vi & BIT(1);
2341 break;
2342 case 6:
2343 case 7:
2344 wmmps_ac = psta->uapsd_vo & BIT(1);
2345 break;
2346 case 0:
2347 case 3:
2348 default:
2349 wmmps_ac = psta->uapsd_be & BIT(1);
2350 break;
2351 }
2352
2353 if (!wmmps_ac)
2354 continue;
2355
2356 list_del_init(&pxmitframe->list);
2357
2358 psta->sleepq_len--;
2359 psta->sleepq_ac_len--;
2360
2361 if (psta->sleepq_ac_len > 0) {
2362 pxmitframe->attrib.mdata = 1;
2363 pxmitframe->attrib.eosp = 0;
2364 } else {
2365 pxmitframe->attrib.mdata = 0;
2366 pxmitframe->attrib.eosp = 1;
2367 }
2368
2369 pxmitframe->attrib.triggered = 1;
2370
2371 rtw_hal_xmit23aframe_enqueue(padapter, pxmitframe);
2372
2373 if ((psta->sleepq_ac_len == 0) && (!psta->has_legacy_ac) &&
2374 (wmmps_ac)) {
2375 pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
2376
2377 /* upate BCN for TIM IE */
2378 update_beacon23a(padapter, _TIM_IE_, NULL, false);
2379 }
2380 }
2381 spin_unlock_bh(&pxmitpriv->lock);
2382}
2383
2384#endif
2385
2386void rtw_sctx_init23a(struct submit_ctx *sctx, int timeout_ms)
2387{
2388 sctx->timeout_ms = timeout_ms;
2389 init_completion(&sctx->done);
2390 sctx->status = RTW_SCTX_SUBMITTED;
2391}
2392
2393int rtw_sctx_wait23a(struct submit_ctx *sctx)
2394{
2395 int ret = _FAIL;
2396 unsigned long expire;
2397 int status = 0;
2398
2399 expire = sctx->timeout_ms ? msecs_to_jiffies(sctx->timeout_ms) :
2400 MAX_SCHEDULE_TIMEOUT;
2401 if (!wait_for_completion_timeout(&sctx->done, expire)) {
2402 /* timeout, do something?? */
2403 status = RTW_SCTX_DONE_TIMEOUT;
2404 DBG_8723A("%s timeout\n", __func__);
2405 } else {
2406 status = sctx->status;
2407 }
2408
2409 if (status == RTW_SCTX_DONE_SUCCESS)
2410 ret = _SUCCESS;
2411
2412 return ret;
2413}
2414
2415static bool rtw_sctx_chk_waring_status(int status)
2416{
2417 switch (status) {
2418 case RTW_SCTX_DONE_UNKNOWN:
2419 case RTW_SCTX_DONE_BUF_ALLOC:
2420 case RTW_SCTX_DONE_BUF_FREE:
2421 case RTW_SCTX_DONE_DRV_STOP:
2422 case RTW_SCTX_DONE_DEV_REMOVE:
2423 return true;
2424 default:
2425 return false;
2426 }
2427}
2428
2429void rtw23a_sctx_done_err(struct submit_ctx **sctx, int status)
2430{
2431 if (*sctx) {
2432 if (rtw_sctx_chk_waring_status(status))
2433 DBG_8723A("%s status:%d\n", __func__, status);
2434 (*sctx)->status = status;
2435 complete(&(*sctx)->done);
2436 *sctx = NULL;
2437 }
2438}
2439
2440void rtw_sctx_done23a(struct submit_ctx **sctx)
2441{
2442 rtw23a_sctx_done_err(sctx, RTW_SCTX_DONE_SUCCESS);
2443}
2444
2445int rtw_ack_tx_wait23a(struct xmit_priv *pxmitpriv, u32 timeout_ms)
2446{
2447 struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops;
2448
2449 pack_tx_ops->timeout_ms = timeout_ms;
2450 pack_tx_ops->status = RTW_SCTX_SUBMITTED;
2451
2452 return rtw_sctx_wait23a(pack_tx_ops);
2453}
2454
2455void rtw_ack_tx_done23a(struct xmit_priv *pxmitpriv, int status)
2456{
2457 struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops;
2458
2459 if (pxmitpriv->ack_tx)
2460 rtw23a_sctx_done_err(&pack_tx_ops, status);
2461 else
2462 DBG_8723A("%s ack_tx not set\n", __func__);
2463}