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