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