1 /** @file wifi-uap.c
2 *
3 * @brief This file provides UAP related APIs.
4 *
5 * Copyright 2008-2024 NXP
6 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 */
10
11 #include <mlan_api.h>
12
13 /* Additional WMSDK header files */
14 #include <wmerrno.h>
15 #include <osa.h>
16 #include <wifi.h>
17 #if defined(RW610)
18 #include "wifi-imu.h"
19 #else
20 #include "wifi-sdio.h"
21 #endif
22 #if CONFIG_WPA_SUPP_AP
23 #include "wifi_nxp_internal.h"
24 #include "rtos_wpa_supp_if.h"
25 #endif
26 #include "wifi-internal.h"
27 #include "mlan_ieee.h"
28 #include <mlan_remap_mem_operations.h>
29
30 /* fixme: Some of the following options could be added to kconfig. While
31 adding the ranges in kconfig use the ones given as macros in
32 mlan_uap_cmdevent.c */
33 #ifdef RW610
34 #define UAP_BEACON_PERIOD 100U
35 #else
36 #define UAP_BEACON_PERIOD 200U
37 #endif
38 #define UAP_DTIM_PERIOD 1
39 #define MAX_RATES 14U
40
41 #if CONFIG_5GHz_SUPPORT
42 static uint8_t rates_5ghz[] = {0x8c, 0x98, 0xb0, 0x12, 0x24, 0x48, 0x60, 0x6c, 0x00};
43 #endif
44
45 static uint8_t rates_2ghz[] = {0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, 0x00};
46
47 static uint8_t rates_2ghz_b[] = {0x82, 0x84, 0x8b, 0x96, 0x00};
48
49 #if CONFIG_11AC
50 /**
51 * @brief initialize AP bss config
52 * @param pmpriv A pointer to mlan_private structure
53 * @param band BAND_5G/BAND_2GHZ
54 * @return 0 -- success, otherwise fail
55 */
wifi_check_11ac_capability(mlan_private * pmpriv,t_u8 band)56 static bool wifi_check_11ac_capability(mlan_private *pmpriv, t_u8 band)
57 {
58 mlan_adapter *pmadapter = pmpriv->adapter;
59 bool enable_11ac = MFALSE;
60
61 ENTER();
62 #if CONFIG_WIFI_CAPA
63 if (!pmadapter->usr_dot_11ac_enable)
64 {
65 return enable_11ac;
66 }
67 #endif
68 if ((band == BAND_CONFIG_5GHZ) && !(pmadapter->fw_bands & BAND_AAC))
69 {
70 PRINTM(MCMND, "FW don't support 5G AC\n");
71 LEAVE();
72 return enable_11ac;
73 }
74 if ((band == BAND_CONFIG_ACS_MODE || band == BAND_CONFIG_MANUAL) && !(pmadapter->fw_bands & BAND_GAC))
75 {
76 PRINTM(MCMND, "FW don't support 2G AC");
77 LEAVE();
78 return enable_11ac;
79 }
80 enable_11ac = MTRUE;
81
82 LEAVE();
83 return enable_11ac;
84 }
85
86 #define VHT_CAP_11AC_MASK 0x007fffff
87
88 /**
89 * @brief enable/disable 11AC
90 *
91 * @param pmpriv A pointer to mlan_private structure
92 * @param action MLAN_ACT_DISABLE or MLAN_ACT_ENABLE
93 * @param band band config
94 *
95 * @return 0--success, otherwise failure
96 */
wifi_uap_set_11ac_status(mlan_private * pmpriv,t_u8 action,t_u8 bandwidth,t_u8 channel)97 static int wifi_uap_set_11ac_status(mlan_private *pmpriv, t_u8 action, t_u8 bandwidth, t_u8 channel)
98 {
99 mlan_adapter *pmadapter = pmpriv->adapter;
100 int ret = 0;
101 mlan_ds_11ac_vht_cfg vht_cfg;
102
103 (void)memset(&vht_cfg, 0, sizeof(vht_cfg));
104
105 #if CONFIG_5GHz_SUPPORT
106 if (channel > MAX_CHANNELS_BG)
107 {
108 vht_cfg.band = BAND_SELECT_A;
109 }
110 else
111 {
112 vht_cfg.band = BAND_SELECT_BG;
113 }
114 #else
115 vht_cfg.band = BAND_SELECT_BG;
116 #endif
117 vht_cfg.txrx = MLAN_RADIO_TXRX;
118
119 vht_cfg.vht_cap_info = pmadapter->usr_dot_11ac_dev_cap_a;
120 if (action == MLAN_ACT_DISABLE)
121 {
122 vht_cfg.bwcfg = BW_FOLLOW_HTCAP;
123 vht_cfg.vht_cap_info &= ~VHT_CAP_11AC_MASK;
124 vht_cfg.vht_rx_mcs = vht_cfg.vht_tx_mcs = 0xffff;
125 vht_cfg.skip_usr_11ac_mcs_cfg = MTRUE;
126 }
127 else
128 {
129 if (BANDWIDTH_80MHZ == bandwidth)
130 {
131 vht_cfg.bwcfg = BW_FOLLOW_VHTCAP;
132 }
133 else
134 {
135 vht_cfg.bwcfg = BW_FOLLOW_HTCAP;
136 }
137
138 vht_cfg.vht_cap_info &= ~DEFALUT_11AC_CAP_BEAMFORMING_RESET_MASK;
139 #ifdef RW610
140 vht_cfg.vht_cap_info &= ~DEFALUT_11AC_CAP_SHORTGI_80MHZ_RESET_MASK;
141 #endif
142 vht_cfg.vht_tx_mcs = pmadapter->usr_dot_11ac_mcs_support >> 16;
143 vht_cfg.vht_rx_mcs = pmadapter->usr_dot_11ac_mcs_support & 0xffff;
144 vht_cfg.skip_usr_11ac_mcs_cfg = MTRUE;
145 }
146
147 if ((GET_VHTCAP_MAXMPDULEN(vht_cfg.vht_cap_info)) != 0U)
148 {
149 RESET_11ACMAXMPDULEN(vht_cfg.vht_cap_info);
150 }
151 else
152 {
153 /** Do Nothing */
154 }
155
156 wifi_d("Uap:11ac=%d vht_cap_info=0x%x, vht_tx_mcs=0x%x, vht_rx_mcs=0x%x\r\n", action, vht_cfg.vht_cap_info,
157 vht_cfg.vht_tx_mcs, vht_cfg.vht_rx_mcs);
158 ret = (int)wlan_11ac_ioctl_vhtcfg(pmpriv, (t_u8)MLAN_ACT_SET, &vht_cfg);
159 return ret;
160 }
161 #endif
162
163 #if CONFIG_11AX
164 /**
165 * @brief initialize AP bss config
166 * @param pmpriv A pointer to mlan_private structure
167 * @param band BAND_5G/BAND_2GHZ
168 * @return 0 -- success, otherwise fail
169 */
wifi_check_11ax_capability(mlan_private * pmpriv,t_u8 band)170 static t_u8 wifi_check_11ax_capability(mlan_private *pmpriv, t_u8 band)
171 {
172 mlan_adapter *pmadapter = pmpriv->adapter;
173 t_u8 enable_11ax = MFALSE;
174
175 ENTER();
176 #if CONFIG_WIFI_CAPA
177 if (!pmadapter->usr_dot_11ax_enable)
178 {
179 return enable_11ax;
180 }
181 #endif
182 if ((band == BAND_CONFIG_5GHZ) && !(pmadapter->fw_bands & BAND_AAX))
183 {
184 PRINTM(MCMND, "FW don't support 5G AX\n");
185 LEAVE();
186 return enable_11ax;
187 }
188 if ((band == BAND_CONFIG_ACS_MODE || band == BAND_CONFIG_MANUAL) && !(pmadapter->fw_bands & BAND_GAX))
189 {
190 PRINTM(MCMND, "FW don't support 2G AX\n");
191 LEAVE();
192 return enable_11ax;
193 }
194 enable_11ax = MTRUE;
195 PRINTM(MCMND, "enable_11ax=%d\n", enable_11ax);
196 LEAVE();
197 return enable_11ax;
198 }
199
200 /**
201 * @brief enable/disable 11AX
202 *
203 * @param pmpriv A pointer to mlan_private structure
204 * @param action MLAN_ACT_DISABLE or MLAN_ACT_ENABLE
205 * @param band band config
206 *
207 * @return 0--success, otherwise failure
208 */
wifi_uap_set_11ax_status(mlan_private * pmpriv,t_u8 action,t_u8 band,t_u8 bandwidth)209 int wifi_uap_set_11ax_status(mlan_private *pmpriv, t_u8 action, t_u8 band, t_u8 bandwidth)
210 {
211 mlan_adapter *pmadapter = pmpriv->adapter;
212 int ret = 0;
213 mlan_ds_11ax_he_cfg he_cfg;
214
215 ENTER();
216 if ((band == BAND_CONFIG_5GHZ && !(pmadapter->fw_bands & BAND_AAX)) ||
217 ((band == BAND_CONFIG_ACS_MODE || band == BAND_CONFIG_MANUAL) && !(pmadapter->fw_bands & BAND_GAX)))
218 {
219 PRINTM(MERROR, "fw doesn't support 11ax\n");
220 ret = -WM_FAIL;
221 goto done;
222 }
223 memset(&he_cfg, 0, sizeof(he_cfg));
224 if (band == BAND_CONFIG_5GHZ)
225 {
226 he_cfg.band = MBIT(1);
227 (void)memcpy((void *)&he_cfg.he_cap, (const void *)pmadapter->hw_he_cap, pmadapter->hw_hecap_len);
228 }
229 else if (band == BAND_CONFIG_ACS_MODE || band == BAND_CONFIG_MANUAL)
230 {
231 he_cfg.band = MBIT(0);
232 (void)memcpy((void *)&he_cfg.he_cap, (const void *)pmadapter->hw_2g_he_cap, pmadapter->hw_2g_hecap_len);
233 if (bandwidth == BANDWIDTH_20MHZ)
234 {
235 he_cfg.he_cap.he_phy_cap[0] &= ~(MBIT(1));
236 }
237 }
238 else
239 {
240 PRINTM(MERROR, "Invalid band!\n");
241 ret = -WM_E_INVAL;
242 goto done;
243 }
244
245 #ifdef RW610
246 he_cfg.he_cap.he_phy_cap[0] &= ~DEFAULT_11AX_CAP_40MHZIH2_4GHZBAND_RESET_MASK;
247 #endif
248
249 #if CONFIG_11AX_TWT
250 /* uap mode clear TWT request bit */
251 he_cfg.he_cap.he_mac_cap[0] &= ~HE_MAC_CAP_TWT_REQ_SUPPORT;
252 #endif
253
254 if (action == MLAN_ACT_DISABLE)
255 {
256 if (he_cfg.he_cap.len && (he_cfg.he_cap.ext_id == HE_CAPABILITY))
257 memset(he_cfg.he_cap.he_txrx_mcs_support, 0xff, sizeof(he_cfg.he_cap.he_txrx_mcs_support));
258 else
259 {
260 PRINTM(MCMND, "11ax already disabled\n");
261 goto done;
262 }
263 }
264 DBG_HEXDUMP(MCMD_D, "HE_CFG ", (t_u8 *)&he_cfg, sizeof(he_cfg));
265 ret = wlan_cmd_11ax_cfg(pmpriv, HostCmd_ACT_GEN_SET, &he_cfg);
266 done:
267 LEAVE();
268 return ret;
269 }
270 #endif /* CONFIG_11AX */
271
wifi_uap_clear_domain_info()272 void wifi_uap_clear_domain_info()
273 {
274 wifi_get_command_lock();
275 HostCmd_DS_COMMAND *cmd = wifi_get_command_buffer();
276 HostCmd_DS_802_11D_DOMAIN_INFO *domain_info = (HostCmd_DS_802_11D_DOMAIN_INFO *)((t_u8 *)cmd + S_DS_GEN);
277
278 (void)memset(cmd, 0x00, sizeof(HostCmd_DS_COMMAND));
279 cmd->seq_num = HostCmd_SET_SEQ_NO_BSS_INFO(0 /* seq_num */, 0 /* bss_num */, BSS_TYPE_UAP);
280 cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11D_DOMAIN_INFO);
281 cmd->size = S_DS_GEN + sizeof(domain_info->action) + sizeof(MrvlIEtypesHeader_t);
282
283 domain_info->action = HostCmd_ACT_GEN_SET;
284 domain_info->domain.header.type = wlan_cpu_to_le16(TLV_TYPE_DOMAIN);
285
286 wifi_wait_for_cmdresp(NULL);
287 }
288
wifi_uap_prepare_and_send_cmd(mlan_private * pmpriv,t_u16 cmd_no,t_u16 cmd_action,t_u32 cmd_oid,t_void * pioctl_buf,t_void * pdata_buf,mlan_bss_type bss_type,void * priv)289 int wifi_uap_prepare_and_send_cmd(mlan_private *pmpriv,
290 t_u16 cmd_no,
291 t_u16 cmd_action,
292 t_u32 cmd_oid,
293 t_void *pioctl_buf,
294 t_void *pdata_buf,
295 mlan_bss_type bss_type,
296 void *priv)
297 {
298 (void)wifi_get_command_lock();
299 HostCmd_DS_COMMAND *cmd = wifi_get_command_buffer();
300
301 cmd->seq_num = HostCmd_SET_SEQ_NO_BSS_INFO(0U /* seq_num */, 0U /* bss_num */, (uint16_t)bss_type);
302 cmd->result = 0x0;
303
304 mlan_status rv = wlan_ops_uap_prepare_cmd(pmpriv, cmd_no, cmd_action, cmd_oid, pioctl_buf, pdata_buf, cmd);
305 if (rv != MLAN_STATUS_SUCCESS)
306 {
307 wifi_w("Failed to prepare cmd for uAP");
308 (void)wifi_put_command_lock();
309 return (int)rv;
310 }
311
312 (void)wifi_wait_for_cmdresp(priv);
313 return wm_wifi.cmd_resp_status;
314 }
315
316 /*
317 * Note: wlan_uap_domain_info() and wlan_uap_callback_domain_info() are the
318 * original function which handles this functionality. However, it does it
319 * through and IOCTL and its control flow will not work in our case. To
320 * elaborate, it first gets the channel number by sending a command to
321 * firmware. Then in the cmd resp handler to sends the domain info
322 * command. As per the current design of our driver we cannot send command
323 * from command resp handler. Hence, we have modified the control flow to
324 * suit our design.
325 *
326 * This Api is set as callback and called during uap start phase,
327 * getting region code by pmadapter.
328 * Then it sends 80211 domain info command to firmware
329 */
wifi_uap_downld_domain_params(int band)330 int wifi_uap_downld_domain_params(int band)
331 {
332 int rv;
333 mlan_adapter *pmadapter = mlan_adap;
334 mlan_private *priv_uap = pmadapter->priv[1];
335 int region_code = pmadapter->region_code;
336 const t_u8 *country_code = NULL;
337 int chan_spacing = 1;
338 int no_of_chan = 0;
339 t_u16 first_chan = 0, next_chan = 0, max_tx_power = 0;
340 wlan_802_11d_domain_reg_t *pdomain = &pmadapter->domain_reg;
341 const chan_freq_power_t *cfp;
342
343 /* get band and sub band lists */
344 #if CONFIG_5GHz_SUPPORT
345 if (band == BAND_A)
346 {
347 chan_spacing = 4;
348 no_of_chan = pmadapter->region_channel[BAND_5GHZ].num_cfp;
349 cfp = pmadapter->region_channel[BAND_5GHZ].pcfp;
350 }
351 else
352 #endif
353 {
354 no_of_chan = pmadapter->region_channel[BAND_2GHZ].num_cfp;
355 cfp = pmadapter->region_channel[BAND_2GHZ].pcfp;
356 }
357
358 /* get country code string from region code */
359 country_code = wlan_11d_code_2_region(pmadapter, (t_u8)region_code);
360 if (country_code == NULL)
361 {
362 wuap_e("wifi_uap_downld_domain_params get country_code from region_code failed");
363 return -WM_FAIL;
364 }
365
366 (void)__memset(pmadapter, pdomain, 0, sizeof(wlan_802_11d_domain_reg_t));
367 (void)__memcpy(pmadapter, pdomain->country_code, country_code, COUNTRY_CODE_LEN);
368 pdomain->band = band;
369
370 for (int i = 0; i < no_of_chan; i++)
371 {
372 if (first_chan && next_chan &&
373 next_chan + chan_spacing == cfp[i].channel &&
374 max_tx_power == cfp[i].max_tx_power)
375 {
376 next_chan = cfp[i].channel;
377 continue;
378 }
379
380 if (first_chan && next_chan)
381 {
382 pdomain->sub_band[pdomain->no_of_sub_band].first_chan = first_chan;
383 pdomain->sub_band[pdomain->no_of_sub_band].no_of_chan =
384 (next_chan - first_chan) / chan_spacing + 1;
385 pdomain->sub_band[pdomain->no_of_sub_band].max_tx_pwr = max_tx_power;
386 pdomain->no_of_sub_band ++;
387 first_chan = 0;
388 }
389
390 first_chan = next_chan = cfp[i].channel;
391 max_tx_power = cfp[i].max_tx_power;
392 }
393
394 if (first_chan)
395 {
396 pdomain->sub_band[pdomain->no_of_sub_band].first_chan = first_chan;
397 pdomain->sub_band[pdomain->no_of_sub_band].no_of_chan =
398 (next_chan - first_chan) / chan_spacing + 1;
399 pdomain->sub_band[pdomain->no_of_sub_band].max_tx_pwr = max_tx_power;
400 pdomain->no_of_sub_band ++;
401 }
402 rv = wifi_uap_prepare_and_send_cmd(priv_uap, HostCmd_CMD_802_11D_DOMAIN_INFO, HostCmd_ACT_GEN_SET, 0, NULL, NULL,
403 MLAN_BSS_TYPE_UAP, NULL);
404 if (rv != 0)
405 {
406 wuap_w("Unable to send uap domain info");
407 return -WM_FAIL;
408 }
409
410 return WM_SUCCESS;
411 }
412
wifi_cmd_uap_config(char * ssid,t_u8 * mac_addr,enum wlan_security_type security,int key_mgmt,char * passphrase,char * password,t_u8 channel,wifi_scan_chan_list_t scan_chan_list,t_u8 pwe_derivation,t_u8 transition_disable,t_u16 beacon_period,t_u8 bandwidth,t_u8 dtim_period,t_u8 chan_sw_count,mlan_bss_type bss_type,bool mfpc,bool mfpr)413 static int wifi_cmd_uap_config(char *ssid,
414 t_u8 *mac_addr,
415 enum wlan_security_type security,
416 int key_mgmt,
417 char *passphrase,
418 char *password,
419 t_u8 channel,
420 wifi_scan_chan_list_t scan_chan_list,
421 t_u8 pwe_derivation,
422 t_u8 transition_disable,
423 t_u16 beacon_period,
424 t_u8 bandwidth,
425 t_u8 dtim_period,
426 t_u8 chan_sw_count,
427 mlan_bss_type bss_type,
428 bool mfpc,
429 bool mfpr)
430 {
431 t_u32 ssid_len = strlen(ssid);
432 uint8_t i;
433 const t_u8 wmm_oui[4] = {0x00, 0x50, 0xf2, 0x02};
434 #if (CONFIG_UAP_AMPDU_TX) || (CONFIG_UAP_AMPDU_RX)
435 int ret;
436 t_u8 supported_mcs_set[] = {0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
437 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
438 #endif
439 #if CONFIG_11AC
440 bool enable_11ac = MFALSE;
441 #endif
442 #if CONFIG_11AX
443 t_u8 enable_11ax = MFALSE;
444 #endif
445
446 if (!(security == WLAN_SECURITY_NONE || security == WLAN_SECURITY_WPA2 ||
447 security == WLAN_SECURITY_WPA_WPA2_MIXED || security == WLAN_SECURITY_WPA3_SAE ||
448 security == WLAN_SECURITY_WPA2_WPA3_SAE_MIXED
449 #if CONFIG_DRIVER_OWE
450 || security == WLAN_SECURITY_OWE_ONLY
451 #endif
452 ))
453 {
454 return -WM_E_INVAL;
455 }
456
457 #if !CONFIG_WPA_SUPP
458 int passphrase_len = (int)strlen(passphrase);
459 int password_len = (int)strlen(password);
460 #endif
461
462 mlan_private *pmpriv = (mlan_private *)mlan_adap->priv[1];
463 wifi_uap_set_beacon_period(beacon_period);
464
465 /* fixme: check if this needs to go on heap */
466 mlan_ds_bss bss;
467 (void)memset(&bss, 0x00, sizeof(mlan_ds_bss));
468
469 bss.sub_command = MLAN_OID_UAP_BSS_CONFIG;
470
471 bss.param.bss_config.ssid.ssid_len = ssid_len;
472 (void)memcpy((void *)bss.param.bss_config.ssid.ssid, (const void *)ssid, ssid_len);
473
474 if (mac_addr != NULL)
475 {
476 (void)memcpy((void *)bss.param.bss_config.mac_addr, (const void *)mac_addr, MLAN_MAC_ADDR_LENGTH);
477 }
478
479 if (bss_type == MLAN_BSS_TYPE_UAP)
480 { /* Not required for WFD */
481 bss.param.bss_config.beacon_period = beacon_period;
482 bss.param.bss_config.dtim_period = dtim_period;
483 if (!wm_wifi.hidden_ssid)
484 bss.param.bss_config.bcast_ssid_ctl = 1;
485 else if (wm_wifi.hidden_ssid == 1)
486 bss.param.bss_config.bcast_ssid_ctl = 0;
487 else if (wm_wifi.hidden_ssid == 2)
488 bss.param.bss_config.bcast_ssid_ctl = 2;
489
490 if (chan_sw_count != 0U)
491 {
492 bss.param.bss_config.dtim_period = 1;
493 bss.param.bss_config.chan_sw_count = chan_sw_count;
494 }
495 }
496 /* Auto channel selection is not handled in 5GHz band, only
497 * manual channel selection is supported right now.
498 */
499 if (channel != 0U)
500 {
501 #if CONFIG_5GHz_SUPPORT
502 if (channel > MAX_CHANNELS_BG)
503 {
504 mlan_private *priv_sta = (mlan_private *)mlan_adap->priv[0];
505 if ((priv_sta->media_connected == MFALSE) && wlan_11h_radar_detect_required(pmpriv, channel))
506 {
507 wuap_e("Cannot start uAP on DFS channel %d", channel);
508 return -WM_E_INVAL;
509 }
510 #if CONFIG_UNII4_BAND_SUPPORT
511 /* TODO: Temporary work around until firmware fix is available */
512 if (channel == 173)
513 {
514 bss.param.bss_config.band_cfg = BAND_CONFIG_CH_173;
515 }
516 else
517 #endif
518 {
519 bss.param.bss_config.band_cfg = BAND_CONFIG_5GHZ;
520 }
521 (void)memcpy((void *)bss.param.bss_config.rates, (const void *)rates_5ghz, sizeof(rates_5ghz));
522 }
523 else
524 {
525 if (channel == 14)
526 {
527 (void)memcpy((void *)bss.param.bss_config.rates, (const void *)rates_2ghz_b, sizeof(rates_2ghz_b));
528 }
529 else
530 {
531 (void)memcpy((void *)bss.param.bss_config.rates, (const void *)rates_2ghz, sizeof(rates_2ghz));
532 }
533 bss.param.bss_config.band_cfg = BAND_CONFIG_MANUAL;
534 }
535 #else
536 if (channel == 14)
537 {
538 (void)memcpy((void *)bss.param.bss_config.rates, (const void *)rates_2ghz_b, sizeof(rates_2ghz_b));
539 }
540 else
541 {
542 (void)memcpy((void *)bss.param.bss_config.rates, (const void *)rates_2ghz, sizeof(rates_2ghz));
543 }
544 bss.param.bss_config.band_cfg = BAND_CONFIG_MANUAL;
545 #endif
546 bss.param.bss_config.channel = channel;
547 }
548 else
549 {
550 /* Auto channel selection from all channels*/
551 bss.param.bss_config.band_cfg = BAND_CONFIG_ACS_MODE;
552 bss.param.bss_config.channel = 0;
553
554 if (scan_chan_list.num_of_chan != 0U)
555 {
556 /* Specify channels if any for Auto channel selection */
557 bss.param.bss_config.num_of_chan = scan_chan_list.num_of_chan;
558 for (i = 0; i < scan_chan_list.num_of_chan; i++)
559 {
560 bss.param.bss_config.chan_list[i].chan_number = scan_chan_list.chan_number[i];
561 #if CONFIG_5GHz_SUPPORT
562 if (scan_chan_list.chan_number[i] > MAX_CHANNELS_BG)
563 {
564 bss.param.bss_config.chan_list[i].band_config_type = BAND_CONFIG_5GHZ;
565 (void)memcpy((void *)bss.param.bss_config.rates, (const void *)rates_5ghz, sizeof(rates_5ghz));
566 }
567 else
568 #endif
569 {
570 bss.param.bss_config.chan_list[i].band_config_type = 0x10;
571 (void)memcpy(bss.param.bss_config.rates, rates_2ghz, sizeof(rates_2ghz));
572 }
573 }
574 }
575 }
576
577 #if CONFIG_11AC
578 enable_11ac = wifi_check_11ac_capability(pmpriv, bss.param.bss_config.band_cfg);
579 #endif
580 #if CONFIG_11AX
581 enable_11ax = wifi_check_11ax_capability(pmpriv, bss.param.bss_config.band_cfg);
582 #endif
583 #if !CONFIG_WPA_SUPP
584 if (security == WLAN_SECURITY_NONE)
585 {
586 bss.param.bss_config.protocol = PROTOCOL_NO_SECURITY;
587 }
588
589 if (security == WLAN_SECURITY_WPA2 || security == WLAN_SECURITY_WPA_WPA2_MIXED ||
590 security == WLAN_SECURITY_WPA3_SAE || security == WLAN_SECURITY_WPA2_WPA3_SAE_MIXED
591 #if CONFIG_DRIVER_OWE
592 || security == WLAN_SECURITY_OWE_ONLY
593 #endif
594 )
595 {
596 bss.param.bss_config.wpa_cfg.pairwise_cipher_wpa2 = CIPHER_AES_CCMP;
597 bss.param.bss_config.wpa_cfg.group_cipher = CIPHER_AES_CCMP;
598 if (security == WLAN_SECURITY_WPA2)
599 {
600 bss.param.bss_config.protocol = PROTOCOL_WPA2;
601 if (key_mgmt & WLAN_KEY_MGMT_PSK)
602 {
603 bss.param.bss_config.key_mgmt = KEY_MGMT_PSK;
604 }
605 if (key_mgmt & WLAN_KEY_MGMT_PSK_SHA256)
606 {
607 bss.param.bss_config.key_mgmt |= KEY_MGMT_PSK_SHA256;
608 }
609 }
610 else if (security == WLAN_SECURITY_WPA_WPA2_MIXED)
611 {
612 bss.param.bss_config.protocol = PROTOCOL_WPA2_MIXED;
613 if (key_mgmt & WLAN_KEY_MGMT_PSK)
614 {
615 bss.param.bss_config.key_mgmt = KEY_MGMT_PSK;
616 }
617 if (key_mgmt & WLAN_KEY_MGMT_PSK_SHA256)
618 {
619 bss.param.bss_config.key_mgmt |= KEY_MGMT_PSK_SHA256;
620 }
621 bss.param.bss_config.wpa_cfg.pairwise_cipher_wpa = CIPHER_TKIP | CIPHER_AES_CCMP;
622 bss.param.bss_config.wpa_cfg.pairwise_cipher_wpa2 = CIPHER_TKIP | CIPHER_AES_CCMP;
623 bss.param.bss_config.wpa_cfg.group_cipher = CIPHER_TKIP;
624 }
625 else if (security == WLAN_SECURITY_WPA3_SAE)
626 {
627 bss.param.bss_config.protocol = PROTOCOL_WPA3_SAE;
628 if (key_mgmt & WLAN_KEY_MGMT_SAE)
629 {
630 bss.param.bss_config.key_mgmt = KEY_MGMT_SAE;
631 }
632 }
633 else if (security == WLAN_SECURITY_WPA2_WPA3_SAE_MIXED)
634 {
635 bss.param.bss_config.protocol = PROTOCOL_WPA2 | PROTOCOL_WPA3_SAE;
636 if (key_mgmt & WLAN_KEY_MGMT_PSK)
637 {
638 bss.param.bss_config.key_mgmt = KEY_MGMT_PSK;
639 }
640 if (key_mgmt & WLAN_KEY_MGMT_PSK_SHA256)
641 {
642 bss.param.bss_config.key_mgmt |= KEY_MGMT_PSK_SHA256;
643 }
644 if (key_mgmt & WLAN_KEY_MGMT_SAE)
645 {
646 bss.param.bss_config.key_mgmt |= KEY_MGMT_SAE;
647 }
648 }
649 #if CONFIG_DRIVER_OWE
650 else if (security == WLAN_SECURITY_OWE_ONLY)
651 {
652 bss.param.bss_config.protocol = PROTOCOL_OWE;
653 if (key_mgmt & WLAN_KEY_MGMT_OWE)
654 {
655 bss.param.bss_config.key_mgmt = KEY_MGMT_OWE;
656 }
657 }
658 #endif
659 else
660 { /* Do Nothing */
661 }
662 /***************************************
663 * Operation UINT16 Bits[15:2]: Reserved *
664 * Bit[1]: Authenticator *
665 * Bit[0]: KeyExchange *
666 ****************************************/
667 bss.param.bss_config.key_mgmt_operation = 0x00;
668
669 #if CONFIG_HOST_PMK
670 if ((security == WLAN_SECURITY_WPA2 || security == WLAN_SECURITY_WPA2_WPA3_SAE_MIXED) && passphrase_len < 64)
671 {
672 char pmk_bin[PMK_BIN_LEN] = {0};
673 char pmk_hex[PMK_HEX_LEN + 2] = {0};
674 bss.param.bss_config.wpa_cfg.length = PMK_HEX_LEN;
675 mrvl_generate_psk(ssid, strlen(ssid), passphrase, pmk_bin);
676 wm_bin2hex((uint8_t *)pmk_bin, pmk_hex, PMK_BIN_LEN, PMK_HEX_LEN + 2);
677 wuap_d("psk %s, pmk_hex %s", passphrase, pmk_hex);
678 (void)memcpy((void *)bss.param.bss_config.wpa_cfg.passphrase, (const void *)pmk_hex, PMK_HEX_LEN);
679 }
680 else
681 {
682 #endif
683 if (security == WLAN_SECURITY_WPA2 || security == WLAN_SECURITY_WPA_WPA2_MIXED ||
684 security == WLAN_SECURITY_WPA2_WPA3_SAE_MIXED)
685 {
686 /*app has converted pmk with psk*/
687 bss.param.bss_config.wpa_cfg.length = (t_u32)passphrase_len;
688 (void)memcpy((void *)bss.param.bss_config.wpa_cfg.passphrase, (const void *)passphrase,
689 (size_t)passphrase_len);
690 }
691 #if CONFIG_HOST_PMK
692 }
693 #endif
694 if (security == WLAN_SECURITY_WPA3_SAE || security == WLAN_SECURITY_WPA2_WPA3_SAE_MIXED)
695 {
696 bss.param.bss_config.auth_mode = MLAN_AUTH_MODE_AUTO;
697 bss.param.bss_config.pwe_derivation = pwe_derivation;
698 bss.param.bss_config.transition_disable = transition_disable;
699 bss.param.bss_config.wpa_cfg.password_length = (t_u32)password_len;
700 (void)memcpy((void *)bss.param.bss_config.wpa_cfg.password, (const void *)password, (size_t)password_len);
701 }
702 }
703 #endif
704 #if (CONFIG_UAP_AMPDU_TX) || (CONFIG_UAP_AMPDU_RX)
705 bss.param.bss_config.ht_cap_info = wm_wifi.ht_cap_info == 0 ? (t_u16)0x112c : wm_wifi.ht_cap_info;
706 wm_wifi.ht_tx_cfg = wm_wifi.ht_tx_cfg == 0 ? (t_u16)0x002c : wm_wifi.ht_tx_cfg;
707
708 if (bandwidth == BANDWIDTH_40MHZ
709 #if CONFIG_11AC
710 || bandwidth == BANDWIDTH_80MHZ
711 #endif
712 )
713 {
714 if (ISSUPP_CHANWIDTH40(mlan_adap->hw_dot_11n_dev_cap) != 0U)
715 {
716 bss.param.bss_config.ht_cap_info |= MBIT(1);
717 wm_wifi.ht_tx_cfg |= MBIT(1);
718 if (ISSUPP_SHORTGI40(mlan_adap->hw_dot_11n_dev_cap) != 0U)
719 {
720 bss.param.bss_config.ht_cap_info |= MBIT(6);
721 wm_wifi.ht_tx_cfg |= MBIT(6);
722 }
723 }
724 }
725 else if (bandwidth == BANDWIDTH_20MHZ)
726 {
727 wm_wifi.ht_tx_cfg &= ~MBIT(1);
728 wm_wifi.ht_tx_cfg &= ~MBIT(6);
729 bss.param.bss_config.ht_cap_info &= ~MBIT(12);
730 }
731 else
732 {
733 /*Do Nothing*/
734 }
735
736 if (ISSUPP_RXLDPC(mlan_adap->hw_dot_11n_dev_cap) != 0U)
737 {
738 SETHT_LDPCCODINGCAP(bss.param.bss_config.ht_cap_info);
739 SETHT_LDPCCODINGCAP(wm_wifi.ht_tx_cfg);
740 }
741 ret = wifi_uap_set_httxcfg_int(wm_wifi.ht_tx_cfg);
742 if (ret != WM_SUCCESS)
743 {
744 wuap_e("Cannot set uAP HT TX Cfg:%x", wm_wifi.ht_tx_cfg);
745 return -WM_E_INVAL;
746 }
747
748 if (!ISSUPP_TXSTBC(mlan_adap->hw_dot_11n_dev_cap))
749 bss.param.bss_config.ht_cap_info &= (~MBIT(7));
750 if (!ISSUPP_RXSTBC(mlan_adap->hw_dot_11n_dev_cap))
751 bss.param.bss_config.ht_cap_info &= (~(MBIT(8) | MBIT(9)));
752 if (!ISSUPP_CHANWIDTH40(mlan_adap->hw_dot_11n_dev_cap))
753 bss.param.bss_config.ht_cap_info &= (~MBIT(12));
754
755 #ifdef RW610
756 /* Set Tx Beam Forming Cap */
757 bss.param.bss_config.tx_bf_cap = mlan_adap->priv[1]->tx_bf_cap;
758 #endif
759
760 #if CONFIG_11AC
761 if (enable_11ac)
762 {
763 (void)wifi_uap_set_11ac_status(pmpriv, MLAN_ACT_ENABLE, bandwidth, channel);
764 }
765 else
766 {
767 (void)wifi_uap_set_11ac_status(pmpriv, MLAN_ACT_DISABLE, bandwidth, channel);
768 }
769 #endif
770 #if CONFIG_11AX
771 if (enable_11ax)
772 {
773 wifi_uap_set_11ax_status(pmpriv, MLAN_ACT_ENABLE, bss.param.bss_config.band_cfg, bandwidth);
774 }
775 else
776 {
777 wifi_uap_set_11ax_status(pmpriv, MLAN_ACT_DISABLE, bss.param.bss_config.band_cfg, bandwidth);
778 }
779 #endif
780 #ifdef RW610_SERIES
781 bss.param.bss_config.ampdu_param = 0x17;
782 #else
783 bss.param.bss_config.ampdu_param = 0x03;
784 #endif
785 (void)memcpy((void *)bss.param.bss_config.supported_mcs_set, (const void *)supported_mcs_set,
786 sizeof(bss.param.bss_config.supported_mcs_set));
787 #endif
788 /*
789 * Note that we are leaving htcap info set to zero by default. This
790 * will ensure that 11N is disabled.
791 */
792
793 memset(&bss.param.bss_config.wmm_para, 0x00, sizeof(wmm_parameter_t));
794
795 memcpy(&bss.param.bss_config.wmm_para.ouitype, wmm_oui, sizeof(wmm_oui));
796 #if CONFIG_WIFI_CAPA
797 if (pmpriv->adapter->usr_dot_11n_enable)
798 #endif
799 {
800 bss.param.bss_config.wmm_para.ouisubtype = 0x01;
801 bss.param.bss_config.wmm_para.version = 0x01;
802 bss.param.bss_config.wmm_para.reserved = 0x00;
803
804 memcpy(&bss.param.bss_config.wmm_para.ac_params, &mlan_adap->ac_params,
805 sizeof(wmm_ac_parameters_t) * MAX_AC_QUEUES);
806 for (i = 0; i < MAX_AC_QUEUES; i++)
807 {
808 bss.param.bss_config.wmm_para.ac_params[i].tx_op_limit =
809 wlan_cpu_to_le16(mlan_adap->ac_params[i].tx_op_limit);
810 }
811 }
812
813 mlan_ioctl_req ioctl_buf;
814 (void)memset(&ioctl_buf, 0x00, sizeof(mlan_ioctl_req));
815
816 ioctl_buf.req_id = (t_u32)MLAN_IOCTL_BSS;
817 /** Pointer to buffer */
818 ioctl_buf.pbuf = (t_u8 *)&bss;
819
820 return wifi_uap_prepare_and_send_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, HostCmd_ACT_GEN_SET, 0, &ioctl_buf, NULL,
821 bss_type, NULL);
822 }
823
824 static wifi_uap_11d_apis_t wifi_uap_11d_apis = {
825 .wifi_uap_downld_domain_params_p = wifi_uap_downld_domain_params,
826 };
827
wifi_uap_enable_11d_support(void)828 int wifi_uap_enable_11d_support(void)
829 {
830 wuap_d("Enabling 11d support APIs");
831
832 wm_wifi.enable_11d_support = true;
833 wm_wifi.uap_support_11d_apis = &wifi_uap_11d_apis;
834 return WM_SUCCESS;
835 }
836
wifi_uap_ctrl_deauth(bool enable)837 int wifi_uap_ctrl_deauth(bool enable)
838 {
839 mlan_private *pmpriv = (mlan_private *)mlan_adap->priv[1];
840 return wifi_uap_prepare_and_send_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB, HostCmd_ACT_GEN_SET, (t_u32)StopDeauth_i,
841 NULL, &enable, MLAN_BSS_TYPE_UAP, NULL);
842 }
843
wifi_uap_set_beacon_period(const t_u16 beacon_period)844 void wifi_uap_set_beacon_period(const t_u16 beacon_period)
845 {
846 wm_wifi.beacon_period = beacon_period;
847 }
848
wifi_uap_set_bandwidth(const t_u8 bandwidth)849 int wifi_uap_set_bandwidth(const t_u8 bandwidth)
850 {
851 if (bandwidth == BANDWIDTH_20MHZ || bandwidth == BANDWIDTH_40MHZ
852 #if CONFIG_11AC
853 || bandwidth == BANDWIDTH_80MHZ
854 #endif
855 )
856 {
857 #ifdef RW610
858 if (bandwidth != BANDWIDTH_20MHZ)
859 {
860 wuap_e("Error! RW610 only supports 20MHz");
861 return -WM_FAIL;
862 }
863 #endif
864 wm_wifi.bandwidth = bandwidth;
865 return WM_SUCCESS;
866 }
867 return (-WM_FAIL);
868 }
869
wifi_uap_get_bandwidth()870 t_u8 wifi_uap_get_bandwidth()
871 {
872 return wm_wifi.bandwidth;
873 }
874
wifi_uap_set_hidden_ssid(const t_u8 hidden_ssid)875 void wifi_uap_set_hidden_ssid(const t_u8 hidden_ssid)
876 {
877 wm_wifi.hidden_ssid = hidden_ssid;
878 }
879
wifi_uap_set_ecsa(void)880 void wifi_uap_set_ecsa(void)
881 {
882 #if defined(SD8801)
883 wm_wifi.chan_sw_count = 7;
884 #endif
885 }
886
wifi_uap_set_htcapinfo(const t_u16 ht_cap_info)887 void wifi_uap_set_htcapinfo(const t_u16 ht_cap_info)
888 {
889 wm_wifi.ht_cap_info = ht_cap_info;
890 }
891
wifi_uap_set_httxcfg(const t_u16 ht_tx_cfg)892 void wifi_uap_set_httxcfg(const t_u16 ht_tx_cfg)
893 {
894 wm_wifi.ht_tx_cfg = ht_tx_cfg;
895 }
896
897 #if CONFIG_WPA_SUPP
898 /**
899 * @brief Get second channel offset
900 *
901 * @param chan channel num
902 * @return second channel offset
903 */
wlan_get_second_channel_offset(mlan_private * priv,int chan)904 t_u8 wlan_get_second_channel_offset(mlan_private *priv, int chan)
905 {
906 t_u8 chan2Offset = SEC_CHAN_NONE;
907
908 /* Special Case: 20Mhz-only Channel */
909 #if CONFIG_UNII4_BAND_SUPPORT
910 if (priv->adapter->region_code != COUNTRY_CODE_US && chan == 165)
911 #else
912 if (chan == 165)
913 #endif
914 return chan2Offset;
915
916 switch (chan)
917 {
918 case 36:
919 case 44:
920 case 52:
921 case 60:
922 case 100:
923 case 108:
924 case 116:
925 case 124:
926 case 132:
927 case 140:
928 case 149:
929 case 157:
930 #if CONFIG_UNII4_BAND_SUPPORT
931 case 165:
932 case 173:
933 #endif
934 chan2Offset = SEC_CHAN_ABOVE;
935 break;
936 case 40:
937 case 48:
938 case 56:
939 case 64:
940 case 104:
941 case 112:
942 case 120:
943 case 128:
944 case 136:
945 case 144:
946 case 153:
947 case 161:
948 #if CONFIG_UNII4_BAND_SUPPORT
949 case 169:
950 case 177:
951 #endif
952 chan2Offset = SEC_CHAN_BELOW;
953 break;
954 }
955 return chan2Offset;
956 }
957
wifi_get_sec_channel_offset(unsigned int chan)958 t_u8 wifi_get_sec_channel_offset(unsigned int chan)
959 {
960 mlan_private *pmpriv = (mlan_private *)mlan_adap->priv[1];
961 mlan_adapter *pmadapter = pmpriv->adapter;
962 t_u16 band;
963 t_u8 chan_offset;
964
965 #if CONFIG_5GHz_SUPPORT
966 if (chan > MAX_CHANNELS_BG)
967 {
968 band = BAND_AN;
969 }
970 else
971 {
972 band = BAND_GN;
973 }
974 #else
975 band = BAND_GN;
976 #endif
977
978 chan_offset = SEC_CHAN_ABOVE;
979
980 if (band & BAND_GN)
981 {
982 if ((chan == 1) || (chan == 2) || (chan == 3) || (chan == 4))
983 chan_offset = SEC_CHAN_ABOVE;
984 else if ((chan == 10) || (chan == 11) || (chan == 12) || (chan == 13))
985 chan_offset = SEC_CHAN_BELOW;
986 else if (chan == 14)
987 chan_offset = SEC_CHAN_NONE;
988
989 /* check if channel 12 is supported in the region */
990 if (!wlan_find_cfp_by_band_and_channel(pmadapter, band, 12))
991 if ((chan == 8) || (chan == 9))
992 chan_offset = SEC_CHAN_BELOW;
993 }
994 #if CONFIG_5GHz_SUPPORT
995 else if (band & BAND_AN)
996 chan_offset = wlan_get_second_channel_offset(pmpriv, chan);
997 #endif
998
999 return chan_offset;
1000 }
1001 #endif
1002
1003 #if CONFIG_WIFI_CAPA
wifi_uap_config_wifi_capa(uint8_t wlan_capa)1004 void wifi_uap_config_wifi_capa(uint8_t wlan_capa)
1005 {
1006 if (wlan_capa & WIFI_SUPPORT_LEGACY)
1007 {
1008 if (wlan_capa & WIFI_SUPPORT_11N)
1009 {
1010 mlan_adap->usr_dot_11n_enable = MTRUE;
1011 #if CONFIG_11AC
1012 if (wlan_capa & WIFI_SUPPORT_11AC)
1013 {
1014 mlan_adap->usr_dot_11ac_enable = MTRUE;
1015 #if CONFIG_11AX
1016 if (wlan_capa & WIFI_SUPPORT_11AX)
1017 {
1018 mlan_adap->usr_dot_11ax_enable = MTRUE;
1019 }
1020 else
1021 {
1022 mlan_adap->usr_dot_11ax_enable = MFALSE;
1023 }
1024 #endif
1025 }
1026 else
1027 #endif
1028 {
1029 #if CONFIG_11AC
1030 mlan_adap->usr_dot_11ac_enable = MFALSE;
1031 #endif
1032 #if CONFIG_11AX
1033 mlan_adap->usr_dot_11ax_enable = MFALSE;
1034 #endif
1035 }
1036 }
1037 else
1038 {
1039 mlan_adap->usr_dot_11n_enable = MFALSE;
1040 #if CONFIG_11AC
1041 mlan_adap->usr_dot_11ac_enable = MFALSE;
1042 #endif
1043 #if CONFIG_11AX
1044 mlan_adap->usr_dot_11ax_enable = MFALSE;
1045 #endif
1046 }
1047 }
1048 else
1049 {
1050 wuap_e("Invalid wifi capaibility setting\n");
1051 }
1052 return;
1053 }
1054 #endif
1055
wifi_uap_start(mlan_bss_type type,char * ssid,uint8_t * mac_addr,int security,int key_mgmt,char * passphrase,char * password,int channel,wifi_scan_chan_list_t scan_chan_list,uint8_t pwe_derivation,uint8_t transition_disable,bool mfpc,bool mfpr,uint8_t dtim)1056 int wifi_uap_start(mlan_bss_type type,
1057 char *ssid,
1058 uint8_t *mac_addr,
1059 int security,
1060 int key_mgmt,
1061 char *passphrase,
1062 char *password,
1063 int channel,
1064 wifi_scan_chan_list_t scan_chan_list,
1065 uint8_t pwe_derivation,
1066 uint8_t transition_disable,
1067 bool mfpc,
1068 #if CONFIG_WIFI_DTIM_PERIOD
1069 bool mfpr,
1070 uint8_t dtim
1071 #else
1072 bool mfpr
1073 #endif
1074 )
1075 {
1076 wuap_d("Configuring");
1077 #if CONFIG_11AC
1078 if ((BANDWIDTH_80MHZ == wm_wifi.bandwidth) && (channel <= MAX_CHANNELS_BG))
1079 {
1080 wuap_e(
1081 "Cannot start uAP if bandwidth is configured to 80MHz, "
1082 "while channel is selected automatically or set to less than %d.",
1083 MAX_CHANNELS_BG);
1084 return -WM_FAIL;
1085 }
1086 else
1087 {
1088 /** Do Nothing */
1089 }
1090 #endif
1091 if (channel == 14)
1092 {
1093 wm_wifi.bandwidth = BANDWIDTH_20MHZ;
1094 }
1095
1096 /* Configure SSID */
1097 int rv = wifi_cmd_uap_config(ssid, mac_addr, (enum wlan_security_type)security, key_mgmt, passphrase, password,
1098 (t_u8)channel, scan_chan_list, pwe_derivation, transition_disable,
1099 wm_wifi.beacon_period == 0U ? UAP_BEACON_PERIOD : wm_wifi.beacon_period,
1100 wm_wifi.bandwidth == 0U ? BANDWIDTH_40MHZ : wm_wifi.bandwidth,
1101 #if CONFIG_WIFI_DTIM_PERIOD
1102 dtim == 0 ? UAP_DTIM_PERIOD : dtim,
1103 #else
1104 UAP_DTIM_PERIOD,
1105 #endif
1106 wm_wifi.chan_sw_count, type, mfpc, mfpr);
1107
1108 if (rv != WM_SUCCESS)
1109 {
1110 wuap_e("config failed. Cannot start");
1111 return rv;
1112 }
1113
1114 if ((security == WLAN_SECURITY_WPA2 || security == WLAN_SECURITY_WPA_WPA2_MIXED ||
1115 security == WLAN_SECURITY_WPA3_SAE || security == WLAN_SECURITY_WPA2_WPA3_SAE_MIXED
1116 #if CONFIG_DRIVER_OWE
1117 || security == WLAN_SECURITY_OWE_ONLY
1118 #endif
1119 ))
1120 {
1121 (void)wifi_uap_pmf_getset(HostCmd_ACT_GEN_SET, (uint8_t *)&mfpc, (uint8_t *)&mfpr);
1122 }
1123
1124 mlan_private *pmpriv = (mlan_private *)mlan_adap->priv[1];
1125
1126 if (wm_wifi.enable_11d_support && wm_wifi.uap_support_11d_apis)
1127 {
1128 wuap_d("Downloading domain params");
1129 wm_wifi.uap_support_11d_apis->wifi_uap_downld_domain_params_p(BAND_B);
1130 #if CONFIG_5GHz_SUPPORT
1131 wm_wifi.uap_support_11d_apis->wifi_uap_downld_domain_params_p(BAND_A);
1132 #endif
1133 }
1134
1135 wuap_d("Starting BSS");
1136 /* Start BSS */
1137 return wifi_uap_prepare_and_send_cmd(pmpriv, HOST_CMD_APCMD_BSS_START, HostCmd_ACT_GEN_SET, 0, NULL, NULL, type,
1138 NULL);
1139 }
1140
wifi_uap_bss_sta_list(wifi_sta_list_t ** list)1141 int wifi_uap_bss_sta_list(wifi_sta_list_t **list)
1142 {
1143 if (list == MNULL)
1144 {
1145 return -WM_E_INVAL;
1146 }
1147
1148 mlan_private *pmpriv = (mlan_private *)mlan_adap->priv[1];
1149
1150 /* Start BSS */
1151 return wifi_uap_prepare_and_send_cmd(pmpriv, HOST_CMD_APCMD_STA_LIST, HostCmd_ACT_GEN_GET, 0, NULL, NULL,
1152 MLAN_BSS_TYPE_UAP, list);
1153
1154 /* *list must have been filled now if everything went well */
1155 }
1156
1157
wifi_sta_deauth(uint8_t * mac_addr,uint16_t reason_code)1158 int wifi_sta_deauth(uint8_t *mac_addr, uint16_t reason_code)
1159 {
1160 mlan_private *pmpriv = (mlan_private *)mlan_adap->priv[1];
1161 mlan_deauth_param deauth;
1162
1163 if (mac_addr == MNULL)
1164 {
1165 return -WM_FAIL;
1166 }
1167
1168 (void)memcpy((void *)deauth.mac_addr, (const void *)mac_addr, MLAN_MAC_ADDR_LENGTH);
1169 deauth.reason_code = reason_code;
1170
1171 if (pmpriv->media_connected == MFALSE)
1172 {
1173 return -WM_FAIL;
1174 }
1175
1176 /* Start BSS */
1177 return wifi_uap_prepare_and_send_cmd(pmpriv, HOST_CMD_APCMD_STA_DEAUTH, HostCmd_ACT_GEN_SET, 0, NULL, &deauth,
1178 MLAN_BSS_TYPE_UAP, NULL);
1179 }
1180
wifi_uap_stop()1181 int wifi_uap_stop()
1182 {
1183 mlan_private *pmpriv = (mlan_private *)mlan_adap->priv[1];
1184 int rv = 0;
1185
1186 /* Start BSS */
1187 rv = wifi_uap_prepare_and_send_cmd(pmpriv, HOST_CMD_APCMD_BSS_STOP, HostCmd_ACT_GEN_SET, 0, NULL, NULL,
1188 MLAN_BSS_TYPE_UAP, NULL);
1189 wifi_uap_clear_domain_info();
1190
1191 return rv;
1192 }
1193
1194 #if CONFIG_WPA_SUPP_AP
1195 #ifdef SD8801
wifi_uap_acs_config_set()1196 static int wifi_uap_acs_config_set()
1197 {
1198 uint8_t i = 0;
1199 uint32_t size = S_DS_GEN + sizeof(HostCmd_DS_ACS_CONFIG) - 1U;
1200 uint8_t active_chan_list[40];
1201 uint8_t active_num_chans = 0;
1202 MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = NULL;
1203 HostCmd_DS_COMMAND *cmd;
1204
1205 wifi_get_active_channel_list(active_chan_list, &active_num_chans, 0);
1206
1207 (void)wifi_get_command_lock();
1208
1209 cmd = wifi_get_command_buffer();
1210
1211 memset(cmd, 0x00, size);
1212
1213 cmd->command = wlan_cpu_to_le16(HostCmd_MMH_ACS_CFG);
1214 HostCmd_DS_ACS_CONFIG *acs_cmd = (HostCmd_DS_ACS_CONFIG *)((uint32_t)cmd + S_DS_GEN);
1215 uint8_t *tlv = acs_cmd->tlv_buffer;
1216
1217 tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)(void *)tlv;
1218
1219 memset(tlv_chan_list, 0x00, sizeof(MrvlIEtypesHeader_t) + active_num_chans * sizeof(ChanScanParamSet_t));
1220
1221 tlv_chan_list->header.type = TLV_TYPE_CHANLIST;
1222 tlv_chan_list->header.len = active_num_chans * sizeof(ChanScanParamSet_t);
1223
1224 for (i = 0; i < active_num_chans; i++)
1225 {
1226 tlv_chan_list->chan_scan_param[i].chan_number = active_chan_list[i];
1227 tlv_chan_list->chan_scan_param[i].min_scan_time = MRVDRV_ACTIVE_SCAN_CHAN_TIME;
1228 tlv_chan_list->chan_scan_param[i].max_scan_time = MRVDRV_ACTIVE_SCAN_CHAN_TIME;
1229 }
1230
1231 size += sizeof(tlv_chan_list->header) + tlv_chan_list->header.len;
1232
1233 cmd->size = (t_u16)size;
1234 cmd->seq_num = (0x01) << 12;
1235 cmd->result = 0x00;
1236
1237 (void)wifi_wait_for_cmdresp(NULL);
1238
1239 return WM_SUCCESS;
1240 }
1241 #endif
1242
wifi_uap_do_acs(const int * freq_list)1243 int wifi_uap_do_acs(const int *freq_list)
1244 {
1245 #ifndef SD8801
1246 mlan_private *pmpriv = (mlan_private *)mlan_adap->priv[1];
1247 #endif
1248 MrvlIEtypes_channel_band_t *tlv_chan_band = MNULL;
1249 MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = MNULL;
1250 ChanScanParamSet_t *pscan_chan = MNULL;
1251 t_u8 *tlv = MNULL;
1252 uint8_t active_chan_list[WIFI_MAX_CHANNEL_NUM];
1253 uint8_t active_num_chans = 0;
1254 t_u16 scan_chan_num = 0;
1255 t_u16 cmd_size;
1256 int i;
1257
1258 wifi_get_command_lock();
1259 HostCmd_DS_COMMAND *cmd = wifi_get_command_buffer();
1260 HostCmd_DS_SYS_CONFIG *sys_config = (HostCmd_DS_SYS_CONFIG *)&cmd->params.sys_config;
1261
1262 cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
1263 cmd->seq_num = HostCmd_SET_SEQ_NO_BSS_INFO(0 /* seq_num */, 0 /* bss_num */, MLAN_BSS_TYPE_UAP);
1264 cmd->result = 0x00;
1265 sys_config->action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
1266 cmd_size = sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN;
1267
1268 /* set band config tlv */
1269 tlv = (t_u8 *)sys_config->tlv_buffer;
1270 tlv_chan_band = (MrvlIEtypes_channel_band_t *)tlv;
1271 tlv_chan_band->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_CHAN_BAND_CONFIG);
1272 tlv_chan_band->header.len = wlan_cpu_to_le16(sizeof(t_u8) + sizeof(t_u8));
1273 tlv_chan_band->band_config = BAND_CONFIG_ACS_MODE;
1274 tlv_chan_band->channel = 0;
1275 cmd_size += sizeof(MrvlIEtypes_channel_band_t);
1276 tlv += sizeof(MrvlIEtypes_channel_band_t);
1277
1278 /* set scan channel list tlv */
1279 tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)tlv;
1280 tlv_chan_list->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
1281 pscan_chan = tlv_chan_list->chan_scan_param;
1282
1283 /* fill in scan channel list */
1284 if (freq_list && freq_list[0] != 0)
1285 {
1286 /* use hostapd channel list */
1287 for (i = 0; i < WIFI_MAX_CHANNEL_NUM; i++)
1288 {
1289 if (freq_list[i] == 0)
1290 break;
1291
1292 (void)memset(pscan_chan, 0x00, sizeof(ChanScanParamSet_t));
1293 pscan_chan->chan_number = freq_to_chan(freq_list[i]);
1294 pscan_chan->radio_type = freq_list[i] >= 5180 ? BAND_5GHZ : BAND_2GHZ;
1295 pscan_chan++;
1296 }
1297 scan_chan_num = i;
1298 }
1299 else
1300 {
1301 /* create our own scan channel list on default 2.4G, as error protection */
1302 wifi_get_active_channel_list(active_chan_list, &active_num_chans, BAND_2GHZ);
1303 if (active_num_chans != 0 && active_num_chans < WIFI_MAX_CHANNEL_NUM)
1304 {
1305 for (i = 0; i < active_num_chans; i++)
1306 {
1307 (void)memset(pscan_chan, 0x00, sizeof(ChanScanParamSet_t));
1308 pscan_chan->chan_number = active_chan_list[i];
1309 pscan_chan->radio_type = BAND_2GHZ;
1310 pscan_chan++;
1311 }
1312 scan_chan_num = active_num_chans;
1313 }
1314 }
1315
1316 tlv_chan_list->header.len = wlan_cpu_to_le16(scan_chan_num * sizeof(ChanScanParamSet_t));
1317 cmd_size += sizeof(tlv_chan_list->header) + (scan_chan_num * sizeof(ChanScanParamSet_t));
1318 tlv += sizeof(tlv_chan_list->header) + (scan_chan_num * sizeof(ChanScanParamSet_t));
1319
1320 cmd->size = (t_u16)wlan_cpu_to_le16(cmd_size);
1321
1322 wifi_wait_for_cmdresp(NULL);
1323
1324 /* Start ACS SCAN */
1325 #ifdef SD8801
1326 return wifi_uap_acs_config_set();
1327 #else
1328 return wifi_uap_prepare_and_send_cmd(pmpriv, HostCMD_APCMD_ACS_SCAN, HostCmd_ACT_GEN_SET, 0, NULL, NULL,
1329 MLAN_BSS_TYPE_UAP, NULL);
1330 #endif
1331 }
1332 #endif
1333
1334 #if CONFIG_WIFI_UAP_WORKAROUND_STICKY_TIM
1335 /*
1336 * The following configuration was added because of a particular
1337 * bug on 8787 and 8782 firmware. The firmware bugzilla ID for the
1338 * bug is 39609. The bug causes the firmware to send packets to the
1339 * STA even after giving ACK for IEEE PS. The prov. mode scanning
1340 * coupled with this bug causes large scale packet losses and TCP
1341 * backoffs finally resulting in long load times for HTTP served
1342 * pages for prov. UI.
1343 */
1344
1345 /** TLV header length */
1346 #define TLVHEADER_LEN 4
1347
1348 #define MRVL_STICKY_TIM_CONFIG_TLV_ID (PROPRIETARY_TLV_BASE_ID + 0x96)
1349 /** TLV : Sticky TIM MAC address */
1350 #define MRVL_STICKY_TIM_STA_MAC_ADDR_TLV_ID (PROPRIETARY_TLV_BASE_ID + 0x97)
1351
1352 /** TLV buffer : sticky tim config */
1353 typedef PACK_START struct _tlvbuf_sticky_tim_config
1354 {
1355 /** Header */
1356 t_u16 tag;
1357 /** Length */
1358 t_u16 length;
1359 /** Enable */
1360 t_u16 enable;
1361 /** Duration */
1362 t_u16 duration;
1363 /** Sticky Bitmask */
1364 t_u16 sticky_bitmask;
1365 } PACK_END tlvbuf_sticky_tim_config;
1366
1367 /** TLV buffer : sticky tim sta mac address */
1368 typedef PACK_START struct _tlvbuf_sticky_tim_sta_mac_addr
1369 {
1370 /** Header */
1371 t_u16 tag;
1372 /** Length */
1373 t_u16 length;
1374 /** Control */
1375 t_u16 control;
1376 /** Station MAC address */
1377 t_u8 sta_mac_address[MLAN_MAC_ADDR_LENGTH];
1378 } PACK_END tlvbuf_sticky_tim_sta_mac_addr;
1379
1380 /*
1381 * This configures sticky TIM configuration for given MAC.
1382 *
1383 * Note that this is not present in mlan. So we have to add it here.
1384 */
wifi_uap_enable_sticky_bit(const uint8_t * mac_addr)1385 void wifi_uap_enable_sticky_bit(const uint8_t *mac_addr)
1386 {
1387 static bool global_sticky_enabled;
1388
1389 uint32_t size = S_DS_GEN + sizeof(HostCmd_DS_SYS_CONFIG) - 1;
1390
1391 wifi_get_command_lock();
1392 HostCmd_DS_COMMAND *cmd = wifi_get_command_buffer();
1393
1394 cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
1395 HostCmd_DS_SYS_CONFIG *sys_config_cmd = (HostCmd_DS_SYS_CONFIG *)((uint32_t)cmd + S_DS_GEN);
1396 sys_config_cmd->action = HostCmd_ACT_GEN_SET;
1397 uint8_t *tlv = sys_config_cmd->tlv_buffer;
1398
1399 if (!global_sticky_enabled)
1400 {
1401 /*
1402 * This enables the global sticky TIM bit enable. This
1403 * needs to be done only once.
1404 */
1405 tlvbuf_sticky_tim_config *tlv_sticky_tim_cfg = (tlvbuf_sticky_tim_config *)tlv;
1406
1407 tlv_sticky_tim_cfg->tag = MRVL_STICKY_TIM_CONFIG_TLV_ID;
1408 tlv_sticky_tim_cfg->length = sizeof(tlvbuf_sticky_tim_config) - TLVHEADER_LEN;
1409 tlv_sticky_tim_cfg->enable = 1;
1410 /* Set it permanently */
1411 tlv_sticky_tim_cfg->duration = 0;
1412 /* MoreData bit and TIM bit is made sticky */
1413 tlv_sticky_tim_cfg->sticky_bitmask = (t_u16)0x3;
1414
1415 size += sizeof(MrvlIEtypesHeader_t) + tlv_sticky_tim_cfg->length;
1416 tlv += sizeof(MrvlIEtypesHeader_t) + tlv_sticky_tim_cfg->length;
1417
1418 global_sticky_enabled = true;
1419 }
1420
1421 tlvbuf_sticky_tim_sta_mac_addr *tim_cfg = (tlvbuf_sticky_tim_sta_mac_addr *)tlv;
1422
1423 tim_cfg->tag = MRVL_STICKY_TIM_STA_MAC_ADDR_TLV_ID;
1424 tim_cfg->length = sizeof(tlvbuf_sticky_tim_sta_mac_addr) - TLVHEADER_LEN;
1425 (void)memcpy((void *)tim_cfg->sta_mac_address, (const void *)mac_addr, MLAN_MAC_ADDR_LENGTH);
1426 tim_cfg->control = 1;
1427
1428 size += sizeof(MrvlIEtypesHeader_t) + tim_cfg->length;
1429
1430 cmd->size = size;
1431 cmd->seq_num = (0x01) << 12;
1432 cmd->result = 0x00;
1433
1434 wifi_wait_for_cmdresp(NULL);
1435 }
1436 #endif /* CONFIG_WIFI_UAP_WORKAROUND_STICKY_TIM */
1437
1438 /*
1439 * Note: This function handles only one (first) TLV from the response.
1440 */
wifi_uap_handle_cmd_resp(HostCmd_DS_COMMAND * resp)1441 void wifi_uap_handle_cmd_resp(HostCmd_DS_COMMAND *resp)
1442 {
1443 mlan_private *pmpriv = (mlan_private *)mlan_adap->priv[1];
1444 HostCmd_DS_SYS_CONFIG *sys_config = (HostCmd_DS_SYS_CONFIG *)&resp->params.sys_config;
1445 uint8_t *tlv = sys_config->tlv_buffer;
1446 MrvlIEtypesHeader_t *header = (MrvlIEtypesHeader_t *)(void *)tlv;
1447 if (resp->result == 0U)
1448 {
1449 switch (header->type)
1450 {
1451 case TLV_TYPE_UAP_TX_POWER:
1452 {
1453 MrvlIEtypes_tx_power_t *tlv_tx_power = (MrvlIEtypes_tx_power_t *)(void *)tlv;
1454 if (sys_config->action == HostCmd_ACT_GEN_GET)
1455 {
1456 if (wm_wifi.cmd_resp_priv != NULL)
1457 {
1458 uint8_t *tx_power = (uint8_t *)wm_wifi.cmd_resp_priv;
1459 wm_wifi.cmd_resp_priv = NULL;
1460 *tx_power = tlv_tx_power->tx_power;
1461 }
1462 }
1463 wm_wifi.cmd_resp_status = WM_SUCCESS;
1464 }
1465 break;
1466 case TLV_TYPE_UAP_STA_AGEOUT_TIMER:
1467 {
1468 MrvlIEtypes_sta_ageout_t *tlv_sta_ageout_timer = (MrvlIEtypes_sta_ageout_t *)(void *)tlv;
1469 if (sys_config->action == HostCmd_ACT_GEN_GET)
1470 {
1471 if (wm_wifi.cmd_resp_priv != NULL)
1472 {
1473 uint32_t *sta_ageout_timer = (uint32_t *)wm_wifi.cmd_resp_priv;
1474 wm_wifi.cmd_resp_priv = NULL;
1475 *sta_ageout_timer = tlv_sta_ageout_timer->sta_ageout_timer;
1476 }
1477 }
1478 wm_wifi.cmd_resp_status = WM_SUCCESS;
1479 }
1480 break;
1481 case TLV_TYPE_UAP_PS_STA_AGEOUT_TIMER:
1482 {
1483 MrvlIEtypes_ps_sta_ageout_t *tlv_ps_sta_ageout_timer = (MrvlIEtypes_ps_sta_ageout_t *)(void *)tlv;
1484 if (sys_config->action == HostCmd_ACT_GEN_GET)
1485 {
1486 if (wm_wifi.cmd_resp_priv != NULL)
1487 {
1488 uint32_t *ps_sta_ageout_timer = (uint32_t *)wm_wifi.cmd_resp_priv;
1489 wm_wifi.cmd_resp_priv = NULL;
1490 *ps_sta_ageout_timer = tlv_ps_sta_ageout_timer->ps_sta_ageout_timer;
1491 }
1492 }
1493 wm_wifi.cmd_resp_status = WM_SUCCESS;
1494 }
1495 break;
1496 case TLV_TYPE_UAP_GRP_REKEY_TIME:
1497 {
1498 MrvlIEtypes_group_rekey_time_t *tlv_group_rekey_timer = (MrvlIEtypes_group_rekey_time_t *)(void *)tlv;
1499 if (sys_config->action == HostCmd_ACT_GEN_GET)
1500 {
1501 if (wm_wifi.cmd_resp_priv != NULL)
1502 {
1503 uint32_t *group_rekey_timer = (uint32_t *)wm_wifi.cmd_resp_priv;
1504 wm_wifi.cmd_resp_priv = NULL;
1505 *group_rekey_timer = tlv_group_rekey_timer->gk_rekey_time;
1506 }
1507 }
1508 wm_wifi.cmd_resp_status = WM_SUCCESS;
1509 }
1510 break;
1511 case TLV_TYPE_UAP_MCBC_DATA_RATE:
1512 {
1513 MrvlIEtypes_mcbc_rate_t *tlv_mcbc_rate = (MrvlIEtypes_mcbc_rate_t *)(void *)tlv;
1514 if (sys_config->action == HostCmd_ACT_GEN_GET)
1515 {
1516 if (wm_wifi.cmd_resp_priv != NULL)
1517 {
1518 uint16_t *mcbc_rate = (uint16_t *)wm_wifi.cmd_resp_priv;
1519 wm_wifi.cmd_resp_priv = NULL;
1520 *mcbc_rate = tlv_mcbc_rate->mcbc_data_rate;
1521 }
1522 }
1523 wm_wifi.cmd_resp_status = WM_SUCCESS;
1524 }
1525 break;
1526 case TLV_TYPE_RATES:
1527 {
1528 MrvlIEtypes_RatesParamSet_t *tlv_rates = (MrvlIEtypes_RatesParamSet_t *)(void *)tlv;
1529
1530 if (sys_config->action == HostCmd_ACT_GEN_GET)
1531 {
1532 if (wm_wifi.cmd_resp_priv != NULL)
1533 {
1534 char *rates = (char *)wm_wifi.cmd_resp_priv;
1535 wm_wifi.cmd_resp_priv = NULL;
1536 (void)memset((void *)rates, 0, MAX_RATES);
1537 (void)memcpy((void *)rates, (const void *)tlv_rates->rates,
1538 MIN(MAX_RATES, tlv_rates->header.len));
1539 }
1540 }
1541 wm_wifi.cmd_resp_status = WM_SUCCESS;
1542 }
1543 break;
1544 case TLV_TYPE_UAP_CHAN_BAND_CONFIG:
1545 {
1546 MrvlIEtypes_channel_band_t *tlv_cb = (MrvlIEtypes_channel_band_t *)(void *)tlv;
1547 pmpriv->uap_state_chan_cb.band_config = tlv_cb->band_config;
1548 pmpriv->uap_state_chan_cb.channel = tlv_cb->channel;
1549 if (wm_wifi.cmd_resp_priv != NULL)
1550 {
1551 t_u8 *channel = (t_u8 *)wm_wifi.cmd_resp_priv;
1552 wm_wifi.cmd_resp_priv = NULL;
1553 *channel = tlv_cb->channel;
1554 }
1555 wm_wifi.cmd_resp_status = WM_SUCCESS;
1556 }
1557 break;
1558 case TLV_TYPE_UAP_MAX_STA_CNT:
1559 {
1560 MrvlIEtypes_max_sta_count_t *tlv_sta_cnt = (MrvlIEtypes_max_sta_count_t *)(void *)tlv;
1561 pmpriv->uap_state_chan_cb.max_sta_count = tlv_sta_cnt->max_sta_count;
1562 pmpriv->uap_max_sta = tlv_sta_cnt->max_sta_count;
1563 if (wm_wifi.cmd_resp_priv != NULL)
1564 {
1565 int *sta_count = (int *)wm_wifi.cmd_resp_priv;
1566 wm_wifi.cmd_resp_priv = NULL;
1567 *sta_count = (int)tlv_sta_cnt->max_sta_count;
1568 }
1569 wm_wifi.cmd_resp_status = WM_SUCCESS;
1570 }
1571 break;
1572 default:
1573 wm_wifi.cmd_resp_status = WM_SUCCESS;
1574 break;
1575 }
1576 }
1577 else
1578 {
1579 wm_wifi.cmd_resp_status = -WM_FAIL;
1580 }
1581 }
1582
wifi_uap_rates_getset(uint8_t action,char * rates,uint8_t num_rates)1583 int wifi_uap_rates_getset(uint8_t action, char *rates, uint8_t num_rates)
1584 {
1585 uint8_t i = 0;
1586 uint32_t size = S_DS_GEN + sizeof(HostCmd_DS_SYS_CONFIG) - 1U;
1587
1588 (void)wifi_get_command_lock();
1589 HostCmd_DS_COMMAND *cmd = wifi_get_command_buffer();
1590
1591 cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
1592 HostCmd_DS_SYS_CONFIG *sys_config_cmd = (HostCmd_DS_SYS_CONFIG *)((uint32_t)cmd + S_DS_GEN);
1593 uint8_t *tlv = sys_config_cmd->tlv_buffer;
1594
1595 MrvlIEtypes_RatesParamSet_t *tlv_rates = (MrvlIEtypes_RatesParamSet_t *)(void *)tlv;
1596
1597 if (action == HostCmd_ACT_GEN_GET)
1598 {
1599 sys_config_cmd->action = HostCmd_ACT_GEN_GET;
1600 }
1601 else
1602 {
1603 sys_config_cmd->action = HostCmd_ACT_GEN_SET;
1604 for (i = 0; i < num_rates; i++)
1605 {
1606 tlv_rates->rates[i] = (t_u8)rates[i];
1607 }
1608 }
1609
1610 tlv_rates->header.type = wlan_cpu_to_le16(TLV_TYPE_RATES);
1611 tlv_rates->header.len = wlan_cpu_to_le16(i);
1612
1613 size += sizeof(MrvlIEtypesHeader_t) + i;
1614 tlv += sizeof(MrvlIEtypesHeader_t) + i;
1615
1616 cmd->size = (t_u16)size;
1617 cmd->seq_num = (0x01) << 12;
1618 cmd->result = 0x00;
1619
1620 (void)wifi_wait_for_cmdresp(action == HostCmd_ACT_GEN_GET ? rates : NULL);
1621
1622 return wm_wifi.cmd_resp_status;
1623 }
1624
wifi_uap_mcbc_rate_getset(uint8_t action,uint16_t * mcbc_rate)1625 int wifi_uap_mcbc_rate_getset(uint8_t action, uint16_t *mcbc_rate)
1626 {
1627 uint32_t size = S_DS_GEN + sizeof(HostCmd_DS_SYS_CONFIG) - 1U;
1628
1629 (void)wifi_get_command_lock();
1630 HostCmd_DS_COMMAND *cmd = wifi_get_command_buffer();
1631
1632 cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
1633 HostCmd_DS_SYS_CONFIG *sys_config_cmd = (HostCmd_DS_SYS_CONFIG *)((uint32_t)cmd + S_DS_GEN);
1634 uint8_t *tlv = sys_config_cmd->tlv_buffer;
1635
1636 MrvlIEtypes_mcbc_rate_t *tlv_mcbc_rate = (MrvlIEtypes_mcbc_rate_t *)(void *)tlv;
1637
1638 if (action == HostCmd_ACT_GEN_GET)
1639 {
1640 sys_config_cmd->action = HostCmd_ACT_GEN_GET;
1641 }
1642 else
1643 {
1644 sys_config_cmd->action = HostCmd_ACT_GEN_SET;
1645 tlv_mcbc_rate->mcbc_data_rate = *mcbc_rate;
1646 }
1647
1648 tlv_mcbc_rate->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_MCBC_DATA_RATE);
1649 tlv_mcbc_rate->header.len = wlan_cpu_to_le16(sizeof(t_u16));
1650
1651 size += sizeof(MrvlIEtypes_mcbc_rate_t);
1652 tlv += sizeof(MrvlIEtypes_mcbc_rate_t);
1653
1654 cmd->size = (t_u16)size;
1655 cmd->seq_num = (0x01) << 12;
1656 cmd->result = 0x00;
1657
1658 (void)wifi_wait_for_cmdresp(action == HostCmd_ACT_GEN_GET ? mcbc_rate : NULL);
1659
1660 return wm_wifi.cmd_resp_status;
1661 }
1662
wifi_uap_tx_power_getset(uint8_t action,uint8_t * tx_power_dbm)1663 int wifi_uap_tx_power_getset(uint8_t action, uint8_t *tx_power_dbm)
1664 {
1665 uint32_t size = S_DS_GEN + sizeof(HostCmd_DS_SYS_CONFIG) - 1U;
1666
1667 (void)wifi_get_command_lock();
1668 HostCmd_DS_COMMAND *cmd = wifi_get_command_buffer();
1669
1670 cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
1671 HostCmd_DS_SYS_CONFIG *sys_config_cmd = (HostCmd_DS_SYS_CONFIG *)((uint32_t)cmd + S_DS_GEN);
1672 uint8_t *tlv = sys_config_cmd->tlv_buffer;
1673
1674 MrvlIEtypes_tx_power_t *tlv_tx_power = (MrvlIEtypes_tx_power_t *)(void *)tlv;
1675
1676 if (action == HostCmd_ACT_GEN_GET)
1677 {
1678 sys_config_cmd->action = HostCmd_ACT_GEN_GET;
1679 }
1680 else
1681 {
1682 sys_config_cmd->action = HostCmd_ACT_GEN_SET;
1683 tlv_tx_power->tx_power = *tx_power_dbm;
1684 }
1685 tlv_tx_power->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_TX_POWER);
1686 tlv_tx_power->header.len = wlan_cpu_to_le16(sizeof(t_u8));
1687
1688 size += sizeof(MrvlIEtypes_tx_power_t);
1689 tlv += sizeof(MrvlIEtypes_tx_power_t);
1690
1691 cmd->size = (uint16_t)size;
1692 cmd->seq_num = (0x01) << 12;
1693 cmd->result = 0x00;
1694
1695 (void)wifi_wait_for_cmdresp(action == HostCmd_ACT_GEN_GET ? tx_power_dbm : NULL);
1696
1697 return wm_wifi.cmd_resp_status;
1698 }
1699
wifi_uap_sta_ageout_timer_getset(uint8_t action,uint32_t * sta_ageout_timer)1700 int wifi_uap_sta_ageout_timer_getset(uint8_t action, uint32_t *sta_ageout_timer)
1701 {
1702 uint32_t size = S_DS_GEN + sizeof(HostCmd_DS_SYS_CONFIG) - 1U;
1703
1704 (void)wifi_get_command_lock();
1705 HostCmd_DS_COMMAND *cmd = wifi_get_command_buffer();
1706
1707 cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
1708 HostCmd_DS_SYS_CONFIG *sys_config_cmd = (HostCmd_DS_SYS_CONFIG *)((uint32_t)cmd + S_DS_GEN);
1709 uint8_t *tlv = sys_config_cmd->tlv_buffer;
1710
1711 MrvlIEtypes_sta_ageout_t *tlv_sta_ageout_timer = (MrvlIEtypes_sta_ageout_t *)(void *)tlv;
1712
1713 if (action == HostCmd_ACT_GEN_GET)
1714 {
1715 sys_config_cmd->action = HostCmd_ACT_GEN_GET;
1716 }
1717 else
1718 {
1719 sys_config_cmd->action = HostCmd_ACT_GEN_SET;
1720 tlv_sta_ageout_timer->sta_ageout_timer = wlan_cpu_to_le32(*sta_ageout_timer);
1721 }
1722 tlv_sta_ageout_timer->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_STA_AGEOUT_TIMER);
1723 tlv_sta_ageout_timer->header.len = wlan_cpu_to_le16(sizeof(t_u32));
1724
1725 size += sizeof(MrvlIEtypes_sta_ageout_t);
1726 tlv += sizeof(MrvlIEtypes_sta_ageout_t);
1727
1728 cmd->size = (t_u16)size;
1729 cmd->seq_num = (0x01) << 12;
1730 cmd->result = 0x00;
1731
1732 (void)wifi_wait_for_cmdresp(action == HostCmd_ACT_GEN_GET ? sta_ageout_timer : NULL);
1733
1734 return wm_wifi.cmd_resp_status;
1735 }
1736
wifi_uap_ps_sta_ageout_timer_getset(uint8_t action,uint32_t * ps_sta_ageout_timer)1737 int wifi_uap_ps_sta_ageout_timer_getset(uint8_t action, uint32_t *ps_sta_ageout_timer)
1738 {
1739 uint32_t size = S_DS_GEN + sizeof(HostCmd_DS_SYS_CONFIG) - 1U;
1740
1741 (void)wifi_get_command_lock();
1742 HostCmd_DS_COMMAND *cmd = wifi_get_command_buffer();
1743
1744 cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
1745 HostCmd_DS_SYS_CONFIG *sys_config_cmd = (HostCmd_DS_SYS_CONFIG *)((uint32_t)cmd + S_DS_GEN);
1746 uint8_t *tlv = sys_config_cmd->tlv_buffer;
1747
1748 MrvlIEtypes_ps_sta_ageout_t *tlv_ps_sta_ageout_timer = (MrvlIEtypes_ps_sta_ageout_t *)(void *)tlv;
1749
1750 if (action == HostCmd_ACT_GEN_GET)
1751 {
1752 sys_config_cmd->action = HostCmd_ACT_GEN_GET;
1753 }
1754 else
1755 {
1756 sys_config_cmd->action = HostCmd_ACT_GEN_SET;
1757 tlv_ps_sta_ageout_timer->ps_sta_ageout_timer = wlan_cpu_to_le32(*ps_sta_ageout_timer);
1758 }
1759 tlv_ps_sta_ageout_timer->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_PS_STA_AGEOUT_TIMER);
1760 tlv_ps_sta_ageout_timer->header.len = wlan_cpu_to_le16(sizeof(t_u32));
1761
1762 size += sizeof(MrvlIEtypes_ps_sta_ageout_t);
1763 tlv += sizeof(MrvlIEtypes_ps_sta_ageout_t);
1764
1765 cmd->size = (uint16_t)size;
1766 cmd->seq_num = (0x01) << 12;
1767 cmd->result = 0x00;
1768
1769 (void)wifi_wait_for_cmdresp(action == HostCmd_ACT_GEN_GET ? ps_sta_ageout_timer : NULL);
1770
1771 return wm_wifi.cmd_resp_status;
1772 }
1773
wifi_uap_group_rekey_timer_getset(uint8_t action,uint32_t * group_rekey_timer)1774 int wifi_uap_group_rekey_timer_getset(uint8_t action, uint32_t *group_rekey_timer)
1775 {
1776 uint32_t size = S_DS_GEN + sizeof(HostCmd_DS_SYS_CONFIG) - 1U;
1777
1778 (void)wifi_get_command_lock();
1779 HostCmd_DS_COMMAND *cmd = wifi_get_command_buffer();
1780
1781 cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
1782 HostCmd_DS_SYS_CONFIG *sys_config_cmd = (HostCmd_DS_SYS_CONFIG *)((uint32_t)cmd + S_DS_GEN);
1783 uint8_t *tlv = sys_config_cmd->tlv_buffer;
1784
1785 MrvlIEtypes_group_rekey_time_t *tlv_group_rekey_timer = (MrvlIEtypes_group_rekey_time_t *)(void *)tlv;
1786
1787 if (action == HostCmd_ACT_GEN_GET)
1788 {
1789 sys_config_cmd->action = HostCmd_ACT_GEN_GET;
1790 }
1791 else
1792 {
1793 sys_config_cmd->action = HostCmd_ACT_GEN_SET;
1794 tlv_group_rekey_timer->gk_rekey_time = wlan_cpu_to_le32(*group_rekey_timer);
1795 }
1796 tlv_group_rekey_timer->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_GRP_REKEY_TIME);
1797 tlv_group_rekey_timer->header.len = wlan_cpu_to_le16(sizeof(t_u32));
1798
1799 size += sizeof(MrvlIEtypes_group_rekey_time_t);
1800 tlv += sizeof(MrvlIEtypes_group_rekey_time_t);
1801
1802 cmd->size = (t_u16)size;
1803 cmd->seq_num = (0x01) << 12;
1804 cmd->result = 0x00;
1805
1806 (void)wifi_wait_for_cmdresp(action == HostCmd_ACT_GEN_GET ? group_rekey_timer : NULL);
1807
1808 return wm_wifi.cmd_resp_status;
1809 }
1810
1811 /* Content reproduced from wlan_uap_get_channel() */
wifi_send_uap_get_channel_cmd(int * channel)1812 static int wifi_send_uap_get_channel_cmd(int *channel)
1813 {
1814 mlan_private *pmpriv = (mlan_private *)mlan_adap->priv[1];
1815 t_u16 tlv_type = TLV_TYPE_UAP_CHAN_BAND_CONFIG;
1816
1817 int rv = wifi_uap_prepare_and_send_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, HostCmd_ACT_GEN_GET, 0, MNULL,
1818 &tlv_type, MLAN_BSS_TYPE_UAP, channel);
1819 if (rv != WM_SUCCESS)
1820 {
1821 return rv;
1822 }
1823
1824 if (wm_wifi.cmd_resp_status != 0)
1825 {
1826 wifi_w("Unable to uap channel");
1827 return wm_wifi.cmd_resp_status;
1828 }
1829
1830 return rv;
1831 }
1832
1833 /* Content reproduced from wlan_uap_get_channel() */
wifi_send_uap_max_sta_num_cmd(uint8_t action,unsigned int * max_sta_num)1834 static int wifi_send_uap_max_sta_num_cmd(uint8_t action, unsigned int *max_sta_num)
1835 {
1836 mlan_private *pmpriv = (mlan_private *)mlan_adap->priv[1];
1837 MrvlIEtypes_max_sta_count_t max_sta_count_tlv;
1838
1839 (void)memset(&max_sta_count_tlv, 0, sizeof(MrvlIEtypes_max_sta_count_t));
1840
1841 max_sta_count_tlv.header.type = TLV_TYPE_UAP_MAX_STA_CNT;
1842
1843 if (action == HostCmd_ACT_GEN_SET)
1844 {
1845 max_sta_count_tlv.header.len = (t_u16)sizeof(MrvlIEtypes_max_sta_count_t);
1846 max_sta_count_tlv.max_sta_count = (t_u16)*max_sta_num;
1847 }
1848
1849 int rv = wifi_uap_prepare_and_send_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, action, 0, MNULL, &max_sta_count_tlv,
1850 MLAN_BSS_TYPE_UAP, max_sta_num);
1851 if (rv != WM_SUCCESS)
1852 {
1853 return rv;
1854 }
1855
1856 if (wm_wifi.cmd_resp_status != 0)
1857 {
1858 wifi_w("Unable to uap max_sta_num");
1859 return wm_wifi.cmd_resp_status;
1860 }
1861
1862 return rv;
1863 }
1864
wifi_get_uap_max_clients(unsigned int * max_sta_num)1865 int wifi_get_uap_max_clients(unsigned int *max_sta_num)
1866 {
1867 return wifi_send_uap_max_sta_num_cmd(HostCmd_ACT_GEN_GET, max_sta_num);
1868 }
1869
wifi_set_uap_max_clients(unsigned int * max_sta_num)1870 int wifi_set_uap_max_clients(unsigned int *max_sta_num)
1871 {
1872 return wifi_send_uap_max_sta_num_cmd(HostCmd_ACT_GEN_SET, max_sta_num);
1873 }
1874
1875 /*
1876 * Note: channel can be NULL. The side effects of this function also are of
1877 * interest to us as pmpriv->uap_state_chan_cb.band_config and
1878 * pmpriv->uap_state_chan_cb.channel are updated.
1879 */
wifi_get_uap_channel(int * channel)1880 int wifi_get_uap_channel(int *channel)
1881 {
1882 return wifi_send_uap_get_channel_cmd(channel);
1883 }
1884
wifi_uap_pmf_getset(uint8_t action,uint8_t * mfpc,uint8_t * mfpr)1885 int wifi_uap_pmf_getset(uint8_t action, uint8_t *mfpc, uint8_t *mfpr)
1886 {
1887 uint32_t size = S_DS_GEN + sizeof(HostCmd_DS_PMF_PARAMS);
1888 wifi_pmf_params_t wifi_pmf_params;
1889
1890 (void)wifi_get_command_lock();
1891 HostCmd_DS_COMMAND *cmd = wifi_get_command_buffer();
1892
1893 cmd->command = wlan_cpu_to_le16(HostCmd_CMD_PMF_PARAMS);
1894 HostCmd_DS_PMF_PARAMS *sys_pmf_params = (HostCmd_DS_PMF_PARAMS *)((uint32_t)cmd + S_DS_GEN);
1895
1896 (void)memset(sys_pmf_params, 0x00, sizeof(HostCmd_DS_PMF_PARAMS));
1897
1898 if (action == HostCmd_ACT_GEN_GET)
1899 {
1900 sys_pmf_params->action = HostCmd_ACT_GEN_GET;
1901 }
1902 else
1903 {
1904 sys_pmf_params->action = HostCmd_ACT_GEN_SET;
1905 }
1906
1907 sys_pmf_params->params.mfpc = *mfpc;
1908 sys_pmf_params->params.mfpr = *mfpr;
1909
1910 cmd->size = (t_u16)size;
1911 cmd->seq_num = (0x01) << 12;
1912 cmd->result = 0x00;
1913
1914 (void)wifi_wait_for_cmdresp(action == HostCmd_ACT_GEN_GET ? &wifi_pmf_params : NULL);
1915
1916 if (action == HostCmd_ACT_GEN_GET)
1917 {
1918 *mfpc = wifi_pmf_params.mfpc;
1919 *mfpr = wifi_pmf_params.mfpr;
1920 }
1921
1922 return wm_wifi.cmd_resp_status;
1923 }
1924
wifi_uap_get_pmfcfg(t_u8 * mfpc,t_u8 * mfpr)1925 int wifi_uap_get_pmfcfg(t_u8 *mfpc, t_u8 *mfpr)
1926 {
1927 return wifi_uap_pmf_getset(HostCmd_ACT_GEN_GET, mfpc, mfpr);
1928 }
1929
1930 #if CONFIG_UAP_STA_MAC_ADDR_FILTER
wifi_set_sta_mac_filter(int filter_mode,int mac_count,unsigned char * mac_addr)1931 int wifi_set_sta_mac_filter(int filter_mode, int mac_count, unsigned char *mac_addr)
1932 {
1933 t_u8 *buffer = NULL;
1934 t_u16 cmd_len = 0;
1935 t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
1936
1937 HostCmd_DS_GEN *cmd_buf = NULL;
1938 MrvlIEtypes_mac_filter_t *tlv = NULL;
1939 HostCmd_DS_SYS_CONFIG *sys_config = NULL;
1940
1941 /* Initialize the command length */
1942 if (filter_mode == 0)
1943 {
1944 cmd_len = sizeof(HostCmd_DS_GEN) + (sizeof(HostCmd_DS_SYS_CONFIG) - 1) +
1945 (sizeof(MrvlIEtypes_mac_filter_t) - 1) + (WLAN_MAX_STA_FILTER_NUM * MLAN_MAC_ADDR_LENGTH);
1946 }
1947 else
1948 {
1949 cmd_len = sizeof(HostCmd_DS_GEN) + (sizeof(HostCmd_DS_SYS_CONFIG) - 1) +
1950 (sizeof(MrvlIEtypes_mac_filter_t) - 1) + mac_count * MLAN_MAC_ADDR_LENGTH;
1951 }
1952
1953 /* Initialize the command buffer */
1954 buffer = (t_u8 *)OSA_MemoryAllocate(buf_len);
1955 if (!buffer)
1956 {
1957 wuap_e("ERR:Cannot allocate buffer for command!\r\n");
1958 return -WM_FAIL;
1959 }
1960
1961 memset(buffer, 0, buf_len);
1962
1963 /* Locate headers */
1964 cmd_buf = (HostCmd_DS_GEN *)buffer;
1965 sys_config = (HostCmd_DS_SYS_CONFIG *)(buffer + sizeof(HostCmd_DS_GEN));
1966 tlv = (MrvlIEtypes_mac_filter_t *)(buffer + sizeof(HostCmd_DS_GEN) + (sizeof(HostCmd_DS_SYS_CONFIG) - 1));
1967
1968 /* Fill the command buffer */
1969 cmd_buf->command = HOST_CMD_APCMD_SYS_CONFIGURE;
1970 cmd_buf->size = cmd_len;
1971 cmd_buf->seq_num = HostCmd_SET_SEQ_NO_BSS_INFO(0 /* seq_num */, 0 /* bss_num */, MLAN_BSS_TYPE_UAP);
1972 cmd_buf->result = 0;
1973
1974 sys_config->action = HostCmd_ACT_GEN_SET;
1975
1976 tlv->count = mac_count;
1977 tlv->filter_mode = filter_mode;
1978 tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_STA_MAC_ADDR_FILTER);
1979
1980 if (tlv->count)
1981 {
1982 tlv->header.len = tlv->count * MLAN_MAC_ADDR_LENGTH + 2;
1983 (void)memcpy(tlv->mac_address, mac_addr, mac_count * MLAN_MAC_ADDR_LENGTH);
1984 }
1985 else
1986 {
1987 tlv->header.len = WLAN_MAX_STA_FILTER_NUM * MLAN_MAC_ADDR_LENGTH + 2;
1988 }
1989
1990 if (is_uap_started())
1991 {
1992 wuap_e("down the uap before setting sta filter\n\r");
1993 OSA_MemoryFree(buffer);
1994 return -WM_FAIL;
1995 }
1996
1997 wifi_get_command_lock();
1998
1999 HostCmd_DS_COMMAND *cmd = wifi_get_command_buffer();
2000
2001 (void)memcpy((t_u8 *)cmd, cmd_buf, cmd_len);
2002
2003 wifi_wait_for_cmdresp(NULL);
2004
2005 OSA_MemoryFree(buffer);
2006
2007 return WM_SUCCESS;
2008 }
2009
2010 #endif
2011
2012 #if CONFIG_WPA_SUPP_AP
2013
wifi_uap_client_assoc(t_u8 * sta_addr,unsigned char is_11n_enabled)2014 void wifi_uap_client_assoc(t_u8 *sta_addr, unsigned char is_11n_enabled)
2015 {
2016 #if (CONFIG_UAP_AMPDU_TX) || (CONFIG_UAP_AMPDU_RX)
2017 wlan_request_ralist_lock(mlan_adap->priv[1]);
2018 /* Clear corresponding tx/rx table if necessary */
2019 if (wlan_11n_get_txbastream_tbl((mlan_private *)mlan_adap->priv[1], sta_addr))
2020 {
2021 wlan_11n_delete_txbastream_tbl_entry((mlan_private *)mlan_adap->priv[1], sta_addr);
2022 }
2023
2024 wlan_cleanup_reorder_tbl((mlan_private *)mlan_adap->priv[1], sta_addr);
2025 #if CONFIG_WMM
2026 wlan_ralist_del_enh(mlan_adap->priv[1], sta_addr);
2027 #endif
2028 /* txbastream table also is used as connected STAs data base */
2029 wlan_11n_create_txbastream_tbl((mlan_private *)mlan_adap->priv[1], sta_addr, BA_STREAM_NOT_SETUP);
2030 wlan_11n_update_txbastream_tbl_tx_thresh((mlan_private *)mlan_adap->priv[1], sta_addr, 3);
2031
2032 if (is_11n_enabled)
2033 {
2034 wlan_11n_update_txbastream_tbl_ampdu_supported((mlan_private *)mlan_adap->priv[1], sta_addr, MTRUE);
2035 }
2036
2037 wlan_release_ralist_lock(mlan_adap->priv[1]);
2038
2039 #endif /* CONFIG_UAP_AMPDU_TX || CONFIG_UAP_AMPDU_RX */
2040
2041 #if CONFIG_WMM
2042 wlan_ralist_add_enh(mlan_adap->priv[1], sta_addr);
2043 #endif
2044 }
2045
wifi_uap_client_deauth(t_u8 * sta_addr)2046 void wifi_uap_client_deauth(t_u8 *sta_addr)
2047 {
2048 #if (CONFIG_UAP_AMPDU_TX) || (CONFIG_UAP_AMPDU_RX)
2049 if ((mlan_private *)mlan_adap->priv[1]->is_11n_enabled)
2050 {
2051 wlan_cleanup_reorder_tbl((mlan_private *)mlan_adap->priv[1], sta_addr);
2052 wlan_request_ralist_lock((mlan_private *)mlan_adap->priv[1]);
2053 wlan_11n_delete_txbastream_tbl_entry((mlan_private *)mlan_adap->priv[1], sta_addr);
2054 wlan_release_ralist_lock((mlan_private *)mlan_adap->priv[1]);
2055 }
2056 #endif /* CONFIG_UAP_AMPDU_TX || CONFIG_UAP_AMPDU_RX */
2057
2058 #if CONFIG_WMM
2059 wlan_ralist_del_enh(mlan_adap->priv[1], sta_addr);
2060 #endif
2061 }
2062
2063 /**
2064 * @brief Verify RSN IE
2065 *
2066 * @param rsn_ie Pointer RSN IE
2067 * @param sys_config Pointer to mlan_uap_bss_param structure
2068 *
2069 * @return MTRUE/MFALSE
2070 */
wifi_check_rsn_ie(IEEEtypes_Rsn_t * rsn_ie,mlan_uap_bss_param * sys_config)2071 static t_u8 wifi_check_rsn_ie(IEEEtypes_Rsn_t *rsn_ie, mlan_uap_bss_param *sys_config)
2072 {
2073 int left = 0;
2074 int count = 0;
2075 int i = 0;
2076 wpa_suite_auth_key_mgmt_t *key_mgmt = NULL;
2077 left = rsn_ie->len + 2;
2078 if (left < (int)sizeof(IEEEtypes_Rsn_t))
2079 return MFALSE;
2080 sys_config->wpa_cfg.group_cipher = 0;
2081 sys_config->wpa_cfg.pairwise_cipher_wpa2 = 0;
2082 sys_config->key_mgmt = 0;
2083 /* check the group cipher */
2084 switch (rsn_ie->group_cipher.type)
2085 {
2086 case WPA_CIPHER_TKIP2:
2087 sys_config->wpa_cfg.group_cipher = CIPHER_TKIP;
2088 break;
2089 case WPA_CIPHER_AES_CCM:
2090 case WPA_CIPHER_AES_GCM:
2091 case WPA_CIPHER_AES_CCM_256:
2092 case WPA_CIPHER_AES_GCM_256:
2093 sys_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
2094 break;
2095 default:
2096 break;
2097 }
2098 count = wlan_le16_to_cpu(rsn_ie->pairwise_cipher.count);
2099 for (i = 0; i < count; i++)
2100 {
2101 switch (rsn_ie->pairwise_cipher.list[i].type)
2102 {
2103 case WPA_CIPHER_TKIP2:
2104 sys_config->wpa_cfg.pairwise_cipher_wpa2 |= CIPHER_TKIP;
2105 break;
2106 case WPA_CIPHER_AES_CCM:
2107 case WPA_CIPHER_AES_GCM:
2108 case WPA_CIPHER_AES_CCM_256:
2109 case WPA_CIPHER_AES_GCM_256:
2110 sys_config->wpa_cfg.pairwise_cipher_wpa2 |= CIPHER_AES_CCMP;
2111 break;
2112 default:
2113 break;
2114 }
2115 }
2116 left -= sizeof(IEEEtypes_Rsn_t) + (count - 1) * sizeof(wpa_suite);
2117 if (left < (int)sizeof(wpa_suite_auth_key_mgmt_t))
2118 return MFALSE;
2119 key_mgmt = (wpa_suite_auth_key_mgmt_t *)((u8 *)rsn_ie + sizeof(IEEEtypes_Rsn_t) + (count - 1) * sizeof(wpa_suite));
2120 count = wlan_le16_to_cpu(key_mgmt->count);
2121 if (left < (int)(sizeof(wpa_suite_auth_key_mgmt_t) + (count - 1) * sizeof(wpa_suite)))
2122 return MFALSE;
2123 for (i = 0; i < count; i++)
2124 {
2125 switch (key_mgmt->list[i].type)
2126 {
2127 case RSN_AKM_8021X:
2128 case RSN_AKM_8021X_SHA256:
2129 case RSN_AKM_8021X_SUITEB:
2130 case RSN_AKM_8021X_SUITEB_192:
2131 #if CONFIG_11R
2132 case RSN_AKM_FT_8021X:
2133 case RSN_AKM_FT_8021X_SHA384:
2134 #endif
2135 sys_config->key_mgmt |= KEY_MGMT_EAP;
2136 break;
2137 case RSN_AKM_PSK:
2138 #if CONFIG_11R
2139 case RSN_AKM_FT_PSK:
2140 #endif
2141 sys_config->key_mgmt |= KEY_MGMT_PSK;
2142 break;
2143 case RSN_AKM_PSK_SHA256:
2144 sys_config->key_mgmt |= KEY_MGMT_PSK_SHA256;
2145 break;
2146 #if UAP_HOST_MLME
2147 case RSN_AKM_SAE:
2148 #if CONFIG_11R
2149 case RSN_AKM_FT_SAE:
2150 #endif
2151 sys_config->key_mgmt |= KEY_MGMT_SAE;
2152 break;
2153 case RSN_AKM_OWE:
2154 #if CONFIG_DRIVER_OWE
2155 sys_config->key_mgmt |= KEY_MGMT_OWE;
2156 #endif
2157 break;
2158 #endif
2159 }
2160 }
2161 return MTRUE;
2162 }
2163
2164 /**
2165 * @brief Verify WPA IE`
2166 * @param wpa_ie Pointer WPA IE
2167 * @param sys_config Pointer to mlan_uap_bss_param structure
2168 *
2169 * @return MTRUE/MFALSE
2170 */
wifi_check_wpa_ie(IEEEtypes_Wpa_t * wpa_ie,mlan_uap_bss_param * sys_config)2171 static t_u8 wifi_check_wpa_ie(IEEEtypes_Wpa_t *wpa_ie, mlan_uap_bss_param *sys_config)
2172 {
2173 int left = 0;
2174 int count = 0;
2175 int i = 0;
2176 wpa_suite_auth_key_mgmt_t *key_mgmt = NULL;
2177 left = wpa_ie->len + 2;
2178 if (left < (int)sizeof(IEEEtypes_Wpa_t))
2179 return MFALSE;
2180 sys_config->wpa_cfg.group_cipher = 0;
2181 sys_config->wpa_cfg.pairwise_cipher_wpa = 0;
2182 switch (wpa_ie->group_cipher.type)
2183 {
2184 case WPA_CIPHER_TKIP2:
2185 sys_config->wpa_cfg.group_cipher = CIPHER_TKIP;
2186 break;
2187 case WPA_CIPHER_AES_CCM:
2188 sys_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
2189 break;
2190 default:
2191 break;
2192 }
2193 count = wlan_le16_to_cpu(wpa_ie->pairwise_cipher.count);
2194 for (i = 0; i < count; i++)
2195 {
2196 switch (wpa_ie->pairwise_cipher.list[i].type)
2197 {
2198 case WPA_CIPHER_TKIP2:
2199 sys_config->wpa_cfg.pairwise_cipher_wpa |= CIPHER_TKIP;
2200 break;
2201 case WPA_CIPHER_AES_CCM:
2202 sys_config->wpa_cfg.pairwise_cipher_wpa |= CIPHER_AES_CCMP;
2203 break;
2204 default:
2205 break;
2206 }
2207 }
2208 left -= sizeof(IEEEtypes_Wpa_t) + (count - 1) * sizeof(wpa_suite);
2209 if (left < (int)sizeof(wpa_suite_auth_key_mgmt_t))
2210 return MFALSE;
2211 key_mgmt = (wpa_suite_auth_key_mgmt_t *)((u8 *)wpa_ie + sizeof(IEEEtypes_Wpa_t) + (count - 1) * sizeof(wpa_suite));
2212 count = wlan_le16_to_cpu(key_mgmt->count);
2213 if (left < (int)(sizeof(wpa_suite_auth_key_mgmt_t) + (count - 1) * sizeof(wpa_suite)))
2214 return MFALSE;
2215 for (i = 0; i < count; i++)
2216 {
2217 switch (key_mgmt->list[i].type)
2218 {
2219 case RSN_AKM_8021X:
2220 sys_config->key_mgmt = KEY_MGMT_EAP;
2221 break;
2222 case RSN_AKM_PSK:
2223 sys_config->key_mgmt = KEY_MGMT_PSK;
2224 break;
2225 }
2226 }
2227 return MTRUE;
2228 }
2229
2230 /**
2231 * @brief Find RSN/WPA IES
2232 *
2233 * @param ie Pointer IE buffer
2234 * @param sys_config Pointer to mlan_uap_bss_param structure
2235 * @return MTRUE/MFALSE
2236 */
wifi_find_wpa_ies(const t_u8 * ie,int len,mlan_uap_bss_param * sys_config)2237 static t_u8 wifi_find_wpa_ies(const t_u8 *ie, int len, mlan_uap_bss_param *sys_config)
2238 {
2239 int bytes_left = len;
2240 const t_u8 *pcurrent_ptr = ie;
2241 t_u16 total_ie_len;
2242 t_u8 element_len;
2243 t_u8 wpa2 = 0;
2244 t_u8 wpa = 0;
2245 t_u8 ret = MFALSE;
2246 IEEEtypes_ElementId_e element_id;
2247 IEEEtypes_VendorSpecific_t *pvendor_ie;
2248 const t_u8 wpa_oui[4] = {0x00, 0x50, 0xf2, 0x01};
2249 while (bytes_left >= 2)
2250 {
2251 element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
2252 element_len = *((t_u8 *)pcurrent_ptr + 1);
2253 total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
2254 if (bytes_left < total_ie_len)
2255 {
2256 PRINTM(MERROR, "InterpretIE: Error in processing IE, bytes left < IE length\n");
2257 bytes_left = 0;
2258 continue;
2259 }
2260 switch (element_id)
2261 {
2262 case RSN_IE:
2263 wpa2 = wifi_check_rsn_ie((IEEEtypes_Rsn_t *)pcurrent_ptr, sys_config);
2264 break;
2265 case VENDOR_SPECIFIC_221:
2266 pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
2267 if (!memcmp(pvendor_ie->vend_hdr.oui, wpa_oui, sizeof(pvendor_ie->vend_hdr.oui)) &&
2268 (pvendor_ie->vend_hdr.oui_type == wpa_oui[3]))
2269 {
2270 wpa = wifi_check_wpa_ie((IEEEtypes_Wpa_t *)pcurrent_ptr, sys_config);
2271 }
2272 break;
2273 default:
2274 break;
2275 }
2276 pcurrent_ptr += element_len + 2;
2277 /* Need to account for IE ID and IE Len */
2278 bytes_left -= (element_len + 2);
2279 }
2280 if (wpa && wpa2)
2281 {
2282 sys_config->protocol = PROTOCOL_WPA | PROTOCOL_WPA2;
2283 ret = MTRUE;
2284 }
2285 else if (wpa2)
2286 {
2287 sys_config->protocol = PROTOCOL_WPA2;
2288 ret = MTRUE;
2289 }
2290 else if (wpa)
2291 {
2292 sys_config->protocol = PROTOCOL_WPA;
2293 ret = MTRUE;
2294 }
2295 return ret;
2296 }
2297
2298 /**
2299 * @brief Find and set WMM IES
2300 * @param priv Pointer to moal_private
2301 * @param ie Pointer IE buffer
2302 * @param sys_config Pointer to mlan_uap_bss_param structure
2303 *
2304 * @return N/A
2305 *
2306 **/
wifi_set_wmm_ies(mlan_private * priv,const t_u8 * ie,int len,mlan_uap_bss_param * sys_config)2307 static t_void wifi_set_wmm_ies(mlan_private *priv, const t_u8 *ie, int len, mlan_uap_bss_param *sys_config)
2308 {
2309 int bytes_left = len;
2310 const t_u8 *pcurrent_ptr = ie;
2311 t_u16 total_ie_len;
2312 t_u8 element_len;
2313 IEEEtypes_VendorSpecific_t *pvendor_ie;
2314 IEEEtypes_ElementId_e element_id;
2315 const t_u8 wmm_oui[4] = {0x00, 0x50, 0xf2, 0x02};
2316
2317 while (bytes_left >= 2)
2318 {
2319 element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
2320 element_len = *((t_u8 *)pcurrent_ptr + 1);
2321 total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
2322 if (bytes_left < total_ie_len)
2323 {
2324 PRINTM(MERROR, "InterpretIE: Error in processing IE, bytes left < IE length\n");
2325 bytes_left = 0;
2326 continue;
2327 }
2328 switch (element_id)
2329 {
2330 case VENDOR_SPECIFIC_221:
2331 pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
2332 if (!memcmp(pvendor_ie->vend_hdr.oui, wmm_oui, sizeof(pvendor_ie->vend_hdr.oui)) &&
2333 pvendor_ie->vend_hdr.oui_type == wmm_oui[3])
2334 {
2335 if (total_ie_len == sizeof(IEEEtypes_WmmParameter_t))
2336 {
2337 #if CONFIG_WIFI_CAPA
2338 if (priv->adapter->usr_dot_11n_enable)
2339 #endif
2340 {
2341 /*
2342 * Only accept and copy the WMM IE if
2343 * it matches the size expected for the
2344 * WMM Parameter IE.
2345 */
2346 memcpy(&sys_config->wmm_para, pcurrent_ptr + sizeof(IEEEtypes_Header_t), element_len);
2347
2348 /** Disable U-APSD for now */
2349 sys_config->wmm_para.qos_info &= 0x7F;
2350
2351 /** set uap_host_based_config to true */
2352 sys_config->uap_host_based_config = MTRUE;
2353 }
2354 #if CONFIG_WIFI_CAPA
2355 else
2356 {
2357 memset(sys_config->wmm_para.ac_params, 0x00, sizeof(wmm_ac_parameters_t) * MAX_AC_QUEUES);
2358 }
2359 #endif
2360 }
2361 }
2362
2363 break;
2364 default:
2365 break;
2366 }
2367 pcurrent_ptr += element_len + 2;
2368 /* Need to account for IE ID and IE Len */
2369 bytes_left -= (element_len + 2);
2370 }
2371 }
2372
2373 /**
2374 * @brief Set/Get system configuration parameters
2375 *
2376 * @param priv A pointer to moal_private structure
2377 * @param action MLAN_ACT_SET or MLAN_ACT_GET
2378 * @param wait_option Wait option
2379 * @param sys_cfg A pointer to mlan_uap_bss_param structure
2380 *
2381 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2382 */
wifi_set_get_sys_config(mlan_private * priv,t_u16 action,mlan_uap_bss_param * sys_cfg)2383 mlan_status wifi_set_get_sys_config(mlan_private *priv, t_u16 action, mlan_uap_bss_param *sys_cfg)
2384 {
2385 int ret;
2386 mlan_ds_bss bss;
2387 mlan_ioctl_req ioctl_buf;
2388
2389 ENTER();
2390
2391 (void)memset(&bss, 0x00, sizeof(mlan_ds_bss));
2392
2393 bss.sub_command = MLAN_OID_UAP_BSS_CONFIG;
2394
2395 if (action == MLAN_ACT_SET)
2396 memcpy(&bss.param.bss_config, sys_cfg, sizeof(mlan_uap_bss_param));
2397
2398 (void)memset(&ioctl_buf, 0x00, sizeof(mlan_ioctl_req));
2399
2400 ioctl_buf.req_id = (t_u32)MLAN_IOCTL_BSS;
2401 /** Pointer to buffer */
2402 ioctl_buf.pbuf = (t_u8 *)&bss;
2403
2404 ret = wifi_uap_prepare_and_send_cmd(priv, HOST_CMD_APCMD_SYS_CONFIGURE, HostCmd_ACT_GEN_SET, 0, &ioctl_buf, NULL,
2405 MLAN_BSS_TYPE_UAP, NULL);
2406 if (ret != WM_SUCCESS)
2407 {
2408 return MLAN_STATUS_FAILURE;
2409 }
2410
2411 return MLAN_STATUS_SUCCESS;
2412 }
2413
2414 #define IE_MASK_WPS 0x0001
2415 #define IE_MASK_P2P 0x0002
2416 #define IE_MASK_WFD 0x0004
2417 #define IE_MASK_VENDOR 0x0008
2418 #define IE_MASK_EXTCAP 0x0010
2419
2420 /**
2421 * @brief get specific ie
2422 *
2423 * @param ie Pointer to IEs
2424 * @param len Total length of ie
2425 * @param ie_out Pointer to out IE buf
2426 * @param ie_out_len Total length of ie_out
2427 * @param mask IE mask
2428 *
2429 * @return out IE length
2430 */
wifi_get_specific_ie(const t_u8 * ie,int len,t_u8 * ie_out,t_u32 ie_out_len,t_u16 mask)2431 static t_u16 wifi_get_specific_ie(const t_u8 *ie, int len, t_u8 *ie_out, t_u32 ie_out_len, t_u16 mask)
2432 {
2433 int left_len = len;
2434 const t_u8 *pos = ie;
2435 int length;
2436 t_u8 id = 0;
2437 t_u16 out_len = 0;
2438 IEEEtypes_VendorSpecific_t *pvendor_ie = NULL;
2439 const u8 wps_oui[4] = {0x00, 0x50, 0xf2, 0x04};
2440 const u8 p2p_oui[4] = {0x50, 0x6f, 0x9a, 0x09};
2441 const u8 wfd_oui[4] = {0x50, 0x6f, 0x9a, 0x0a};
2442 const t_u8 wmm_oui[4] = {0x00, 0x50, 0xf2, 0x02};
2443
2444 ENTER();
2445 while (left_len >= 2)
2446 {
2447 length = *(pos + 1);
2448 id = *pos;
2449 if ((length + 2) > left_len)
2450 break;
2451 if (id == VENDOR_SPECIFIC_221)
2452 {
2453 pvendor_ie = (IEEEtypes_VendorSpecific_t *)pos;
2454 if (!memcmp(pvendor_ie->vend_hdr.oui, wmm_oui, sizeof(pvendor_ie->vend_hdr.oui)) &&
2455 pvendor_ie->vend_hdr.oui_type == wmm_oui[3])
2456 {
2457 PRINTM(MIOCTL, "find WMM IE\n");
2458 }
2459 else if (!memcmp(pvendor_ie->vend_hdr.oui, p2p_oui, sizeof(pvendor_ie->vend_hdr.oui)) &&
2460 pvendor_ie->vend_hdr.oui_type == p2p_oui[3])
2461 {
2462 if (mask & IE_MASK_P2P)
2463 {
2464 /** only get first p2p ie here */
2465 __memcpy(NULL, ie_out + out_len, pos, length + 2);
2466 out_len += length + 2;
2467 break;
2468 }
2469 }
2470 else if (!memcmp(pvendor_ie->vend_hdr.oui, wps_oui, sizeof(pvendor_ie->vend_hdr.oui)) &&
2471 pvendor_ie->vend_hdr.oui_type == wps_oui[3])
2472 {
2473 if (mask & IE_MASK_WPS)
2474 {
2475 if ((out_len + length + 2) < (int)ie_out_len)
2476 {
2477 __memcpy(NULL, ie_out + out_len, pos, length + 2);
2478 out_len += length + 2;
2479 }
2480 else
2481 {
2482 PRINTM(MERROR, "get_specific_ie: IE too big, fail copy WPS IE\n");
2483 break;
2484 }
2485 }
2486 }
2487 else if (!memcmp(pvendor_ie->vend_hdr.oui, wfd_oui, sizeof(pvendor_ie->vend_hdr.oui)) &&
2488 pvendor_ie->vend_hdr.oui_type == wfd_oui[3])
2489 {
2490 if (mask & IE_MASK_WFD)
2491 {
2492 if ((out_len + length + 2) < (int)ie_out_len)
2493 {
2494 __memcpy(NULL, ie_out + out_len, pos, length + 2);
2495 out_len += length + 2;
2496 }
2497 else
2498 {
2499 PRINTM(MERROR, "get_specific_ie: IE too big, fail copy WFD IE\n");
2500 break;
2501 }
2502 }
2503 }
2504 else if (mask & IE_MASK_VENDOR)
2505 {
2506 if ((out_len + length + 2) < (int)ie_out_len)
2507 {
2508 __memcpy(NULL, ie_out + out_len, pos, length + 2);
2509 out_len += length + 2;
2510 }
2511 else
2512 {
2513 PRINTM(MERROR, "get_specific_ie:IE too big, fail copy VENDOR IE\n");
2514 break;
2515 }
2516 }
2517 }
2518 pos += (length + 2);
2519 left_len -= (length + 2);
2520 }
2521 LEAVE();
2522 return out_len;
2523 }
2524
2525 /**
2526 * @brief Find specific IE from IE buffer
2527 *
2528 * @param ie Pointer to IEs
2529 * @param len Total length of ie
2530 * @param spec_ie Pointer to specific IE buffer
2531 * @param spec_len Total length of specific IE
2532 *
2533 * @return out IE length
2534 */
wifi_find_ie(const t_u8 * ie,int len,const t_u8 * spec_ie,int spec_len)2535 static t_u8 wifi_find_ie(const t_u8 *ie, int len, const t_u8 *spec_ie, int spec_len)
2536 {
2537 int left_len = len;
2538 const t_u8 *pos = ie;
2539 int length;
2540
2541 while (left_len >= 2)
2542 {
2543 length = *(pos + 1);
2544 if ((length + 2) > left_len)
2545 break;
2546 if ((length + 2) == spec_len)
2547 {
2548 if (!memcmp(pos, spec_ie, spec_len))
2549 return MTRUE;
2550 }
2551 pos += (length + 2);
2552 left_len -= (length + 2);
2553 }
2554 return MFALSE;
2555 }
2556
2557 /**
2558 * @brief Filter specific IE in ie buf
2559 *
2560 * @param priv pointer to moal private structure
2561 * @param ie Pointer to IEs
2562 * @param len Total length of ie
2563 * @param ie_out Pointer to out IE buf
2564 * @param ie_out_len Total length of ie_out
2565 * @param wps_flag flag for wps/p2p
2566 * @param dup_ie Pointer to duplicate ie
2567 * @param dup_ie_len duplicate IE len
2568 *
2569 * @return out IE length
2570 */
wifi_filter_beacon_ies(mlan_private * priv,const t_u8 * ie,int len,t_u8 * ie_out,t_u32 ie_out_len,t_u16 wps_flag,const t_u8 * dup_ie,int dup_ie_len)2571 static t_u16 wifi_filter_beacon_ies(mlan_private *priv,
2572 const t_u8 *ie,
2573 int len,
2574 t_u8 *ie_out,
2575 t_u32 ie_out_len,
2576 t_u16 wps_flag,
2577 const t_u8 *dup_ie,
2578 int dup_ie_len)
2579 {
2580 int left_len = len;
2581 const t_u8 *pos = ie;
2582 int length;
2583 t_u8 id = 0;
2584 t_u16 out_len = 0;
2585 IEEEtypes_VendorSpecific_t *pvendor_ie = NULL;
2586 const u8 wps_oui[4] = {0x00, 0x50, 0xf2, 0x04};
2587 const u8 p2p_oui[4] = {0x50, 0x6f, 0x9a, 0x09};
2588 const u8 wfd_oui[4] = {0x50, 0x6f, 0x9a, 0x0a};
2589 const t_u8 wmm_oui[4] = {0x00, 0x50, 0xf2, 0x02};
2590 t_u8 find_p2p_ie = MFALSE;
2591 t_u8 enable_11d = MFALSE;
2592 #if CONFIG_11AX
2593 t_u8 ext_id = 0;
2594 #endif
2595 // int ie_len;
2596
2597 /* ERP_INFO/EXTENDED_SUPPORT_RATES/HT_CAPABILITY/HT_OPERATION/WMM
2598 * and WPS/P2P/WFD IE will be fileter out
2599 */
2600 while (left_len >= 2)
2601 {
2602 length = *(pos + 1);
2603 id = *pos;
2604 if ((length + 2) > left_len)
2605 break;
2606 if (dup_ie && dup_ie_len && wifi_find_ie(dup_ie, dup_ie_len, pos, length + 2))
2607 {
2608 wifi_d("skip duplicate IE");
2609 pos += (length + 2);
2610 left_len -= (length + 2);
2611 continue;
2612 }
2613 switch (id)
2614 {
2615 case COUNTRY_INFO:
2616 enable_11d = MTRUE;
2617 if ((out_len + length + 2) < (int)ie_out_len)
2618 {
2619 __memcpy(priv, ie_out + out_len, pos, length + 2);
2620 out_len += length + 2;
2621 }
2622 else
2623 {
2624 wifi_d("IE too big, fail copy COUNTRY INFO IE");
2625 }
2626 break;
2627 case HT_CAPABILITY:
2628 case HT_OPERATION:
2629 #if CONFIG_11AC
2630 case VHT_CAPABILITY:
2631 case VHT_OPERATION:
2632 #endif
2633 #if UAP_HOST_MLME
2634 if ((out_len + length + 2) < (int)ie_out_len)
2635 {
2636 __memcpy(priv, ie_out + out_len, pos, length + 2);
2637 out_len += length + 2;
2638 }
2639 else
2640 {
2641 wifi_d("IE too big, fail copy COUNTRY INFO IE");
2642 }
2643 #endif
2644 break;
2645 case EXTENDED_SUPPORTED_RATES:
2646 case WLAN_EID_ERP_INFO:
2647 /* Fall Through */
2648 case REGULATORY_CLASS:
2649 /* Fall Through */
2650 case OVERLAPBSSSCANPARAM:
2651 #ifdef WAPI_AP
2652 /* Fall Through */
2653 case WAPI_IE:
2654 #endif
2655 break;
2656 #if CONFIG_11AX
2657 case EXTENSION:
2658 ext_id = *(pos + 2);
2659 #if UAP_SUPPORT
2660 #if CONFIG_11AX
2661 if (ext_id == HE_CAPABILITY)
2662 {
2663 mlan_ds_11ax_he_cfg he_cfg;
2664 IEEEtypes_HECap_t *hecap_ie = NULL;
2665 (void)memset((void *)&he_cfg, 0, sizeof(mlan_ds_11ax_he_cfg));
2666
2667 if (priv->uap_channel <= 14)
2668 he_cfg.band = MBIT(0);
2669 else
2670 he_cfg.band = MBIT(1);
2671
2672 wifi_d("Retrieve 11ax cfg by channel=%d band=%d", priv->uap_channel, he_cfg.band);
2673
2674 if (0 == wlan_cmd_11ax_cfg(priv, HostCmd_ACT_GEN_GET, &he_cfg))
2675 {
2676 t_u16 he_cap_len;
2677 hecap_ie = (IEEEtypes_HECap_t *)&he_cfg.he_cap.len;
2678 he_cap_len = he_cfg.he_cap.len;
2679 hecap_ie->ieee_hdr.len = he_cap_len;
2680 hecap_ie->ieee_hdr.element_id = he_cfg.he_cap.id;
2681
2682 __memcpy(priv, ie_out + out_len, hecap_ie, hecap_ie->ieee_hdr.len + 2);
2683
2684 out_len += hecap_ie->ieee_hdr.len + 2;
2685 }
2686 else
2687 {
2688 wifi_d("Fail to get 11ax he_cap parameters");
2689 }
2690 }
2691 else
2692 #endif
2693 #endif
2694 {
2695 if ((out_len + length + 2) < (int)ie_out_len)
2696 {
2697 __memcpy(priv, ie_out + out_len, pos, length + 2);
2698 out_len += length + 2;
2699 }
2700 else
2701 {
2702 wifi_d("IE too big, fail copy EXTENSION IE");
2703 }
2704 }
2705 break;
2706 #endif
2707 case EXT_CAPABILITY:
2708 /* filter out EXTCAP */
2709 if (wps_flag & IE_MASK_EXTCAP)
2710 {
2711 #if 0
2712 ie_len = length + 2;
2713 if (MLAN_STATUS_SUCCESS !=
2714 wifi_set_get_gen_ie(priv, MLAN_ACT_SET,
2715 (t_u8 *)pos, &ie_len,
2716 MOAL_IOCTL_WAIT))
2717 PRINTM(MERROR,
2718 "Fail to set EXTCAP IE\n");
2719 #endif
2720 break;
2721 }
2722 if ((out_len + length + 2) < (int)ie_out_len)
2723 {
2724 __memcpy(priv, ie_out + out_len, pos, length + 2);
2725 out_len += length + 2;
2726 }
2727 else
2728 {
2729 wifi_d("IE too big, fail copy EXTCAP IE");
2730 }
2731 break;
2732 case VENDOR_SPECIFIC_221:
2733 /* filter out wmm ie */
2734 pvendor_ie = (IEEEtypes_VendorSpecific_t *)pos;
2735 if (!memcmp(pvendor_ie->vend_hdr.oui, wmm_oui, sizeof(pvendor_ie->vend_hdr.oui)) &&
2736 pvendor_ie->vend_hdr.oui_type == wmm_oui[3])
2737 {
2738 break;
2739 }
2740 /* filter out wps ie */
2741 else if (!memcmp(pvendor_ie->vend_hdr.oui, wps_oui, sizeof(pvendor_ie->vend_hdr.oui)) &&
2742 pvendor_ie->vend_hdr.oui_type == wps_oui[3])
2743 {
2744 if (wps_flag & IE_MASK_WPS)
2745 break;
2746 }
2747 /* filter out first p2p ie */
2748 else if (!memcmp(pvendor_ie->vend_hdr.oui, p2p_oui, sizeof(pvendor_ie->vend_hdr.oui)) &&
2749 pvendor_ie->vend_hdr.oui_type == p2p_oui[3])
2750 {
2751 if (!find_p2p_ie && (wps_flag & IE_MASK_P2P))
2752 {
2753 find_p2p_ie = MTRUE;
2754 break;
2755 }
2756 }
2757 /* filter out wfd ie */
2758 else if (!memcmp(pvendor_ie->vend_hdr.oui, wfd_oui, sizeof(pvendor_ie->vend_hdr.oui)) &&
2759 pvendor_ie->vend_hdr.oui_type == wfd_oui[3])
2760 {
2761 if (wps_flag & IE_MASK_WFD)
2762 break;
2763 }
2764 else if (wps_flag & IE_MASK_VENDOR)
2765 {
2766 // filter out vendor IE
2767 break;
2768 }
2769 if ((out_len + length + 2) < (int)ie_out_len)
2770 {
2771 __memcpy(priv, ie_out + out_len, pos, length + 2);
2772 out_len += length + 2;
2773 }
2774 else
2775 {
2776 wifi_d("IE too big, fail copy VENDOR_SPECIFIC_221 IE");
2777 }
2778 break;
2779 default:
2780 if ((out_len + length + 2) < (int)ie_out_len)
2781 {
2782 __memcpy(priv, ie_out + out_len, pos, length + 2);
2783 out_len += length + 2;
2784 }
2785 else
2786 {
2787 wifi_d("IE too big, fail copy %d IE", id);
2788 }
2789 break;
2790 }
2791
2792 pos += (length + 2);
2793 left_len -= (length + 2);
2794 }
2795
2796 #if UAP_SUPPORT
2797 if (enable_11d && !priv->bss_started && !wlan_11d_is_enabled(priv))
2798 {
2799 wuap_d("Enable 11D support");
2800 wifi_enable_uap_11d_support();
2801 }
2802 #endif
2803 return out_len;
2804 }
2805
wifi_nxp_set_mgmt_ies(mlan_private * priv,char * tail_ies,unsigned short tail_ies_len,char * beacon_ies,unsigned short beacon_ies_len,char * proberesp_ies,unsigned short proberesp_ies_len,char * assocresp_ies,unsigned short assocresp_ies_len)2806 static int wifi_nxp_set_mgmt_ies(mlan_private *priv,
2807 char *tail_ies,
2808 unsigned short tail_ies_len,
2809 char *beacon_ies,
2810 unsigned short beacon_ies_len,
2811 char *proberesp_ies,
2812 unsigned short proberesp_ies_len,
2813 char *assocresp_ies,
2814 unsigned short assocresp_ies_len)
2815 {
2816 int ret = WM_SUCCESS;
2817 const t_u8 *ie = NULL;
2818 t_u8 ie_buffer[MAX_IE_SIZE];
2819 t_u16 ie_len, ie_length = 0;
2820 custom_ie *beacon_ies_data = NULL;
2821 custom_ie *beacon_wps_ies_data = NULL;
2822 custom_ie *proberesp_ies_data = NULL;
2823 custom_ie *assocresp_ies_data = NULL;
2824
2825 beacon_ies_data = (custom_ie *)OSA_MemoryAllocate(sizeof(custom_ie));
2826 beacon_wps_ies_data = (custom_ie *)OSA_MemoryAllocate(sizeof(custom_ie));
2827 proberesp_ies_data = (custom_ie *)OSA_MemoryAllocate(sizeof(custom_ie));
2828
2829 assocresp_ies_data = (custom_ie *)OSA_MemoryAllocate(sizeof(custom_ie));
2830
2831 if ((!beacon_ies_data) || (!beacon_wps_ies_data) || (!proberesp_ies_data) || (!assocresp_ies_data))
2832 {
2833 if (beacon_ies_data)
2834 {
2835 OSA_MemoryFree(beacon_ies_data);
2836 }
2837 if (beacon_wps_ies_data)
2838 {
2839 OSA_MemoryFree(beacon_wps_ies_data);
2840 }
2841 if (proberesp_ies_data)
2842 {
2843 OSA_MemoryFree(proberesp_ies_data);
2844 }
2845 if (assocresp_ies_data)
2846 {
2847 OSA_MemoryFree(assocresp_ies_data);
2848 }
2849 return -WM_FAIL;
2850 }
2851
2852 ie = (const t_u8 *)tail_ies;
2853 ie_len = tail_ies_len;
2854 ie_length = 0;
2855
2856 if ((ie != NULL) && (ie_len != 0U))
2857 {
2858 if (priv->beacon_vendor_index != -1)
2859 {
2860 ret = wifi_clear_mgmt_ie2(MLAN_BSS_TYPE_UAP, priv->beacon_vendor_index);
2861 if (ret != WM_SUCCESS)
2862 {
2863 wuap_e("Clear uAP vendor IE failed");
2864 ret = -WM_FAIL;
2865 goto done;
2866 }
2867 priv->beacon_vendor_index = -1;
2868 }
2869
2870 ie_length = wifi_get_specific_ie(ie, ie_len, ie_buffer, MAX_IE_SIZE, IE_MASK_VENDOR);
2871 #if CONFIG_WIFI_IO_DUMP
2872 PRINTF("VENDOR IE\r\n");
2873 dump_hex(ie_buffer, ie_length);
2874 #endif
2875
2876 if (ie_length)
2877 {
2878 priv->beacon_vendor_index =
2879 wifi_set_mgmt_ie2(MLAN_BSS_TYPE_UAP, MGMT_MASK_BEACON | MGMT_MASK_ASSOC_RESP | MGMT_MASK_PROBE_RESP,
2880 (void *)ie_buffer, ie_length);
2881
2882 if (priv->beacon_vendor_index == -1)
2883 {
2884 wuap_e("Set uAP vendor IE failed");
2885 ret = -WM_FAIL;
2886 goto done;
2887 }
2888 }
2889
2890 ie_length = wifi_filter_beacon_ies(priv, ie, ie_len, ie_buffer, MAX_IE_SIZE,
2891 IE_MASK_WPS | IE_MASK_WFD | IE_MASK_P2P | IE_MASK_VENDOR,
2892 (const t_u8 *)proberesp_ies, proberesp_ies_len);
2893 #if CONFIG_WIFI_IO_DUMP
2894 PRINTF("Beacon IE\r\n");
2895 dump_hex(ie_buffer, ie_length);
2896 #endif
2897 }
2898
2899 beacon_ies_data->ie_index = priv->beacon_index;
2900
2901 if (ie_length)
2902 {
2903 beacon_ies_data->mgmt_subtype_mask = MGMT_MASK_BEACON | MGMT_MASK_ASSOC_RESP | MGMT_MASK_PROBE_RESP;
2904 beacon_ies_data->ie_length = ie_length;
2905 memcpy(beacon_ies_data->ie_buffer, (void *)ie_buffer, ie_length);
2906 }
2907 else
2908 {
2909 beacon_ies_data->mgmt_subtype_mask = MGMT_MASK_CLEAR;
2910 }
2911
2912 ie = (const t_u8 *)beacon_ies;
2913 ie_len = beacon_ies_len;
2914 ie_length = 0;
2915
2916 if ((ie != NULL) && (ie_len != 0U))
2917 {
2918 ie_length = wifi_filter_beacon_ies(priv, ie, ie_len, ie_buffer, MAX_IE_SIZE, IE_MASK_VENDOR, NULL, 0);
2919 #if CONFIG_WIFI_IO_DUMP
2920 PRINTF("Beacon WPS IE\r\n");
2921 dump_hex(ie_buffer, ie_length);
2922 #endif
2923 }
2924
2925 beacon_wps_ies_data->ie_index = priv->beacon_wps_index;
2926 if (ie_length)
2927 {
2928 beacon_wps_ies_data->mgmt_subtype_mask = MGMT_MASK_BEACON;
2929 beacon_wps_ies_data->ie_length = ie_length;
2930 memcpy(beacon_wps_ies_data->ie_buffer, (void *)ie_buffer, ie_length);
2931 }
2932 else
2933 {
2934 beacon_wps_ies_data->mgmt_subtype_mask = MGMT_MASK_CLEAR;
2935 }
2936
2937 ie = (const t_u8 *)proberesp_ies;
2938 ie_len = proberesp_ies_len;
2939 ie_length = 0;
2940
2941 if ((ie != NULL) && (ie_len != 0U))
2942 {
2943 ie_length =
2944 wifi_filter_beacon_ies(priv, ie, ie_len, ie_buffer, MAX_IE_SIZE, IE_MASK_P2P | IE_MASK_VENDOR, NULL, 0);
2945 #if CONFIG_WIFI_IO_DUMP
2946 PRINTF("ProbeResp IE\r\n");
2947 dump_hex(ie_buffer, ie_length);
2948 #endif
2949 }
2950
2951 proberesp_ies_data->ie_index = priv->proberesp_index;
2952 if (ie_length)
2953 {
2954 proberesp_ies_data->mgmt_subtype_mask = MGMT_MASK_PROBE_RESP;
2955 proberesp_ies_data->ie_length = ie_length;
2956 memcpy(proberesp_ies_data->ie_buffer, (void *)ie_buffer, ie_length);
2957 }
2958 else
2959 {
2960 proberesp_ies_data->mgmt_subtype_mask = MGMT_MASK_CLEAR;
2961 }
2962
2963 ie = (const t_u8 *)assocresp_ies;
2964 ie_len = assocresp_ies_len;
2965 ie_length = 0;
2966
2967 if ((ie != NULL) && (ie_len != 0U))
2968 {
2969 #if CONFIG_WIFI_IO_DUMP
2970 PRINTF("AssocResp IE\r\n");
2971 dump_hex(ie, ie_len);
2972 #endif
2973 }
2974
2975 assocresp_ies_data->ie_index = priv->assocresp_index;
2976 if (ie_len)
2977 {
2978 assocresp_ies_data->mgmt_subtype_mask = MGMT_MASK_ASSOC_RESP;
2979 assocresp_ies_data->ie_length = ie_len;
2980 memcpy(assocresp_ies_data->ie_buffer, (void *)ie, ie_len);
2981 }
2982 else
2983 {
2984 assocresp_ies_data->mgmt_subtype_mask = MGMT_MASK_CLEAR;
2985 }
2986
2987 ret = wifi_set_custom_ie(beacon_ies_data, beacon_wps_ies_data, proberesp_ies_data, assocresp_ies_data);
2988 if (ret != WM_SUCCESS)
2989 {
2990 ret = -WM_FAIL;
2991 goto done;
2992 }
2993 ret = WM_SUCCESS;
2994 done:
2995 if (beacon_ies_data)
2996 {
2997 OSA_MemoryFree(beacon_ies_data);
2998 }
2999 if (beacon_wps_ies_data)
3000 {
3001 OSA_MemoryFree(beacon_wps_ies_data);
3002 }
3003 if (proberesp_ies_data)
3004 {
3005 OSA_MemoryFree(proberesp_ies_data);
3006 }
3007 if (assocresp_ies_data)
3008 {
3009 OSA_MemoryFree(assocresp_ies_data);
3010 }
3011
3012 return ret;
3013 }
3014
3015 #if CONFIG_5GHz_SUPPORT
3016 /**
3017 * @brief Get second channel offset
3018 *
3019 * @param priv A pointer to moal_private structure
3020 * @param chan channel num
3021 * @return second channel offset
3022 */
wifi_get_second_channel_offset(mlan_private * priv,int chan)3023 t_u8 wifi_get_second_channel_offset(mlan_private *priv, int chan)
3024 {
3025 t_u8 chan2Offset = SEC_CHAN_NONE;
3026
3027 #if CONFIG_UNII4_BAND_SUPPORT
3028 mlan_adapter *pmadapter = priv->adapter;
3029 if (pmadapter->region_code != COUNTRY_CODE_US && chan == 165)
3030 #else
3031 if (chan == 165)
3032 #endif
3033 return chan2Offset;
3034
3035 switch (chan)
3036 {
3037 case 36:
3038 case 44:
3039 case 52:
3040 case 60:
3041 case 100:
3042 case 108:
3043 case 116:
3044 case 124:
3045 case 132:
3046 #if CONFIG_11AC
3047 case 140:
3048 #endif
3049 case 149:
3050 case 157:
3051 #if CONFIG_UNII4_BAND_SUPPORT
3052 case 165:
3053 case 173:
3054 #endif
3055 chan2Offset = SEC_CHAN_ABOVE;
3056 break;
3057 case 40:
3058 case 48:
3059 case 56:
3060 case 64:
3061 case 104:
3062 case 112:
3063 case 120:
3064 case 128:
3065 case 136:
3066 #if CONFIG_11AC
3067 case 144:
3068 #endif
3069 case 153:
3070 case 161:
3071 #if CONFIG_UNII4_BAND_SUPPORT
3072 case 169:
3073 case 177:
3074 #endif
3075 chan2Offset = SEC_CHAN_BELOW;
3076 break;
3077 }
3078 return chan2Offset;
3079 }
3080 #endif
3081
3082 /**
3083 * @brief Look up specific IE in a buf
3084 *
3085 * @param ie Pointer to IEs
3086 * @param len Total length of ie
3087 * @param id Element id to lookup
3088 *
3089 * @return Pointer of the specific IE -- success, NULL -- fail
3090 */
wifi_parse_ie_tlv(const t_u8 * ie,int len,t_u8 id)3091 const t_u8 *wifi_parse_ie_tlv(const t_u8 *ie, int len, t_u8 id)
3092 {
3093 int left_len = len;
3094 const t_u8 *pos = ie;
3095 int length;
3096
3097 /* IE format:
3098 * | u8 | id |
3099 * | u8 | len |
3100 * | var | data |
3101 */
3102 while (left_len >= 2)
3103 {
3104 length = *(pos + 1);
3105 if ((*pos == id) && (length + 2) <= left_len)
3106 return pos;
3107 pos += (length + 2);
3108 left_len -= (length + 2);
3109 }
3110
3111 return NULL;
3112 }
3113
3114 /**
3115 * @brief Look up specific IE in Extension IE
3116 *
3117 * @param ie Pointer to IEs
3118 * @param len Total length of ie
3119 * @param ext_id Extended Element id to lookup
3120 *
3121 * @return Pointer of the specific Extended IE -- success, NULL
3122 * -- fail
3123 */
wifi_parse_ext_ie_tlv(const t_u8 * ie,int len,t_u8 ext_id)3124 const t_u8 *wifi_parse_ext_ie_tlv(const t_u8 *ie, int len, t_u8 ext_id)
3125 {
3126 int left_len = len;
3127 const t_u8 *pos = ie;
3128 int length;
3129
3130 /* Extension IE format:
3131 * | u8 | id |
3132 * | u8 | len |
3133 * | u8 | ext_id |
3134 * | var | data |
3135 */
3136 while (left_len >= 2)
3137 {
3138 length = *(pos + 1);
3139 if ((*pos == EXTENSION) && (length + 2) <= left_len)
3140 {
3141 if (*(pos + 2) == ext_id)
3142 return pos;
3143 }
3144 pos += (length + 2);
3145 left_len -= (length + 2);
3146 }
3147 return NULL;
3148 }
3149
3150 /**
3151 * @brief get ht_cap from beacon ie
3152 *
3153 * @param ie Pointer to IEs
3154 * @param len Total length of ie
3155 *
3156 * @return ht_cap
3157 */
wifi_get_htcap_info(const t_u8 * ie,int len)3158 static t_u16 wifi_get_htcap_info(const t_u8 *ie, int len)
3159 {
3160 t_u16 ht_cap_info = 0;
3161 IEEEtypes_HTCap_t *htcap_ie = NULL;
3162 htcap_ie = (IEEEtypes_HTCap_t *)wifi_parse_ie_tlv(ie, len, HT_CAPABILITY);
3163 if (htcap_ie)
3164 {
3165 /* hostap has converted ht_cap_info to little endian, here
3166 * conver to host endian */
3167 ht_cap_info = wlan_le16_to_cpu(htcap_ie->ht_cap.ht_cap_info);
3168 wifi_d("Get ht_cap from beacon ies: 0x%x\r\n", ht_cap_info);
3169 }
3170 return ht_cap_info;
3171 }
3172
3173 #if CONFIG_11AC
3174 /**
3175 * @brief get vht_cap from beacon ie
3176 *
3177 * @param ie Pointer to IEs
3178 * @param len Total length of ie
3179 *
3180 * @return Pointer to vht_cap ie
3181 */
wifi_get_vhtcap_info(const t_u8 * ie,int len)3182 static IEEEtypes_VHTCap_t *wifi_get_vhtcap_info(const t_u8 *ie, int len)
3183 {
3184 IEEEtypes_VHTCap_t *vhtcap_ie = NULL;
3185 vhtcap_ie = (IEEEtypes_VHTCap_t *)wifi_parse_ie_tlv(ie, len, VHT_CAPABILITY);
3186 if (vhtcap_ie)
3187 wifi_d("Get vht_cap from beacon ies: 0x%x\r\n", vhtcap_ie->vht_cap.vht_cap_info);
3188 return vhtcap_ie;
3189 }
3190
3191 /**
3192 * @brief get vht_oper from beacon ie
3193 *
3194 * @param ie Pointer to IEs
3195 * @param len Total length of ie
3196 *
3197 * @return Pointer to vht_opr ie
3198 */
wifi_get_vht_oprat_ie(const t_u8 * ie,int len)3199 static IEEEtypes_VHTOprat_t *wifi_get_vht_oprat_ie(const t_u8 *ie, int len)
3200 {
3201 IEEEtypes_VHTOprat_t *vht_oprat_ie = NULL;
3202 vht_oprat_ie = (IEEEtypes_VHTOprat_t *)wifi_parse_ie_tlv(ie, len, VHT_OPERATION);
3203 if (vht_oprat_ie)
3204 wifi_d("Get vht_oprat_ie from beacon ies: chan_width=%d\r\n", vht_oprat_ie->chan_width);
3205 return vht_oprat_ie;
3206 }
3207
3208 /**
3209 * @brief enable/disable 11AC
3210 *
3211 * @param priv A pointer to moal_private structure
3212 * @param action MLAN_ACT_DISABLE or MLAN_ACT_ENABLE
3213 * @param vht20_40 Enable VHT 20 MHz or 40 MHz band
3214 * @param vhtcap_ie A pointer to vht capability IE
3215 *
3216 * @return 0--success, otherwise failure
3217 */
wifi_uap_set_11ac_status2(mlan_private * priv,t_u8 action,t_u8 vht20_40,IEEEtypes_VHTCap_t * vhtcap_ie)3218 int wifi_uap_set_11ac_status2(mlan_private *priv, t_u8 action, t_u8 vht20_40, IEEEtypes_VHTCap_t *vhtcap_ie)
3219 {
3220 mlan_adapter *pmadapter = priv->adapter;
3221 mlan_ds_11ac_vht_cfg vht_cfg;
3222 int ret = 0;
3223
3224 ENTER();
3225
3226 (void)memset(&vht_cfg, 0, sizeof(vht_cfg));
3227
3228 #if CONFIG_5GHz_SUPPORT
3229 if (priv->uap_channel > MAX_CHANNELS_BG)
3230 {
3231 vht_cfg.band = BAND_SELECT_A;
3232 }
3233 else
3234 {
3235 vht_cfg.band = BAND_SELECT_BG;
3236 }
3237 #else
3238 vht_cfg.band = BAND_SELECT_BG;
3239 #endif
3240 vht_cfg.txrx = MLAN_RADIO_TXRX;
3241
3242 /*
3243 * p2p GO (negotiation or auto GO) cases, wpa_supplicant will download
3244 * invalid vht capability with value 0 in beacon parameters, so for p2p
3245 * GO case (vht_cap_info = 0), driver will use hardware 11ac vht
3246 * capability value instead of up layer value.
3247 */
3248 if (vhtcap_ie && vhtcap_ie->vht_cap.vht_cap_info != 0)
3249 {
3250 vht_cfg.vht_cap_info = wlan_le32_to_cpu(vhtcap_ie->vht_cap.vht_cap_info);
3251 /** todo mcs configuration */
3252 }
3253 else
3254 {
3255 #if CONFIG_5GHz_SUPPORT
3256 vht_cfg.vht_cap_info = pmadapter->usr_dot_11ac_dev_cap_a;
3257 #else
3258 vht_cfg.vht_cap_info = pmadapter->usr_dot_11ac_dev_cap_bg;
3259 #endif
3260 }
3261 if (action == MLAN_ACT_DISABLE)
3262 {
3263 vht_cfg.bwcfg = MFALSE;
3264 vht_cfg.vht_cap_info &= ~VHT_CAP_11AC_MASK;
3265 vht_cfg.vht_rx_mcs = vht_cfg.vht_tx_mcs = 0xffff;
3266 vht_cfg.skip_usr_11ac_mcs_cfg = MTRUE;
3267 }
3268 else
3269 {
3270 if (vht20_40)
3271 vht_cfg.bwcfg = MFALSE;
3272 else
3273 vht_cfg.bwcfg = MTRUE;
3274 vht_cfg.vht_cap_info &= ~DEFALUT_11AC_CAP_BEAMFORMING_RESET_MASK;
3275 vht_cfg.vht_tx_mcs = pmadapter->usr_dot_11ac_mcs_support >> 16;
3276 vht_cfg.vht_rx_mcs = pmadapter->usr_dot_11ac_mcs_support & 0xffff;
3277 vht_cfg.skip_usr_11ac_mcs_cfg = MTRUE;
3278 }
3279
3280 if ((GET_VHTCAP_MAXMPDULEN(vht_cfg.vht_cap_info)) != 0U)
3281 {
3282 RESET_11ACMAXMPDULEN(vht_cfg.vht_cap_info);
3283 }
3284 else
3285 {
3286 /** Do Nothing */
3287 }
3288
3289 wifi_d("Uap:11ac=%d vht_cap_info=0x%x, vht_tx_mcs=0x%x, vht_rx_mcs=0x%x\r\n", action, vht_cfg.vht_cap_info,
3290 vht_cfg.vht_tx_mcs, vht_cfg.vht_rx_mcs);
3291
3292 ret = (int)wlan_11ac_ioctl_vhtcfg(priv, (t_u8)MLAN_ACT_SET, &vht_cfg);
3293 return ret;
3294 }
3295 #endif
3296
3297 #if CONFIG_11AX
3298
3299 /**
3300 * @brief enable/disable 11AX
3301 *
3302 * @param pmpriv A pointer to mlan_private structure
3303 * @param action MLAN_ACT_DISABLE or MLAN_ACT_ENABLE
3304 * @param band band config
3305 *
3306 * @return 0--success, otherwise failure
3307 */
wifi_uap_set_11ax_status2(mlan_private * pmpriv,t_u8 action,t_u8 band,IEEEtypes_HECap_t * hecap_ie,t_u8 bandwidth)3308 int wifi_uap_set_11ax_status2(mlan_private *pmpriv, t_u8 action, t_u8 band, IEEEtypes_HECap_t *hecap_ie, t_u8 bandwidth)
3309 {
3310 mlan_adapter *pmadapter = pmpriv->adapter;
3311 int ret = 0;
3312 mlan_ds_11ax_he_cfg he_cfg;
3313
3314 ENTER();
3315 if ((band == BAND_CONFIG_5GHZ && !(pmadapter->fw_bands & BAND_AAX)) ||
3316 ((band == BAND_CONFIG_ACS_MODE || band == BAND_CONFIG_MANUAL) && !(pmadapter->fw_bands & BAND_GAX)))
3317 {
3318 PRINTM(MERROR, "fw doesn't support 11ax\n");
3319 ret = -WM_FAIL;
3320 goto done;
3321 }
3322 memset(&he_cfg, 0, sizeof(he_cfg));
3323 if (band == BAND_CONFIG_5GHZ)
3324 {
3325 he_cfg.band = MBIT(1);
3326 (void)memcpy((void *)&he_cfg.he_cap, (const void *)pmadapter->hw_he_cap, pmadapter->hw_hecap_len);
3327 }
3328 else if (band == BAND_CONFIG_ACS_MODE || band == BAND_CONFIG_MANUAL)
3329 {
3330 he_cfg.band = MBIT(0);
3331 (void)memcpy((void *)&he_cfg.he_cap, (const void *)pmadapter->hw_2g_he_cap, pmadapter->hw_2g_hecap_len);
3332 if (bandwidth == BANDWIDTH_20MHZ)
3333 {
3334 he_cfg.he_cap.he_phy_cap[0] &= ~(MBIT(1));
3335 }
3336 }
3337 else
3338 {
3339 PRINTM(MERROR, "Invalid band!\n");
3340 ret = -WM_E_INVAL;
3341 goto done;
3342 }
3343 #ifdef RW610
3344 he_cfg.he_cap.he_phy_cap[0] &= ~DEFAULT_11AX_CAP_40MHZIH2_4GHZBAND_RESET_MASK;
3345 #endif
3346 #if CONFIG_11AX_TWT
3347 /* uap mode clear TWT request bit */
3348 he_cfg.he_cap.he_mac_cap[0] &= ~HE_MAC_CAP_TWT_REQ_SUPPORT;
3349 #endif
3350 #if 0
3351 if (wlan_cmd_11ax_cfg(pmpriv, HostCmd_ACT_GEN_GET, &he_cfg))
3352 {
3353 PRINTM(MERROR, "Fail to get 11ax cfg!\n");
3354 ret = -WM_FAIL;
3355 goto done;
3356 }
3357 #endif
3358 if (hecap_ie)
3359 {
3360 DBG_HEXDUMP(MCMD_D, "hecap_ie", (t_u8 *)hecap_ie, hecap_ie->ieee_hdr.len + sizeof(IEEEtypes_Header_t));
3361 he_cfg.he_cap.id = hecap_ie->ieee_hdr.element_id;
3362 he_cfg.he_cap.len = hecap_ie->ieee_hdr.len;
3363 memcpy(&he_cfg.he_cap.ext_id, &hecap_ie->ext_id, he_cfg.he_cap.len);
3364 if ((band == BAND_2GHZ) && (bandwidth == BANDWIDTH_20MHZ))
3365 {
3366 he_cfg.he_cap.he_phy_cap[0] &= ~(MBIT(1));
3367 }
3368 }
3369
3370 if (action == MLAN_ACT_DISABLE)
3371 {
3372 if (he_cfg.he_cap.len && (he_cfg.he_cap.ext_id == HE_CAPABILITY))
3373 memset(he_cfg.he_cap.he_txrx_mcs_support, 0xff, sizeof(he_cfg.he_cap.he_txrx_mcs_support));
3374 else
3375 {
3376 PRINTM(MCMND, "11ax already disabled\n");
3377 goto done;
3378 }
3379 }
3380 DBG_HEXDUMP(MCMD_D, "HE_CFG ", (t_u8 *)&he_cfg, sizeof(he_cfg));
3381 ret = wlan_cmd_11ax_cfg(pmpriv, HostCmd_ACT_GEN_SET, &he_cfg);
3382 done:
3383 LEAVE();
3384 return ret;
3385 }
3386 #endif /* CONFIG_11AX */
3387
3388 #if CONFIG_5GHz_SUPPORT
wifi_set_uap_dfs_cac(mlan_private * priv,Band_Config_t * bandcfg,t_u8 ht_enabled)3389 static void wifi_set_uap_dfs_cac(mlan_private *priv, Band_Config_t *bandcfg, t_u8 ht_enabled)
3390 {
3391 if (priv->uap_channel > MAX_CHANNELS_BG)
3392 {
3393 mlan_private *priv_sta = (mlan_private *)mlan_adap->priv[0];
3394 if ((priv_sta->media_connected == MTRUE) && wlan_11h_radar_detect_required(priv, priv->uap_channel))
3395 {
3396 nxp_wifi_dfs_cac_info cacinfo;
3397 t_u8 center_chan = 0;
3398
3399 memset(&cacinfo, 0, sizeof(nxp_wifi_dfs_cac_info));
3400 cacinfo.center_freq = channel_to_frequency(priv->uap_channel, bandcfg->chanBand);
3401 cacinfo.ht_enabled = ht_enabled;
3402 cacinfo.ch_offset = bandcfg->chan2Offset;
3403 cacinfo.center_freq2 = 0;
3404
3405 switch (bandcfg->chanWidth)
3406 {
3407 case CHAN_BW_20MHZ:
3408 if (ht_enabled)
3409 cacinfo.ch_width = CHAN_BAND_WIDTH_20;
3410 else
3411 cacinfo.ch_width = CHAN_BAND_WIDTH_20_NOHT;
3412 cacinfo.center_freq1 = cacinfo.center_freq;
3413 break;
3414
3415 case CHAN_BW_40MHZ:
3416 cacinfo.ch_width = CHAN_BAND_WIDTH_40;
3417 if (bandcfg->chan2Offset == SEC_CHAN_ABOVE)
3418 cacinfo.center_freq1 = cacinfo.center_freq + 10;
3419 else if (bandcfg->chan2Offset == SEC_CHAN_BELOW)
3420 cacinfo.center_freq1 = cacinfo.center_freq - 10;
3421 break;
3422
3423 #if (CONFIG_11AC)
3424 case CHAN_BW_80MHZ:
3425 cacinfo.ch_width = CHAN_BAND_WIDTH_80;
3426 center_chan = wlan_get_center_freq_idx(priv, BAND_AAC, priv->uap_channel, CHANNEL_BW_80MHZ);
3427 cacinfo.center_freq1 = channel_to_frequency(center_chan, bandcfg->chanBand);
3428 break;
3429 #endif
3430
3431 default:
3432 break;
3433 }
3434
3435 /* STA has connected to EXT-AP on DFS channel, then uAP should support start network
3436 * on DFS channel. If DFS is offloaded to the driver, supplicant won't setup uAP until
3437 * the CAC is done by driver. When DFS master mode is not supported, driver needs to
3438 * send the EVENT_DFS_CAC_STARTED event to supplicant to set the cac_started flag, and
3439 * send EVENT_DFS_CAC_FINISHED event to supplicant to continue AP setup for DFS channel */
3440 if (wm_wifi.supp_if_callbk_fns->dfs_cac_started_callbk_fn)
3441 {
3442 wm_wifi.supp_if_callbk_fns->dfs_cac_started_callbk_fn(wm_wifi.hapd_if_priv, &cacinfo);
3443 }
3444 if (wm_wifi.supp_if_callbk_fns->dfs_cac_finished_callbk_fn)
3445 {
3446 wm_wifi.supp_if_callbk_fns->dfs_cac_finished_callbk_fn(wm_wifi.hapd_if_priv, &cacinfo);
3447 }
3448 }
3449 }
3450 }
3451 #endif
3452
wifi_nxp_beacon_config(nxp_wifi_ap_info_t * params)3453 int wifi_nxp_beacon_config(nxp_wifi_ap_info_t *params)
3454 {
3455 mlan_private *priv = (mlan_private *)mlan_adap->priv[1];
3456 mlan_private *remain_priv = NULL;
3457 // mlan_adapter *pmadapter = priv->adapter;
3458
3459 const t_u8 *ie = NULL;
3460 int ret = 0, ie_len;
3461 mlan_uap_bss_param *sys_config = NULL;
3462 // int i = 0;
3463 t_u8 rates_b[5] = {0x82, 0x84, 0x8b, 0x96, 0x00};
3464 t_u8 rates_bg[13] = {0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, 0x00};
3465 #if CONFIG_5GHz_SUPPORT
3466 t_u8 rates_a[9] = {0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0x00};
3467 #endif
3468 t_u8 supported_mcs_set[] = {0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
3470 t_u8 chan2Offset = SEC_CHAN_NONE;
3471 t_u8 enable_11n = MTRUE;
3472 t_u8 bandwidth = BANDWIDTH_40MHZ;
3473 t_u16 ht_cap = 0;
3474 #if CONFIG_11AC
3475 t_u8 enable_11ac = MFALSE;
3476 t_u8 vht20_40 = MFALSE;
3477 IEEEtypes_VHTCap_t *vhtcap_ie = NULL;
3478 IEEEtypes_VHTOprat_t *vhtopr_ie = NULL;
3479 #endif
3480 #if CONFIG_11AX
3481 IEEEtypes_HECap_t *hecap_ie = NULL;
3482 t_u8 enable_11ax = MFALSE;
3483 #endif
3484 Band_Config_t bandcfg;
3485 wifi_scan_chan_list_t scan_chan_list;
3486
3487 ENTER();
3488
3489 (void)bandwidth;
3490
3491 if (!params)
3492 {
3493 return -WM_FAIL;
3494 }
3495
3496 memset(&scan_chan_list, 0, sizeof(wifi_scan_chan_list_t));
3497
3498 ie = (const t_u8 *)params->tail_ie.ie;
3499 ie_len = params->tail_ie.ie_len;
3500 remain_priv = priv->adapter->priv[priv->adapter->remain_bss_index];
3501 if (wifi_is_remain_on_channel() && remain_priv)
3502 {
3503 wuap_d("Cancel Remain on Channel before Starting AP");
3504 wifi_remain_on_channel(false, 0, 0);
3505 }
3506
3507 if (params->beacon_set)
3508 {
3509 ret = wifi_nxp_set_mgmt_ies(priv, params->tail_ie.ie, params->tail_ie.ie_len, params->beacon_ies.ie,
3510 params->beacon_ies.ie_len, params->proberesp_ies.ie, params->proberesp_ies.ie_len,
3511 params->assocresp_ies.ie, params->assocresp_ies.ie_len);
3512 if (ret != WM_SUCCESS)
3513 {
3514 wuap_e("Set uAP mgmt ie failed");
3515 return -WM_FAIL;
3516 }
3517 }
3518 else
3519 {
3520 sys_config = OSA_MemoryAllocate(sizeof(mlan_uap_bss_param));
3521 if (!sys_config)
3522 {
3523 wuap_e("Fail to alloc memory for mlan_uap_bss_param");
3524 ret = -WM_FAIL;
3525 goto done;
3526 }
3527
3528 memset(&bandcfg, 0, sizeof(Band_Config_t));
3529
3530 if (priv->uap_max_sta)
3531 sys_config->max_sta_count = priv->uap_max_sta;
3532
3533 /* Setting the default values */
3534 sys_config->channel = params->chan.channel;
3535 priv->uap_channel = sys_config->channel;
3536 if (priv->uap_channel != 0U)
3537 {
3538 #if CONFIG_5GHz_SUPPORT
3539 if (priv->uap_channel > MAX_CHANNELS_BG)
3540 {
3541 mlan_private *priv_sta = (mlan_private *)mlan_adap->priv[0];
3542 if ((priv_sta->media_connected == MFALSE) && wlan_11h_radar_detect_required(priv, priv->uap_channel))
3543 {
3544 wuap_e("Cannot start uAP on DFS channel %d", priv->uap_channel);
3545 ret = -WM_FAIL;
3546 goto done;
3547 }
3548
3549 bandcfg.chanBand = BAND_5GHZ;
3550 }
3551 else
3552 {
3553 bandcfg.chanBand = BAND_2GHZ;
3554 }
3555 #else
3556 bandcfg.chanBand = BAND_2GHZ;
3557 #endif
3558 }
3559
3560 sys_config->preamble_type = 0;
3561 sys_config->mgmt_ie_passthru_mask = priv->mgmt_frame_passthru_mask;
3562 memcpy(sys_config->mac_addr, params->bssid, ETH_ALEN);
3563
3564 /* Set frag_threshold, rts_threshold, and retry limit */
3565 sys_config->frag_threshold = MLAN_FRAG_MAX_VALUE;
3566 sys_config->rts_threshold = MLAN_RTS_MAX_VALUE;
3567
3568 sys_config->pwe_derivation = params->sae_pwe;
3569
3570 if (params->beacon_int)
3571 sys_config->beacon_period = params->beacon_int;
3572
3573 if (params->dtim_period)
3574 sys_config->dtim_period = params->dtim_period;
3575
3576 if (sys_config->channel <= MAX_CHANNELS_BG)
3577 {
3578 if (sys_config->channel == 14)
3579 {
3580 memcpy(sys_config->rates, rates_b, sizeof(rates_b));
3581 }
3582 else
3583 {
3584 memcpy(sys_config->rates, rates_bg, sizeof(rates_bg));
3585 }
3586 }
3587 #if CONFIG_5GHz_SUPPORT
3588 else
3589 {
3590 memcpy(sys_config->rates, rates_a, sizeof(rates_a));
3591 }
3592 #endif
3593
3594 if (params->chan.ht_enabled != 1)
3595 {
3596 enable_11n = MFALSE;
3597 }
3598
3599 if (params->chan.sec_channel_offset == 1)
3600 {
3601 chan2Offset = SEC_CHAN_ABOVE;
3602 }
3603 else if (params->chan.sec_channel_offset == -1)
3604 {
3605 chan2Offset = SEC_CHAN_BELOW;
3606 }
3607
3608 if (params->chan.bandwidth == 20)
3609 {
3610 bandwidth = BANDWIDTH_20MHZ;
3611 bandcfg.chanWidth = CHAN_BW_20MHZ;
3612 }
3613 else if (params->chan.bandwidth == 40)
3614 {
3615 bandwidth = BANDWIDTH_40MHZ;
3616 bandcfg.chanWidth = CHAN_BW_40MHZ;
3617 }
3618 #if CONFIG_11AC && CONFIG_5GHz_SUPPORT
3619 else if (params->chan.bandwidth == 80)
3620 {
3621 bandwidth = BANDWIDTH_80MHZ;
3622 bandcfg.chanWidth = CHAN_BW_80MHZ;
3623 chan2Offset = wifi_get_second_channel_offset(priv, priv->uap_channel);
3624 }
3625 #endif
3626
3627 bandcfg.chan2Offset = chan2Offset;
3628 (void)memcpy((void *)&sys_config->band_cfg, (const void *)&bandcfg, sizeof(bandcfg));
3629
3630 #if CONFIG_11AC
3631 if (params->chan.vht_enabled == 1)
3632 {
3633 enable_11ac = wifi_check_11ac_capability(priv, bandcfg.chanBand);
3634 if (enable_11ac && ((bandwidth == BANDWIDTH_20MHZ) || (bandwidth == BANDWIDTH_40MHZ)))
3635 {
3636 vht20_40 = MTRUE;
3637 }
3638 }
3639 #endif
3640 #if CONFIG_11AX
3641 if (params->chan.he_enabled == 1)
3642 {
3643 enable_11ax = wifi_check_11ax_capability(priv, bandcfg.chanBand);
3644 }
3645 #endif
3646
3647 /* Disable GreenField by default */
3648 sys_config->ht_cap_info = 0x10c;
3649 if (enable_11n)
3650 sys_config->ht_cap_info |= 0x20;
3651 if (chan2Offset)
3652 {
3653 sys_config->ht_cap_info |= 0x1042;
3654 sys_config->ampdu_param = 3;
3655 }
3656
3657 if (enable_11n)
3658 {
3659 ht_cap = wifi_get_htcap_info(ie, ie_len);
3660 if (ht_cap)
3661 {
3662 if (bandcfg.chanBand == BAND_2GHZ)
3663 sys_config->ht_cap_info = (ht_cap & 0x13ff) | 0x0c;
3664 else
3665 sys_config->ht_cap_info = (ht_cap & 0x13ff) | 0x0c;
3666 }
3667 wifi_d(
3668 "11n=%d, ht_cap=0x%x, channel=%d, bandcfg:chanBand=0x%x chanWidth=0x%x chan2Offset=0x%x "
3669 "scanMode=0x%x\n",
3670 enable_11n, sys_config->ht_cap_info, priv->uap_channel, bandcfg.chanBand, bandcfg.chanWidth,
3671 bandcfg.chan2Offset, bandcfg.scanMode);
3672
3673 ret = wifi_uap_set_httxcfg_int(ht_cap);
3674 if (ret != WM_SUCCESS)
3675 {
3676 wuap_e("Cannot set uAP HT TX Cfg:%x", sys_config->ht_cap_info);
3677 ret = -WM_FAIL;
3678 goto done;
3679 }
3680
3681 sys_config->ampdu_param = 3;
3682
3683 /* Set MCS32 with 40MHz support */
3684 if ((bandcfg.chanWidth == CHAN_BW_40MHZ) || (bandcfg.chanWidth == CHAN_BW_80MHZ))
3685 SETHT_MCS32(supported_mcs_set);
3686
3687 (void)memcpy((void *)sys_config->supported_mcs_set, (const void *)supported_mcs_set,
3688 sizeof(sys_config->supported_mcs_set));
3689 }
3690
3691 if (!params->ssid.ssid_len)
3692 {
3693 ret = -WM_FAIL;
3694 goto done;
3695 }
3696 memcpy(sys_config->ssid.ssid, params->ssid.ssid, MIN(MLAN_MAX_SSID_LENGTH, params->ssid.ssid_len));
3697 sys_config->ssid.ssid_len = MIN(MLAN_MAX_SSID_LENGTH, params->ssid.ssid_len);
3698 /**
3699 * hidden_ssid=0: broadcast SSID in beacons.
3700 * hidden_ssid=1: send empty SSID (length=0) in beacon.
3701 * hidden_ssid=2: clear SSID (ACSII 0), but keep the original length
3702 */
3703 if (!params->hide_ssid)
3704 sys_config->bcast_ssid_ctl = 1;
3705 else if (params->hide_ssid == 1)
3706 sys_config->bcast_ssid_ctl = 0;
3707 else if (params->hide_ssid == 2)
3708 sys_config->bcast_ssid_ctl = 2;
3709
3710 sys_config->auth_mode = MLAN_AUTH_MODE_OPEN;
3711
3712 sys_config->protocol = PROTOCOL_NO_SECURITY;
3713 if ((params->wpa_version & WIFI_NXP_WPA_VERSION_1) && (params->wpa_version & WIFI_NXP_WPA_VERSION_2))
3714 sys_config->protocol = PROTOCOL_WPA | PROTOCOL_WPA2;
3715 else if (params->wpa_version & WIFI_NXP_WPA_VERSION_2)
3716 sys_config->protocol = PROTOCOL_WPA2;
3717 else if (params->wpa_version & WIFI_NXP_WPA_VERSION_1)
3718 sys_config->protocol = PROTOCOL_WPA;
3719
3720 if (params->key_mgmt_suites || (params->privacy && params->wpa_version))
3721 wifi_find_wpa_ies(ie, ie_len, sys_config);
3722
3723 /*find and set wmm ie*/
3724 wifi_set_wmm_ies(priv, ie, ie_len, sys_config);
3725
3726 #if CONFIG_11AC
3727 if (enable_11ac && enable_11n)
3728 {
3729 vhtcap_ie = wifi_get_vhtcap_info(ie, ie_len);
3730 vhtopr_ie = wifi_get_vht_oprat_ie(ie, ie_len);
3731 // Enable VHT80
3732 if (vhtopr_ie && vhtopr_ie->chan_width)
3733 vht20_40 = 0;
3734 wifi_uap_set_11ac_status2(priv, MLAN_ACT_ENABLE, vht20_40, vhtcap_ie);
3735 }
3736 else
3737 {
3738 wifi_uap_set_11ac_status2(priv, MLAN_ACT_DISABLE, vht20_40, NULL);
3739 }
3740 #endif
3741 #if CONFIG_11AX
3742 if (enable_11ax && enable_11n)
3743 {
3744 hecap_ie = (IEEEtypes_HECap_t *)wifi_parse_ext_ie_tlv(ie, ie_len, HE_CAPABILITY);
3745 wifi_uap_set_11ax_status2(priv, MLAN_ACT_ENABLE, bandcfg.chanBand, hecap_ie, bandwidth);
3746 }
3747 else
3748 wifi_uap_set_11ax_status2(priv, MLAN_ACT_DISABLE, bandcfg.chanBand, NULL, bandwidth);
3749 #endif
3750
3751 if (params->ap_max_inactivity)
3752 {
3753 sys_config->sta_ageout_timer = params->ap_max_inactivity * 10;
3754 sys_config->ps_sta_ageout_timer = params->ap_max_inactivity * 10;
3755 }
3756 PRINTM(MIOCTL, "inactivity_timeout=%d\n", params->ap_max_inactivity);
3757 PRINTM(MIOCTL, "sta_ageout_timer=%d ps_sta_ageout_timer=%d\n", sys_config->sta_ageout_timer,
3758 sys_config->ps_sta_ageout_timer);
3759
3760 if (MLAN_STATUS_SUCCESS != wifi_set_get_sys_config(priv, MLAN_ACT_SET, sys_config))
3761 {
3762 wuap_e("Set uAP sys config failed");
3763 ret = -WM_FAIL;
3764 goto done;
3765 }
3766
3767 ret = wifi_nxp_set_mgmt_ies(priv, params->tail_ie.ie, params->tail_ie.ie_len, params->beacon_ies.ie,
3768 params->beacon_ies.ie_len, params->proberesp_ies.ie, params->proberesp_ies.ie_len,
3769 params->assocresp_ies.ie, params->assocresp_ies.ie_len);
3770 if (ret != WM_SUCCESS)
3771 {
3772 wuap_e("Set uAP mgmt ie failed");
3773 ret = -WM_FAIL;
3774 goto done;
3775 }
3776
3777 if (wm_wifi.enable_11d_support && wm_wifi.uap_support_11d_apis)
3778 {
3779 wuap_d("Downloading domain params");
3780 wm_wifi.uap_support_11d_apis->wifi_uap_downld_domain_params_p(BAND_B);
3781 #if CONFIG_5GHz_SUPPORT
3782 wm_wifi.uap_support_11d_apis->wifi_uap_downld_domain_params_p(BAND_A);
3783 #endif
3784 }
3785
3786 #if CONFIG_5GHz_SUPPORT
3787 wifi_set_uap_dfs_cac(priv, &bandcfg, enable_11n);
3788 #endif
3789 priv->uap_host_based = MTRUE;
3790
3791 if (!params->beacon_set)
3792 {
3793 wuap_d("Starting BSS");
3794 /* Start BSS */
3795 if (MLAN_STATUS_SUCCESS != wifi_uap_prepare_and_send_cmd(priv, HOST_CMD_APCMD_BSS_START,
3796 HostCmd_ACT_GEN_SET, 0, NULL, NULL,
3797 MLAN_BSS_TYPE_UAP, NULL))
3798 {
3799 wuap_e("Start BSS failed");
3800 priv->uap_host_based = MFALSE;
3801 ret = -WM_FAIL;
3802 goto done;
3803 }
3804 wuap_d("wlan: AP started");
3805
3806 (void)wifi_set_rx_mgmt_indication(MLAN_BSS_TYPE_UAP, WIFI_MGMT_AUTH | MGMT_MASK_ASSOC_REQ |
3807 MGMT_MASK_REASSOC_REQ | WIFI_MGMT_DEAUTH |
3808 WIFI_MGMT_ACTION | WIFI_MGMT_DIASSOC);
3809 }
3810
3811 done:
3812 if (sys_config != NULL)
3813 {
3814 OSA_MemoryFree(sys_config);
3815 }
3816 }
3817
3818 LEAVE();
3819 return ret;
3820 }
3821
wifi_get_default_ht_capab()3822 t_u16 wifi_get_default_ht_capab()
3823 {
3824 t_u16 ht_capab;
3825 t_u8 mcs_set[16];
3826 t_u8 a_mpdu_params;
3827
3828 wifi_setup_ht_cap(&ht_capab, &mcs_set[0], &a_mpdu_params, 0);
3829
3830 return ht_capab;
3831 }
3832
3833 #if CONFIG_11AC
wifi_get_default_vht_capab()3834 t_u32 wifi_get_default_vht_capab()
3835 {
3836 t_u32 vht_capab;
3837 t_u8 vht_mcs_set[8];
3838
3839 wifi_setup_vht_cap(&vht_capab, &vht_mcs_set[0], 0);
3840
3841 return vht_capab;
3842 }
3843 #endif
3844
3845 /**
3846 * @brief Set/Get sta information parameters
3847 *
3848 * @param priv A pointer to moal_private structure
3849 * @param action MLAN_ACT_SET or MLAN_ACT_GET
3850 * @param wait_option Wait option
3851 * @param sys_cfg A pointer to mlan_uap_bss_param structure
3852 *
3853 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3854 */
wifi_uap_sta_info(mlan_private * priv,t_u16 action,mlan_ds_sta_info * sta_info)3855 static mlan_status wifi_uap_sta_info(mlan_private *priv, t_u16 action, mlan_ds_sta_info *sta_info)
3856 {
3857 int ret;
3858 mlan_ds_bss bss;
3859 mlan_ioctl_req ioctl_buf;
3860
3861 ENTER();
3862
3863 (void)memset(&bss, 0x00, sizeof(mlan_ds_bss));
3864
3865 bss.sub_command = MLAN_OID_UAP_ADD_STATION;
3866
3867 // if (action == HostCmd_ACT_ADD_STA)
3868 memcpy((void *)&bss.param.sta_info, (const void *)sta_info, sizeof(mlan_ds_sta_info) + (size_t)sta_info->tlv_len);
3869
3870 (void)memset(&ioctl_buf, 0x00, sizeof(mlan_ioctl_req));
3871
3872 ioctl_buf.req_id = (t_u32)MLAN_IOCTL_BSS;
3873 /** Pointer to buffer */
3874 ioctl_buf.pbuf = (t_u8 *)&bss;
3875
3876 ret = wifi_uap_prepare_and_send_cmd(priv, HostCmd_CMD_ADD_NEW_STATION, action, 0, &ioctl_buf, NULL,
3877 MLAN_BSS_TYPE_UAP, NULL);
3878 if (ret != WM_SUCCESS)
3879 {
3880 return MLAN_STATUS_FAILURE;
3881 }
3882
3883 return MLAN_STATUS_SUCCESS;
3884 }
3885
3886 /**
3887 * @brief uap remove sta
3888 *
3889 * @param priv A pointer to moal_private structure
3890 * @param addr A pointer to mac address
3891 *
3892 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3893 */
wifi_uap_sta_remove(mlan_private * priv,const uint8_t * addr)3894 static mlan_status wifi_uap_sta_remove(mlan_private *priv, const uint8_t *addr)
3895 {
3896 int ret;
3897 mlan_deauth_param data_buf;
3898
3899 ENTER();
3900
3901 (void)memset(&data_buf, 0x00, sizeof(data_buf));
3902
3903 memcpy((void *)data_buf.mac_addr, (const void *)addr, sizeof(data_buf.mac_addr));
3904 data_buf.reason_code = WLAN_REASON_UNSPECIFIED;
3905
3906 ret = wifi_uap_prepare_and_send_cmd(priv, HOST_CMD_APCMD_STA_DEAUTH, 0, 0, NULL, &data_buf,
3907 MLAN_BSS_TYPE_UAP, NULL);
3908 if (ret != WM_SUCCESS)
3909 {
3910 return MLAN_STATUS_FAILURE;
3911 }
3912
3913 return MLAN_STATUS_SUCCESS;
3914 }
3915
wifi_nxp_sta_add(nxp_wifi_sta_info_t * params)3916 int wifi_nxp_sta_add(nxp_wifi_sta_info_t *params)
3917 {
3918 mlan_private *priv = (mlan_private *)mlan_adap->priv[1];
3919 int ret = 0;
3920 mlan_ds_sta_info *sta_info = NULL;
3921 t_u8 *pos;
3922 t_u8 qosinfo;
3923 MrvlIEtypes_Data_t *tlv;
3924 t_u32 req_len = 0;
3925 #if CONFIG_11AX
3926 MrvlExtIEtypes_Data_t *ext_tlv;
3927 #endif
3928
3929 ENTER();
3930
3931 if (!params)
3932 {
3933 ret = -WM_FAIL;
3934 goto done;
3935 }
3936
3937 req_len = sizeof(mlan_ds_sta_info);
3938 if (params->ext_capab_len)
3939 req_len += sizeof(MrvlIEtypesHeader_t) + params->ext_capab_len;
3940 if (params->supp_rates_len)
3941 req_len += sizeof(MrvlIEtypesHeader_t) + params->supp_rates_len;
3942 if (params->qosinfo)
3943 req_len += sizeof(MrvlIEtypesHeader_t) + sizeof(qosinfo);
3944 if (params->ht_capab_len)
3945 req_len += sizeof(MrvlIEtypesHeader_t) + sizeof(ieee80211_ht_capab_t);
3946 #if CONFIG_11AC
3947 if (params->vht_capab_len)
3948 req_len += sizeof(MrvlIEtypesHeader_t) + sizeof(ieee80211_vht_capab_t);
3949 #endif
3950
3951 #if CONFIG_11AX
3952 if (params->he_capab_len)
3953 req_len += sizeof(MrvlExtIEtypesHeader_t) + params->he_capab_len;
3954 #endif
3955
3956 sta_info = OSA_MemoryAllocate(req_len);
3957 if (!sta_info)
3958 {
3959 wuap_e("Fail to alloc memory for mlan_ds_sta_info");
3960 ret = -WM_FAIL;
3961 goto done;
3962 }
3963
3964 memset(sta_info, 0x00, req_len);
3965
3966 sta_info->listen_interval = params->listen_interval;
3967 sta_info->aid = params->aid;
3968 sta_info->cap_info = params->capability;
3969 sta_info->tlv_len = 0;
3970 sta_info->sta_flags = params->flags;
3971
3972 memcpy(sta_info->peer_mac, params->addr, MLAN_MAC_ADDR_LENGTH);
3973
3974 wuap_d("wlan: UAP/GO add peer station, address =" MACSTR "", MAC2STR(params->addr));
3975
3976 wuap_d("sta_flags=0x%x listen_interval=%d aid=%d cap_info=0x%x", params->flags, params->listen_interval,
3977 params->aid, params->capability);
3978
3979 pos = &sta_info->tlv[0];
3980 if (params->ext_capab_len)
3981 {
3982 tlv = (MrvlIEtypes_Data_t *)pos;
3983 tlv->header.type = EXT_CAPABILITY;
3984 tlv->header.len = params->ext_capab_len;
3985 memcpy(tlv->data, params->ext_capab, tlv->header.len);
3986 pos += sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
3987 sta_info->tlv_len += sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
3988 tlv = (MrvlIEtypes_Data_t *)pos;
3989 }
3990 if (params->supp_rates_len)
3991 {
3992 tlv = (MrvlIEtypes_Data_t *)pos;
3993 tlv->header.type = SUPPORTED_RATES;
3994 tlv->header.len = params->supp_rates_len;
3995 memcpy(tlv->data, params->supp_rates, tlv->header.len);
3996 pos += sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
3997 sta_info->tlv_len += sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
3998 tlv = (MrvlIEtypes_Data_t *)pos;
3999 }
4000 if (params->qosinfo)
4001 {
4002 tlv = (MrvlIEtypes_Data_t *)pos;
4003 tlv->header.type = QOS_INFO;
4004 tlv->header.len = sizeof(qosinfo);
4005 qosinfo = params->qosinfo;
4006 memcpy(tlv->data, &qosinfo, tlv->header.len);
4007 pos += sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
4008 sta_info->tlv_len += sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
4009 tlv = (MrvlIEtypes_Data_t *)pos;
4010 }
4011 if (params->ht_capab_len)
4012 {
4013 tlv = (MrvlIEtypes_Data_t *)pos;
4014 tlv->header.type = HT_CAPABILITY;
4015 tlv->header.len = sizeof(ieee80211_ht_capab_t);
4016 memcpy(tlv->data, ¶ms->ht_capab, tlv->header.len);
4017 pos += sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
4018 sta_info->tlv_len += sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
4019 tlv = (MrvlIEtypes_Data_t *)pos;
4020 }
4021 #if CONFIG_11AC
4022 if (params->vht_capab_len)
4023 {
4024 tlv = (MrvlIEtypes_Data_t *)pos;
4025 tlv->header.type = VHT_CAPABILITY;
4026 tlv->header.len = sizeof(ieee80211_vht_capab_t);
4027 memcpy(tlv->data, ¶ms->vht_capab, tlv->header.len);
4028 pos += sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
4029 sta_info->tlv_len += sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
4030 tlv = (MrvlIEtypes_Data_t *)pos;
4031 }
4032 #endif
4033 #if CONFIG_11AX
4034 if (params->he_capab_len)
4035 {
4036 ext_tlv = (MrvlExtIEtypes_Data_t *)pos;
4037 ext_tlv->header.type = EXTENSION;
4038 ext_tlv->header.len = params->he_capab_len + sizeof(u8);
4039 ext_tlv->header.ext_id = HE_CAPABILITY;
4040 memcpy(ext_tlv->data, (u8 *)¶ms->he_capab, params->he_capab_len);
4041 pos += sizeof(MrvlExtIEtypesHeader_t) + params->he_capab_len;
4042 sta_info->tlv_len += sizeof(MrvlExtIEtypesHeader_t) + params->he_capab_len;
4043 tlv = (MrvlIEtypes_Data_t *)pos;
4044 }
4045 #endif
4046
4047 if (MLAN_STATUS_SUCCESS != wifi_uap_sta_info(priv, HostCmd_ACT_ADD_STA, sta_info))
4048 {
4049 wuap_e("uAP add station failed");
4050 ret = -WM_FAIL;
4051 goto done;
4052 }
4053
4054 done:
4055 if (sta_info)
4056 OSA_MemoryFree(sta_info);
4057
4058 LEAVE();
4059 return ret;
4060 }
4061
wifi_nxp_sta_remove(const uint8_t * addr)4062 int wifi_nxp_sta_remove(const uint8_t *addr)
4063 {
4064 mlan_private *priv = (mlan_private *)mlan_adap->priv[1];
4065 int ret = 0;
4066 #if 0
4067 mlan_ds_sta_info *sta_info = NULL;
4068 #endif
4069 ENTER();
4070
4071 if (!addr)
4072 {
4073 ret = -WM_FAIL;
4074 goto done;
4075 }
4076
4077 if (MLAN_STATUS_SUCCESS != wifi_uap_sta_remove(priv, addr))
4078 {
4079 wuap_e("uAP remove station failed");
4080 ret = -WM_FAIL;
4081 goto done;
4082 }
4083
4084 #if 0
4085 sta_info = OSA_MemoryAllocate(sizeof(mlan_ds_sta_info));
4086 if (!sta_info)
4087 {
4088 wuap_e("Fail to alloc memory for mlan_ds_sta_info");
4089 ret = -WM_FAIL;
4090 goto done;
4091 }
4092
4093 memset(sta_info, 0x00, sizeof(mlan_ds_sta_info));
4094
4095 memcpy(sta_info->peer_mac, addr, MLAN_MAC_ADDR_LENGTH);
4096
4097 wuap_d("wlan: UAP/GO remove peer station, address =" MACSTR "", MAC2STR(addr));
4098
4099 if (MLAN_STATUS_SUCCESS != wifi_uap_sta_info(priv, HostCmd_ACT_REMOVE_STA, sta_info))
4100 {
4101 wuap_e("uAP remove station failed");
4102 ret = -WM_FAIL;
4103 goto done;
4104 }
4105 #endif
4106
4107 done:
4108 #if 0
4109 if (sta_info)
4110 OSA_MemoryFree(sta_info);
4111 #endif
4112
4113 LEAVE();
4114 return ret;
4115 }
4116
wifi_set_uap_rts(int rts_threshold)4117 int wifi_set_uap_rts(int rts_threshold)
4118 {
4119 mlan_private *pmpriv = (mlan_private *)mlan_adap->priv[1];
4120 MrvlIEtypes_rts_threshold_t rts_threshold_tlv;
4121
4122 (void)memset(&rts_threshold_tlv, 0, sizeof(MrvlIEtypes_rts_threshold_t));
4123 rts_threshold_tlv.header.type = TLV_TYPE_UAP_RTS_THRESHOLD;
4124 rts_threshold_tlv.header.len = (t_u16)sizeof(MrvlIEtypes_rts_threshold_t);
4125 rts_threshold_tlv.rts_threshold = (t_u16)rts_threshold;
4126
4127 int rv = wifi_uap_prepare_and_send_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, HostCmd_ACT_GEN_SET, 0, MNULL,
4128 &rts_threshold_tlv, MLAN_BSS_TYPE_UAP, NULL);
4129 if (rv != WM_SUCCESS)
4130 {
4131 return rv;
4132 }
4133
4134 if (wm_wifi.cmd_resp_status != 0)
4135 {
4136 wifi_w("Unable to set rts threshold");
4137 return wm_wifi.cmd_resp_status;
4138 }
4139
4140 return rv;
4141 }
4142
wifi_set_uap_frag(int frag_threshold)4143 int wifi_set_uap_frag(int frag_threshold)
4144 {
4145 mlan_private *pmpriv = (mlan_private *)mlan_adap->priv[1];
4146 MrvlIEtypes_frag_threshold_t frag_threshold_tlv;
4147
4148 (void)memset(&frag_threshold_tlv, 0, sizeof(MrvlIEtypes_frag_threshold_t));
4149 frag_threshold_tlv.header.type = TLV_TYPE_UAP_RTS_THRESHOLD;
4150 frag_threshold_tlv.header.len = (t_u16)sizeof(MrvlIEtypes_frag_threshold_t);
4151 frag_threshold_tlv.frag_threshold = (t_u16)frag_threshold;
4152
4153 int rv = wifi_uap_prepare_and_send_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, HostCmd_ACT_GEN_SET, 0, MNULL,
4154 &frag_threshold_tlv, MLAN_BSS_TYPE_UAP, NULL);
4155 if (rv != WM_SUCCESS)
4156 {
4157 return rv;
4158 }
4159
4160 if (wm_wifi.cmd_resp_status != 0)
4161 {
4162 wifi_w("Unable to set frag threshold");
4163 return wm_wifi.cmd_resp_status;
4164 }
4165
4166 return rv;
4167 }
4168
wifi_nxp_uap_disconnect(mlan_private * priv,t_u16 reason_code,t_u8 * mac)4169 void wifi_nxp_uap_disconnect(mlan_private *priv, t_u16 reason_code, t_u8 *mac)
4170 {
4171 wlan_mgmt_pkt *pmgmt_pkt_hdr = MNULL;
4172 nxp_wifi_event_mlme_t *mgmt_rx = &wm_wifi.mgmt_rx;
4173 t_u8 *pos = MNULL;
4174 t_u16 reason;
4175 t_u32 payload_len;
4176
4177 pmgmt_pkt_hdr = wifi_PrepDefaultMgtMsg(SUBTYPE_DEAUTH, (mlan_802_11_mac_addr *)(void *)priv->curr_addr,
4178 (mlan_802_11_mac_addr *)(void *)mac, (mlan_802_11_mac_addr *)(void *)priv->curr_addr, 100);
4179 if (pmgmt_pkt_hdr == MNULL)
4180 {
4181 wifi_e("No memory available for deauth");
4182 return;
4183 }
4184
4185 pos = (t_u8 *)pmgmt_pkt_hdr + sizeof(wlan_mgmt_pkt);
4186 reason = wlan_cpu_to_le16(reason_code);
4187 (void)memcpy(pos, &reason, sizeof(reason));
4188 payload_len = sizeof(reason) + sizeof(pmgmt_pkt_hdr->wlan_header);
4189
4190 if (payload_len <= (int)sizeof(mgmt_rx->frame.frame))
4191 {
4192 memset(mgmt_rx, 0, sizeof(nxp_wifi_event_mlme_t));
4193 mgmt_rx->frame.frame_len = payload_len;
4194 (void)memcpy((void *)mgmt_rx->frame.frame, (const void *)(&pmgmt_pkt_hdr->wlan_header), mgmt_rx->frame.frame_len);
4195 if (wm_wifi.supp_if_callbk_fns->mgmt_rx_callbk_fn)
4196 {
4197 wm_wifi.supp_if_callbk_fns->mgmt_rx_callbk_fn(wm_wifi.hapd_if_priv,
4198 mgmt_rx, mgmt_rx->frame.frame_len, -30);
4199 }
4200 }
4201 else
4202 {
4203 wifi_e("Insufficient frame buffer");
4204 }
4205
4206 #if !CONFIG_MEM_POOLS
4207 OSA_MemoryFree(pmgmt_pkt_hdr);
4208 #else
4209 OSA_MemoryPoolFree(buf_1536_MemoryPool, pmgmt_pkt_hdr);
4210 #endif
4211 }
4212
wifi_nxp_stop_ap()4213 int wifi_nxp_stop_ap()
4214 {
4215 mlan_private *priv = (mlan_private *)mlan_adap->priv[1];
4216 int ret = WM_SUCCESS;
4217
4218 if ((mlan_adap->in_reset == MTRUE) && (priv->media_connected == MFALSE))
4219 {
4220 return ret;
4221 }
4222
4223 (void)wifi_set_rx_mgmt_indication(MLAN_BSS_TYPE_UAP, 0);
4224
4225 if (priv->beacon_vendor_index != -1)
4226 {
4227 ret = wifi_clear_mgmt_ie2(MLAN_BSS_TYPE_UAP, priv->beacon_vendor_index);
4228 if (ret != WM_SUCCESS)
4229 {
4230 wuap_e("Clear uAP vendor IE failed");
4231 return -WM_FAIL;
4232 }
4233 priv->beacon_vendor_index = -1;
4234 }
4235
4236 ret = wifi_nxp_set_mgmt_ies(priv, NULL, 0, NULL, 0, NULL, 0, NULL, 0);
4237 if (ret != WM_SUCCESS)
4238 {
4239 wuap_e("Set uAP mgmt ie failed");
4240 ret = -WM_FAIL;
4241 goto done;
4242 }
4243
4244 wuap_d("Stopping BSS"); /* Stop BSS */
4245 if (MLAN_STATUS_SUCCESS != wifi_uap_prepare_and_send_cmd(priv, HOST_CMD_APCMD_BSS_STOP, HostCmd_ACT_GEN_SET, 0,
4246 NULL, NULL, MLAN_BSS_TYPE_UAP, NULL))
4247 {
4248 wuap_e("Stop BSS failed");
4249 return -WM_FAIL;
4250 }
4251 wifi_uap_clear_domain_info();
4252 priv->uap_host_based = MFALSE;
4253
4254 wuap_d("wlan: AP stopped");
4255
4256 done:
4257 LEAVE();
4258 return ret;
4259 }
4260
wifi_nxp_init_ap(nxp_wifi_ap_info_t * params)4261 int wifi_nxp_init_ap(nxp_wifi_ap_info_t *params)
4262 {
4263 int ret = 0;
4264 /* to do */
4265 return ret;
4266 }
4267
wifi_nxp_set_acl(nxp_wifi_acl_info_t * params)4268 int wifi_nxp_set_acl(nxp_wifi_acl_info_t *params)
4269 {
4270 mlan_private *priv = (mlan_private *)mlan_adap->priv[1];
4271 int ret = -WM_FAIL;
4272 mlan_uap_bss_param *sys_config = NULL;
4273 bool bss_started = MFALSE;
4274
4275 if (!params)
4276 {
4277 goto done;
4278 }
4279
4280 sys_config = OSA_MemoryAllocate(sizeof(mlan_uap_bss_param));
4281
4282 if (!sys_config)
4283 {
4284 wuap_e("Fail to alloc memory for mlan_uap_bss_param");
4285 goto done;
4286 }
4287
4288 memset(sys_config, 0x00, sizeof(mlan_uap_bss_param));
4289
4290 if (params->num_mac_acl <= MAX_MAC_FILTER_NUM)
4291 sys_config->filter.mac_count = params->num_mac_acl;
4292 else
4293 sys_config->filter.mac_count = MAX_MAC_FILTER_NUM;
4294
4295 if (params->acl_policy == 1U)
4296 sys_config->filter.filter_mode = MAC_FILTER_MODE_ALLOW_MAC;
4297 else if (params->acl_policy == 0U)
4298 sys_config->filter.filter_mode = MAC_FILTER_MODE_BLOCK_MAC;
4299 memcpy(sys_config->filter.mac_list, params->mac_acl, sys_config->filter.mac_count * sizeof(mlan_802_11_mac_addr));
4300
4301 if (priv->uap_host_based == MTRUE)
4302 {
4303 bss_started = MTRUE;
4304
4305 if (MLAN_STATUS_SUCCESS != wifi_uap_prepare_and_send_cmd(priv, HOST_CMD_APCMD_BSS_STOP, HostCmd_ACT_GEN_SET, 0,
4306 NULL, NULL, MLAN_BSS_TYPE_UAP, NULL))
4307 {
4308 wuap_e("Stop BSS failed");
4309 }
4310 }
4311
4312 if (MLAN_STATUS_SUCCESS == wifi_set_get_sys_config(priv, MLAN_ACT_SET, sys_config))
4313 {
4314 ret = WM_SUCCESS;
4315 }
4316
4317 if (bss_started)
4318 {
4319 if (MLAN_STATUS_SUCCESS != wifi_uap_prepare_and_send_cmd(priv, HOST_CMD_APCMD_BSS_START, HostCmd_ACT_GEN_SET, 0,
4320 NULL, NULL, MLAN_BSS_TYPE_UAP, NULL))
4321 {
4322 wuap_e("Start BSS failed");
4323 }
4324 }
4325
4326 done:
4327 if (sys_config)
4328 OSA_MemoryFree(sys_config);
4329
4330 LEAVE();
4331 return ret;
4332 }
4333
4334 #endif /* CONFIG_WPA_SUPP_AP */
4335