1
2
3
4
5
6
7#define _RTW_IOCTL_SET_C_
8
9#include <osdep_service.h>
10#include <drv_types.h>
11#include <rtw_ioctl_set.h>
12#include <hal_intf.h>
13
14static const struct {
15 int channel_plan;
16 char *name;
17} channel_table[] = { { RT_CHANNEL_DOMAIN_FCC, "US" },
18 { RT_CHANNEL_DOMAIN_ETSI, "EU" },
19 { RT_CHANNEL_DOMAIN_MKK, "JP" },
20 { RT_CHANNEL_DOMAIN_CHINA, "CN"} };
21
22extern void indicate_wx_scan_complete_event(struct adapter *padapter);
23
24u8 rtw_do_join(struct adapter *padapter)
25{
26 struct list_head *plist, *phead;
27 u8 *pibss = NULL;
28 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
29 struct __queue *queue = &pmlmepriv->scanned_queue;
30 u8 ret = _SUCCESS;
31
32 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
33 phead = get_list_head(queue);
34 plist = phead->next;
35
36 pmlmepriv->cur_network.join_res = -2;
37
38 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
39
40 pmlmepriv->pscanned = plist;
41
42 pmlmepriv->to_join = true;
43
44 if (list_empty(&queue->queue)) {
45 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
46 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
47
48
49
50
51 if (!pmlmepriv->LinkDetectInfo.bBusyTraffic ||
52 pmlmepriv->to_roaming > 0) {
53
54 ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
55 if (ret != _SUCCESS)
56 pmlmepriv->to_join = false;
57 } else {
58 pmlmepriv->to_join = false;
59 ret = _FAIL;
60 }
61
62 goto exit;
63 } else {
64 int select_ret;
65
66 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
67 select_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
68 if (select_ret == _SUCCESS) {
69 pmlmepriv->to_join = false;
70 mod_timer(&pmlmepriv->assoc_timer,
71 jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
72 } else {
73 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
74
75
76
77 struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network;
78
79 pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
80
81 pibss = padapter->registrypriv.dev_network.MacAddress;
82
83 memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
84
85 rtw_update_registrypriv_dev_network(padapter);
86
87 rtw_generate_random_ibss(pibss);
88
89 if (rtw_createbss_cmd(padapter) != _SUCCESS) {
90 ret = false;
91 goto exit;
92 }
93 pmlmepriv->to_join = false;
94 } else {
95
96 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
97
98
99
100 if (!pmlmepriv->LinkDetectInfo.bBusyTraffic ||
101 pmlmepriv->to_roaming > 0) {
102 ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
103 if (ret != _SUCCESS)
104 pmlmepriv->to_join = false;
105 } else {
106 ret = _FAIL;
107 pmlmepriv->to_join = false;
108 }
109 }
110 }
111 }
112
113exit:
114 return ret;
115}
116
117u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid)
118{
119 u8 status = _SUCCESS;
120 u32 cur_time = 0;
121 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
122
123 if ((bssid[0] == 0x00 && bssid[1] == 0x00 && bssid[2] == 0x00 &&
124 bssid[3] == 0x00 && bssid[4] == 0x00 && bssid[5] == 0x00) ||
125 (bssid[0] == 0xFF && bssid[1] == 0xFF && bssid[2] == 0xFF &&
126 bssid[3] == 0xFF && bssid[4] == 0xFF && bssid[5] == 0xFF)) {
127 status = _FAIL;
128 goto exit;
129 }
130
131 spin_lock_bh(&pmlmepriv->lock);
132
133 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
134 goto handle_tkip_countermeasure;
135 else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
136 goto release_mlme_lock;
137
138 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
139 if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN)) {
140 if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE))
141 goto release_mlme_lock;
142 } else {
143 rtw_disassoc_cmd(padapter, 0, true);
144
145 if (check_fwstate(pmlmepriv, _FW_LINKED))
146 rtw_indicate_disconnect(padapter);
147
148 rtw_free_assoc_resources(padapter);
149
150 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
151 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
152 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
153 }
154 }
155 }
156
157handle_tkip_countermeasure:
158
159
160 if (padapter->securitypriv.btkip_countermeasure) {
161 cur_time = jiffies;
162
163 if (cur_time - padapter->securitypriv.btkip_countermeasure_time > 60 * HZ) {
164 padapter->securitypriv.btkip_countermeasure = false;
165 padapter->securitypriv.btkip_countermeasure_time = 0;
166 } else {
167 status = _FAIL;
168 goto release_mlme_lock;
169 }
170 }
171
172 memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
173 pmlmepriv->assoc_by_bssid = true;
174
175 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
176 pmlmepriv->to_join = true;
177 else
178 status = rtw_do_join(padapter);
179
180release_mlme_lock:
181 spin_unlock_bh(&pmlmepriv->lock);
182
183exit:
184 return status;
185}
186
187u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
188{
189 u8 status = _SUCCESS;
190 u32 cur_time = 0;
191
192 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
193 struct wlan_network *pnetwork = &pmlmepriv->cur_network;
194
195 if (!padapter->hw_init_completed) {
196 status = _FAIL;
197 goto exit;
198 }
199
200 spin_lock_bh(&pmlmepriv->lock);
201
202 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
203 goto handle_tkip_countermeasure;
204 else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
205 goto release_mlme_lock;
206
207 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
208 if (pmlmepriv->assoc_ssid.ssid_length == ssid->ssid_length &&
209 !memcmp(&pmlmepriv->assoc_ssid.ssid, ssid->ssid, ssid->ssid_length)) {
210 if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
211 if (!rtw_is_same_ibss(padapter, pnetwork)) {
212
213 rtw_disassoc_cmd(padapter, 0, true);
214
215 if (check_fwstate(pmlmepriv, _FW_LINKED))
216 rtw_indicate_disconnect(padapter);
217
218 rtw_free_assoc_resources(padapter);
219
220 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
221 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
222 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
223 }
224 } else {
225 goto release_mlme_lock;
226 }
227 } else {
228 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1);
229 }
230 } else {
231 rtw_disassoc_cmd(padapter, 0, true);
232
233 if (check_fwstate(pmlmepriv, _FW_LINKED))
234 rtw_indicate_disconnect(padapter);
235
236 rtw_free_assoc_resources(padapter);
237
238 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
239 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
240 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
241 }
242 }
243 }
244
245handle_tkip_countermeasure:
246
247 if (padapter->securitypriv.btkip_countermeasure) {
248 cur_time = jiffies;
249
250 if (cur_time - padapter->securitypriv.btkip_countermeasure_time > 60 * HZ) {
251 padapter->securitypriv.btkip_countermeasure = false;
252 padapter->securitypriv.btkip_countermeasure_time = 0;
253 } else {
254 status = _FAIL;
255 goto release_mlme_lock;
256 }
257 }
258
259 memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
260 pmlmepriv->assoc_by_bssid = false;
261
262 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
263 pmlmepriv->to_join = true;
264 else
265 status = rtw_do_join(padapter);
266
267release_mlme_lock:
268 spin_unlock_bh(&pmlmepriv->lock);
269
270exit:
271 return status;
272}
273
274u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter,
275 enum ndis_802_11_network_infra networktype)
276{
277 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
278 struct wlan_network *cur_network = &pmlmepriv->cur_network;
279 enum ndis_802_11_network_infra *pold_state = &cur_network->network.InfrastructureMode;
280
281 if (*pold_state != networktype) {
282 spin_lock_bh(&pmlmepriv->lock);
283
284 if (*pold_state == Ndis802_11APMode) {
285
286 cur_network->join_res = -1;
287
288#ifdef CONFIG_88EU_AP_MODE
289 stop_ap_mode(padapter);
290#endif
291 }
292
293 if (check_fwstate(pmlmepriv, _FW_LINKED) ||
294 *pold_state == Ndis802_11IBSS)
295 rtw_disassoc_cmd(padapter, 0, true);
296
297 if (check_fwstate(pmlmepriv, _FW_LINKED) ||
298 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
299 rtw_free_assoc_resources(padapter);
300
301 if (*pold_state == Ndis802_11Infrastructure ||
302 *pold_state == Ndis802_11IBSS) {
303 if (check_fwstate(pmlmepriv, _FW_LINKED))
304 rtw_indicate_disconnect(padapter);
305 }
306
307 *pold_state = networktype;
308
309 _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
310
311 switch (networktype) {
312 case Ndis802_11IBSS:
313 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
314 break;
315 case Ndis802_11Infrastructure:
316 set_fwstate(pmlmepriv, WIFI_STATION_STATE);
317 break;
318 case Ndis802_11APMode:
319 set_fwstate(pmlmepriv, WIFI_AP_STATE);
320#ifdef CONFIG_88EU_AP_MODE
321 start_ap_mode(padapter);
322#endif
323 break;
324 case Ndis802_11AutoUnknown:
325 case Ndis802_11InfrastructureMax:
326 break;
327 }
328 spin_unlock_bh(&pmlmepriv->lock);
329 }
330
331 return true;
332}
333
334u8 rtw_set_802_11_disassociate(struct adapter *padapter)
335{
336 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
337
338 spin_lock_bh(&pmlmepriv->lock);
339
340 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
341 rtw_disassoc_cmd(padapter, 0, true);
342 rtw_indicate_disconnect(padapter);
343 rtw_free_assoc_resources(padapter);
344 rtw_pwr_wakeup(padapter);
345 }
346
347 spin_unlock_bh(&pmlmepriv->lock);
348
349 return true;
350}
351
352u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_ssid *pssid, int ssid_max_num)
353{
354 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
355 u8 res = true;
356
357 if (!padapter) {
358 res = false;
359 goto exit;
360 }
361 if (!padapter->hw_init_completed) {
362 res = false;
363 goto exit;
364 }
365
366 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ||
367 pmlmepriv->LinkDetectInfo.bBusyTraffic) {
368
369 res = true;
370 } else {
371 if (rtw_is_scan_deny(padapter)) {
372 indicate_wx_scan_complete_event(padapter);
373 return _SUCCESS;
374 }
375
376 spin_lock_bh(&pmlmepriv->lock);
377
378 res = rtw_sitesurvey_cmd(padapter, pssid, ssid_max_num, NULL, 0);
379
380 spin_unlock_bh(&pmlmepriv->lock);
381 }
382exit:
383 return res;
384}
385
386u8 rtw_set_802_11_authentication_mode(struct adapter *padapter, enum ndis_802_11_auth_mode authmode)
387{
388 struct security_priv *psecuritypriv = &padapter->securitypriv;
389 int res;
390 u8 ret;
391
392 psecuritypriv->ndisauthtype = authmode;
393
394 if (psecuritypriv->ndisauthtype > 3)
395 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
396
397 res = rtw_set_auth(padapter, psecuritypriv);
398
399 if (res == _SUCCESS)
400 ret = true;
401 else
402 ret = false;
403
404 return ret;
405}
406
407u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep)
408{
409 int keyid, res;
410 struct security_priv *psecuritypriv = &padapter->securitypriv;
411 u8 ret = _SUCCESS;
412
413 keyid = wep->KeyIndex & 0x3fffffff;
414
415 if (keyid >= 4) {
416 ret = false;
417 goto exit;
418 }
419
420 switch (wep->KeyLength) {
421 case 5:
422 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
423 break;
424 case 13:
425 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
426 break;
427 default:
428 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
429 break;
430 }
431
432 memcpy(&psecuritypriv->dot11DefKey[keyid].skey[0],
433 &wep->KeyMaterial, wep->KeyLength);
434
435 psecuritypriv->dot11DefKeylen[keyid] = wep->KeyLength;
436
437 psecuritypriv->dot11PrivacyKeyIndex = keyid;
438
439 res = rtw_set_key(padapter, psecuritypriv, keyid, 1);
440
441 if (res == _FAIL)
442 ret = false;
443exit:
444 return ret;
445}
446
447
448u16 rtw_get_cur_max_rate(struct adapter *adapter)
449{
450 int i = 0;
451 u8 *p;
452 u16 rate = 0, max_rate = 0;
453 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
454 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
455 struct registry_priv *pregistrypriv = &adapter->registrypriv;
456 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
457 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
458 u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0;
459 u32 ht_ielen = 0;
460
461 if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
462 !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
463 return 0;
464
465 if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N | WIRELESS_11_5N)) {
466 p = rtw_get_ie(&pcur_bss->ies[12], WLAN_EID_HT_CAPABILITY,
467 &ht_ielen, pcur_bss->ie_length - 12);
468 if (p && ht_ielen > 0) {
469
470 bw_40MHz = (pmlmeext->cur_bwmode && (HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH & pmlmeinfo->HT_info.infos[0])) ? 1 : 0;
471
472 short_GI_20 = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & IEEE80211_HT_CAP_SGI_20) ? 1 : 0;
473 short_GI_40 = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & IEEE80211_HT_CAP_SGI_40) ? 1 : 0;
474
475 max_rate = rtw_mcs_rate(
476 RF_1T1R,
477 bw_40MHz & pregistrypriv->cbw40_enable,
478 short_GI_20,
479 short_GI_40,
480 pmlmeinfo->HT_caps.mcs.rx_mask
481 );
482 }
483 } else {
484 while (pcur_bss->SupportedRates[i] != 0 &&
485 pcur_bss->SupportedRates[i] != 0xFF) {
486 rate = pcur_bss->SupportedRates[i] & 0x7F;
487 if (rate > max_rate)
488 max_rate = rate;
489 i++;
490 }
491
492 max_rate *= 5;
493 }
494
495 return max_rate;
496}
497
498
499int rtw_set_country(struct adapter *adapter, const char *country_code)
500{
501 int i;
502 int channel_plan = RT_CHANNEL_DOMAIN_WORLD_WIDE_5G;
503
504 for (i = 0; i < ARRAY_SIZE(channel_table); i++) {
505 if (strcmp(channel_table[i].name, country_code) == 0) {
506 channel_plan = channel_table[i].channel_plan;
507 break;
508 }
509 }
510
511 return rtw_set_chplan_cmd(adapter, channel_plan, 1);
512}
513