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