1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2012 Realtek Corporation. */
3
4 #define _RTW_IOCTL_SET_C_
5
6 #include "../include/osdep_service.h"
7 #include "../include/drv_types.h"
8 #include "../include/rtw_ioctl_set.h"
9 #include "../include/hal_intf.h"
10
11 #include "../include/usb_osintf.h"
12 #include "../include/usb_ops.h"
13
rtw_do_join(struct adapter * padapter)14 u8 rtw_do_join(struct adapter *padapter)
15 {
16 struct list_head *plist, *phead;
17 u8 *pibss = NULL;
18 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
19 struct __queue *queue = &pmlmepriv->scanned_queue;
20 u8 ret = _SUCCESS;
21
22 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
23 phead = get_list_head(queue);
24 plist = phead->next;
25
26 pmlmepriv->cur_network.join_res = -2;
27
28 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
29
30 pmlmepriv->pscanned = plist;
31
32 pmlmepriv->to_join = true;
33
34 if (list_empty(&queue->queue)) {
35 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
36 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
37
38 /* when set_ssid/set_bssid for rtw_do_join(), but scanning queue is empty */
39 /* we try to issue sitesurvey firstly */
40
41 if (!pmlmepriv->LinkDetectInfo.bBusyTraffic ||
42 pmlmepriv->to_roaming > 0) {
43 /* submit site_survey_cmd */
44 ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1);
45 if (ret != _SUCCESS)
46 pmlmepriv->to_join = false;
47 } else {
48 pmlmepriv->to_join = false;
49 ret = _FAIL;
50 }
51
52 return ret;
53 } else {
54 int select_ret;
55
56 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
57 select_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
58 if (select_ret == _SUCCESS) {
59 pmlmepriv->to_join = false;
60 _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
61 } else {
62 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
63 /* submit createbss_cmd to change to a ADHOC_MASTER */
64
65 /* pmlmepriv->lock has been acquired by caller... */
66 struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network;
67
68 pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
69
70 pibss = padapter->registrypriv.dev_network.MacAddress;
71
72 memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
73
74 rtw_update_registrypriv_dev_network(padapter);
75
76 rtw_generate_random_ibss(pibss);
77
78 if (rtw_createbss_cmd(padapter) != _SUCCESS)
79 return false;
80
81 pmlmepriv->to_join = false;
82 } else {
83 /* can't associate ; reset under-linking */
84 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
85
86 /* when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue */
87 /* we try to issue sitesurvey firstly */
88 if (!pmlmepriv->LinkDetectInfo.bBusyTraffic ||
89 pmlmepriv->to_roaming > 0) {
90 ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1);
91 if (ret != _SUCCESS)
92 pmlmepriv->to_join = false;
93 } else {
94 ret = _FAIL;
95 pmlmepriv->to_join = false;
96 }
97 }
98 }
99 }
100
101 return ret;
102 }
103
rtw_set_802_11_bssid(struct adapter * padapter,u8 * bssid)104 u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid)
105 {
106 u8 status = _SUCCESS;
107 u32 cur_time = 0;
108 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
109
110 if ((bssid[0] == 0x00 && bssid[1] == 0x00 && bssid[2] == 0x00 &&
111 bssid[3] == 0x00 && bssid[4] == 0x00 && bssid[5] == 0x00) ||
112 (bssid[0] == 0xFF && bssid[1] == 0xFF && bssid[2] == 0xFF &&
113 bssid[3] == 0xFF && bssid[4] == 0xFF && bssid[5] == 0xFF)) {
114 status = _FAIL;
115 goto exit;
116 }
117
118 spin_lock_bh(&pmlmepriv->lock);
119
120 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
121 goto handle_tkip_countermeasure;
122 else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
123 goto release_mlme_lock;
124
125 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
126 if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN)) {
127 if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE))
128 goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
129 } else {
130 rtw_disassoc_cmd(padapter, 0, true);
131
132 if (check_fwstate(pmlmepriv, _FW_LINKED))
133 rtw_indicate_disconnect(padapter);
134
135 rtw_free_assoc_resources(padapter, 1);
136
137 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
138 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
139 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
140 }
141 }
142 }
143
144 handle_tkip_countermeasure:
145 /* should we add something here...? */
146
147 if (padapter->securitypriv.btkip_countermeasure) {
148 cur_time = jiffies;
149
150 if ((cur_time - padapter->securitypriv.btkip_countermeasure_time) > 60 * HZ) {
151 padapter->securitypriv.btkip_countermeasure = false;
152 padapter->securitypriv.btkip_countermeasure_time = 0;
153 } else {
154 status = _FAIL;
155 goto release_mlme_lock;
156 }
157 }
158
159 memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
160 pmlmepriv->assoc_by_bssid = true;
161
162 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
163 pmlmepriv->to_join = true;
164 else
165 status = rtw_do_join(padapter);
166
167 release_mlme_lock:
168 spin_unlock_bh(&pmlmepriv->lock);
169
170 exit:
171 return status;
172 }
173
rtw_set_802_11_ssid(struct adapter * padapter,struct ndis_802_11_ssid * ssid)174 u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
175 {
176 u8 status = _SUCCESS;
177 u32 cur_time = 0;
178
179 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
180 struct wlan_network *pnetwork = &pmlmepriv->cur_network;
181
182 if (!padapter->hw_init_completed) {
183 status = _FAIL;
184 goto exit;
185 }
186
187 spin_lock_bh(&pmlmepriv->lock);
188
189 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
190 goto handle_tkip_countermeasure;
191 } else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
192 goto release_mlme_lock;
193 }
194
195 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
196 if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) &&
197 (!memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, ssid->SsidLength))) {
198 if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
199 if (!rtw_is_same_ibss(padapter, pnetwork)) {
200 /* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */
201 rtw_disassoc_cmd(padapter, 0, true);
202
203 if (check_fwstate(pmlmepriv, _FW_LINKED))
204 rtw_indicate_disconnect(padapter);
205
206 rtw_free_assoc_resources(padapter, 1);
207
208 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
209 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
210 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
211 }
212 } else {
213 goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
214 }
215 } else {
216 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1);
217 }
218 } else {
219 rtw_disassoc_cmd(padapter, 0, true);
220
221 if (check_fwstate(pmlmepriv, _FW_LINKED))
222 rtw_indicate_disconnect(padapter);
223
224 rtw_free_assoc_resources(padapter, 1);
225
226 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
227 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
228 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
229 }
230 }
231 }
232
233 handle_tkip_countermeasure:
234
235 if (padapter->securitypriv.btkip_countermeasure) {
236 cur_time = jiffies;
237
238 if ((cur_time - padapter->securitypriv.btkip_countermeasure_time) > 60 * HZ) {
239 padapter->securitypriv.btkip_countermeasure = false;
240 padapter->securitypriv.btkip_countermeasure_time = 0;
241 } else {
242 status = _FAIL;
243 goto release_mlme_lock;
244 }
245 }
246
247 memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
248 pmlmepriv->assoc_by_bssid = false;
249
250 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
251 pmlmepriv->to_join = true;
252 } else {
253 status = rtw_do_join(padapter);
254 }
255
256 release_mlme_lock:
257 spin_unlock_bh(&pmlmepriv->lock);
258
259 exit:
260 return status;
261 }
262
rtw_set_802_11_infrastructure_mode(struct adapter * padapter,enum ndis_802_11_network_infra networktype)263 u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter,
264 enum ndis_802_11_network_infra networktype)
265 {
266 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
267 struct wlan_network *cur_network = &pmlmepriv->cur_network;
268 enum ndis_802_11_network_infra *pold_state = &cur_network->network.InfrastructureMode;
269
270 if (*pold_state != networktype) {
271 spin_lock_bh(&pmlmepriv->lock);
272
273 if (*pold_state == Ndis802_11APMode) {
274 /* change to other mode from Ndis802_11APMode */
275 cur_network->join_res = -1;
276
277 stop_ap_mode(padapter);
278 }
279
280 if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
281 (*pold_state == Ndis802_11IBSS))
282 rtw_disassoc_cmd(padapter, 0, true);
283
284 if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
285 (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)))
286 rtw_free_assoc_resources(padapter, 1);
287
288 if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) {
289 if (check_fwstate(pmlmepriv, _FW_LINKED))
290 rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have chked whether issue dis-assoc_cmd or not */
291 }
292
293 *pold_state = networktype;
294
295 _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
296
297 switch (networktype) {
298 case Ndis802_11IBSS:
299 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
300 break;
301 case Ndis802_11Infrastructure:
302 set_fwstate(pmlmepriv, WIFI_STATION_STATE);
303 break;
304 case Ndis802_11APMode:
305 set_fwstate(pmlmepriv, WIFI_AP_STATE);
306 break;
307 case Ndis802_11AutoUnknown:
308 case Ndis802_11InfrastructureMax:
309 break;
310 }
311 spin_unlock_bh(&pmlmepriv->lock);
312 }
313
314 return true;
315 }
316
rtw_set_802_11_disassociate(struct adapter * padapter)317 u8 rtw_set_802_11_disassociate(struct adapter *padapter)
318 {
319 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
320
321 spin_lock_bh(&pmlmepriv->lock);
322
323 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
324 rtw_disassoc_cmd(padapter, 0, true);
325 rtw_indicate_disconnect(padapter);
326 rtw_free_assoc_resources(padapter, 1);
327 rtw_pwr_wakeup(padapter);
328 }
329
330 spin_unlock_bh(&pmlmepriv->lock);
331
332 return true;
333 }
334
rtw_set_802_11_bssid_list_scan(struct adapter * padapter,struct ndis_802_11_ssid * pssid,int ssid_max_num)335 u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_ssid *pssid, int ssid_max_num)
336 {
337 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
338 u8 res = true;
339
340 if (!padapter) {
341 res = false;
342 goto exit;
343 }
344 if (!padapter->hw_init_completed) {
345 res = false;
346 goto exit;
347 }
348
349 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) ||
350 (pmlmepriv->LinkDetectInfo.bBusyTraffic)) {
351 /* Scan or linking is in progress, do nothing. */
352 res = true;
353 } else {
354 spin_lock_bh(&pmlmepriv->lock);
355
356 res = rtw_sitesurvey_cmd(padapter, pssid, ssid_max_num);
357
358 spin_unlock_bh(&pmlmepriv->lock);
359 }
360 exit:
361
362 return res;
363 }
364
rtw_set_802_11_authentication_mode(struct adapter * padapter,enum ndis_802_11_auth_mode authmode)365 u8 rtw_set_802_11_authentication_mode(struct adapter *padapter, enum ndis_802_11_auth_mode authmode)
366 {
367 struct security_priv *psecuritypriv = &padapter->securitypriv;
368 int res;
369 u8 ret;
370
371 psecuritypriv->ndisauthtype = authmode;
372
373 if (psecuritypriv->ndisauthtype > 3)
374 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
375
376 res = rtw_set_auth(padapter, psecuritypriv);
377
378 if (res == _SUCCESS)
379 ret = true;
380 else
381 ret = false;
382
383 return ret;
384 }
385
rtw_set_802_11_add_wep(struct adapter * padapter,struct ndis_802_11_wep * wep)386 u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep)
387 {
388 int keyid, res;
389 struct security_priv *psecuritypriv = &padapter->securitypriv;
390 u8 ret = _SUCCESS;
391
392 keyid = wep->KeyIndex & 0x3fffffff;
393
394 if (keyid >= 4) {
395 ret = false;
396 goto exit;
397 }
398
399 switch (wep->KeyLength) {
400 case 5:
401 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
402 break;
403 case 13:
404 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
405 break;
406 default:
407 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
408 break;
409 }
410
411 memcpy(&psecuritypriv->dot11DefKey[keyid].skey[0], &wep->KeyMaterial, wep->KeyLength);
412
413 psecuritypriv->dot11DefKeylen[keyid] = wep->KeyLength;
414
415 psecuritypriv->dot11PrivacyKeyIndex = keyid;
416
417 res = rtw_set_key(padapter, psecuritypriv, keyid, 1);
418
419 if (res == _FAIL)
420 ret = false;
421 exit:
422
423 return ret;
424 }
425
426 /*
427 * rtw_get_cur_max_rate -
428 * @adapter: pointer to struct adapter structure
429 *
430 * Return 0 or 100Kbps
431 */
rtw_get_cur_max_rate(struct adapter * adapter)432 u16 rtw_get_cur_max_rate(struct adapter *adapter)
433 {
434 int i = 0;
435 u8 *p;
436 u16 rate = 0, max_rate = 0;
437 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
438 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
439 struct registry_priv *pregistrypriv = &adapter->registrypriv;
440 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
441 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
442 struct ieee80211_ht_cap *pht_capie;
443 u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0;
444 u16 mcs_rate = 0;
445 u32 ht_ielen = 0;
446
447 if ((!check_fwstate(pmlmepriv, _FW_LINKED)) &&
448 (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)))
449 return 0;
450
451 if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N)) {
452 p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength - 12);
453 if (p && ht_ielen > 0) {
454 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
455
456 memcpy(&mcs_rate, pht_capie->mcs.rx_mask, 2);
457
458 /* cur_bwmod is updated by beacon, pmlmeinfo is updated by association response */
459 bw_40MHz = (pmlmeext->cur_bwmode && (HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH & pmlmeinfo->HT_info.infos[0])) ? 1 : 0;
460
461 short_GI_20 = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & IEEE80211_HT_CAP_SGI_20) ? 1 : 0;
462 short_GI_40 = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & IEEE80211_HT_CAP_SGI_40) ? 1 : 0;
463
464 max_rate = rtw_mcs_rate(bw_40MHz & (pregistrypriv->cbw40_enable),
465 short_GI_20,
466 short_GI_40,
467 pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate);
468 }
469 } else {
470 while ((pcur_bss->SupportedRates[i] != 0) && (pcur_bss->SupportedRates[i] != 0xFF)) {
471 rate = pcur_bss->SupportedRates[i] & 0x7F;
472 if (rate > max_rate)
473 max_rate = rate;
474 i++;
475 }
476
477 max_rate *= 5;
478 }
479
480 return max_rate;
481 }
482