Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[deliverable/linux.git] / drivers / staging / rtl8723au / os_dep / ioctl_cfg80211.c
CommitLineData
b1925ad8
LF
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 _IOCTL_CFG80211_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
b1925ad8
LF
19#include <xmit_osdep.h>
20
21#include "ioctl_cfg80211.h"
b1925ad8
LF
22
23#define RTW_MAX_MGMT_TX_CNT 8
24
25#define RTW_MAX_REMAIN_ON_CHANNEL_DURATION 65535 /* ms */
26#define RTW_MAX_NUM_PMKIDS 4
27
b1925ad8
LF
28static const u32 rtw_cipher_suites[] = {
29 WLAN_CIPHER_SUITE_WEP40,
30 WLAN_CIPHER_SUITE_WEP104,
31 WLAN_CIPHER_SUITE_TKIP,
32 WLAN_CIPHER_SUITE_CCMP,
33};
34
35#define RATETAB_ENT(_rate, _rateid, _flags) { \
36 .bitrate = (_rate), \
37 .hw_value = (_rateid), \
38 .flags = (_flags), \
39}
40
41#define CHAN2G(_channel, _freq, _flags) { \
42 .band = IEEE80211_BAND_2GHZ, \
43 .center_freq = (_freq), \
44 .hw_value = (_channel), \
45 .flags = (_flags), \
46 .max_antenna_gain = 0, \
47 .max_power = 30, \
48}
49
50#define CHAN5G(_channel, _flags) { \
51 .band = IEEE80211_BAND_5GHZ, \
52 .center_freq = 5000 + (5 * (_channel)), \
53 .hw_value = (_channel), \
54 .flags = (_flags), \
55 .max_antenna_gain = 0, \
56 .max_power = 30, \
57}
58
59static struct ieee80211_rate rtw_rates[] = {
60 RATETAB_ENT(10, 0x1, 0),
61 RATETAB_ENT(20, 0x2, 0),
62 RATETAB_ENT(55, 0x4, 0),
63 RATETAB_ENT(110, 0x8, 0),
64 RATETAB_ENT(60, 0x10, 0),
65 RATETAB_ENT(90, 0x20, 0),
66 RATETAB_ENT(120, 0x40, 0),
67 RATETAB_ENT(180, 0x80, 0),
68 RATETAB_ENT(240, 0x100, 0),
69 RATETAB_ENT(360, 0x200, 0),
70 RATETAB_ENT(480, 0x400, 0),
71 RATETAB_ENT(540, 0x800, 0),
72};
73
74#define rtw_a_rates (rtw_rates + 4)
75#define RTW_A_RATES_NUM 8
76#define rtw_g_rates (rtw_rates + 0)
77#define RTW_G_RATES_NUM 12
78
79#define RTW_2G_CHANNELS_NUM 14
80#define RTW_5G_CHANNELS_NUM 37
81
82static struct ieee80211_channel rtw_2ghz_channels[] = {
83 CHAN2G(1, 2412, 0),
84 CHAN2G(2, 2417, 0),
85 CHAN2G(3, 2422, 0),
86 CHAN2G(4, 2427, 0),
87 CHAN2G(5, 2432, 0),
88 CHAN2G(6, 2437, 0),
89 CHAN2G(7, 2442, 0),
90 CHAN2G(8, 2447, 0),
91 CHAN2G(9, 2452, 0),
92 CHAN2G(10, 2457, 0),
93 CHAN2G(11, 2462, 0),
94 CHAN2G(12, 2467, 0),
95 CHAN2G(13, 2472, 0),
96 CHAN2G(14, 2484, 0),
97};
98
99static struct ieee80211_channel rtw_5ghz_a_channels[] = {
100 CHAN5G(34, 0), CHAN5G(36, 0),
101 CHAN5G(38, 0), CHAN5G(40, 0),
102 CHAN5G(42, 0), CHAN5G(44, 0),
103 CHAN5G(46, 0), CHAN5G(48, 0),
104 CHAN5G(52, 0), CHAN5G(56, 0),
105 CHAN5G(60, 0), CHAN5G(64, 0),
106 CHAN5G(100, 0), CHAN5G(104, 0),
107 CHAN5G(108, 0), CHAN5G(112, 0),
108 CHAN5G(116, 0), CHAN5G(120, 0),
109 CHAN5G(124, 0), CHAN5G(128, 0),
110 CHAN5G(132, 0), CHAN5G(136, 0),
111 CHAN5G(140, 0), CHAN5G(149, 0),
112 CHAN5G(153, 0), CHAN5G(157, 0),
113 CHAN5G(161, 0), CHAN5G(165, 0),
114 CHAN5G(184, 0), CHAN5G(188, 0),
115 CHAN5G(192, 0), CHAN5G(196, 0),
116 CHAN5G(200, 0), CHAN5G(204, 0),
117 CHAN5G(208, 0), CHAN5G(212, 0),
118 CHAN5G(216, 0),
119};
120
121static void rtw_2g_channels_init(struct ieee80211_channel *channels)
122{
123 memcpy((void *)channels, (void *)rtw_2ghz_channels,
124 sizeof(struct ieee80211_channel) * RTW_2G_CHANNELS_NUM);
125}
126
127static void rtw_5g_channels_init(struct ieee80211_channel *channels)
128{
129 memcpy((void *)channels, (void *)rtw_5ghz_a_channels,
130 sizeof(struct ieee80211_channel) * RTW_5G_CHANNELS_NUM);
131}
132
133static void rtw_2g_rates_init(struct ieee80211_rate *rates)
134{
135 memcpy(rates, rtw_g_rates,
136 sizeof(struct ieee80211_rate) * RTW_G_RATES_NUM);
137}
138
139static void rtw_5g_rates_init(struct ieee80211_rate *rates)
140{
141 memcpy(rates, rtw_a_rates,
142 sizeof(struct ieee80211_rate) * RTW_A_RATES_NUM);
143}
144
145static struct ieee80211_supported_band *
146rtw_spt_band_alloc(enum ieee80211_band band)
147{
148 struct ieee80211_supported_band *spt_band = NULL;
149 int n_channels, n_bitrates;
150
151 if (band == IEEE80211_BAND_2GHZ) {
152 n_channels = RTW_2G_CHANNELS_NUM;
153 n_bitrates = RTW_G_RATES_NUM;
154 } else if (band == IEEE80211_BAND_5GHZ) {
155 n_channels = RTW_5G_CHANNELS_NUM;
156 n_bitrates = RTW_A_RATES_NUM;
157 } else {
158 goto exit;
159 }
160 spt_band = kzalloc(sizeof(struct ieee80211_supported_band) +
161 sizeof(struct ieee80211_channel) * n_channels +
162 sizeof(struct ieee80211_rate) * n_bitrates,
163 GFP_KERNEL);
164 if (!spt_band)
165 goto exit;
166
167 spt_band->channels =
168 (struct ieee80211_channel *)(((u8 *) spt_band) +
169 sizeof(struct
170 ieee80211_supported_band));
171 spt_band->bitrates =
172 (struct ieee80211_rate *)(((u8 *) spt_band->channels) +
173 sizeof(struct ieee80211_channel) *
174 n_channels);
175 spt_band->band = band;
176 spt_band->n_channels = n_channels;
177 spt_band->n_bitrates = n_bitrates;
178
179 if (band == IEEE80211_BAND_2GHZ) {
180 rtw_2g_channels_init(spt_band->channels);
181 rtw_2g_rates_init(spt_band->bitrates);
182 } else if (band == IEEE80211_BAND_5GHZ) {
183 rtw_5g_channels_init(spt_band->channels);
184 rtw_5g_rates_init(spt_band->bitrates);
185 }
186
187 /* spt_band.ht_cap */
188
189exit:
190 return spt_band;
191}
192
193static const struct ieee80211_txrx_stypes
194rtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
195 [NL80211_IFTYPE_ADHOC] = {
196 .tx = 0xffff,
197 .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
198 },
199 [NL80211_IFTYPE_STATION] = {
200 .tx = 0xffff,
201 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
202 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
203 },
204 [NL80211_IFTYPE_AP] = {
205 .tx = 0xffff,
206 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
207 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
208 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
209 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
210 BIT(IEEE80211_STYPE_AUTH >> 4) |
211 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
212 BIT(IEEE80211_STYPE_ACTION >> 4)
213 },
214 [NL80211_IFTYPE_AP_VLAN] = {
215 /* copy AP */
216 .tx = 0xffff,
217 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
218 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
219 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
220 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
221 BIT(IEEE80211_STYPE_AUTH >> 4) |
222 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
223 BIT(IEEE80211_STYPE_ACTION >> 4)
224 },
225 [NL80211_IFTYPE_P2P_CLIENT] = {
226 .tx = 0xffff,
227 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
228 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
229 },
230 [NL80211_IFTYPE_P2P_GO] = {
231 .tx = 0xffff,
232 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
233 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
234 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
235 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
236 BIT(IEEE80211_STYPE_AUTH >> 4) |
237 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
238 BIT(IEEE80211_STYPE_ACTION >> 4)
239 },
240};
241
b1925ad8
LF
242static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter,
243 struct wlan_network *pnetwork)
244{
245 int ret = 0;
246 struct ieee80211_channel *notify_channel;
247 struct cfg80211_bss *bss;
b1925ad8
LF
248 u16 channel;
249 u32 freq;
b1925ad8
LF
250 u8 *notify_ie;
251 size_t notify_ielen;
252 s32 notify_signal;
b1925ad8
LF
253 struct wireless_dev *wdev = padapter->rtw_wdev;
254 struct wiphy *wiphy = wdev->wiphy;
255 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
256
37cb982c 257 channel = pnetwork->network.DSConfig;
b1925ad8
LF
258 if (channel <= RTW_CH_MAX_2G_CHANNEL)
259 freq = ieee80211_channel_to_frequency(channel,
260 IEEE80211_BAND_2GHZ);
261 else
262 freq = ieee80211_channel_to_frequency(channel,
263 IEEE80211_BAND_5GHZ);
264
265 notify_channel = ieee80211_get_channel(wiphy, freq);
266
1de65ccb
JS
267 notify_ie = pnetwork->network.IEs;
268 notify_ielen = pnetwork->network.IELength;
b1925ad8
LF
269
270 /* We've set wiphy's signal_type as CFG80211_SIGNAL_TYPE_MBM:
271 * signal strength in mBm (100*dBm)
272 */
273 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
274 is_same_network23a(&pmlmepriv->cur_network.network,
275 &pnetwork->network)) {
276 notify_signal = 100 * translate_percentage_to_dbm(padapter->recvpriv.signal_strength); /* dbm */
277 } else {
278 notify_signal = 100 * translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength); /* dbm */
279 }
b1925ad8 280
4062f7aa 281 bss = cfg80211_inform_bss(wiphy, notify_channel,
993c52ba
JS
282 pnetwork->network.MacAddress,
283 pnetwork->network.tsf,
11a80e88 284 pnetwork->network.capability,
143ced27 285 pnetwork->network.beacon_interval,
4062f7aa
JS
286 notify_ie, notify_ielen,
287 notify_signal, GFP_ATOMIC);
b1925ad8
LF
288
289 if (unlikely(!bss)) {
290 DBG_8723A("rtw_cfg80211_inform_bss error\n");
291 return -EINVAL;
292 }
293
294 cfg80211_put_bss(wiphy, bss);
295
b1925ad8
LF
296 return ret;
297}
298
299void rtw_cfg80211_indicate_connect(struct rtw_adapter *padapter)
300{
301 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
302 struct wlan_network *cur_network = &pmlmepriv->cur_network;
303 struct wireless_dev *pwdev = padapter->rtw_wdev;
b1925ad8
LF
304
305 DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
306
307 if (pwdev->iftype != NL80211_IFTYPE_STATION &&
308 pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
309 return;
310
311 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
312 return;
313
56828797 314 if (padapter->mlmepriv.to_roaming > 0) {
b1925ad8
LF
315 struct wiphy *wiphy = pwdev->wiphy;
316 struct ieee80211_channel *notify_channel;
317 u32 freq;
37cb982c 318 u16 channel = cur_network->network.DSConfig;
b1925ad8
LF
319
320 if (channel <= RTW_CH_MAX_2G_CHANNEL)
321 freq =
322 ieee80211_channel_to_frequency(channel,
323 IEEE80211_BAND_2GHZ);
324 else
325 freq =
326 ieee80211_channel_to_frequency(channel,
327 IEEE80211_BAND_5GHZ);
328
329 notify_channel = ieee80211_get_channel(wiphy, freq);
330
331 DBG_8723A("%s call cfg80211_roamed\n", __func__);
332 cfg80211_roamed(padapter->pnetdev, notify_channel,
333 cur_network->network.MacAddress,
334 pmlmepriv->assoc_req +
335 sizeof(struct ieee80211_hdr_3addr) + 2,
336 pmlmepriv->assoc_req_len -
337 sizeof(struct ieee80211_hdr_3addr) - 2,
338 pmlmepriv->assoc_rsp +
339 sizeof(struct ieee80211_hdr_3addr) + 6,
340 pmlmepriv->assoc_rsp_len -
341 sizeof(struct ieee80211_hdr_3addr) - 6,
342 GFP_ATOMIC);
343 } else {
344 cfg80211_connect_result(padapter->pnetdev,
345 cur_network->network.MacAddress,
346 pmlmepriv->assoc_req +
347 sizeof(struct ieee80211_hdr_3addr) + 2,
348 pmlmepriv->assoc_req_len -
349 sizeof(struct ieee80211_hdr_3addr) - 2,
350 pmlmepriv->assoc_rsp +
351 sizeof(struct ieee80211_hdr_3addr) + 6,
352 pmlmepriv->assoc_rsp_len -
353 sizeof(struct ieee80211_hdr_3addr) - 6,
354 WLAN_STATUS_SUCCESS, GFP_ATOMIC);
355 }
356}
357
358void rtw_cfg80211_indicate_disconnect(struct rtw_adapter *padapter)
359{
360 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
361 struct wireless_dev *pwdev = padapter->rtw_wdev;
b1925ad8
LF
362
363 DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
364
365 if (pwdev->iftype != NL80211_IFTYPE_STATION &&
366 pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
367 return;
368
369 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
370 return;
371
b1925ad8
LF
372 if (!padapter->mlmepriv.not_indic_disco) {
373 if (check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING)) {
374 cfg80211_connect_result(padapter->pnetdev, NULL, NULL,
375 0, NULL, 0,
376 WLAN_STATUS_UNSPECIFIED_FAILURE,
377 GFP_ATOMIC);
378 } else {
379 cfg80211_disconnected(padapter->pnetdev, 0, NULL,
380 0, GFP_ATOMIC);
381 }
382 }
383}
384
385#ifdef CONFIG_8723AU_AP_MODE
16b9632d 386static int set_pairwise_key(struct rtw_adapter *padapter, struct sta_info *psta)
b1925ad8
LF
387{
388 struct cmd_obj *ph2c;
389 struct set_stakey_parm *psetstakey_para;
390 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
16b9632d 391 int res = _SUCCESS;
b1925ad8
LF
392
393 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
394 if (ph2c == NULL) {
395 res = _FAIL;
396 goto exit;
397 }
398
399 psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
400 if (psetstakey_para == NULL) {
401 kfree(ph2c);
402 res = _FAIL;
403 goto exit;
404 }
405
406 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
407
7989bcf3 408 psetstakey_para->algorithm = psta->dot118021XPrivacy;
b1925ad8 409
888df442 410 ether_addr_copy(psetstakey_para->addr, psta->hwaddr);
b1925ad8
LF
411
412 memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
413
414 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
415
416exit:
417 return res;
418}
419
2dcf6b4c
JS
420static int set_group_key(struct rtw_adapter *padapter, struct key_params *parms,
421 u32 alg, u8 keyid)
b1925ad8 422{
b1925ad8
LF
423 struct cmd_obj *pcmd;
424 struct setkey_parm *psetkeyparm;
425 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
426 int res = _SUCCESS;
427
428 DBG_8723A("%s\n", __func__);
429
4e489d91
JS
430 if (keyid >= 4) {
431 res = _FAIL;
432 goto exit;
433 }
434
b1925ad8
LF
435 pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
436 if (!pcmd) {
437 res = _FAIL;
438 goto exit;
439 }
440 psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
441 if (!psetkeyparm) {
442 kfree(pcmd);
443 res = _FAIL;
444 goto exit;
445 }
446
4e489d91 447 psetkeyparm->keyid = keyid;
b1925ad8 448 if (is_wep_enc(alg))
4e489d91 449 padapter->mlmepriv.key_mask |= BIT(psetkeyparm->keyid);
b1925ad8
LF
450
451 psetkeyparm->algorithm = alg;
452
453 psetkeyparm->set_tx = 1;
454
2dcf6b4c 455 memcpy(&psetkeyparm->key, parms->key, parms->key_len);
b1925ad8
LF
456
457 pcmd->cmdcode = _SetKey_CMD_;
458 pcmd->parmbuf = (u8 *) psetkeyparm;
459 pcmd->cmdsz = (sizeof(struct setkey_parm));
460 pcmd->rsp = NULL;
461 pcmd->rspsz = 0;
462
b1925ad8
LF
463 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
464
465exit:
466 return res;
467}
468
f7ce87cd 469static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, u8 key_index,
f88ab54c 470 int set_tx, const u8 *sta_addr,
5dab9e7d 471 struct key_params *keyparms)
b1925ad8
LF
472{
473 int ret = 0;
c36e122f 474 int key_len;
b1925ad8
LF
475 struct sta_info *psta = NULL, *pbcmc_sta = NULL;
476 struct rtw_adapter *padapter = netdev_priv(dev);
b1925ad8
LF
477 struct security_priv *psecuritypriv = &padapter->securitypriv;
478 struct sta_priv *pstapriv = &padapter->stapriv;
479
480 DBG_8723A("%s\n", __func__);
481
7ef2743d 482 if (!is_broadcast_ether_addr(sta_addr)) {
f88ab54c 483 psta = rtw_get_stainfo23a(pstapriv, sta_addr);
b1925ad8
LF
484 if (!psta) {
485 /* ret = -EINVAL; */
486 DBG_8723A("rtw_set_encryption(), sta has already "
487 "been removed or never been added\n");
488 goto exit;
489 }
490 }
491
c36e122f
JS
492 key_len = keyparms->key_len;
493
5dab9e7d
JS
494 if (!psta && (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
495 keyparms->cipher == WLAN_CIPHER_SUITE_WEP104)) {
b1925ad8
LF
496 DBG_8723A("r871x_set_encryption, crypt.alg = WEP\n");
497
b1925ad8 498 DBG_8723A("r871x_set_encryption, wep_key_idx =%d, len =%d\n",
f7ce87cd 499 key_index, key_len);
b1925ad8 500
b1925ad8
LF
501 if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
502 /* wep default key has not been set, so use
503 this key index as default key. */
504
505 psecuritypriv->ndisencryptstatus =
506 Ndis802_11Encryption1Enabled;
55db5d02
JS
507 psecuritypriv->dot11PrivacyAlgrthm = keyparms->cipher;
508 psecuritypriv->dot118021XGrpPrivacy = keyparms->cipher;
b1925ad8 509
f7ce87cd 510 psecuritypriv->dot11PrivacyKeyIndex = key_index;
b1925ad8
LF
511 }
512
f7ce87cd 513 memcpy(&psecuritypriv->wep_key[key_index].key,
c36e122f 514 keyparms->key, key_len);
b1925ad8 515
f7ce87cd 516 psecuritypriv->wep_key[key_index].keylen = key_len;
b1925ad8 517
2dcf6b4c 518 set_group_key(padapter, keyparms, keyparms->cipher, key_index);
b1925ad8
LF
519
520 goto exit;
b1925ad8
LF
521 }
522
4e297c21 523 if (!psta) { /* group key */
0996cf9c 524 if (set_tx == 0) { /* group key */
5dab9e7d
JS
525 if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
526 keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) {
9cd613c7 527 DBG_8723A("%s, set group_key, WEP\n", __func__);
b1925ad8
LF
528
529 memcpy(psecuritypriv->
f7ce87cd 530 dot118021XGrpKey[key_index].skey,
7ef2743d 531 keyparms->key, key_len);
b1925ad8 532
55db5d02
JS
533 psecuritypriv->dot118021XGrpPrivacy =
534 keyparms->cipher;
5dab9e7d 535 } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) {
b1925ad8
LF
536 DBG_8723A("%s, set group_key, TKIP\n",
537 __func__);
538
4e297c21
JS
539 psecuritypriv->dot118021XGrpPrivacy =
540 WLAN_CIPHER_SUITE_TKIP;
b1925ad8
LF
541
542 memcpy(psecuritypriv->
f7ce87cd 543 dot118021XGrpKey[key_index].skey,
fd381874 544 keyparms->key,
c36e122f 545 (key_len > 16 ? 16 : key_len));
b1925ad8 546
b1925ad8
LF
547 /* set mic key */
548 memcpy(psecuritypriv->
f7ce87cd 549 dot118021XGrptxmickey[key_index].skey,
fd381874 550 &keyparms->key[16], 8);
b1925ad8 551 memcpy(psecuritypriv->
f7ce87cd 552 dot118021XGrprxmickey[key_index].skey,
fd381874 553 &keyparms->key[24], 8);
b1925ad8 554
9216c517 555 psecuritypriv->busetkipkey = 1;
b1925ad8 556
5dab9e7d
JS
557 } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) {
558 DBG_8723A("%s, set group_key, CCMP\n",
b1925ad8
LF
559 __func__);
560
4e297c21
JS
561 psecuritypriv->dot118021XGrpPrivacy =
562 WLAN_CIPHER_SUITE_CCMP;
b1925ad8
LF
563
564 memcpy(psecuritypriv->
fd381874
JS
565 dot118021XGrpKey[key_index].skey,
566 keyparms->key,
c36e122f 567 (key_len > 16 ? 16 : key_len));
b1925ad8
LF
568 } else {
569 DBG_8723A("%s, set group_key, none\n",
570 __func__);
571
7ef2743d 572 psecuritypriv->dot118021XGrpPrivacy = 0;
b1925ad8
LF
573 }
574
f7ce87cd 575 psecuritypriv->dot118021XGrpKeyid = key_index;
b1925ad8 576
9216c517 577 psecuritypriv->binstallGrpkey = 1;
b1925ad8
LF
578
579 psecuritypriv->dot11PrivacyAlgrthm =
580 psecuritypriv->dot118021XGrpPrivacy;
581
2dcf6b4c 582 set_group_key(padapter, keyparms,
b1925ad8 583 psecuritypriv->dot118021XGrpPrivacy,
f7ce87cd 584 key_index);
b1925ad8
LF
585
586 pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
587 if (pbcmc_sta) {
588 pbcmc_sta->ieee8021x_blocked = false;
589 /* rx will use bmc_sta's dot118021XPrivacy */
590 pbcmc_sta->dot118021XPrivacy =
591 psecuritypriv->dot118021XGrpPrivacy;
592
593 }
594
595 }
596
597 goto exit;
598 }
599
4e297c21
JS
600 if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) {
601 /* psk/802_1x */
0996cf9c 602 if (set_tx == 1) {
4e297c21
JS
603 /* pairwise key */
604 memcpy(psta->dot118021x_UncstKey.skey,
fd381874 605 keyparms->key, (key_len > 16 ? 16 : key_len));
b1925ad8 606
4e297c21
JS
607 if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
608 keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) {
609 DBG_8723A("%s, set pairwise key, WEP\n",
610 __func__);
b1925ad8 611
55db5d02
JS
612 psecuritypriv->dot118021XGrpPrivacy =
613 keyparms->cipher;
4e297c21
JS
614 } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) {
615 DBG_8723A("%s, set pairwise key, TKIP\n",
616 __func__);
b1925ad8 617
4e297c21
JS
618 psta->dot118021XPrivacy =
619 WLAN_CIPHER_SUITE_TKIP;
b1925ad8 620
4e297c21
JS
621 /* set mic key */
622 memcpy(psta->dot11tkiptxmickey.skey,
fd381874 623 &keyparms->key[16], 8);
4e297c21 624 memcpy(psta->dot11tkiprxmickey.skey,
fd381874 625 &keyparms->key[24], 8);
b1925ad8 626
4e297c21 627 psecuritypriv->busetkipkey = 1;
b1925ad8 628
4e297c21
JS
629 } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) {
630 DBG_8723A("%s, set pairwise key, CCMP\n",
631 __func__);
b1925ad8 632
4e297c21
JS
633 psta->dot118021XPrivacy =
634 WLAN_CIPHER_SUITE_CCMP;
635 } else {
636 DBG_8723A("%s, set pairwise key, none\n",
637 __func__);
b1925ad8 638
4e297c21
JS
639 psta->dot118021XPrivacy = 0;
640 }
b1925ad8 641
4e297c21 642 set_pairwise_key(padapter, psta);
b1925ad8 643
4e297c21 644 psta->ieee8021x_blocked = false;
b1925ad8 645
4e297c21
JS
646 psta->bpairwise_key_installed = true;
647 } else { /* group key??? */
648 if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
649 keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) {
650 memcpy(psecuritypriv->
f7ce87cd 651 dot118021XGrpKey[key_index].skey,
7ef2743d 652 keyparms->key, key_len);
4e297c21
JS
653
654 psecuritypriv->dot118021XGrpPrivacy =
55db5d02 655 keyparms->cipher;
4e297c21
JS
656 } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) {
657 psecuritypriv->dot118021XGrpPrivacy =
658 WLAN_CIPHER_SUITE_TKIP;
b1925ad8 659
4e297c21 660 memcpy(psecuritypriv->
f7ce87cd 661 dot118021XGrpKey[key_index].skey,
fd381874 662 keyparms->key,
c36e122f 663 (key_len > 16 ? 16 : key_len));
b1925ad8 664
4e297c21
JS
665 /* set mic key */
666 memcpy(psecuritypriv->
f7ce87cd 667 dot118021XGrptxmickey[key_index].skey,
fd381874 668 &keyparms->key[16], 8);
4e297c21 669 memcpy(psecuritypriv->
f7ce87cd 670 dot118021XGrprxmickey[key_index].skey,
fd381874 671 &keyparms->key[24], 8);
b1925ad8 672
4e297c21 673 psecuritypriv->busetkipkey = 1;
4e297c21
JS
674 } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) {
675 psecuritypriv->dot118021XGrpPrivacy =
676 WLAN_CIPHER_SUITE_CCMP;
677
678 memcpy(psecuritypriv->
f7ce87cd 679 dot118021XGrpKey[key_index].skey,
fd381874 680 keyparms->key,
c36e122f 681 (key_len > 16 ? 16 : key_len));
4e297c21
JS
682 } else {
683 psecuritypriv->dot118021XGrpPrivacy = 0;
684 }
685
f7ce87cd 686 psecuritypriv->dot118021XGrpKeyid = key_index;
4e297c21
JS
687
688 psecuritypriv->binstallGrpkey = 1;
689
690 psecuritypriv->dot11PrivacyAlgrthm =
691 psecuritypriv->dot118021XGrpPrivacy;
692
2dcf6b4c 693 set_group_key(padapter, keyparms,
4e297c21 694 psecuritypriv->dot118021XGrpPrivacy,
f7ce87cd 695 key_index);
4e297c21
JS
696
697 pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
698 if (pbcmc_sta) {
699 /* rx will use bmc_sta's
700 dot118021XPrivacy */
701 pbcmc_sta->ieee8021x_blocked = false;
702 pbcmc_sta->dot118021XPrivacy =
703 psecuritypriv->dot118021XGrpPrivacy;
b1925ad8
LF
704 }
705 }
706 }
707
708exit:
709
710 return ret;
b1925ad8
LF
711}
712#endif
713
5292a891 714static int rtw_cfg80211_set_encryption(struct net_device *dev, u8 key_index,
f88ab54c 715 int set_tx, const u8 *sta_addr,
a9e346fb 716 struct key_params *keyparms)
b1925ad8
LF
717{
718 int ret = 0;
d0dc2666 719 int key_len;
b1925ad8
LF
720 struct rtw_adapter *padapter = netdev_priv(dev);
721 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
722 struct security_priv *psecuritypriv = &padapter->securitypriv;
b1925ad8
LF
723
724 DBG_8723A("%s\n", __func__);
725
d0dc2666
JS
726 key_len = keyparms->key_len;
727
8188b1cb
JS
728 if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
729 keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) {
b1925ad8
LF
730 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
731 ("wpa_set_encryption, crypt.alg = WEP\n"));
732 DBG_8723A("wpa_set_encryption, crypt.alg = WEP\n");
733
b1925ad8
LF
734 if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
735 /* wep default key has not been set, so use this
736 key index as default key. */
737
b1925ad8
LF
738 psecuritypriv->ndisencryptstatus =
739 Ndis802_11Encryption1Enabled;
7ef2743d
JS
740 psecuritypriv->dot11PrivacyAlgrthm = keyparms->cipher;
741 psecuritypriv->dot118021XGrpPrivacy = keyparms->cipher;
b1925ad8 742
5292a891 743 psecuritypriv->dot11PrivacyKeyIndex = key_index;
b1925ad8
LF
744 }
745
5292a891 746 memcpy(&psecuritypriv->wep_key[key_index].key,
e1343f90 747 keyparms->key, key_len);
b1925ad8 748
5292a891 749 psecuritypriv->wep_key[key_index].keylen = key_len;
b1925ad8 750
5292a891 751 rtw_set_key23a(padapter, psecuritypriv, key_index, 0);
b1925ad8
LF
752
753 goto exit;
754 }
755
756 if (padapter->securitypriv.dot11AuthAlgrthm ==
757 dot11AuthAlgrthm_8021X) { /* 802_1x */
758 struct sta_info *psta, *pbcmc_sta;
759 struct sta_priv *pstapriv = &padapter->stapriv;
760
761 if (check_fwstate(pmlmepriv,
762 WIFI_STATION_STATE | WIFI_MP_STATE)) {
763 /* sta mode */
764 psta = rtw_get_stainfo23a(pstapriv, get_bssid(pmlmepriv));
765 if (psta == NULL) {
766 DBG_8723A("%s, : Obtain Sta_info fail\n",
767 __func__);
768 } else {
769 /* Jeff: don't disable ieee8021x_blocked
770 while clearing key */
efd4216c
JS
771 if (keyparms->cipher != IW_AUTH_CIPHER_NONE &&
772 keyparms->cipher != 0)
b1925ad8
LF
773 psta->ieee8021x_blocked = false;
774
775 if ((padapter->securitypriv.ndisencryptstatus ==
776 Ndis802_11Encryption2Enabled) ||
777 (padapter->securitypriv.ndisencryptstatus ==
778 Ndis802_11Encryption3Enabled)) {
779 psta->dot118021XPrivacy =
780 padapter->securitypriv.
781 dot11PrivacyAlgrthm;
782 }
783
0996cf9c 784 if (set_tx == 1) {
b1925ad8 785 /* pairwise key */
0996cf9c
JS
786 DBG_8723A("%s, : set_tx == 1\n",
787 __func__);
b1925ad8
LF
788
789 memcpy(psta->dot118021x_UncstKey.skey,
e1343f90 790 keyparms->key,
d0dc2666 791 (key_len > 16 ? 16 : key_len));
b1925ad8 792
8188b1cb
JS
793 if (keyparms->cipher ==
794 WLAN_CIPHER_SUITE_TKIP) {
b1925ad8
LF
795 memcpy(psta->dot11tkiptxmickey.
796 skey,
e1343f90 797 &keyparms->key[16], 8);
b1925ad8
LF
798 memcpy(psta->dot11tkiprxmickey.
799 skey,
e1343f90 800 &keyparms->key[24], 8);
b1925ad8
LF
801
802 padapter->securitypriv.
9216c517 803 busetkipkey = 0;
b1925ad8
LF
804 }
805 DBG_8723A(" ~~~~set sta key:unicastkey\n");
806
807 rtw_setstakey_cmd23a(padapter,
808 (unsigned char *)psta,
809 true);
810 } else { /* group key */
811 memcpy(padapter->securitypriv.
5292a891 812 dot118021XGrpKey[key_index].skey,
e1343f90 813 keyparms->key,
d0dc2666 814 (key_len > 16 ? 16 : key_len));
b1925ad8 815 memcpy(padapter->securitypriv.
5292a891 816 dot118021XGrptxmickey[key_index].
e1343f90 817 skey, &keyparms->key[16], 8);
b1925ad8 818 memcpy(padapter->securitypriv.
5292a891 819 dot118021XGrprxmickey[key_index].
e1343f90 820 skey, &keyparms->key[24], 8);
b1925ad8 821 padapter->securitypriv.binstallGrpkey =
9216c517 822 1;
b1925ad8
LF
823 DBG_8723A
824 (" ~~~~set sta key:groupkey\n");
825
826 padapter->securitypriv.
5292a891 827 dot118021XGrpKeyid = key_index;
b1925ad8
LF
828
829 rtw_set_key23a(padapter,
830 &padapter->securitypriv,
5292a891 831 key_index, 1);
b1925ad8
LF
832 }
833 }
834
835 pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
836 if (pbcmc_sta) {
837 /* Jeff: don't disable ieee8021x_blocked
838 while clearing key */
efd4216c
JS
839 if (keyparms->cipher != IW_AUTH_CIPHER_NONE &&
840 keyparms->cipher != 0)
b1925ad8
LF
841 pbcmc_sta->ieee8021x_blocked = false;
842
843 if ((padapter->securitypriv.ndisencryptstatus ==
844 Ndis802_11Encryption2Enabled) ||
845 (padapter->securitypriv.ndisencryptstatus ==
846 Ndis802_11Encryption3Enabled)) {
847 pbcmc_sta->dot118021XPrivacy =
848 padapter->securitypriv.
849 dot11PrivacyAlgrthm;
850 }
851 }
852 } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { /* adhoc mode */
853 }
854 }
855
856exit:
857
858 DBG_8723A("%s, ret =%d\n", __func__, ret);
859
860
861
862 return ret;
863}
864
865static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev,
866 u8 key_index, bool pairwise,
867 const u8 *mac_addr, struct key_params *params)
868{
0996cf9c 869 int set_tx, ret = 0;
b1925ad8
LF
870 struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
871 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
872 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
f88ab54c 873 u8 sta_addr[ETH_ALEN];
b1925ad8 874
a790d58e 875 DBG_8723A("%s(%s): adding key for %pM\n", __func__, ndev->name,
b1925ad8
LF
876 mac_addr);
877 DBG_8723A("cipher = 0x%x\n", params->cipher);
878 DBG_8723A("key_len = 0x%x\n", params->key_len);
879 DBG_8723A("seq_len = 0x%x\n", params->seq_len);
880 DBG_8723A("key_index =%d\n", key_index);
881 DBG_8723A("pairwise =%d\n", pairwise);
882
b1925ad8
LF
883 switch (params->cipher) {
884 case IW_AUTH_CIPHER_NONE:
b1925ad8 885 case WLAN_CIPHER_SUITE_WEP40:
7ef2743d
JS
886 if (params->key_len != WLAN_KEY_LEN_WEP40) {
887 ret = -EINVAL;
888 goto exit;
889 }
b1925ad8 890 case WLAN_CIPHER_SUITE_WEP104:
7ef2743d
JS
891 if (params->key_len != WLAN_KEY_LEN_WEP104) {
892 ret = -EINVAL;
893 goto exit;
894 }
b1925ad8 895 case WLAN_CIPHER_SUITE_TKIP:
b1925ad8 896 case WLAN_CIPHER_SUITE_CCMP:
b1925ad8 897 break;
b1925ad8
LF
898 default:
899 ret = -ENOTSUPP;
efd4216c 900 goto exit;
b1925ad8
LF
901 }
902
7ef2743d
JS
903 if (key_index >= WEP_KEYS || params->key_len < 0) {
904 ret = -EINVAL;
905 goto exit;
906 }
907
f88ab54c 908 eth_broadcast_addr(sta_addr);
b1925ad8 909
0996cf9c
JS
910 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
911 set_tx = 0; /* for wpa/wpa2 group key */
912 else
913 set_tx = 1; /* for wpa/wpa2 pairwise key */
b1925ad8 914
b1925ad8 915 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
0996cf9c 916 ret = rtw_cfg80211_set_encryption(ndev, key_index, set_tx,
f0bf8dd5 917 sta_addr, params);
b1925ad8
LF
918 } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
919#ifdef CONFIG_8723AU_AP_MODE
920 if (mac_addr)
f88ab54c 921 ether_addr_copy(sta_addr, mac_addr);
b1925ad8 922
0996cf9c 923 ret = rtw_cfg80211_ap_set_encryption(ndev, key_index, set_tx,
f0bf8dd5 924 sta_addr, params);
b1925ad8
LF
925#endif
926 } else {
927 DBG_8723A("error! fw_state = 0x%x, iftype =%d\n",
928 pmlmepriv->fw_state, rtw_wdev->iftype);
929
930 }
931
efd4216c 932exit:
b1925ad8
LF
933 return ret;
934}
935
936static int
937cfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev,
938 u8 key_index, bool pairwise, const u8 *mac_addr,
939 void *cookie,
940 void (*callback) (void *cookie, struct key_params *))
941{
a790d58e 942 DBG_8723A("%s(%s)\n", __func__, ndev->name);
b1925ad8
LF
943 return 0;
944}
945
946static int cfg80211_rtw_del_key(struct wiphy *wiphy, struct net_device *ndev,
947 u8 key_index, bool pairwise,
948 const u8 *mac_addr)
949{
950 struct rtw_adapter *padapter = netdev_priv(ndev);
951 struct security_priv *psecuritypriv = &padapter->securitypriv;
952
a790d58e 953 DBG_8723A("%s(%s): key_index =%d\n", __func__, ndev->name, key_index);
b1925ad8
LF
954
955 if (key_index == psecuritypriv->dot11PrivacyKeyIndex) {
956 /* clear the flag of wep default key set. */
957 psecuritypriv->bWepDefaultKeyIdxSet = 0;
958 }
959
960 return 0;
961}
962
963static int cfg80211_rtw_set_default_key(struct wiphy *wiphy,
964 struct net_device *ndev, u8 key_index,
965 bool unicast, bool multicast)
966{
967 struct rtw_adapter *padapter = netdev_priv(ndev);
968 struct security_priv *psecuritypriv = &padapter->securitypriv;
969
a790d58e
JS
970 DBG_8723A("%s(%s): key_index =%d, unicast =%d, multicast =%d.\n",
971 __func__, ndev->name, key_index, unicast, multicast);
b1925ad8 972
e0827909
JS
973 if (key_index < NUM_WEP_KEYS &&
974 (psecuritypriv->dot11PrivacyAlgrthm == WLAN_CIPHER_SUITE_WEP40 ||
975 psecuritypriv->dot11PrivacyAlgrthm == WLAN_CIPHER_SUITE_WEP104)) {
b1925ad8
LF
976 /* set wep default key */
977 psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
978
979 psecuritypriv->dot11PrivacyKeyIndex = key_index;
980
9e3d6df2
JS
981 psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
982 psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40;
e0827909
JS
983 if (psecuritypriv->wep_key[key_index].keylen == 13) {
984 psecuritypriv->dot11PrivacyAlgrthm =
985 WLAN_CIPHER_SUITE_WEP104;
986 psecuritypriv->dot118021XGrpPrivacy =
987 WLAN_CIPHER_SUITE_WEP104;
b1925ad8
LF
988 }
989
990 /* set the flag to represent that wep default key
991 has been set */
992 psecuritypriv->bWepDefaultKeyIdxSet = 1;
993 }
994
995 return 0;
996}
997
27fd731e
JS
998static u16 rtw_get_cur_max_rate(struct rtw_adapter *adapter)
999{
1000 int i = 0;
1001 const u8 *p;
1002 u16 rate = 0, max_rate = 0;
1003 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
1004 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1005 struct registry_priv *pregistrypriv = &adapter->registrypriv;
1006 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1007 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1008 struct ieee80211_ht_cap *pht_capie;
1009 u8 rf_type = 0;
1010 u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0;
1011 u16 mcs_rate = 0;
1012
1d33b076 1013 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
1de65ccb 1014 pcur_bss->IEs, pcur_bss->IELength);
27fd731e
JS
1015 if (p && p[1] > 0) {
1016 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1017
1018 memcpy(&mcs_rate, &pht_capie->mcs, 2);
1019
1020 /* bw_40MHz = (pht_capie->cap_info&
1021 IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1:0; */
1022 /* cur_bwmod is updated by beacon, pmlmeinfo is
1023 updated by association response */
1024 bw_40MHz = (pmlmeext->cur_bwmode &&
1025 (pmlmeinfo->HT_info.ht_param &
1026 IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) ? 1:0;
1027
1028 /* short_GI = (pht_capie->cap_info & (IEEE80211_HT_CAP
1029 _SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; */
1030 short_GI_20 = (pmlmeinfo->ht_cap.cap_info &
1031 cpu_to_le16(IEEE80211_HT_CAP_SGI_20)) ? 1:0;
1032 short_GI_40 = (pmlmeinfo->ht_cap.cap_info &
1033 cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) ? 1:0;
1034
1035 rf_type = rtl8723a_get_rf_type(adapter);
1036 max_rate = rtw_mcs_rate23a(rf_type, bw_40MHz &
1037 pregistrypriv->cbw40_enable,
1038 short_GI_20, short_GI_40,
1039 &pmlmeinfo->ht_cap.mcs);
1040 } else {
1041 while (pcur_bss->SupportedRates[i] != 0 &&
1042 pcur_bss->SupportedRates[i] != 0xFF) {
1043 rate = pcur_bss->SupportedRates[i] & 0x7F;
1044 if (rate>max_rate)
1045 max_rate = rate;
1046 i++;
1047 }
1048
1049 max_rate = max_rate * 10 / 2;
1050 }
1051
1052 return max_rate;
1053}
1054
b1925ad8
LF
1055static int cfg80211_rtw_get_station(struct wiphy *wiphy,
1056 struct net_device *ndev,
f9da455b 1057 const u8 *mac, struct station_info *sinfo)
b1925ad8
LF
1058{
1059 int ret = 0;
1060 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1061 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1062 struct sta_info *psta = NULL;
1063 struct sta_priv *pstapriv = &padapter->stapriv;
1064
1065 sinfo->filled = 0;
1066
1067 if (!mac) {
a790d58e 1068 DBG_8723A("%s(%s): mac ==%p\n", __func__, ndev->name, mac);
b1925ad8
LF
1069 ret = -ENOENT;
1070 goto exit;
1071 }
1072
1073 psta = rtw_get_stainfo23a(pstapriv, mac);
1074 if (psta == NULL) {
1075 DBG_8723A("%s, sta_info is null\n", __func__);
1076 ret = -ENOENT;
1077 goto exit;
1078 }
a790d58e 1079 DBG_8723A("%s(%s): mac =" MAC_FMT "\n", __func__, ndev->name,
b1925ad8 1080 MAC_ARG(mac));
b1925ad8
LF
1081
1082 /* for infra./P2PClient mode */
1083 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
1084 check_fwstate(pmlmepriv, _FW_LINKED)) {
1085 struct wlan_network *cur_network = &pmlmepriv->cur_network;
1086
cc2db7cb 1087 if (!ether_addr_equal(mac, cur_network->network.MacAddress)) {
b1925ad8
LF
1088 DBG_8723A("%s, mismatch bssid =" MAC_FMT "\n", __func__,
1089 MAC_ARG(cur_network->network.MacAddress));
1090 ret = -ENOENT;
1091 goto exit;
1092 }
1093
1094 sinfo->filled |= STATION_INFO_SIGNAL;
1095 sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv.
1096 signal_strength);
1097
1098 sinfo->filled |= STATION_INFO_TX_BITRATE;
27fd731e 1099 sinfo->txrate.legacy = rtw_get_cur_max_rate(padapter);
b1925ad8
LF
1100
1101 sinfo->filled |= STATION_INFO_RX_PACKETS;
1102 sinfo->rx_packets = sta_rx_data_pkts(psta);
1103
1104 sinfo->filled |= STATION_INFO_TX_PACKETS;
1105 sinfo->tx_packets = psta->sta_stats.tx_pkts;
1106 }
1107
1108 /* for Ad-Hoc/AP mode */
1109 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
1110 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1111 check_fwstate(pmlmepriv, WIFI_AP_STATE)) &&
1112 check_fwstate(pmlmepriv, _FW_LINKED)
1113 ) {
1114 /* TODO: should acquire station info... */
1115 }
1116
1117exit:
1118 return ret;
1119}
1120
efc7144f
JS
1121int cfg80211_infrastructure_mode(struct rtw_adapter* padapter,
1122 enum nl80211_iftype ifmode)
1123{
1124 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1125 struct wlan_network *cur_network = &pmlmepriv->cur_network;
1126 enum nl80211_iftype old_mode;
1127
1128 old_mode = cur_network->network.ifmode;
1129
1130 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_,
1131 ("+%s: old =%d new =%d fw_state = 0x%08x\n", __func__,
1132 old_mode, ifmode, get_fwstate(pmlmepriv)));
1133
1134 if (old_mode != ifmode) {
1135 spin_lock_bh(&pmlmepriv->lock);
1136
1137 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1138 (" change mode!"));
1139
1140 if (old_mode == NL80211_IFTYPE_AP ||
1141 old_mode == NL80211_IFTYPE_P2P_GO) {
1142 /* change to other mode from Ndis802_11APMode */
1143 cur_network->join_res = -1;
1144
1145#ifdef CONFIG_8723AU_AP_MODE
1146 stop_ap_mode23a(padapter);
1147#endif
1148 }
1149
1150 if (check_fwstate(pmlmepriv, _FW_LINKED) ||
1151 old_mode == NL80211_IFTYPE_ADHOC)
1152 rtw_disassoc_cmd23a(padapter, 0, true);
1153
1154 if (check_fwstate(pmlmepriv, _FW_LINKED) ||
1155 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
1156 rtw_free_assoc_resources23a(padapter, 1);
1157
1158 if (old_mode == NL80211_IFTYPE_STATION ||
1159 old_mode == NL80211_IFTYPE_P2P_CLIENT ||
1160 old_mode == NL80211_IFTYPE_ADHOC) {
1161 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1162 /* will clr Linked_state; before this function,
1163 we must have chked whether issue
1164 dis-assoc_cmd or not */
1165 rtw_indicate_disconnect23a(padapter);
1166 }
1167 }
1168
1169 cur_network->network.ifmode = ifmode;
1170
1171 _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
1172
1173 switch (ifmode) {
1174 case NL80211_IFTYPE_ADHOC:
1175 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
1176 break;
1177
1178 case NL80211_IFTYPE_P2P_CLIENT:
1179 case NL80211_IFTYPE_STATION:
1180 set_fwstate(pmlmepriv, WIFI_STATION_STATE);
1181 break;
1182
1183 case NL80211_IFTYPE_P2P_GO:
1184 case NL80211_IFTYPE_AP:
1185 set_fwstate(pmlmepriv, WIFI_AP_STATE);
1186#ifdef CONFIG_8723AU_AP_MODE
1187 start_ap_mode23a(padapter);
1188 /* rtw_indicate_connect23a(padapter); */
1189#endif
1190 break;
1191
1192 default:
1193 break;
1194 }
1195
1196 /* SecClearAllKeys(adapter); */
1197
1198 /* RT_TRACE(COMP_OID_SET, DBG_LOUD,
1199 ("set_infrastructure: fw_state:%x after changing mode\n", */
1200 /* get_fwstate(pmlmepriv))); */
1201
1202 spin_unlock_bh(&pmlmepriv->lock);
1203 }
1204
1205 return _SUCCESS;
1206}
1207
b1925ad8
LF
1208static int cfg80211_rtw_change_iface(struct wiphy *wiphy,
1209 struct net_device *ndev,
1210 enum nl80211_iftype type, u32 *flags,
1211 struct vif_params *params)
1212{
1213 enum nl80211_iftype old_type;
b1925ad8
LF
1214 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1215 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1216 struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
b1925ad8 1217 int ret = 0;
b1925ad8 1218
a790d58e 1219 DBG_8723A("%s(%s): call netdev_open23a\n", __func__, ndev->name);
b1925ad8
LF
1220
1221 old_type = rtw_wdev->iftype;
a790d58e
JS
1222 DBG_8723A("%s(%s): old_iftype =%d, new_iftype =%d\n",
1223 __func__, ndev->name, old_type, type);
b1925ad8
LF
1224
1225 if (old_type != type) {
b1925ad8
LF
1226 pmlmeext->action_public_rxseq = 0xffff;
1227 pmlmeext->action_public_dialog_token = 0xff;
1228 }
1229
1230 switch (type) {
1231 case NL80211_IFTYPE_ADHOC:
b1925ad8
LF
1232 case NL80211_IFTYPE_P2P_CLIENT:
1233 case NL80211_IFTYPE_STATION:
b1925ad8
LF
1234 case NL80211_IFTYPE_P2P_GO:
1235 case NL80211_IFTYPE_AP:
efc7144f 1236 case NL80211_IFTYPE_UNSPECIFIED:
b1925ad8
LF
1237 break;
1238 default:
1239 return -EOPNOTSUPP;
1240 }
1241
1242 rtw_wdev->iftype = type;
1243
efc7144f 1244 if (cfg80211_infrastructure_mode(padapter, type) != _SUCCESS) {
b1925ad8
LF
1245 rtw_wdev->iftype = old_type;
1246 ret = -EPERM;
1247 goto exit;
1248 }
1249
efc7144f 1250 rtw_setopmode_cmd23a(padapter, type);
b1925ad8
LF
1251
1252exit:
1253 return ret;
1254}
1255
1256void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv,
1257 bool aborted)
1258{
1259 spin_lock_bh(&pwdev_priv->scan_req_lock);
1260 if (pwdev_priv->scan_request != NULL) {
b1925ad8 1261 DBG_8723A("%s with scan req\n", __func__);
141bd353 1262
b1925ad8
LF
1263 if (pwdev_priv->scan_request->wiphy !=
1264 pwdev_priv->rtw_wdev->wiphy)
1265 DBG_8723A("error wiphy compare\n");
1266 else
1267 cfg80211_scan_done(pwdev_priv->scan_request, aborted);
1268
1269 pwdev_priv->scan_request = NULL;
1270 } else {
b1925ad8 1271 DBG_8723A("%s without scan req\n", __func__);
b1925ad8
LF
1272 }
1273 spin_unlock_bh(&pwdev_priv->scan_req_lock);
1274}
1275
1276void rtw_cfg80211_surveydone_event_callback(struct rtw_adapter *padapter)
1277{
1278 struct list_head *plist, *phead, *ptmp;
1279 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1280 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
1281 struct wlan_network *pnetwork;
1282
b1925ad8
LF
1283 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1284
1285 phead = get_list_head(queue);
1286
1287 list_for_each_safe(plist, ptmp, phead) {
1288 pnetwork = container_of(plist, struct wlan_network, list);
1289
1290 /* report network only if the current channel set
1291 contains the channel to which this network belongs */
1292 if (rtw_ch_set_search_ch23a
1293 (padapter->mlmeextpriv.channel_set,
37cb982c 1294 pnetwork->network.DSConfig) >= 0)
b1925ad8
LF
1295 rtw_cfg80211_inform_bss(padapter, pnetwork);
1296 }
1297
1298 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1299
1300 /* call this after other things have been done */
1301 rtw_cfg80211_indicate_scan_done(wdev_to_priv(padapter->rtw_wdev),
1302 false);
1303}
1304
1305static int rtw_cfg80211_set_probe_req_wpsp2pie(struct rtw_adapter *padapter,
1306 char *buf, int len)
1307{
1308 int ret = 0;
d3797af4 1309 const u8 *wps_ie;
b1925ad8
LF
1310 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1311
b1925ad8 1312 DBG_8723A("%s, ielen =%d\n", __func__, len);
b1925ad8
LF
1313
1314 if (len > 0) {
d3797af4
JS
1315 wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1316 WLAN_OUI_TYPE_MICROSOFT_WPS,
1317 buf, len);
b1925ad8 1318 if (wps_ie) {
d3797af4 1319 DBG_8723A("probe_req_wps_ielen =%d\n", wps_ie[1]);
141bd353 1320
b1925ad8
LF
1321 if (pmlmepriv->wps_probe_req_ie) {
1322 pmlmepriv->wps_probe_req_ie_len = 0;
1323 kfree(pmlmepriv->wps_probe_req_ie);
1324 pmlmepriv->wps_probe_req_ie = NULL;
1325 }
1326
d3797af4 1327 pmlmepriv->wps_probe_req_ie = kmemdup(wps_ie, wps_ie[1],
4a6eea4d 1328 GFP_KERNEL);
b1925ad8
LF
1329 if (pmlmepriv->wps_probe_req_ie == NULL) {
1330 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
1331 __func__, __LINE__);
1332 return -EINVAL;
1333 }
d3797af4 1334 pmlmepriv->wps_probe_req_ie_len = wps_ie[1];
b1925ad8 1335 }
b1925ad8
LF
1336 }
1337
1338 return ret;
1339}
1340
1341static int cfg80211_rtw_scan(struct wiphy *wiphy,
1342 struct cfg80211_scan_request *request)
1343{
1344 int i;
1345 u8 _status = false;
1346 int ret = 0;
1347 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1348 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1349 struct cfg80211_ssid ssid[RTW_SSID_SCAN_AMOUNT];
1350 struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];
b1925ad8
LF
1351 struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
1352 struct cfg80211_ssid *ssids = request->ssids;
b1925ad8
LF
1353 bool need_indicate_scan_done = false;
1354
a790d58e 1355 DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name);
b1925ad8
LF
1356
1357 spin_lock_bh(&pwdev_priv->scan_req_lock);
1358 pwdev_priv->scan_request = request;
1359 spin_unlock_bh(&pwdev_priv->scan_req_lock);
1360
1361 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
b1925ad8 1362 DBG_8723A("%s under WIFI_AP_STATE\n", __func__);
b1925ad8
LF
1363 /* need_indicate_scan_done = true; */
1364 /* goto check_need_indicate_scan_done; */
1365 }
1366
1367 if (rtw_pwr_wakeup(padapter) == _FAIL) {
1368 need_indicate_scan_done = true;
1369 goto check_need_indicate_scan_done;
1370 }
b1925ad8
LF
1371
1372 if (request->ie && request->ie_len > 0) {
1373 rtw_cfg80211_set_probe_req_wpsp2pie(padapter,
1374 (u8 *) request->ie,
1375 request->ie_len);
1376 }
1377
1378 if (pmlmepriv->LinkDetectInfo.bBusyTraffic == true) {
1379 DBG_8723A("%s, bBusyTraffic == true\n", __func__);
1380 need_indicate_scan_done = true;
1381 goto check_need_indicate_scan_done;
1382 }
1383 if (rtw_is_scan_deny(padapter)) {
9cd613c7
JS
1384 DBG_8723A("%s(%s): scan deny\n", __func__,
1385 padapter->pnetdev->name);
b1925ad8
LF
1386 need_indicate_scan_done = true;
1387 goto check_need_indicate_scan_done;
1388 }
1389
1390 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ==
1391 true) {
1392 DBG_8723A("%s, fwstate = 0x%x\n", __func__, pmlmepriv->fw_state);
1393 need_indicate_scan_done = true;
1394 goto check_need_indicate_scan_done;
1395 }
b1925ad8
LF
1396
1397 memset(ssid, 0, sizeof(struct cfg80211_ssid) * RTW_SSID_SCAN_AMOUNT);
1398 /* parsing request ssids, n_ssids */
1399 for (i = 0; i < request->n_ssids && i < RTW_SSID_SCAN_AMOUNT; i++) {
b1925ad8
LF
1400 DBG_8723A("ssid =%s, len =%d\n", ssids[i].ssid,
1401 ssids[i].ssid_len);
b1925ad8
LF
1402 memcpy(ssid[i].ssid, ssids[i].ssid, ssids[i].ssid_len);
1403 ssid[i].ssid_len = ssids[i].ssid_len;
1404 }
1405
1406 /* parsing channels, n_channels */
1407 memset(ch, 0,
1408 sizeof(struct rtw_ieee80211_channel) * RTW_CHANNEL_SCAN_AMOUNT);
1409
1410 if (request->n_channels == 1) {
1411 for (i = 0; i < request->n_channels &&
1412 i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
9cd613c7
JS
1413 DBG_8723A("%s:(%s):" CHAN_FMT "\n",
1414 __func__, padapter->pnetdev->name,
b1925ad8 1415 CHAN_ARG(request->channels[i]));
b1925ad8
LF
1416 ch[i].hw_value = request->channels[i]->hw_value;
1417 ch[i].flags = request->channels[i]->flags;
1418 }
1419 }
1420
1421 spin_lock_bh(&pmlmepriv->lock);
1422 if (request->n_channels == 1) {
1423 memcpy(&ch[1], &ch[0], sizeof(struct rtw_ieee80211_channel));
1424 memcpy(&ch[2], &ch[0], sizeof(struct rtw_ieee80211_channel));
1425 _status = rtw_sitesurvey_cmd23a(padapter, ssid,
1426 RTW_SSID_SCAN_AMOUNT, ch, 3);
1427 } else {
1428 _status = rtw_sitesurvey_cmd23a(padapter, ssid,
1429 RTW_SSID_SCAN_AMOUNT, NULL, 0);
1430 }
1431 spin_unlock_bh(&pmlmepriv->lock);
1432
1433 if (_status == false)
1434 ret = -1;
1435
1436check_need_indicate_scan_done:
1437 if (need_indicate_scan_done)
1438 rtw_cfg80211_surveydone_event_callback(padapter);
1439 return ret;
1440}
1441
1442static int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1443{
1444 DBG_8723A("%s\n", __func__);
1445 return 0;
1446}
1447
1448static int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
1449 struct cfg80211_ibss_params *params)
1450{
a790d58e 1451 DBG_8723A("%s(%s)\n", __func__, ndev->name);
b1925ad8
LF
1452 return 0;
1453}
1454
1455static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
1456{
a790d58e 1457 DBG_8723A("%s(%s)\n", __func__, ndev->name);
b1925ad8
LF
1458 return 0;
1459}
1460
1461static int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv,
1462 u32 wpa_version)
1463{
1464 DBG_8723A("%s, wpa_version =%d\n", __func__, wpa_version);
1465
1466 if (!wpa_version) {
1467 psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
1468 return 0;
1469 }
1470
1471 if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) {
1472 psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK;
1473 }
1474
1475/*
1476 if (wpa_version & NL80211_WPA_VERSION_2)
1477 {
1478 psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK;
1479 }
1480*/
1481
1482 return 0;
1483}
1484
1485static int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv,
1486 enum nl80211_auth_type sme_auth_type)
1487{
1488 DBG_8723A("%s, nl80211_auth_type =%d\n", __func__, sme_auth_type);
1489
1490 switch (sme_auth_type) {
1491 case NL80211_AUTHTYPE_AUTOMATIC:
1492 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
1493
1494 break;
1495 case NL80211_AUTHTYPE_OPEN_SYSTEM:
1496 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1497
1498 if (psecuritypriv->ndisauthtype > Ndis802_11AuthModeWPA)
1499 psecuritypriv->dot11AuthAlgrthm =
1500 dot11AuthAlgrthm_8021X;
1501 break;
1502 case NL80211_AUTHTYPE_SHARED_KEY:
1503 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1504
1505 psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
1506 break;
1507 default:
1508 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1509 /* return -ENOTSUPP; */
1510 }
1511
1512 return 0;
1513}
1514
1515static int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv,
1516 u32 cipher, bool ucast)
1517{
1518 u32 ndisencryptstatus = Ndis802_11EncryptionDisabled;
1519
1520 u32 *profile_cipher = ucast ? &psecuritypriv->dot11PrivacyAlgrthm :
1521 &psecuritypriv->dot118021XGrpPrivacy;
1522
1523 DBG_8723A("%s, ucast =%d, cipher = 0x%x\n", __func__, ucast, cipher);
1524
1525 if (!cipher) {
9e3d6df2 1526 *profile_cipher = 0;
b1925ad8
LF
1527 psecuritypriv->ndisencryptstatus = ndisencryptstatus;
1528 return 0;
1529 }
1530
1531 switch (cipher) {
1532 case IW_AUTH_CIPHER_NONE:
9e3d6df2 1533 *profile_cipher = 0;
b1925ad8
LF
1534 ndisencryptstatus = Ndis802_11EncryptionDisabled;
1535 break;
1536 case WLAN_CIPHER_SUITE_WEP40:
9e3d6df2 1537 *profile_cipher = WLAN_CIPHER_SUITE_WEP40;
b1925ad8
LF
1538 ndisencryptstatus = Ndis802_11Encryption1Enabled;
1539 break;
1540 case WLAN_CIPHER_SUITE_WEP104:
9e3d6df2 1541 *profile_cipher = WLAN_CIPHER_SUITE_WEP104;
b1925ad8
LF
1542 ndisencryptstatus = Ndis802_11Encryption1Enabled;
1543 break;
1544 case WLAN_CIPHER_SUITE_TKIP:
9e3d6df2 1545 *profile_cipher = WLAN_CIPHER_SUITE_TKIP;
b1925ad8
LF
1546 ndisencryptstatus = Ndis802_11Encryption2Enabled;
1547 break;
1548 case WLAN_CIPHER_SUITE_CCMP:
9e3d6df2 1549 *profile_cipher = WLAN_CIPHER_SUITE_CCMP;
b1925ad8
LF
1550 ndisencryptstatus = Ndis802_11Encryption3Enabled;
1551 break;
1552 default:
1553 DBG_8723A("Unsupported cipher: 0x%x\n", cipher);
1554 return -ENOTSUPP;
1555 }
1556
1557 if (ucast)
1558 psecuritypriv->ndisencryptstatus = ndisencryptstatus;
1559
1560 return 0;
1561}
1562
1563static int rtw_cfg80211_set_key_mgt(struct security_priv *psecuritypriv,
1564 u32 key_mgt)
1565{
1566 DBG_8723A("%s, key_mgt = 0x%x\n", __func__, key_mgt);
1567
1568 if (key_mgt == WLAN_AKM_SUITE_8021X)
1569 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1570 else if (key_mgt == WLAN_AKM_SUITE_PSK)
1571 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1572 else
1573 DBG_8723A("Invalid key mgt: 0x%x\n", key_mgt);
1574
1575 return 0;
1576}
1577
1578static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie,
1579 size_t ielen)
1580{
d3797af4 1581 const u8 *wps_ie;
b1925ad8
LF
1582 int group_cipher = 0, pairwise_cipher = 0;
1583 int ret = 0;
58aedb49 1584 const u8 *pwpa, *pwpa2;
b1925ad8
LF
1585 int i;
1586
1587 if (!pie || !ielen) {
1588 /* Treat this as normal case, but need to clear
1589 WIFI_UNDER_WPS */
1590 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1591 goto exit;
1592 }
1593 if (ielen > MAX_WPA_IE_LEN + MAX_WPS_IE_LEN + MAX_P2P_IE_LEN) {
1594 ret = -EINVAL;
1595 goto exit;
1596 }
b1925ad8
LF
1597
1598 /* dump */
1599 DBG_8723A("set wpa_ie(length:%zu):\n", ielen);
1600 for (i = 0; i < ielen; i = i + 8)
7579a7e4
JS
1601 DBG_8723A("0x%.2x 0x%.2x 0x%.2x 0x%.2x "
1602 "0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
1603 pie[i], pie[i + 1], pie[i + 2], pie[i + 3],
1604 pie[i + 4], pie[i + 5], pie[i + 6], pie[i + 7]);
b1925ad8
LF
1605 if (ielen < RSN_HEADER_LEN) {
1606 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
1607 ("Ie len too short %d\n", (int)ielen));
1608 ret = -1;
1609 goto exit;
1610 }
1611
58aedb49
JS
1612 pwpa = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1613 WLAN_OUI_TYPE_MICROSOFT_WPA,
7579a7e4 1614 pie, ielen);
58aedb49
JS
1615 if (pwpa && pwpa[1] > 0) {
1616 if (rtw_parse_wpa_ie23a(pwpa, pwpa[1] + 2, &group_cipher,
1617 &pairwise_cipher, NULL) == _SUCCESS) {
b1925ad8
LF
1618 padapter->securitypriv.dot11AuthAlgrthm =
1619 dot11AuthAlgrthm_8021X;
1620 padapter->securitypriv.ndisauthtype =
1621 Ndis802_11AuthModeWPAPSK;
58aedb49
JS
1622 memcpy(padapter->securitypriv.supplicant_ie, pwpa,
1623 pwpa[1] + 2);
b1925ad8 1624
58aedb49 1625 DBG_8723A("got wpa_ie, wpa_ielen:%u\n", pwpa[1]);
b1925ad8
LF
1626 }
1627 }
1628
7579a7e4 1629 pwpa2 = cfg80211_find_ie(WLAN_EID_RSN, pie, ielen);
58aedb49
JS
1630 if (pwpa2 && pwpa2[1] > 0) {
1631 if (rtw_parse_wpa2_ie23a (pwpa2, pwpa2[1] + 2, &group_cipher,
1632 &pairwise_cipher, NULL) == _SUCCESS) {
b1925ad8
LF
1633 padapter->securitypriv.dot11AuthAlgrthm =
1634 dot11AuthAlgrthm_8021X;
1635 padapter->securitypriv.ndisauthtype =
1636 Ndis802_11AuthModeWPA2PSK;
58aedb49
JS
1637 memcpy(padapter->securitypriv.supplicant_ie, pwpa2,
1638 pwpa2[1] + 2);
b1925ad8 1639
58aedb49 1640 DBG_8723A("got wpa2_ie, wpa2_ielen:%u\n", pwpa2[1]);
b1925ad8
LF
1641 }
1642 }
1643
1644 if (group_cipher == 0) {
1645 group_cipher = WPA_CIPHER_NONE;
1646 }
1647 if (pairwise_cipher == 0) {
1648 pairwise_cipher = WPA_CIPHER_NONE;
1649 }
1650
1651 switch (group_cipher) {
1652 case WPA_CIPHER_NONE:
9e3d6df2 1653 padapter->securitypriv.dot118021XGrpPrivacy = 0;
b1925ad8
LF
1654 padapter->securitypriv.ndisencryptstatus =
1655 Ndis802_11EncryptionDisabled;
1656 break;
1657 case WPA_CIPHER_WEP40:
9e3d6df2 1658 padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40;
b1925ad8
LF
1659 padapter->securitypriv.ndisencryptstatus =
1660 Ndis802_11Encryption1Enabled;
1661 break;
1662 case WPA_CIPHER_TKIP:
9e3d6df2 1663 padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_TKIP;
b1925ad8
LF
1664 padapter->securitypriv.ndisencryptstatus =
1665 Ndis802_11Encryption2Enabled;
1666 break;
1667 case WPA_CIPHER_CCMP:
9e3d6df2 1668 padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_CCMP;
b1925ad8
LF
1669 padapter->securitypriv.ndisencryptstatus =
1670 Ndis802_11Encryption3Enabled;
1671 break;
1672 case WPA_CIPHER_WEP104:
9e3d6df2 1673 padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP104;
b1925ad8
LF
1674 padapter->securitypriv.ndisencryptstatus =
1675 Ndis802_11Encryption1Enabled;
1676 break;
1677 }
1678
1679 switch (pairwise_cipher) {
1680 case WPA_CIPHER_NONE:
9e3d6df2 1681 padapter->securitypriv.dot11PrivacyAlgrthm = 0;
b1925ad8
LF
1682 padapter->securitypriv.ndisencryptstatus =
1683 Ndis802_11EncryptionDisabled;
1684 break;
1685 case WPA_CIPHER_WEP40:
9e3d6df2 1686 padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
b1925ad8
LF
1687 padapter->securitypriv.ndisencryptstatus =
1688 Ndis802_11Encryption1Enabled;
1689 break;
1690 case WPA_CIPHER_TKIP:
9e3d6df2 1691 padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_TKIP;
b1925ad8
LF
1692 padapter->securitypriv.ndisencryptstatus =
1693 Ndis802_11Encryption2Enabled;
1694 break;
1695 case WPA_CIPHER_CCMP:
9e3d6df2 1696 padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_CCMP;
b1925ad8
LF
1697 padapter->securitypriv.ndisencryptstatus =
1698 Ndis802_11Encryption3Enabled;
1699 break;
1700 case WPA_CIPHER_WEP104:
9e3d6df2 1701 padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104;
b1925ad8
LF
1702 padapter->securitypriv.ndisencryptstatus =
1703 Ndis802_11Encryption1Enabled;
1704 break;
1705 }
1706
d3797af4
JS
1707 wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1708 WLAN_OUI_TYPE_MICROSOFT_WPS,
7579a7e4 1709 pie, ielen);
d3797af4
JS
1710 if (wps_ie && wps_ie[1] > 0) {
1711 DBG_8723A("got wps_ie, wps_ielen:%u\n", wps_ie[1]);
1712 padapter->securitypriv.wps_ie_len = wps_ie[1];
1713 memcpy(padapter->securitypriv.wps_ie, wps_ie,
1714 padapter->securitypriv.wps_ie_len);
1715 set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
1716 } else {
1717 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
b1925ad8
LF
1718 }
1719
b1925ad8 1720 /* TKIP and AES disallow multicast packets until installing group key */
9e3d6df2
JS
1721 if (padapter->securitypriv.dot11PrivacyAlgrthm ==
1722 WLAN_CIPHER_SUITE_TKIP ||
1723 padapter->securitypriv.dot11PrivacyAlgrthm ==
1724 WLAN_CIPHER_SUITE_CCMP)
b1925ad8
LF
1725 /* WPS open need to enable multicast */
1726 /* check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true)*/
763b4247 1727 rtl8723a_off_rcr_am(padapter);
b1925ad8
LF
1728
1729 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1730 ("rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->"
1731 "securitypriv.ndisencryptstatus =%d padapter->"
1732 "securitypriv.ndisauthtype =%d\n", pairwise_cipher,
1733 padapter->securitypriv.ndisencryptstatus,
1734 padapter->securitypriv.ndisauthtype));
1735
1736exit:
b1925ad8
LF
1737 if (ret)
1738 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1739 return ret;
1740}
1741
6893c8eb 1742static int rtw_cfg80211_add_wep(struct rtw_adapter *padapter,
deff1155 1743 struct rtw_wep_key *wep, u8 keyid)
1e6e7f60 1744{
deff1155 1745 int res;
1e6e7f60
JS
1746 struct security_priv *psecuritypriv = &padapter->securitypriv;
1747
deff1155 1748 if (keyid >= NUM_WEP_KEYS) {
1e6e7f60
JS
1749 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
1750 ("%s:keyid>4 =>fail\n", __func__));
1751 res = _FAIL;
1752 goto exit;
1753 }
1754
deff1155 1755 switch (wep->keylen) {
4d9c63bb 1756 case WLAN_KEY_LEN_WEP40:
1e6e7f60
JS
1757 psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
1758 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1759 ("%s:wep->KeyLength = 5\n", __func__));
1760 break;
4d9c63bb 1761 case WLAN_KEY_LEN_WEP104:
1e6e7f60
JS
1762 psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104;
1763 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1764 ("%s:wep->KeyLength = 13\n", __func__));
1765 break;
1766 default:
1767 psecuritypriv->dot11PrivacyAlgrthm = 0;
1768 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1769 ("%s:wep->KeyLength!= 5 or 13\n", __func__));
1770 res = _FAIL;
1771 goto exit;
1772 }
1773
1774 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
deff1155
JS
1775 ("%s:before memcpy, wep->KeyLength = 0x%x keyid =%x\n",
1776 __func__, wep->keylen, keyid));
1e6e7f60 1777
deff1155 1778 memcpy(&psecuritypriv->wep_key[keyid], wep, sizeof(struct rtw_wep_key));
1e6e7f60
JS
1779
1780 psecuritypriv->dot11PrivacyKeyIndex = keyid;
1781
1782 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1783 ("%s:security key material : "
1784 "%x %x %x %x %x %x %x %x %x %x %x %x %x\n", __func__,
1785 psecuritypriv->wep_key[keyid].key[0],
1786 psecuritypriv->wep_key[keyid].key[1],
1787 psecuritypriv->wep_key[keyid].key[2],
1788 psecuritypriv->wep_key[keyid].key[3],
1789 psecuritypriv->wep_key[keyid].key[4],
1790 psecuritypriv->wep_key[keyid].key[5],
1791 psecuritypriv->wep_key[keyid].key[6],
1792 psecuritypriv->wep_key[keyid].key[7],
1793 psecuritypriv->wep_key[keyid].key[8],
1794 psecuritypriv->wep_key[keyid].key[9],
1795 psecuritypriv->wep_key[keyid].key[10],
1796 psecuritypriv->wep_key[keyid].key[11],
1797 psecuritypriv->wep_key[keyid].key[12]));
1798
1799 res = rtw_set_key23a(padapter, psecuritypriv, keyid, 1);
1800
1801exit:
1802
1803 return res;
1804}
1805
e73d82ef
JS
1806static int rtw_set_ssid(struct rtw_adapter *padapter,
1807 struct wlan_network *newnetwork)
97c4361d
JS
1808{
1809 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1810 struct wlan_network *pnetwork = &pmlmepriv->cur_network;
1811 int status = _SUCCESS;
1812 u32 cur_time = 0;
1813
1814 DBG_8723A_LEVEL(_drv_always_, "set ssid [%s] fw_state = 0x%08x\n",
e73d82ef 1815 newnetwork->network.Ssid.ssid, get_fwstate(pmlmepriv));
97c4361d
JS
1816
1817 if (padapter->hw_init_completed == false) {
1818 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
1819 ("set_ssid: hw_init_completed == false =>exit!!!\n"));
1820 status = _FAIL;
1821 goto exit;
1822 }
1823
1824 spin_lock_bh(&pmlmepriv->lock);
1825
1826 DBG_8723A("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
1827 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1828 goto handle_tkip_countermeasure;
97c4361d
JS
1829
1830 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1831 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1832 ("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
1833
e73d82ef
JS
1834 if (pmlmepriv->assoc_ssid.ssid_len ==
1835 newnetwork->network.Ssid.ssid_len &&
1836 !memcmp(&pmlmepriv->assoc_ssid.ssid,
1837 newnetwork->network.Ssid.ssid,
1838 newnetwork->network.Ssid.ssid_len)) {
97c4361d
JS
1839 if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
1840 RT_TRACE(_module_rtl871x_ioctl_set_c_,
1841 _drv_err_, ("New SSID is same SSID, "
1842 "fw_state = 0x%08x\n",
1843 get_fwstate(pmlmepriv)));
1844
1845 if (rtw_is_same_ibss23a(padapter, pnetwork)) {
1846 /*
1847 * it means driver is in
1848 * WIFI_ADHOC_MASTER_STATE, we needn't
1849 * create bss again.
1850 */
1851 goto release_mlme_lock;
1852 }
1853
1854 /*
1855 * if in WIFI_ADHOC_MASTER_STATE |
1856 * WIFI_ADHOC_STATE, create bss or
1857 * rejoin again
1858 */
1859 rtw_disassoc_cmd23a(padapter, 0, true);
1860
1861 if (check_fwstate(pmlmepriv, _FW_LINKED))
1862 rtw_indicate_disconnect23a(padapter);
1863
1864 rtw_free_assoc_resources23a(padapter, 1);
1865
1866 if (check_fwstate(pmlmepriv,
1867 WIFI_ADHOC_MASTER_STATE)) {
1868 _clr_fwstate_(pmlmepriv,
1869 WIFI_ADHOC_MASTER_STATE);
1870 set_fwstate(pmlmepriv,
1871 WIFI_ADHOC_STATE);
1872 }
1873 } else {
1874 rtw_lps_ctrl_wk_cmd23a(padapter,
1875 LPS_CTRL_JOINBSS, 1);
1876 }
1877 } else {
1878 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1879 ("Set SSID not the same ssid\n"));
1880 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
e73d82ef
JS
1881 ("set_ssid =[%s] len = 0x%x\n",
1882 newnetwork->network.Ssid.ssid,
1883 newnetwork->network.Ssid.ssid_len));
97c4361d
JS
1884 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1885 ("assoc_ssid =[%s] len = 0x%x\n",
1886 pmlmepriv->assoc_ssid.ssid,
1887 pmlmepriv->assoc_ssid.ssid_len));
1888
1889 rtw_disassoc_cmd23a(padapter, 0, true);
1890
1891 if (check_fwstate(pmlmepriv, _FW_LINKED))
1892 rtw_indicate_disconnect23a(padapter);
1893
1894 rtw_free_assoc_resources23a(padapter, 1);
1895
1896 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1897 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
1898 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
1899 }
1900 }
1901 }
1902
1903handle_tkip_countermeasure:
1904
1905 if (padapter->securitypriv.btkip_countermeasure == true) {
1906 cur_time = jiffies;
1907
1908 if ((cur_time -
1909 padapter->securitypriv.btkip_countermeasure_time) >
1910 60 * HZ) {
1911 padapter->securitypriv.btkip_countermeasure = false;
1912 padapter->securitypriv.btkip_countermeasure_time = 0;
1913 } else {
1914 status = _FAIL;
1915 goto release_mlme_lock;
1916 }
1917 }
1918
e73d82ef
JS
1919 memcpy(&pmlmepriv->assoc_ssid, &newnetwork->network.Ssid,
1920 sizeof(struct cfg80211_ssid));
1921
97c4361d
JS
1922 pmlmepriv->assoc_by_bssid = false;
1923
72795e9d
JS
1924 pmlmepriv->to_join = true;
1925
1926 if (!check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
1927 pmlmepriv->cur_network.join_res = -2;
97c4361d 1928
72795e9d
JS
1929 status = rtw_do_join_network(padapter, newnetwork);
1930 if (status == _SUCCESS) {
1931 pmlmepriv->to_join = false;
1932 } else {
1933 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1934 /* switch to ADHOC_MASTER */
1935 status = rtw_do_join_adhoc(padapter);
1936 if (status != _SUCCESS)
1937 goto release_mlme_lock;
1938 } else {
1939 /* can't associate ; reset under-linking */
1940 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1941 status = _FAIL;
1942 pmlmepriv->to_join = false;
1943 }
1944 }
1945 }
97c4361d
JS
1946release_mlme_lock:
1947 spin_unlock_bh(&pmlmepriv->lock);
1948
1949exit:
1950 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
1951 ("-%s: status =%d\n", __func__, status));
1952
1953 return status;
1954}
1955
b1925ad8
LF
1956static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
1957 struct cfg80211_connect_params *sme)
1958{
1959 int ret = 0;
1960 struct list_head *phead, *plist, *ptmp;
1961 struct wlan_network *pnetwork = NULL;
b1925ad8
LF
1962 /* u8 matched_by_bssid = false; */
1963 /* u8 matched_by_ssid = false; */
1964 u8 matched = false;
1965 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1966 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1967 struct security_priv *psecuritypriv = &padapter->securitypriv;
1968 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
1969
a790d58e 1970 DBG_8723A("=>" "%s(%s)\n", __func__, ndev->name);
b1925ad8
LF
1971 DBG_8723A("privacy =%d, key =%p, key_len =%d, key_idx =%d\n",
1972 sme->privacy, sme->key, sme->key_len, sme->key_idx);
1973
b1925ad8
LF
1974 if (_FAIL == rtw_pwr_wakeup(padapter)) {
1975 ret = -EPERM;
1976 goto exit;
1977 }
1978
1979 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1980 ret = -EPERM;
1981 goto exit;
1982 }
1983
c5178b0b
JS
1984 if (!sme->ssid || !sme->ssid_len ||
1985 sme->ssid_len > IEEE80211_MAX_SSID_LEN) {
b1925ad8
LF
1986 ret = -EINVAL;
1987 goto exit;
1988 }
1989
c5178b0b 1990 DBG_8723A("ssid =%s, len =%zu\n", sme->ssid, sme->ssid_len);
b1925ad8
LF
1991
1992 if (sme->bssid)
1993 DBG_8723A("bssid =" MAC_FMT "\n", MAC_ARG(sme->bssid));
1994
1995 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
1996 ret = -EBUSY;
1997 DBG_8723A("%s, fw_state = 0x%x, goto exit\n", __func__,
1998 pmlmepriv->fw_state);
1999 goto exit;
2000 }
2001 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
2002 rtw_scan_abort23a(padapter);
2003 }
2004
2005 spin_lock_bh(&queue->lock);
2006
2007 phead = get_list_head(queue);
2008
2009 list_for_each_safe(plist, ptmp, phead) {
2010 pnetwork = container_of(plist, struct wlan_network, list);
2011
b1925ad8 2012 if (sme->bssid) {
cc2db7cb
JS
2013 if (!ether_addr_equal(pnetwork->network.MacAddress,
2014 sme->bssid))
b1925ad8
LF
2015 continue;
2016 }
2017
2018 if (sme->ssid && sme->ssid_len) {
2019 if (pnetwork->network.Ssid.ssid_len != sme->ssid_len ||
2020 memcmp(pnetwork->network.Ssid.ssid, sme->ssid,
2021 sme->ssid_len))
2022 continue;
2023 }
2024
2025 if (sme->bssid) {
9ab98d42
JS
2026 if (ether_addr_equal(pnetwork->network.MacAddress,
2027 sme->bssid)) {
b1925ad8
LF
2028 DBG_8723A("matched by bssid\n");
2029
b1925ad8
LF
2030 matched = true;
2031 break;
2032 }
b1925ad8 2033 } else if (sme->ssid && sme->ssid_len) {
9ab98d42
JS
2034 if (!memcmp(pnetwork->network.Ssid.ssid,
2035 sme->ssid, sme->ssid_len) &&
c5178b0b 2036 pnetwork->network.Ssid.ssid_len == sme->ssid_len) {
b1925ad8 2037 DBG_8723A("matched by ssid\n");
c5178b0b 2038
b1925ad8
LF
2039 matched = true;
2040 break;
2041 }
2042 }
2043 }
2044
2045 spin_unlock_bh(&queue->lock);
2046
c5178b0b 2047 if (!matched || !pnetwork) {
b1925ad8
LF
2048 ret = -ENOENT;
2049 DBG_8723A("connect, matched == false, goto exit\n");
2050 goto exit;
2051 }
2052
efc7144f
JS
2053 if (cfg80211_infrastructure_mode(
2054 padapter, pnetwork->network.ifmode) != _SUCCESS) {
b1925ad8
LF
2055 ret = -EPERM;
2056 goto exit;
2057 }
2058
2059 psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
9e3d6df2
JS
2060 psecuritypriv->dot11PrivacyAlgrthm = 0;
2061 psecuritypriv->dot118021XGrpPrivacy = 0;
b1925ad8
LF
2062 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
2063 psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
2064
c5178b0b
JS
2065 ret = rtw_cfg80211_set_wpa_version(psecuritypriv,
2066 sme->crypto.wpa_versions);
b1925ad8
LF
2067 if (ret < 0)
2068 goto exit;
2069
2070 ret = rtw_cfg80211_set_auth_type(psecuritypriv, sme->auth_type);
2071
2072 if (ret < 0)
2073 goto exit;
2074
2075 DBG_8723A("%s, ie_len =%zu\n", __func__, sme->ie_len);
2076
2077 ret = rtw_cfg80211_set_wpa_ie(padapter, sme->ie, sme->ie_len);
2078 if (ret < 0)
2079 goto exit;
2080
2081 if (sme->crypto.n_ciphers_pairwise) {
2082 ret = rtw_cfg80211_set_cipher(psecuritypriv,
2083 sme->crypto.ciphers_pairwise[0],
2084 true);
2085 if (ret < 0)
2086 goto exit;
2087 }
2088
2089 /* For WEP Shared auth */
2090 if ((psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Shared ||
2091 psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Auto) &&
2092 sme->key) {
deff1155
JS
2093 struct rtw_wep_key wep_key;
2094 u8 wep_key_idx, wep_key_len;
b1925ad8
LF
2095 DBG_8723A("%s(): Shared/Auto WEP\n", __func__);
2096
2097 wep_key_idx = sme->key_idx;
2098 wep_key_len = sme->key_len;
2099
deff1155
JS
2100 if (wep_key_idx > WEP_KEYS || !wep_key_len ||
2101 wep_key_len > WLAN_KEY_LEN_WEP104) {
b1925ad8
LF
2102 ret = -EINVAL;
2103 goto exit;
2104 }
2105
deff1155 2106 wep_key_len = wep_key_len <= 5 ? 5 : 13;
b1925ad8 2107
deff1155 2108 memset(&wep_key, 0, sizeof(struct rtw_wep_key));
b1925ad8 2109
deff1155 2110 wep_key.keylen = wep_key_len;
b1925ad8 2111
deff1155
JS
2112 if (wep_key_len == 13) {
2113 padapter->securitypriv.dot11PrivacyAlgrthm =
2114 WLAN_CIPHER_SUITE_WEP104;
2115 padapter->securitypriv.dot118021XGrpPrivacy =
2116 WLAN_CIPHER_SUITE_WEP104;
b1925ad8 2117 } else {
deff1155
JS
2118 padapter->securitypriv.dot11PrivacyAlgrthm =
2119 WLAN_CIPHER_SUITE_WEP40;
2120 padapter->securitypriv.dot118021XGrpPrivacy =
2121 WLAN_CIPHER_SUITE_WEP40;
b1925ad8
LF
2122 }
2123
deff1155 2124 memcpy(wep_key.key, (void *)sme->key, wep_key.keylen);
b1925ad8 2125
deff1155
JS
2126 if (rtw_cfg80211_add_wep(padapter, &wep_key, wep_key_idx) !=
2127 _SUCCESS)
b1925ad8 2128 ret = -EOPNOTSUPP;
b1925ad8 2129
b1925ad8
LF
2130 if (ret < 0)
2131 goto exit;
2132 }
2133
2134 ret = rtw_cfg80211_set_cipher(psecuritypriv,
2135 sme->crypto.cipher_group, false);
2136 if (ret < 0)
c5178b0b 2137 goto exit;
b1925ad8
LF
2138
2139 if (sme->crypto.n_akm_suites) {
2140 ret = rtw_cfg80211_set_key_mgt(psecuritypriv,
2141 sme->crypto.akm_suites[0]);
2142 if (ret < 0)
2143 goto exit;
2144 }
2145
39dbc446
JS
2146 if (psecuritypriv->ndisauthtype > 3)
2147 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
2148
2149 if (rtw_set_auth23a(padapter, psecuritypriv) != _SUCCESS) {
2150 ret = -EBUSY;
2151 goto exit;
2152 }
b1925ad8
LF
2153
2154 /* rtw_set_802_11_encryption_mode(padapter,
2155 padapter->securitypriv.ndisencryptstatus); */
2156
e73d82ef 2157 if (rtw_set_ssid(padapter, pnetwork) != _SUCCESS) {
97c4361d 2158 ret = -EBUSY;
b1925ad8
LF
2159 goto exit;
2160 }
2161
2162 DBG_8723A("set ssid:dot11AuthAlgrthm =%d, dot11PrivacyAlgrthm =%d, "
2163 "dot118021XGrpPrivacy =%d\n", psecuritypriv->dot11AuthAlgrthm,
2164 psecuritypriv->dot11PrivacyAlgrthm,
2165 psecuritypriv->dot118021XGrpPrivacy);
2166
2167exit:
2168
2169 DBG_8723A("<=%s, ret %d\n", __func__, ret);
2170
2171 return ret;
2172}
2173
2174static int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev,
2175 u16 reason_code)
2176{
2177 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2178
a790d58e 2179 DBG_8723A("%s(%s)\n", __func__, ndev->name);
b1925ad8
LF
2180
2181 rtw_set_roaming(padapter, 0);
2182
2183 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
2184 rtw_scan_abort23a(padapter);
2185 LeaveAllPowerSaveMode23a(padapter);
2186 rtw_disassoc_cmd23a(padapter, 500, false);
2187
2188 DBG_8723A("%s...call rtw_indicate_disconnect23a\n", __func__);
2189
2190 padapter->mlmepriv.not_indic_disco = true;
2191 rtw_indicate_disconnect23a(padapter);
2192 padapter->mlmepriv.not_indic_disco = false;
2193
2194 rtw_free_assoc_resources23a(padapter, 1);
2195 }
2196
2197 return 0;
2198}
2199
2200static int cfg80211_rtw_set_txpower(struct wiphy *wiphy,
2201 struct wireless_dev *wdev,
2202 enum nl80211_tx_power_setting type, int mbm)
2203{
2204 DBG_8723A("%s\n", __func__);
2205 return 0;
2206}
2207
2208static int cfg80211_rtw_get_txpower(struct wiphy *wiphy,
2209 struct wireless_dev *wdev, int *dbm)
2210{
2211 DBG_8723A("%s\n", __func__);
2212 *dbm = (12);
2213 return 0;
2214}
2215
2216inline bool rtw_cfg80211_pwr_mgmt(struct rtw_adapter *adapter)
2217{
2218 struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(adapter->rtw_wdev);
2219 return rtw_wdev_priv->power_mgmt;
2220}
2221
2222static int cfg80211_rtw_set_power_mgmt(struct wiphy *wiphy,
2223 struct net_device *ndev,
2224 bool enabled, int timeout)
2225{
2226 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2227 struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(padapter->rtw_wdev);
2228
a790d58e
JS
2229 DBG_8723A("%s(%s): enabled:%u, timeout:%d\n",
2230 __func__, ndev->name, enabled, timeout);
b1925ad8
LF
2231
2232 rtw_wdev_priv->power_mgmt = enabled;
2233
2234 if (!enabled)
2235 LPS_Leave23a(padapter);
2236
2237 return 0;
2238}
2239
2240static int cfg80211_rtw_set_pmksa(struct wiphy *wiphy,
2241 struct net_device *netdev,
2242 struct cfg80211_pmksa *pmksa)
2243{
2244 u8 index, blInserted = false;
2245 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2246 struct security_priv *psecuritypriv = &padapter->securitypriv;
b1925ad8 2247
a790d58e 2248 DBG_8723A("%s(%s)\n", __func__, netdev->name);
b1925ad8 2249
cc2db7cb 2250 if (is_zero_ether_addr(pmksa->bssid))
b1925ad8 2251 return -EINVAL;
b1925ad8
LF
2252
2253 blInserted = false;
2254
2255 /* overwrite PMKID */
2256 for (index = 0; index < NUM_PMKID_CACHE; index++) {
cc2db7cb
JS
2257 if (ether_addr_equal(psecuritypriv->PMKIDList[index].Bssid,
2258 pmksa->bssid)) {
b1925ad8
LF
2259 /* BSSID is matched, the same AP => rewrite with
2260 new PMKID. */
a790d58e
JS
2261 DBG_8723A("%s(%s): BSSID exists in the PMKList.\n",
2262 __func__, netdev->name);
b1925ad8
LF
2263
2264 memcpy(psecuritypriv->PMKIDList[index].PMKID,
2265 pmksa->pmkid, WLAN_PMKID_LEN);
2266 psecuritypriv->PMKIDList[index].bUsed = true;
2267 psecuritypriv->PMKIDIndex = index + 1;
2268 blInserted = true;
2269 break;
2270 }
2271 }
2272
2273 if (!blInserted) {
2274 /* Find a new entry */
a790d58e
JS
2275 DBG_8723A("%s(%s): Use new entry index = %d for this PMKID\n",
2276 __func__, netdev->name, psecuritypriv->PMKIDIndex);
b1925ad8 2277
888df442
JS
2278 ether_addr_copy(
2279 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
2280 Bssid, pmksa->bssid);
b1925ad8
LF
2281 memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
2282 PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2283
2284 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed =
2285 true;
2286 psecuritypriv->PMKIDIndex++;
2287 if (psecuritypriv->PMKIDIndex == 16) {
2288 psecuritypriv->PMKIDIndex = 0;
2289 }
2290 }
2291
2292 return 0;
2293}
2294
2295static int cfg80211_rtw_del_pmksa(struct wiphy *wiphy,
2296 struct net_device *netdev,
2297 struct cfg80211_pmksa *pmksa)
2298{
2299 u8 index, bMatched = false;
2300 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2301 struct security_priv *psecuritypriv = &padapter->securitypriv;
2302
a790d58e 2303 DBG_8723A("%s(%s)\n", __func__, netdev->name);
b1925ad8
LF
2304
2305 for (index = 0; index < NUM_PMKID_CACHE; index++) {
cc2db7cb
JS
2306 if (ether_addr_equal(psecuritypriv->PMKIDList[index].Bssid,
2307 pmksa->bssid)) {
2308 /* BSSID is matched, the same AP => Remove this PMKID
2309 information and reset it. */
43c34be1 2310 eth_zero_addr(psecuritypriv->PMKIDList[index].Bssid);
b1925ad8
LF
2311 memset(psecuritypriv->PMKIDList[index].PMKID, 0x00,
2312 WLAN_PMKID_LEN);
2313 psecuritypriv->PMKIDList[index].bUsed = false;
2314 bMatched = true;
2315 break;
2316 }
2317 }
2318
2319 if (false == bMatched) {
a790d58e
JS
2320 DBG_8723A("%s(%s): do not have matched BSSID\n", __func__,
2321 netdev->name);
b1925ad8
LF
2322 return -EINVAL;
2323 }
2324
2325 return 0;
2326}
2327
2328static int cfg80211_rtw_flush_pmksa(struct wiphy *wiphy,
2329 struct net_device *netdev)
2330{
2331 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2332 struct security_priv *psecuritypriv = &padapter->securitypriv;
2333
a790d58e 2334 DBG_8723A("%s(%s)\n", __func__, netdev->name);
b1925ad8
LF
2335
2336 memset(&psecuritypriv->PMKIDList[0], 0x00,
2337 sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
2338 psecuritypriv->PMKIDIndex = 0;
2339
2340 return 0;
2341}
2342
2343#ifdef CONFIG_8723AU_AP_MODE
2344void rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter,
2345 u8 *pmgmt_frame, uint frame_len)
2346{
2347 s32 freq;
2348 int channel;
2349 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2350 struct net_device *ndev = padapter->pnetdev;
2351
2352 DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name);
2353
2354#if defined(RTW_USE_CFG80211_STA_EVENT)
2355 {
2356 struct station_info sinfo;
2357 u8 ie_offset;
60e78f3d 2358
b1925ad8 2359 if (ieee80211_is_assoc_req(hdr->frame_control))
60e78f3d
JS
2360 ie_offset = offsetof(struct ieee80211_mgmt,
2361 u.assoc_req.variable);
b1925ad8 2362 else /* WIFI_REASSOCREQ */
60e78f3d
JS
2363 ie_offset = offsetof(struct ieee80211_mgmt,
2364 u.reassoc_req.variable);
b1925ad8
LF
2365
2366 sinfo.filled = 0;
2367 sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
60e78f3d
JS
2368 sinfo.assoc_req_ies = pmgmt_frame + ie_offset;
2369 sinfo.assoc_req_ies_len = frame_len - ie_offset;
b1925ad8
LF
2370 cfg80211_new_sta(ndev, hdr->addr2, &sinfo, GFP_ATOMIC);
2371 }
2372#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
2373 channel = pmlmeext->cur_channel;
2374 if (channel <= RTW_CH_MAX_2G_CHANNEL)
2375 freq = ieee80211_channel_to_frequency(channel,
2376 IEEE80211_BAND_2GHZ);
2377 else
2378 freq = ieee80211_channel_to_frequency(channel,
2379 IEEE80211_BAND_5GHZ);
2380
56b0bd91
JS
2381 cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pmgmt_frame, frame_len,
2382 0, GFP_ATOMIC);
b1925ad8
LF
2383#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
2384}
2385
2386void rtw_cfg80211_indicate_sta_disassoc(struct rtw_adapter *padapter,
2387 unsigned char *da,
2388 unsigned short reason)
2389{
2390 s32 freq;
2391 int channel;
b1925ad8 2392 uint frame_len;
cc531f61 2393 struct ieee80211_mgmt mgmt;
b1925ad8
LF
2394 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2395 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2396 struct net_device *ndev = padapter->pnetdev;
2397
2398 DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name);
2399
cc531f61 2400 memset(&mgmt, 0, sizeof(struct ieee80211_mgmt));
1daffaee 2401
b1925ad8
LF
2402#if defined(RTW_USE_CFG80211_STA_EVENT)
2403 cfg80211_del_sta(ndev, da, GFP_ATOMIC);
2404#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
2405 channel = pmlmeext->cur_channel;
2406 if (channel <= RTW_CH_MAX_2G_CHANNEL)
2407 freq = ieee80211_channel_to_frequency(channel,
2408 IEEE80211_BAND_2GHZ);
2409 else
2410 freq = ieee80211_channel_to_frequency(channel,
2411 IEEE80211_BAND_5GHZ);
2412
cc531f61 2413 mgmt.frame_control =
036cdd9c 2414 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
b1925ad8 2415
cc531f61
JS
2416 ether_addr_copy(mgmt.da, myid(&padapter->eeprompriv));
2417 ether_addr_copy(mgmt.sa, da);
2418 ether_addr_copy(mgmt.bssid, get_my_bssid23a(&pmlmeinfo->network));
b1925ad8 2419
cc531f61 2420 mgmt.seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
b1925ad8 2421 pmlmeext->mgnt_seq++;
b1925ad8 2422
cc531f61 2423 mgmt.u.disassoc.reason_code = cpu_to_le16(reason);
b1925ad8 2424
cc531f61 2425 frame_len = sizeof(struct ieee80211_hdr_3addr) + 2;
b1925ad8 2426
cc531f61 2427 cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, (u8 *)&mgmt, frame_len,
56b0bd91 2428 0, GFP_ATOMIC);
b1925ad8
LF
2429#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
2430}
2431
2432static int rtw_cfg80211_monitor_if_open(struct net_device *ndev)
2433{
2434 int ret = 0;
2435
2436 DBG_8723A("%s\n", __func__);
2437
2438 return ret;
2439}
2440
2441static int rtw_cfg80211_monitor_if_close(struct net_device *ndev)
2442{
2443 int ret = 0;
2444
2445 DBG_8723A("%s\n", __func__);
2446
2447 return ret;
2448}
2449
2450static int rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb,
2451 struct net_device *ndev)
2452{
2453 int ret = 0;
2454 int rtap_len;
2455 int qos_len = 0;
2456 int dot11_hdr_len = 24;
2457 int snap_len = 6;
2458 unsigned char *pdata;
2459 unsigned char src_mac_addr[6];
2460 unsigned char dst_mac_addr[6];
2461 struct ieee80211_hdr *dot11_hdr;
2462 struct ieee80211_radiotap_header *rtap_hdr;
2463 struct rtw_adapter *padapter = netdev_priv(ndev);
2464
a790d58e 2465 DBG_8723A("%s(%s)\n", __func__, ndev->name);
b1925ad8
LF
2466
2467 if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
2468 goto fail;
2469
2470 rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;
2471 if (unlikely(rtap_hdr->it_version))
2472 goto fail;
2473
2474 rtap_len = ieee80211_get_radiotap_len(skb->data);
2475 if (unlikely(skb->len < rtap_len))
2476 goto fail;
2477
2478 if (rtap_len != 14) {
2479 DBG_8723A("radiotap len (should be 14): %d\n", rtap_len);
2480 goto fail;
2481 }
2482
2483 /* Skip the ratio tap header */
2484 skb_pull(skb, rtap_len);
2485
2486 dot11_hdr = (struct ieee80211_hdr *)skb->data;
2487 /* Check if the QoS bit is set */
2488 if (ieee80211_is_data(dot11_hdr->frame_control)) {
2489 /* Check if this ia a Wireless Distribution System (WDS) frame
2490 * which has 4 MAC addresses
2491 */
2492 if (ieee80211_is_data_qos(dot11_hdr->frame_control))
2493 qos_len = IEEE80211_QOS_CTL_LEN;
2494 if (ieee80211_has_a4(dot11_hdr->frame_control))
2495 dot11_hdr_len += 6;
2496
2497 memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
2498 memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
2499
2500 /*
2501 * Skip the 802.11 header, QoS (if any) and SNAP,
2502 * but leave spaces for two MAC addresses
2503 */
2504 skb_pull(skb, dot11_hdr_len + qos_len + snap_len -
2505 ETH_ALEN * 2);
2506 pdata = (unsigned char *)skb->data;
888df442
JS
2507 ether_addr_copy(pdata, dst_mac_addr);
2508 ether_addr_copy(pdata + ETH_ALEN, src_mac_addr);
b1925ad8
LF
2509
2510 DBG_8723A("should be eapol packet\n");
2511
2512 /* Use the real net device to transmit the packet */
2513 ret = rtw_xmit23a_entry23a(skb, padapter->pnetdev);
2514
2515 return ret;
2516
2517 } else if (ieee80211_is_action(dot11_hdr->frame_control)) {
38eb09b5 2518 struct ieee80211_mgmt *mgmt;
b1925ad8
LF
2519 /* only for action frames */
2520 struct xmit_frame *pmgntframe;
2521 struct pkt_attrib *pattrib;
2522 unsigned char *pframe;
2523 /* u8 category, action, OUI_Subtype, dialogToken = 0; */
2524 /* unsigned char *frame_body; */
2525 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2526 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2527 u32 len = skb->len;
2528 u8 category, action;
b1925ad8 2529
38eb09b5 2530 mgmt = (struct ieee80211_mgmt *)dot11_hdr;
b1925ad8 2531
a790d58e 2532 DBG_8723A("RTW_Tx:da =" MAC_FMT " via %s(%s)\n",
38eb09b5
JS
2533 MAC_ARG(mgmt->da), __func__, ndev->name);
2534 category = mgmt->u.action.category;
2535 action = mgmt->u.action.u.wme_action.action_code;
2e74d336
JS
2536 DBG_8723A("RTW_Tx:category(%u), action(%u)\n",
2537 category, action);
98fb8129 2538
b1925ad8
LF
2539 /* starting alloc mgmt frame to dump it */
2540 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2541 if (pmgntframe == NULL)
2542 goto fail;
2543
2544 /* update attribute */
2545 pattrib = &pmgntframe->attrib;
2546 update_mgntframe_attrib23a(padapter, pattrib);
2547 pattrib->retry_ctrl = false;
2548
2549 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2550
2551 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2552
2553 memcpy(pframe, skb->data, len);
b1925ad8
LF
2554 pattrib->pktlen = len;
2555
2556 /* update seq number */
2557 pmlmeext->mgnt_seq = le16_to_cpu(dot11_hdr->seq_ctrl) >> 4;
2558 pattrib->seqnum = pmlmeext->mgnt_seq;
2559 pmlmeext->mgnt_seq++;
2560
2561 pattrib->last_txcmdsz = pattrib->pktlen;
2562
2563 dump_mgntframe23a(padapter, pmgntframe);
2564 }
2565
2566fail:
2567
2568 dev_kfree_skb(skb);
2569
2570 return 0;
2571}
2572
2573static int
2574rtw_cfg80211_monitor_if_set_mac_address(struct net_device *ndev, void *addr)
2575{
2576 int ret = 0;
2577
2578 DBG_8723A("%s\n", __func__);
2579
2580 return ret;
2581}
2582
2583static const struct net_device_ops rtw_cfg80211_monitor_if_ops = {
2584 .ndo_open = rtw_cfg80211_monitor_if_open,
2585 .ndo_stop = rtw_cfg80211_monitor_if_close,
2586 .ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry,
2587 .ndo_set_mac_address = rtw_cfg80211_monitor_if_set_mac_address,
2588};
2589
2590static int rtw_cfg80211_add_monitor_if(struct rtw_adapter *padapter, char *name,
2591 struct net_device **ndev)
2592{
2593 int ret = 0;
2594 struct net_device *mon_ndev = NULL;
2595 struct wireless_dev *mon_wdev = NULL;
2596 struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
2597
2598 if (!name) {
9cd613c7
JS
2599 DBG_8723A("%s(%s): without specific name\n",
2600 __func__, padapter->pnetdev->name);
b1925ad8
LF
2601 ret = -EINVAL;
2602 goto out;
2603 }
2604
2605 if (pwdev_priv->pmon_ndev) {
9cd613c7
JS
2606 DBG_8723A("%s(%s): monitor interface exist: %s\n", __func__,
2607 padapter->pnetdev->name, pwdev_priv->pmon_ndev->name);
b1925ad8
LF
2608 ret = -EBUSY;
2609 goto out;
2610 }
2611
2612 mon_ndev = alloc_etherdev(sizeof(struct rtw_adapter));
2613 if (!mon_ndev) {
9cd613c7
JS
2614 DBG_8723A("%s(%s): allocate ndev fail\n", __func__,
2615 padapter->pnetdev->name);
b1925ad8
LF
2616 ret = -ENOMEM;
2617 goto out;
2618 }
2619
2620 mon_ndev->type = ARPHRD_IEEE80211_RADIOTAP;
2621 strncpy(mon_ndev->name, name, IFNAMSIZ);
2622 mon_ndev->name[IFNAMSIZ - 1] = 0;
2623 mon_ndev->destructor = rtw_ndev_destructor;
2624
2625 mon_ndev->netdev_ops = &rtw_cfg80211_monitor_if_ops;
2626
2627 /* wdev */
2628 mon_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
2629 if (!mon_wdev) {
9cd613c7
JS
2630 DBG_8723A("%s(%s): allocate mon_wdev fail\n", __func__,
2631 padapter->pnetdev->name);
b1925ad8
LF
2632 ret = -ENOMEM;
2633 goto out;
2634 }
2635
2636 mon_wdev->wiphy = padapter->rtw_wdev->wiphy;
2637 mon_wdev->netdev = mon_ndev;
2638 mon_wdev->iftype = NL80211_IFTYPE_MONITOR;
2639 mon_ndev->ieee80211_ptr = mon_wdev;
2640
2641 ret = register_netdevice(mon_ndev);
2642 if (ret) {
2643 goto out;
2644 }
2645
2646 *ndev = pwdev_priv->pmon_ndev = mon_ndev;
2647 memcpy(pwdev_priv->ifname_mon, name, IFNAMSIZ + 1);
2648
2649out:
2650 if (ret) {
2651 kfree(mon_wdev);
2652 mon_wdev = NULL;
2653 }
2654
2655 if (ret && mon_ndev) {
2656 free_netdev(mon_ndev);
2657 *ndev = mon_ndev = NULL;
2658 }
2659
2660 return ret;
2661}
2662
2663static struct wireless_dev *
2664cfg80211_rtw_add_virtual_intf(struct wiphy *wiphy, const char *name,
2665 enum nl80211_iftype type, u32 *flags,
2666 struct vif_params *params)
2667{
2668 int ret = 0;
2669 struct net_device *ndev = NULL;
2670 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2671
9cd613c7
JS
2672 DBG_8723A("%s(%s): wiphy:%s, name:%s, type:%d\n", __func__,
2673 padapter->pnetdev->name, wiphy_name(wiphy), name, type);
b1925ad8
LF
2674
2675 switch (type) {
2676 case NL80211_IFTYPE_ADHOC:
2677 case NL80211_IFTYPE_AP_VLAN:
2678 case NL80211_IFTYPE_WDS:
2679 case NL80211_IFTYPE_MESH_POINT:
2680 ret = -ENODEV;
2681 break;
2682 case NL80211_IFTYPE_MONITOR:
2683 ret =
2684 rtw_cfg80211_add_monitor_if(padapter, (char *)name, &ndev);
2685 break;
2686
2687 case NL80211_IFTYPE_P2P_CLIENT:
2688 case NL80211_IFTYPE_STATION:
2689 ret = -ENODEV;
2690 break;
2691
2692 case NL80211_IFTYPE_P2P_GO:
2693 case NL80211_IFTYPE_AP:
2694 ret = -ENODEV;
2695 break;
2696 default:
2697 ret = -ENODEV;
2698 DBG_8723A("Unsupported interface type\n");
2699 break;
2700 }
2701
9cd613c7
JS
2702 DBG_8723A("%s(%s): ndev:%p, ret:%d\n", __func__,
2703 padapter->pnetdev->name,
b1925ad8
LF
2704 ndev, ret);
2705
2706 return ndev ? ndev->ieee80211_ptr : ERR_PTR(ret);
2707}
2708
2709static int cfg80211_rtw_del_virtual_intf(struct wiphy *wiphy,
2710 struct wireless_dev *wdev)
2711{
2712 struct rtw_wdev_priv *pwdev_priv =
2713 (struct rtw_wdev_priv *)wiphy_priv(wiphy);
2714 struct net_device *ndev;
2715 ndev = wdev ? wdev->netdev : NULL;
2716
2717 if (!ndev)
2718 goto exit;
2719
2720 unregister_netdevice(ndev);
2721
2722 if (ndev == pwdev_priv->pmon_ndev) {
2723 pwdev_priv->pmon_ndev = NULL;
2724 pwdev_priv->ifname_mon[0] = '\0';
a790d58e
JS
2725 DBG_8723A("%s(%s): remove monitor interface\n",
2726 __func__, ndev->name);
b1925ad8
LF
2727 }
2728
2729exit:
2730 return 0;
2731}
2732
2733static int rtw_add_beacon(struct rtw_adapter *adapter, const u8 *head,
2734 size_t head_len, const u8 *tail, size_t tail_len)
2735{
2736 int ret = 0;
db97812c 2737 u8 *pbuf;
fb5fd46d 2738 uint len, ielen, wps_ielen = 0;
b1925ad8 2739 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
ddf5c2bd
JS
2740 struct wlan_bssid_ex *bss = &pmlmepriv->cur_network.network;
2741 const struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)head;
fb5fd46d 2742 struct ieee80211_mgmt *tmpmgmt;
b1925ad8
LF
2743 /* struct sta_priv *pstapriv = &padapter->stapriv; */
2744
2745 DBG_8723A("%s beacon_head_len =%zu, beacon_tail_len =%zu\n",
2746 __func__, head_len, tail_len);
2747
2748 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2749 return -EINVAL;
2750
ddf5c2bd 2751 if (head_len < offsetof(struct ieee80211_mgmt, u.beacon.variable))
b1925ad8
LF
2752 return -EINVAL;
2753
2754 pbuf = kzalloc(head_len + tail_len, GFP_KERNEL);
2755 if (!pbuf)
2756 return -ENOMEM;
fb5fd46d 2757 tmpmgmt = (struct ieee80211_mgmt *)pbuf;
ddf5c2bd
JS
2758
2759 bss->beacon_interval = get_unaligned_le16(&mgmt->u.beacon.beacon_int);
2760 bss->capability = get_unaligned_le16(&mgmt->u.beacon.capab_info);
2761 bss->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp);
2762
b1925ad8 2763 /* 24 = beacon header len. */
fb5fd46d
JS
2764 memcpy(pbuf, (void *)head, head_len);
2765 memcpy(pbuf + head_len, (void *)tail, tail_len);
b1925ad8 2766
fb5fd46d
JS
2767 len = head_len + tail_len;
2768 ielen = len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
b1925ad8 2769 /* check wps ie if inclued */
d3797af4
JS
2770 if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
2771 WLAN_OUI_TYPE_MICROSOFT_WPS,
fb5fd46d 2772 tmpmgmt->u.beacon.variable, ielen))
b1925ad8
LF
2773 DBG_8723A("add bcn, wps_ielen =%d\n", wps_ielen);
2774
b1925ad8 2775 /* pbss_network->IEs will not include p2p_ie, wfd ie */
fb5fd46d 2776 rtw_ies_remove_ie23a(tmpmgmt->u.beacon.variable, &ielen, 0,
9300c94b 2777 WLAN_EID_VENDOR_SPECIFIC, P2P_OUI23A, 4);
fb5fd46d 2778 rtw_ies_remove_ie23a(tmpmgmt->u.beacon.variable, &ielen, 0,
9300c94b 2779 WLAN_EID_VENDOR_SPECIFIC, WFD_OUI23A, 4);
b1925ad8 2780
fb5fd46d
JS
2781 len = ielen + offsetof(struct ieee80211_mgmt, u.beacon.variable);
2782 if (rtw_check_beacon_data23a(adapter, tmpmgmt, len) == _SUCCESS) {
b1925ad8 2783 ret = 0;
b1925ad8
LF
2784 } else {
2785 ret = -EINVAL;
2786 }
2787
2788 kfree(pbuf);
2789
2790 return ret;
2791}
2792
2793static int cfg80211_rtw_start_ap(struct wiphy *wiphy, struct net_device *ndev,
2794 struct cfg80211_ap_settings *settings)
2795{
2796 int ret = 0;
2797 struct rtw_adapter *adapter = wiphy_to_adapter(wiphy);
2798
a790d58e
JS
2799 DBG_8723A("%s(%s): hidden_ssid:%d, auth_type:%d\n",
2800 __func__, ndev->name, settings->hidden_ssid,
b1925ad8
LF
2801 settings->auth_type);
2802
2803 ret = rtw_add_beacon(adapter, settings->beacon.head,
2804 settings->beacon.head_len, settings->beacon.tail,
2805 settings->beacon.tail_len);
2806
2807 adapter->mlmeextpriv.mlmext_info.hidden_ssid_mode =
2808 settings->hidden_ssid;
2809
2810 if (settings->ssid && settings->ssid_len) {
2811 struct wlan_bssid_ex *pbss_network =
2812 &adapter->mlmepriv.cur_network.network;
2813 struct wlan_bssid_ex *pbss_network_ext =
2814 &adapter->mlmeextpriv.mlmext_info.network;
2815
b1925ad8
LF
2816 memcpy(pbss_network->Ssid.ssid, (void *)settings->ssid,
2817 settings->ssid_len);
2818 pbss_network->Ssid.ssid_len = settings->ssid_len;
2819 memcpy(pbss_network_ext->Ssid.ssid, (void *)settings->ssid,
2820 settings->ssid_len);
2821 pbss_network_ext->Ssid.ssid_len = settings->ssid_len;
b1925ad8
LF
2822 }
2823
2824 return ret;
2825}
2826
2827static int cfg80211_rtw_change_beacon(struct wiphy *wiphy,
2828 struct net_device *ndev,
2829 struct cfg80211_beacon_data *info)
2830{
2831 int ret = 0;
2832 struct rtw_adapter *adapter = wiphy_to_adapter(wiphy);
2833
a790d58e 2834 DBG_8723A("%s(%s)\n", __func__, ndev->name);
b1925ad8
LF
2835
2836 ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail,
2837 info->tail_len);
2838
2839 return ret;
2840}
2841
2842static int cfg80211_rtw_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
2843{
a790d58e 2844 DBG_8723A("%s(%s)\n", __func__, ndev->name);
b1925ad8
LF
2845 return 0;
2846}
2847
2848static int cfg80211_rtw_add_station(struct wiphy *wiphy,
f9da455b 2849 struct net_device *ndev, const u8 *mac,
b1925ad8
LF
2850 struct station_parameters *params)
2851{
a790d58e 2852 DBG_8723A("%s(%s)\n", __func__, ndev->name);
b1925ad8
LF
2853
2854 return 0;
2855}
2856
2857static int cfg80211_rtw_del_station(struct wiphy *wiphy,
f9da455b 2858 struct net_device *ndev, const u8 *mac)
b1925ad8
LF
2859{
2860 int ret = 0;
2861 struct list_head *phead, *plist, *ptmp;
2862 u8 updated = 0;
2863 struct sta_info *psta;
2864 struct rtw_adapter *padapter = netdev_priv(ndev);
2865 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2866 struct sta_priv *pstapriv = &padapter->stapriv;
2867
a790d58e 2868 DBG_8723A("+%s(%s)\n", __func__, ndev->name);
b1925ad8
LF
2869
2870 if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true) {
2871 DBG_8723A("%s, fw_state != FW_LINKED|WIFI_AP_STATE\n",
2872 __func__);
2873 return -EINVAL;
2874 }
2875
2876 if (!mac) {
2877 DBG_8723A("flush all sta, and cam_entry\n");
2878
2879 flush_all_cam_entry23a(padapter); /* clear CAM */
2880
2881 ret = rtw_sta_flush23a(padapter);
2882
2883 return ret;
2884 }
2885
2886 DBG_8723A("free sta macaddr =" MAC_FMT "\n", MAC_ARG(mac));
2887
2888 if (is_broadcast_ether_addr(mac))
2889 return -EINVAL;
2890
2891 spin_lock_bh(&pstapriv->asoc_list_lock);
2892
2893 phead = &pstapriv->asoc_list;
2894
2895 /* check asoc_queue */
2896 list_for_each_safe(plist, ptmp, phead) {
2897 psta = container_of(plist, struct sta_info, asoc_list);
2898
cc2db7cb 2899 if (ether_addr_equal(mac, psta->hwaddr)) {
b1925ad8
LF
2900 if (psta->dot8021xalg == 1 &&
2901 psta->bpairwise_key_installed == false) {
2902 DBG_8723A("%s, sta's dot8021xalg = 1 and "
2903 "key_installed = false\n", __func__);
2904 } else {
2905 DBG_8723A("free psta =%p, aid =%d\n", psta,
2906 psta->aid);
2907
2908 list_del_init(&psta->asoc_list);
2909 pstapriv->asoc_list_cnt--;
2910
2911 /* spin_unlock_bh(&pstapriv->asoc_list_lock); */
2912 updated =
2913 ap_free_sta23a(padapter, psta, true,
2914 WLAN_REASON_DEAUTH_LEAVING);
2915 /* spin_lock_bh(&pstapriv->asoc_list_lock); */
2916
2917 psta = NULL;
2918
2919 break;
2920 }
2921 }
2922 }
2923
2924 spin_unlock_bh(&pstapriv->asoc_list_lock);
2925
2926 associated_clients_update23a(padapter, updated);
2927
a790d58e 2928 DBG_8723A("-%s(%s)\n", __func__, ndev->name);
b1925ad8
LF
2929
2930 return ret;
2931}
2932
2933static int cfg80211_rtw_change_station(struct wiphy *wiphy,
f9da455b 2934 struct net_device *ndev, const u8 *mac,
b1925ad8
LF
2935 struct station_parameters *params)
2936{
a790d58e 2937 DBG_8723A("%s(%s)\n", __func__, ndev->name);
b1925ad8
LF
2938 return 0;
2939}
2940
2941static int cfg80211_rtw_dump_station(struct wiphy *wiphy,
2942 struct net_device *ndev, int idx, u8 *mac,
2943 struct station_info *sinfo)
2944{
a790d58e 2945 DBG_8723A("%s(%s)\n", __func__, ndev->name);
b1925ad8
LF
2946
2947 /* TODO: dump scanned queue */
2948
2949 return -ENOENT;
2950}
2951
2952static int cfg80211_rtw_change_bss(struct wiphy *wiphy, struct net_device *ndev,
2953 struct bss_parameters *params)
2954{
a790d58e 2955 DBG_8723A("%s(%s)\n", __func__, ndev->name);
b1925ad8
LF
2956 return 0;
2957}
2958#endif /* CONFIG_8723AU_AP_MODE */
2959
b1925ad8
LF
2960static int _cfg80211_rtw_mgmt_tx(struct rtw_adapter *padapter, u8 tx_ch,
2961 const u8 *buf, size_t len)
2962{
2963 struct xmit_frame *pmgntframe;
2964 struct pkt_attrib *pattrib;
2965 unsigned char *pframe;
2966 int ret = _FAIL;
b1925ad8
LF
2967 struct ieee80211_hdr *pwlanhdr;
2968 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2969 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
b1925ad8
LF
2970
2971 if (_FAIL == rtw_pwr_wakeup(padapter)) {
2972 ret = -EFAULT;
2973 goto exit;
2974 }
2975
2976 rtw_set_scan_deny(padapter, 1000);
2977
2978 rtw_scan_abort23a(padapter);
2979
2980 if (tx_ch != rtw_get_oper_ch23a(padapter)) {
2981 if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED))
2982 pmlmeext->cur_channel = tx_ch;
2983 set_channel_bwmode23a(padapter, tx_ch,
2984 HAL_PRIME_CHNL_OFFSET_DONT_CARE,
2985 HT_CHANNEL_WIDTH_20);
2986 }
2987
2988 /* starting alloc mgmt frame to dump it */
2989 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
de62f67a 2990 if (!pmgntframe) {
b1925ad8
LF
2991 /* ret = -ENOMEM; */
2992 ret = _FAIL;
2993 goto exit;
2994 }
2995
2996 /* update attribute */
2997 pattrib = &pmgntframe->attrib;
2998 update_mgntframe_attrib23a(padapter, pattrib);
2999 pattrib->retry_ctrl = false;
3000
3001 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3002
3003 pframe = (u8 *) (pmgntframe->buf_addr) + TXDESC_OFFSET;
3004
3005 memcpy(pframe, (void *)buf, len);
3006 pattrib->pktlen = len;
3007
3008 pwlanhdr = (struct ieee80211_hdr *)pframe;
3009 /* update seq number */
3010 pmlmeext->mgnt_seq = le16_to_cpu(pwlanhdr->seq_ctrl) >> 4;
3011 pattrib->seqnum = pmlmeext->mgnt_seq;
3012 pmlmeext->mgnt_seq++;
3013
b1925ad8
LF
3014 pattrib->last_txcmdsz = pattrib->pktlen;
3015
de62f67a 3016 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
b1925ad8 3017
de62f67a
JS
3018 if (ret != _SUCCESS)
3019 DBG_8723A("%s, ack == false\n", __func__);
3020 else
3021 DBG_8723A("%s, ack == true\n", __func__);
b1925ad8
LF
3022
3023exit:
3024
b1925ad8 3025 DBG_8723A("%s, ret =%d\n", __func__, ret);
b1925ad8
LF
3026
3027 return ret;
3028}
3029
3030static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
b1925ad8 3031 struct cfg80211_mgmt_tx_params *params,
b1925ad8
LF
3032 u64 *cookie)
3033{
3034 struct rtw_adapter *padapter =
3035 (struct rtw_adapter *)wiphy_to_adapter(wiphy);
b1925ad8
LF
3036 int ret = 0;
3037 int tx_ret;
3038 u32 dump_limit = RTW_MAX_MGMT_TX_CNT;
3039 u32 dump_cnt = 0;
3040 bool ack = true;
3041 u8 category, action;
b1925ad8 3042 unsigned long start = jiffies;
b1925ad8
LF
3043 size_t len = params->len;
3044 struct ieee80211_channel *chan = params->chan;
3045 const u8 *buf = params->buf;
ea2ea440 3046 struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *)buf;
b1925ad8
LF
3047 u8 tx_ch = (u8) ieee80211_frequency_to_channel(chan->center_freq);
3048
ea2ea440
JS
3049 if (!ieee80211_is_action(hdr->frame_control))
3050 return -EINVAL;
3051
b1925ad8
LF
3052 /* cookie generation */
3053 *cookie = (unsigned long)buf;
3054
9cd613c7
JS
3055 DBG_8723A("%s(%s): len =%zu, ch =%d\n", __func__,
3056 padapter->pnetdev->name, len, tx_ch);
b1925ad8
LF
3057
3058 /* indicate ack before issue frame to avoid racing with rsp frame */
56b0bd91
JS
3059 cfg80211_mgmt_tx_status(padapter->rtw_wdev, *cookie, buf, len, ack,
3060 GFP_KERNEL);
b1925ad8 3061
b1925ad8 3062 DBG_8723A("RTW_Tx:tx_ch =%d, da =" MAC_FMT "\n", tx_ch,
ea2ea440
JS
3063 MAC_ARG(hdr->da));
3064 category = hdr->u.action.category;
3065 action = hdr->u.action.u.wme_action.action_code;
2e74d336 3066 DBG_8723A("RTW_Tx:category(%u), action(%u)\n", category, action);
b1925ad8 3067
b1925ad8
LF
3068 do {
3069 dump_cnt++;
3070 tx_ret = _cfg80211_rtw_mgmt_tx(padapter, tx_ch, buf, len);
3071 } while (dump_cnt < dump_limit && tx_ret != _SUCCESS);
3072
3073 if (tx_ret != _SUCCESS || dump_cnt > 1) {
9cd613c7
JS
3074 DBG_8723A("%s(%s): %s (%d/%d) in %d ms\n",
3075 __func__, padapter->pnetdev->name,
b1925ad8
LF
3076 tx_ret == _SUCCESS ? "OK" : "FAIL", dump_cnt,
3077 dump_limit, jiffies_to_msecs(jiffies - start));
3078 }
3079
b1925ad8
LF
3080 return ret;
3081}
3082
3083static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy,
3084 struct wireless_dev *wdev,
3085 u16 frame_type, bool reg)
3086{
b1925ad8
LF
3087 if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
3088 return;
3089
3090 return;
3091}
3092
b1925ad8
LF
3093static struct cfg80211_ops rtw_cfg80211_ops = {
3094 .change_virtual_intf = cfg80211_rtw_change_iface,
3095 .add_key = cfg80211_rtw_add_key,
3096 .get_key = cfg80211_rtw_get_key,
3097 .del_key = cfg80211_rtw_del_key,
3098 .set_default_key = cfg80211_rtw_set_default_key,
3099 .get_station = cfg80211_rtw_get_station,
3100 .scan = cfg80211_rtw_scan,
3101 .set_wiphy_params = cfg80211_rtw_set_wiphy_params,
3102 .connect = cfg80211_rtw_connect,
3103 .disconnect = cfg80211_rtw_disconnect,
3104 .join_ibss = cfg80211_rtw_join_ibss,
3105 .leave_ibss = cfg80211_rtw_leave_ibss,
3106 .set_tx_power = cfg80211_rtw_set_txpower,
3107 .get_tx_power = cfg80211_rtw_get_txpower,
3108 .set_power_mgmt = cfg80211_rtw_set_power_mgmt,
3109 .set_pmksa = cfg80211_rtw_set_pmksa,
3110 .del_pmksa = cfg80211_rtw_del_pmksa,
3111 .flush_pmksa = cfg80211_rtw_flush_pmksa,
3112
3113#ifdef CONFIG_8723AU_AP_MODE
3114 .add_virtual_intf = cfg80211_rtw_add_virtual_intf,
3115 .del_virtual_intf = cfg80211_rtw_del_virtual_intf,
3116
3117 .start_ap = cfg80211_rtw_start_ap,
3118 .change_beacon = cfg80211_rtw_change_beacon,
3119 .stop_ap = cfg80211_rtw_stop_ap,
3120
3121 .add_station = cfg80211_rtw_add_station,
3122 .del_station = cfg80211_rtw_del_station,
3123 .change_station = cfg80211_rtw_change_station,
3124 .dump_station = cfg80211_rtw_dump_station,
3125 .change_bss = cfg80211_rtw_change_bss,
3126#endif /* CONFIG_8723AU_AP_MODE */
3127
b1925ad8
LF
3128 .mgmt_tx = cfg80211_rtw_mgmt_tx,
3129 .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register,
3130};
3131
3132static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap,
3133 enum ieee80211_band band, u8 rf_type)
3134{
3135
3136#define MAX_BIT_RATE_40MHZ_MCS15 300 /* Mbps */
3137#define MAX_BIT_RATE_40MHZ_MCS7 150 /* Mbps */
3138
3139 ht_cap->ht_supported = true;
3140
3141 ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
3142 IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 |
3143 IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU;
3144
3145 /*
3146 *Maximum length of AMPDU that the STA can receive.
3147 *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
3148 */
3149 ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
3150
3151 /*Minimum MPDU start spacing , */
3152 ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
3153
3154 ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
3155
3156 /*
3157 *hw->wiphy->bands[IEEE80211_BAND_2GHZ]
3158 *base on ant_num
3159 *rx_mask: RX mask
3160 *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7
3161 *if rx_ant = 2 rx_mask[1]= 0xff;==>MCS8-MCS15
3162 *if rx_ant >= 3 rx_mask[2]= 0xff;
3163 *if BW_40 rx_mask[4]= 0x01;
3164 *highest supported RX rate
3165 */
3166 if (rf_type == RF_1T1R) {
3167 ht_cap->mcs.rx_mask[0] = 0xFF;
3168 ht_cap->mcs.rx_mask[1] = 0x00;
3169 ht_cap->mcs.rx_mask[4] = 0x01;
3170
3171 ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS7;
3172 } else if ((rf_type == RF_1T2R) || (rf_type == RF_2T2R)) {
3173 ht_cap->mcs.rx_mask[0] = 0xFF;
3174 ht_cap->mcs.rx_mask[1] = 0xFF;
3175 ht_cap->mcs.rx_mask[4] = 0x01;
3176
3177 ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS15;
3178 } else {
3179 DBG_8723A("%s, error rf_type =%d\n", __func__, rf_type);
3180 }
3181
3182}
3183
3184void rtw_cfg80211_init_wiphy(struct rtw_adapter *padapter)
3185{
3186 u8 rf_type;
3187 struct ieee80211_supported_band *bands;
3188 struct wireless_dev *pwdev = padapter->rtw_wdev;
3189 struct wiphy *wiphy = pwdev->wiphy;
3190
c2370e83 3191 rf_type = rtl8723a_get_rf_type(padapter);
b1925ad8
LF
3192
3193 DBG_8723A("%s:rf_type =%d\n", __func__, rf_type);
3194
3195 /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */
3196 {
3197 bands = wiphy->bands[IEEE80211_BAND_2GHZ];
3198 if (bands)
3199 rtw_cfg80211_init_ht_capab(&bands->ht_cap,
3200 IEEE80211_BAND_2GHZ,
3201 rf_type);
3202 }
3203
3204 /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */
3205 {
3206 bands = wiphy->bands[IEEE80211_BAND_5GHZ];
3207 if (bands)
3208 rtw_cfg80211_init_ht_capab(&bands->ht_cap,
3209 IEEE80211_BAND_5GHZ,
3210 rf_type);
3211 }
3212}
3213
3214static void rtw_cfg80211_preinit_wiphy(struct rtw_adapter *padapter,
3215 struct wiphy *wiphy)
3216{
3217 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
3218
3219 wiphy->max_scan_ssids = RTW_SSID_SCAN_AMOUNT;
3220 wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
3221 wiphy->max_num_pmkids = RTW_MAX_NUM_PMKIDS;
3222
3223 wiphy->max_remain_on_channel_duration =
3224 RTW_MAX_REMAIN_ON_CHANNEL_DURATION;
3225
3226 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
3227 BIT(NL80211_IFTYPE_ADHOC) |
3228#ifdef CONFIG_8723AU_AP_MODE
3229 BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR) |
b1925ad8
LF
3230#endif
3231 0;
3232
3233#ifdef CONFIG_8723AU_AP_MODE
3234 wiphy->mgmt_stypes = rtw_cfg80211_default_mgmt_stypes;
3235#endif /* CONFIG_8723AU_AP_MODE */
3236
3237 wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
3238
3239 /*
3240 wiphy->iface_combinations = &rtw_combinations;
3241 wiphy->n_iface_combinations = 1;
3242 */
3243
3244 wiphy->cipher_suites = rtw_cipher_suites;
3245 wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites);
3246
3247 /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */
3248 wiphy->bands[IEEE80211_BAND_2GHZ] =
3249 rtw_spt_band_alloc(IEEE80211_BAND_2GHZ);
3250 /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */
3251 wiphy->bands[IEEE80211_BAND_5GHZ] =
3252 rtw_spt_band_alloc(IEEE80211_BAND_5GHZ);
3253
3254 wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
3255 wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAVE_AP_SME;
3256
3257 if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)
3258 wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
3259 else
3260 wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
3261}
3262
3263int rtw_wdev_alloc(struct rtw_adapter *padapter, struct device *dev)
3264{
3265 int ret = 0;
3266 struct wiphy *wiphy;
3267 struct wireless_dev *wdev;
3268 struct rtw_wdev_priv *pwdev_priv;
3269 struct net_device *pnetdev = padapter->pnetdev;
3270
3271 DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
3272
3273 /* wiphy */
3274 wiphy = wiphy_new(&rtw_cfg80211_ops, sizeof(struct rtw_wdev_priv));
3275 if (!wiphy) {
3276 DBG_8723A("Couldn't allocate wiphy device\n");
3277 ret = -ENOMEM;
3278 goto exit;
3279 }
d165e4ef
JS
3280
3281 /* wdev */
3282 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
3283 if (!wdev) {
3284 DBG_8723A("Couldn't allocate wireless device\n");
3285 ret = -ENOMEM;
3286 goto free_wiphy;
3287 }
3288
b1925ad8
LF
3289 set_wiphy_dev(wiphy, dev);
3290 rtw_cfg80211_preinit_wiphy(padapter, wiphy);
3291
3292 ret = wiphy_register(wiphy);
3293 if (ret < 0) {
3294 DBG_8723A("Couldn't register wiphy device\n");
d165e4ef 3295 goto free_wdev;
b1925ad8
LF
3296 }
3297
b1925ad8
LF
3298 wdev->wiphy = wiphy;
3299 wdev->netdev = pnetdev;
3300 /* wdev->iftype = NL80211_IFTYPE_STATION; */
3301 /* for rtw_setopmode_cmd23a() in cfg80211_rtw_change_iface() */
3302 wdev->iftype = NL80211_IFTYPE_MONITOR;
3303 padapter->rtw_wdev = wdev;
3304 pnetdev->ieee80211_ptr = wdev;
3305
3306 /* init pwdev_priv */
3307 pwdev_priv = wdev_to_priv(wdev);
3308 pwdev_priv->rtw_wdev = wdev;
3309 pwdev_priv->pmon_ndev = NULL;
3310 pwdev_priv->ifname_mon[0] = '\0';
3311 pwdev_priv->padapter = padapter;
3312 pwdev_priv->scan_request = NULL;
3313 spin_lock_init(&pwdev_priv->scan_req_lock);
3314
3315 pwdev_priv->p2p_enabled = false;
b1925ad8
LF
3316
3317 if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)
3318 pwdev_priv->power_mgmt = true;
3319 else
3320 pwdev_priv->power_mgmt = false;
3321
3322 return ret;
d165e4ef
JS
3323free_wdev:
3324 kfree(wdev);
b1925ad8
LF
3325free_wiphy:
3326 wiphy_free(wiphy);
3327exit:
3328 return ret;
3329}
3330
3331void rtw_wdev_free(struct wireless_dev *wdev)
3332{
b1925ad8
LF
3333 DBG_8723A("%s(wdev =%p)\n", __func__, wdev);
3334
3335 if (!wdev)
3336 return;
3337
b1925ad8
LF
3338 kfree(wdev->wiphy->bands[IEEE80211_BAND_2GHZ]);
3339 kfree(wdev->wiphy->bands[IEEE80211_BAND_5GHZ]);
3340
3341 wiphy_free(wdev->wiphy);
3342
3343 kfree(wdev);
3344}
3345
3346void rtw_wdev_unregister(struct wireless_dev *wdev)
3347{
3348 struct rtw_wdev_priv *pwdev_priv;
3349
3350 DBG_8723A("%s(wdev =%p)\n", __func__, wdev);
3351
3352 if (!wdev)
3353 return;
3354
3355 pwdev_priv = wdev_to_priv(wdev);
3356
3357 rtw_cfg80211_indicate_scan_done(pwdev_priv, true);
3358
3359 if (pwdev_priv->pmon_ndev) {
3360 DBG_8723A("%s, unregister monitor interface\n", __func__);
3361 unregister_netdev(pwdev_priv->pmon_ndev);
3362 }
3363
3364 wiphy_unregister(wdev->wiphy);
3365}
This page took 0.353833 seconds and 5 git commands to generate.