GNU Linux-libre 5.10.215-gnu1
[releases.git] / drivers / staging / rtl8723bs / core / rtw_ioctl_set.c
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 #define _RTW_IOCTL_SET_C_
8
9 #include <drv_types.h>
10 #include <rtw_debug.h>
11
12 u8 rtw_validate_bssid(u8 *bssid)
13 {
14         u8 ret = true;
15
16         if (is_zero_mac_addr(bssid)
17                 || is_broadcast_mac_addr(bssid)
18                 || is_multicast_mac_addr(bssid)
19         ) {
20                 ret = false;
21         }
22
23         return ret;
24 }
25
26 u8 rtw_validate_ssid(struct ndis_802_11_ssid *ssid)
27 {
28         u8 ret = true;
29
30         if (ssid->SsidLength > 32) {
31                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("ssid length >32\n"));
32                 ret = false;
33                 goto exit;
34         }
35
36 #ifdef CONFIG_VALIDATE_SSID
37         for (i = 0; i < ssid->SsidLength; i++) {
38                 /* wifi, printable ascii code must be supported */
39                 if (!((ssid->Ssid[i] >= 0x20) && (ssid->Ssid[i] <= 0x7e))) {
40                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("ssid has non-printable ascii\n"));
41                         ret = false;
42                         break;
43                 }
44         }
45 #endif /* CONFIG_VALIDATE_SSID */
46
47 exit:
48         return ret;
49 }
50
51 u8 rtw_do_join(struct adapter *padapter);
52 u8 rtw_do_join(struct adapter *padapter)
53 {
54         struct list_head        *plist, *phead;
55         u8 *pibss = NULL;
56         struct  mlme_priv *pmlmepriv = &(padapter->mlmepriv);
57         struct __queue  *queue  = &(pmlmepriv->scanned_queue);
58         u8 ret = _SUCCESS;
59
60         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
61         phead = get_list_head(queue);
62         plist = get_next(phead);
63
64         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("\n rtw_do_join: phead = %p; plist = %p\n\n\n", phead, plist));
65
66         pmlmepriv->cur_network.join_res = -2;
67
68         set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
69
70         pmlmepriv->pscanned = plist;
71
72         pmlmepriv->to_join = true;
73
74         if (list_empty(&queue->queue)) {
75                 spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
76                 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
77
78                 /* when set_ssid/set_bssid for rtw_do_join(), but scanning queue is empty */
79                 /* we try to issue sitesurvey firstly */
80
81                 if (pmlmepriv->LinkDetectInfo.bBusyTraffic == false
82                         || rtw_to_roam(padapter) > 0
83                 ) {
84                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("rtw_do_join(): site survey if scanned_queue is empty\n."));
85                         /*  submit site_survey_cmd */
86                         ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
87                         if (_SUCCESS != ret) {
88                                 pmlmepriv->to_join = false;
89                                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("rtw_do_join(): site survey return error\n."));
90                         }
91                 } else {
92                         pmlmepriv->to_join = false;
93                         ret = _FAIL;
94                 }
95
96                 goto exit;
97         } else {
98                 int select_ret;
99                 spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
100                 select_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
101                 if (select_ret == _SUCCESS) {
102                         pmlmepriv->to_join = false;
103                         _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
104                 } else {
105                         if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
106                                 /*  submit createbss_cmd to change to a ADHOC_MASTER */
107
108                                 /* pmlmepriv->lock has been acquired by caller... */
109                                 struct wlan_bssid_ex    *pdev_network = &(padapter->registrypriv.dev_network);
110
111                                 pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
112
113                                 pibss = padapter->registrypriv.dev_network.MacAddress;
114
115                                 memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
116
117                                 rtw_update_registrypriv_dev_network(padapter);
118
119                                 rtw_generate_random_ibss(pibss);
120
121                                 if (rtw_createbss_cmd(padapter) != _SUCCESS) {
122                                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("***Error =>do_goin: rtw_createbss_cmd status FAIL***\n "));
123                                         ret =  false;
124                                         goto exit;
125                                 }
126
127                                 pmlmepriv->to_join = false;
128
129                                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("***Error => rtw_select_and_join_from_scanned_queue FAIL under STA_Mode***\n "));
130
131                         } else {
132                                 /*  can't associate ; reset under-linking */
133                                 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
134
135                                 /* when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue */
136                                 /* we try to issue sitesurvey firstly */
137                                 if (pmlmepriv->LinkDetectInfo.bBusyTraffic == false
138                                         || rtw_to_roam(padapter) > 0
139                                 ) {
140                                         /* DBG_871X("rtw_do_join() when   no desired bss in scanning queue\n"); */
141                                         ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
142                                         if (_SUCCESS != ret) {
143                                                 pmlmepriv->to_join = false;
144                                                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("do_join(): site survey return error\n."));
145                                         }
146                                 } else {
147                                         ret = _FAIL;
148                                         pmlmepriv->to_join = false;
149                                 }
150                         }
151
152                 }
153
154         }
155
156 exit:
157         return ret;
158 }
159
160 u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid)
161 {
162         u8 status = _SUCCESS;
163
164         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
165
166         DBG_871X_LEVEL(_drv_always_, "set bssid:%pM\n", bssid);
167
168         if ((bssid[0] == 0x00 && bssid[1] == 0x00 && bssid[2] == 0x00 && bssid[3] == 0x00 && bssid[4] == 0x00 && bssid[5] == 0x00) ||
169             (bssid[0] == 0xFF && bssid[1] == 0xFF && bssid[2] == 0xFF && bssid[3] == 0xFF && bssid[4] == 0xFF && bssid[5] == 0xFF)) {
170                 status = _FAIL;
171                 goto exit;
172         }
173
174         spin_lock_bh(&pmlmepriv->lock);
175
176
177         DBG_871X("Set BSSID 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                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_bssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
186
187                 if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN)) {
188                         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == false)
189                                 goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
190                 } else {
191                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("Set BSSID not the same bssid\n"));
192                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_bssid ="MAC_FMT"\n", MAC_ARG(bssid)));
193                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("cur_bssid ="MAC_FMT"\n", MAC_ARG(pmlmepriv->cur_network.network.MacAddress)));
194
195                         rtw_disassoc_cmd(padapter, 0, true);
196
197                         if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
198                                 rtw_indicate_disconnect(padapter);
199
200                         rtw_free_assoc_resources(padapter, 1);
201
202                         if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
203                                 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
204                                 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
205                         }
206                 }
207         }
208
209 handle_tkip_countermeasure:
210         if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) {
211                 status = _FAIL;
212                 goto release_mlme_lock;
213         }
214
215         memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
216         memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
217         pmlmepriv->assoc_by_bssid = true;
218
219         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
220                 pmlmepriv->to_join = true;
221         } else {
222                 status = rtw_do_join(padapter);
223         }
224
225 release_mlme_lock:
226         spin_unlock_bh(&pmlmepriv->lock);
227
228 exit:
229         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
230                 ("rtw_set_802_11_bssid: status =%d\n", status));
231
232         return status;
233 }
234
235 u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
236 {
237         u8 status = _SUCCESS;
238
239         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
240         struct wlan_network *pnetwork = &pmlmepriv->cur_network;
241
242         DBG_871X_LEVEL(_drv_always_, "set ssid [%s] fw_state = 0x%08x\n",
243                         ssid->Ssid, get_fwstate(pmlmepriv));
244
245         if (padapter->hw_init_completed == false) {
246                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
247                          ("set_ssid: hw_init_completed ==false =>exit!!!\n"));
248                 status = _FAIL;
249                 goto exit;
250         }
251
252         spin_lock_bh(&pmlmepriv->lock);
253
254         DBG_871X("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
255         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
256                 goto handle_tkip_countermeasure;
257         } else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) {
258                 goto release_mlme_lock;
259         }
260
261         if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) {
262                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
263                          ("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
264
265                 if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) &&
266                     (!memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, ssid->SsidLength))) {
267                         if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == false)) {
268                                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
269                                          ("Set SSID is the same ssid, fw_state = 0x%08x\n",
270                                           get_fwstate(pmlmepriv)));
271
272                                 if (rtw_is_same_ibss(padapter, pnetwork) == false) {
273                                         /* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */
274                                         rtw_disassoc_cmd(padapter, 0, true);
275
276                                         if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
277                                                 rtw_indicate_disconnect(padapter);
278
279                                         rtw_free_assoc_resources(padapter, 1);
280
281                                         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
282                                                 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
283                                                 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
284                                         }
285                                 } else {
286                                         goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
287                                 }
288                         } else {
289                                 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1);
290                         }
291                 } else {
292                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("Set SSID not the same ssid\n"));
293                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_ssid =[%s] len = 0x%x\n", ssid->Ssid, (unsigned int)ssid->SsidLength));
294                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("assoc_ssid =[%s] len = 0x%x\n", pmlmepriv->assoc_ssid.Ssid, (unsigned int)pmlmepriv->assoc_ssid.SsidLength));
295
296                         rtw_disassoc_cmd(padapter, 0, true);
297
298                         if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
299                                 rtw_indicate_disconnect(padapter);
300
301                         rtw_free_assoc_resources(padapter, 1);
302
303                         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
304                                 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
305                                 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
306                         }
307                 }
308         }
309
310 handle_tkip_countermeasure:
311         if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) {
312                 status = _FAIL;
313                 goto release_mlme_lock;
314         }
315
316         if (rtw_validate_ssid(ssid) == false) {
317                 status = _FAIL;
318                 goto release_mlme_lock;
319         }
320
321         memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
322         pmlmepriv->assoc_by_bssid = false;
323
324         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
325                 pmlmepriv->to_join = true;
326         } else {
327                 status = rtw_do_join(padapter);
328         }
329
330 release_mlme_lock:
331         spin_unlock_bh(&pmlmepriv->lock);
332
333 exit:
334         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
335                 ("-rtw_set_802_11_ssid: status =%d\n", status));
336
337         return status;
338 }
339
340 u8 rtw_set_802_11_connect(struct adapter *padapter, u8 *bssid, struct ndis_802_11_ssid *ssid)
341 {
342         u8 status = _SUCCESS;
343         bool bssid_valid = true;
344         bool ssid_valid = true;
345         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
346
347         if (!ssid || rtw_validate_ssid(ssid) == false)
348                 ssid_valid = false;
349
350         if (!bssid || rtw_validate_bssid(bssid) == false)
351                 bssid_valid = false;
352
353         if (!ssid_valid && !bssid_valid) {
354                 DBG_871X(FUNC_ADPT_FMT" ssid:%p, ssid_valid:%d, bssid:%p, bssid_valid:%d\n",
355                         FUNC_ADPT_ARG(padapter), ssid, ssid_valid, bssid, bssid_valid);
356                 status = _FAIL;
357                 goto exit;
358         }
359
360         if (padapter->hw_init_completed == false) {
361                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
362                          ("set_ssid: hw_init_completed ==false =>exit!!!\n"));
363                 status = _FAIL;
364                 goto exit;
365         }
366
367         spin_lock_bh(&pmlmepriv->lock);
368
369         DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT"  fw_state = 0x%08x\n",
370                 FUNC_ADPT_ARG(padapter), get_fwstate(pmlmepriv));
371
372         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
373                 goto handle_tkip_countermeasure;
374         } else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) {
375                 goto release_mlme_lock;
376         }
377
378 handle_tkip_countermeasure:
379         if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) {
380                 status = _FAIL;
381                 goto release_mlme_lock;
382         }
383
384         if (ssid && ssid_valid)
385                 memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
386         else
387                 memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
388
389         if (bssid && bssid_valid) {
390                 memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
391                 pmlmepriv->assoc_by_bssid = true;
392         } else {
393                 pmlmepriv->assoc_by_bssid = false;
394         }
395
396         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
397                 pmlmepriv->to_join = true;
398         } else {
399                 status = rtw_do_join(padapter);
400         }
401
402 release_mlme_lock:
403         spin_unlock_bh(&pmlmepriv->lock);
404
405 exit:
406         return status;
407 }
408
409 u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter,
410         enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype)
411 {
412         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
413         struct  wlan_network    *cur_network = &pmlmepriv->cur_network;
414         enum NDIS_802_11_NETWORK_INFRASTRUCTURE *pold_state = &(cur_network->network.InfrastructureMode);
415
416         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_,
417                  ("+rtw_set_802_11_infrastructure_mode: old =%d new =%d fw_state = 0x%08x\n",
418                   *pold_state, networktype, get_fwstate(pmlmepriv)));
419
420         if (*pold_state != networktype) {
421                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, (" change mode!"));
422                 /* DBG_871X("change mode, old_mode =%d, new_mode =%d, fw_state = 0x%x\n", *pold_state, networktype, get_fwstate(pmlmepriv)); */
423
424                 if (*pold_state == Ndis802_11APMode) {
425                         /* change to other mode from Ndis802_11APMode */
426                         cur_network->join_res = -1;
427
428                         stop_ap_mode(padapter);
429                 }
430
431                 spin_lock_bh(&pmlmepriv->lock);
432
433                 if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) || (*pold_state == Ndis802_11IBSS))
434                         rtw_disassoc_cmd(padapter, 0, true);
435
436                 if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) ||
437                         (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true))
438                         rtw_free_assoc_resources(padapter, 1);
439
440                 if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) {
441                         if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
442                                 rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have checked whether issue dis-assoc_cmd or not */
443                         }
444                }
445
446                 *pold_state = networktype;
447
448                 _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
449
450                 switch (networktype) {
451                 case Ndis802_11IBSS:
452                         set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
453                         break;
454
455                 case Ndis802_11Infrastructure:
456                         set_fwstate(pmlmepriv, WIFI_STATION_STATE);
457                         break;
458
459                 case Ndis802_11APMode:
460                         set_fwstate(pmlmepriv, WIFI_AP_STATE);
461                         start_ap_mode(padapter);
462                         /* rtw_indicate_connect(padapter); */
463
464                         break;
465
466                 case Ndis802_11AutoUnknown:
467                 case Ndis802_11InfrastructureMax:
468                         break;
469                 }
470
471                 /* SecClearAllKeys(adapter); */
472
473                 /* RT_TRACE(COMP_OID_SET, DBG_LOUD, ("set_infrastructure: fw_state:%x after changing mode\n", */
474                 /*                                                                      get_fwstate(pmlmepriv))); */
475
476                 spin_unlock_bh(&pmlmepriv->lock);
477         }
478         return true;
479 }
480
481
482 u8 rtw_set_802_11_disassociate(struct adapter *padapter)
483 {
484         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
485
486         spin_lock_bh(&pmlmepriv->lock);
487
488         if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
489                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("MgntActrtw_set_802_11_disassociate: rtw_indicate_disconnect\n"));
490
491                 rtw_disassoc_cmd(padapter, 0, true);
492                 rtw_indicate_disconnect(padapter);
493                 /* modify for CONFIG_IEEE80211W, none 11w can use it */
494                 rtw_free_assoc_resources_cmd(padapter);
495                 if (_FAIL == rtw_pwr_wakeup(padapter))
496                         DBG_871X("%s(): rtw_pwr_wakeup fail !!!\n", __func__);
497         }
498
499         spin_unlock_bh(&pmlmepriv->lock);
500
501         return true;
502 }
503
504 u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_ssid *pssid, int ssid_max_num)
505 {
506         struct  mlme_priv       *pmlmepriv = &padapter->mlmepriv;
507         u8 res = true;
508
509         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("+rtw_set_802_11_bssid_list_scan(), fw_state =%x\n", get_fwstate(pmlmepriv)));
510
511         if (padapter == NULL) {
512                 res = false;
513                 goto exit;
514         }
515         if (padapter->hw_init_completed == false) {
516                 res = false;
517                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n ===rtw_set_802_11_bssid_list_scan:hw_init_completed ==false ===\n"));
518                 goto exit;
519         }
520
521         if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true) ||
522                 (pmlmepriv->LinkDetectInfo.bBusyTraffic == true)) {
523                 /*  Scan or linking is in progress, do nothing. */
524                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("rtw_set_802_11_bssid_list_scan fail since fw_state = %x\n", get_fwstate(pmlmepriv)));
525                 res = true;
526
527                 if (check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING)) == true) {
528                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n###_FW_UNDER_SURVEY|_FW_UNDER_LINKING\n\n"));
529                 } else {
530                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n###pmlmepriv->sitesurveyctrl.traffic_busy ==true\n\n"));
531                 }
532         } else {
533                 if (rtw_is_scan_deny(padapter)) {
534                         DBG_871X(FUNC_ADPT_FMT": scan deny\n", FUNC_ADPT_ARG(padapter));
535                         indicate_wx_scan_complete_event(padapter);
536                         return _SUCCESS;
537                 }
538
539                 spin_lock_bh(&pmlmepriv->lock);
540
541                 res = rtw_sitesurvey_cmd(padapter, pssid, ssid_max_num, NULL, 0);
542
543                 spin_unlock_bh(&pmlmepriv->lock);
544         }
545 exit:
546
547         return res;
548 }
549
550 u8 rtw_set_802_11_authentication_mode(struct adapter *padapter, enum NDIS_802_11_AUTHENTICATION_MODE authmode)
551 {
552         struct security_priv *psecuritypriv = &padapter->securitypriv;
553         int res;
554         u8 ret;
555
556         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_802_11_auth.mode(): mode =%x\n", authmode));
557
558         psecuritypriv->ndisauthtype = authmode;
559
560         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("rtw_set_802_11_authentication_mode:psecuritypriv->ndisauthtype =%d", psecuritypriv->ndisauthtype));
561
562         if (psecuritypriv->ndisauthtype > 3)
563                 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
564
565         res = rtw_set_auth(padapter, psecuritypriv);
566
567         if (res == _SUCCESS)
568                 ret = true;
569         else
570                 ret = false;
571
572         return ret;
573 }
574
575 u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep)
576 {
577
578         sint            keyid, res;
579         struct security_priv *psecuritypriv = &(padapter->securitypriv);
580         u8 ret = _SUCCESS;
581
582         keyid = wep->KeyIndex & 0x3fffffff;
583
584         if (keyid >= 4) {
585                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("MgntActrtw_set_802_11_add_wep:keyid>4 =>fail\n"));
586                 ret = false;
587                 goto exit;
588         }
589
590         switch (wep->KeyLength) {
591         case 5:
592                 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
593                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("MgntActrtw_set_802_11_add_wep:wep->KeyLength =5\n"));
594                 break;
595         case 13:
596                 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
597                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("MgntActrtw_set_802_11_add_wep:wep->KeyLength = 13\n"));
598                 break;
599         default:
600                 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
601                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("MgntActrtw_set_802_11_add_wep:wep->KeyLength!=5 or 13\n"));
602                 break;
603         }
604
605         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
606                  ("rtw_set_802_11_add_wep:before memcpy, wep->KeyLength = 0x%x wep->KeyIndex = 0x%x  keyid =%x\n",
607                   wep->KeyLength, wep->KeyIndex, keyid));
608
609         memcpy(&(psecuritypriv->dot11DefKey[keyid].skey[0]), &(wep->KeyMaterial), wep->KeyLength);
610
611         psecuritypriv->dot11DefKeylen[keyid] = wep->KeyLength;
612
613         psecuritypriv->dot11PrivacyKeyIndex = keyid;
614
615         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("rtw_set_802_11_add_wep:security key material : %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
616                 psecuritypriv->dot11DefKey[keyid].skey[0], psecuritypriv->dot11DefKey[keyid].skey[1], psecuritypriv->dot11DefKey[keyid].skey[2],
617                 psecuritypriv->dot11DefKey[keyid].skey[3], psecuritypriv->dot11DefKey[keyid].skey[4], psecuritypriv->dot11DefKey[keyid].skey[5],
618                 psecuritypriv->dot11DefKey[keyid].skey[6], psecuritypriv->dot11DefKey[keyid].skey[7], psecuritypriv->dot11DefKey[keyid].skey[8],
619                 psecuritypriv->dot11DefKey[keyid].skey[9], psecuritypriv->dot11DefKey[keyid].skey[10], psecuritypriv->dot11DefKey[keyid].skey[11],
620                 psecuritypriv->dot11DefKey[keyid].skey[12]));
621
622         res = rtw_set_key(padapter, psecuritypriv, keyid, 1, true);
623
624         if (res == _FAIL)
625                 ret = false;
626 exit:
627
628         return ret;
629 }
630
631 /*
632 * rtw_get_cur_max_rate -
633 * @adapter: pointer to struct adapter structure
634 *
635 * Return 0 or 100Kbps
636 */
637 u16 rtw_get_cur_max_rate(struct adapter *adapter)
638 {
639         int     i = 0;
640         u16 rate = 0, max_rate = 0;
641         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
642         struct wlan_bssid_ex    *pcur_bss = &pmlmepriv->cur_network.network;
643         struct sta_info *psta = NULL;
644         u8 short_GI = 0;
645         u8 rf_type = 0;
646
647         if ((check_fwstate(pmlmepriv, _FW_LINKED) != true)
648                 && (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != true))
649                 return 0;
650
651         psta = rtw_get_stainfo(&adapter->stapriv, get_bssid(pmlmepriv));
652         if (psta == NULL)
653                 return 0;
654
655         short_GI = query_ra_short_GI(psta);
656
657         if (IsSupportedHT(psta->wireless_mode)) {
658                 rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
659
660                 max_rate = rtw_mcs_rate(
661                         rf_type,
662                         ((psta->bw_mode == CHANNEL_WIDTH_40)?1:0),
663                         short_GI,
664                         psta->htpriv.ht_cap.supp_mcs_set
665                 );
666         } else {
667                 while ((pcur_bss->SupportedRates[i] != 0) && (pcur_bss->SupportedRates[i] != 0xFF)) {
668                         rate = pcur_bss->SupportedRates[i]&0x7F;
669                         if (rate > max_rate)
670                                 max_rate = rate;
671                         i++;
672                 }
673
674                 max_rate = max_rate*10/2;
675         }
676
677         return max_rate;
678 }