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