1 /** @file mlan_sta_ioctl.c
2 *
3 * @brief This file provides functions for station ioctl
4 *
5 * Copyright 2008-2024 NXP
6 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 */
10
11 /******************************************************
12 Change log:
13 10/21/2008: initial version
14 ******************************************************/
15
16 #include <mlan_api.h>
17
18 /* Additional WMSDK header files */
19 #include <wmerrno.h>
20 #include <osa.h>
21
22 /* Always keep this include at the end of all include files */
23 #include <mlan_remap_mem_operations.h>
24 /********************************************************
25 Local Variables
26 ********************************************************/
27
28 /********************************************************
29 Global Variables
30 ********************************************************/
31
32 /********************************************************
33 Local Functions
34 ********************************************************/
35
36 mlan_status wlan_misc_ioctl_region(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req);
37 t_u8 wlan_get_random_charactor(pmlan_adapter pmadapter);
38
39 #if (CONFIG_WIFI_RTS_THRESHOLD) || (CONFIG_WIFI_FRAG_THRESHOLD)
40 /**
41 * @brief Set/Get SNMP MIB handler
42 *
43 * @param pmadapter A pointer to mlan_adapter structure
44 * @param pioctl_req A pointer to ioctl request buffer
45 *
46 * @return MLAN_STATUS_PENDING --success, otherwise fail
47 */
wlan_snmp_mib_ioctl(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)48 static mlan_status wlan_snmp_mib_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
49 {
50 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
51 mlan_status ret = MLAN_STATUS_SUCCESS;
52 t_u16 cmd_action = 0;
53 t_u16 cmd_oid = 0;
54 mlan_ds_snmp_mib *mib = MNULL;
55 t_u32 value = 0;
56
57 ENTER();
58
59 if (pioctl_req->buf_len < sizeof(mlan_ds_snmp_mib))
60 {
61 PRINTM(MWARN, "MLAN IOCTL information buffer length is too short.\n");
62 pioctl_req->data_read_written = 0;
63 pioctl_req->buf_len_needed = sizeof(mlan_ds_snmp_mib);
64 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
65 ret = MLAN_STATUS_RESOURCE;
66 goto exit;
67 }
68
69 mib = (mlan_ds_snmp_mib *)pioctl_req->pbuf;
70 if (pioctl_req->action == MLAN_ACT_SET)
71 cmd_action = HostCmd_ACT_GEN_SET;
72 else
73 cmd_action = HostCmd_ACT_GEN_GET;
74
75 switch (mib->sub_command)
76 {
77 case MLAN_OID_SNMP_MIB_RTS_THRESHOLD:
78 value = mib->param.rts_threshold;
79 cmd_oid = RtsThresh_i;
80 break;
81 case MLAN_OID_SNMP_MIB_FRAG_THRESHOLD:
82 value = mib->param.frag_threshold;
83 cmd_oid = FragThresh_i;
84 break;
85 case MLAN_OID_SNMP_MIB_RETRY_COUNT:
86 value = mib->param.retry_count;
87 cmd_oid = ShortRetryLim_i;
88 break;
89 case MLAN_OID_SNMP_MIB_DTIM_PERIOD:
90 value = mib->param.dtim_period;
91 cmd_oid = DtimPeriod_i;
92 break;
93 }
94
95 /* Send request to firmware */
96 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB, cmd_action, cmd_oid, (t_void *)pioctl_req, &value);
97
98 if (ret == MLAN_STATUS_SUCCESS)
99 ret = MLAN_STATUS_PENDING;
100
101 exit:
102 LEAVE();
103 return ret;
104 }
105 #endif
106
107 /**
108 * @brief Set/Get Infra/Ad-hoc band configuration
109 *
110 * @param pmadapter A pointer to mlan_adapter structure
111 * @param pioctl_req A pointer to ioctl request buffer
112 *
113 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
114 */
wlan_radio_ioctl_band_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)115 static mlan_status wlan_radio_ioctl_band_cfg(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
116 {
117 t_u8 i = 0;
118 t_u16 global_band = 0;
119 t_u16 infra_band = 0;
120 mlan_ds_radio_cfg *radio_cfg = MNULL;
121 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
122
123 ENTER();
124
125 radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
126 if (pioctl_req->action == MLAN_ACT_SET)
127 {
128 infra_band = radio_cfg->param.band_cfg.config_bands;
129
130 /* SET Infra band */
131 if ((infra_band | pmadapter->fw_bands) & ~pmadapter->fw_bands)
132 {
133 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
134 LEAVE();
135 return MLAN_STATUS_FAILURE;
136 }
137
138 for (i = 0; i < pmadapter->priv_num; i++)
139 {
140 if (pmadapter->priv[i] && pmadapter->priv[i] != pmpriv &&
141 GET_BSS_ROLE(pmadapter->priv[i]) == MLAN_BSS_ROLE_STA)
142 global_band |= pmadapter->priv[i]->config_bands;
143 }
144 global_band |= infra_band;
145
146 if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code, global_band))
147 {
148 pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
149 LEAVE();
150 return MLAN_STATUS_FAILURE;
151 }
152
153 if (wlan_11d_set_universaltable(pmpriv, global_band))
154 {
155 pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
156 LEAVE();
157 return MLAN_STATUS_FAILURE;
158 }
159 pmpriv->config_bands = infra_band;
160 pmadapter->config_bands = global_band;
161 }
162 else
163 {
164 /* Infra Bands */
165 radio_cfg->param.band_cfg.config_bands = pmpriv->config_bands;
166 /* Adhoc Band */
167 radio_cfg->param.band_cfg.adhoc_start_band = pmadapter->adhoc_start_band;
168 /* Adhoc Channel */
169 radio_cfg->param.band_cfg.adhoc_channel = pmpriv->adhoc_channel;
170 /* FW support Bands */
171 radio_cfg->param.band_cfg.fw_bands = pmadapter->fw_bands;
172 PRINTM(MINFO, "Global config band = %d\n", pmadapter->config_bands);
173 /* adhoc channel bandwidth */
174 radio_cfg->param.band_cfg.sec_chan_offset = pmadapter->chan_bandwidth;
175 }
176
177 LEAVE();
178 return MLAN_STATUS_SUCCESS;
179 }
180
181 /**
182 * @brief Radio command handler
183 *
184 * @param pmadapter A pointer to mlan_adapter structure
185 * @param pioctl_req A pointer to ioctl request buffer
186 *
187 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
188 */
wlan_radio_ioctl(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)189 static mlan_status wlan_radio_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
190 {
191 mlan_status status = MLAN_STATUS_SUCCESS;
192 mlan_ds_radio_cfg *radio_cfg = MNULL;
193
194 ENTER();
195
196 if (pioctl_req->buf_len < sizeof(mlan_ds_radio_cfg))
197 {
198 PRINTM(MWARN, "MLAN IOCTL information buffer length is too short.\n");
199 pioctl_req->data_read_written = 0;
200 pioctl_req->buf_len_needed = sizeof(mlan_ds_radio_cfg);
201 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
202 LEAVE();
203 return MLAN_STATUS_RESOURCE;
204 }
205 radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
206 switch (radio_cfg->sub_command)
207 {
208 case MLAN_OID_BAND_CFG:
209 status = wlan_radio_ioctl_band_cfg(pmadapter, pioctl_req);
210 break;
211 default:
212 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
213 status = MLAN_STATUS_FAILURE;
214 break;
215 }
216
217 LEAVE();
218 return status;
219 }
220
221 /**
222 * @brief Start BSS
223 *
224 * @param pmadapter A pointer to mlan_adapter structure
225 * @param pioctl_req A pointer to ioctl request buffer
226 *
227 * @return MLAN_STATUS_PENDING --success, otherwise fail
228 */
wlan_bss_ioctl_start(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)229 static mlan_status wlan_bss_ioctl_start(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
230 {
231 mlan_status ret = MLAN_STATUS_SUCCESS;
232 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
233 mlan_ds_bss *bss = (mlan_ds_bss *)(void *)pioctl_req->pbuf;
234 t_s32 i = -1;
235 t_u8 zero_mac[] = {0, 0, 0, 0, 0, 0};
236
237 ENTER();
238
239 /* Before ASSOC REQ, If "port ctrl" mode is enabled, move the port to
240 CLOSED state */
241 if (pmpriv->port_ctrl_mode == MTRUE)
242 {
243 PRINTM(MINFO, "bss_ioctl_start(): port_state=CLOSED\n");
244 pmpriv->prior_port_status = pmpriv->port_open;
245 pmpriv->port_open = MFALSE;
246 }
247 pmpriv->scan_block = MFALSE;
248
249 if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA)
250 {
251 if (!bss->param.ssid_bssid.idx || bss->param.ssid_bssid.idx > pmadapter->num_in_scan_table)
252 {
253 /* Search for the requested SSID in the scan table */
254 if (bss->param.ssid_bssid.ssid.ssid_len != 0U)
255 {
256 if (__memcmp(pmadapter, &bss->param.ssid_bssid.bssid, zero_mac, sizeof(zero_mac)) != 0U)
257 {
258 i = wlan_find_ssid_in_list(pmpriv, &bss->param.ssid_bssid.ssid,
259 (t_u8 *)&bss->param.ssid_bssid.bssid, MLAN_BSS_MODE_INFRA);
260 }
261 else
262 {
263 i = wlan_find_ssid_in_list(pmpriv, &bss->param.ssid_bssid.ssid, MNULL, MLAN_BSS_MODE_INFRA);
264 }
265 }
266 else
267 {
268 i = wlan_find_bssid_in_list(pmpriv, (t_u8 *)&bss->param.ssid_bssid.bssid, MLAN_BSS_MODE_INFRA);
269 }
270 }
271 else
272 {
273 i = ((t_s32)bss->param.ssid_bssid.idx - 1);
274 }
275 if (i >= 0)
276 {
277 PRINTM(MINFO, "SSID found in scan list ... associating...\n");
278
279 /* Clear any past association response stored for application
280 retrieval */
281 /* fixme: enable if needed later */
282 /* pmpriv->assoc_rsp_size = 0; */
283 ret = wlan_associate(pmpriv, pioctl_req, &pmadapter->pscan_table[i]);
284 if (ret != MLAN_STATUS_SUCCESS)
285 {
286 goto start_ssid_done;
287 }
288 }
289 else
290 { /* i >= 0 */
291 /* fixme: The below seems related to Adhoc. Check later. */
292 }
293 }
294
295 ret = MLAN_STATUS_PENDING;
296
297 start_ssid_done:
298 LEAVE();
299 return ret;
300 }
301
302 /**
303 * @brief BSS command handler
304 *
305 * @param pmadapter A pointer to mlan_adapter structure
306 * @param pioctl_req A pointer to ioctl request buffer
307 *
308 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
309 */
wlan_bss_ioctl(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)310 static mlan_status wlan_bss_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
311 {
312 mlan_status status = MLAN_STATUS_SUCCESS;
313 mlan_ds_bss *bss = MNULL;
314
315 ENTER();
316
317 if (pioctl_req->buf_len < sizeof(mlan_ds_bss))
318 {
319 PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
320 pioctl_req->data_read_written = 0;
321 pioctl_req->buf_len_needed = sizeof(mlan_ds_bss);
322 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
323 LEAVE();
324 return MLAN_STATUS_RESOURCE;
325 }
326
327 bss = (mlan_ds_bss *)(void *)pioctl_req->pbuf;
328
329 switch (bss->sub_command)
330 {
331 case MLAN_OID_BSS_START:
332 status = wlan_bss_ioctl_start(pmadapter, pioctl_req);
333 break;
334 default:
335 status = MLAN_STATUS_FAILURE;
336 break;
337 }
338
339 LEAVE();
340 return status;
341 }
342
343 /**
344 * @brief Rate command handler
345 *
346 * @param pmadapter A pointer to mlan_adapter structure
347 * @param pioctl_req A pointer to ioctl request buffer
348 *
349 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
350 */
wlan_rate_ioctl(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)351 static mlan_status wlan_rate_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
352 {
353 mlan_status status = MLAN_STATUS_SUCCESS;
354 mlan_ds_rate *rate = MNULL;
355
356 ENTER();
357
358 if (pioctl_req->buf_len < sizeof(mlan_ds_rate))
359 {
360 PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
361 pioctl_req->data_read_written = 0;
362 pioctl_req->buf_len_needed = sizeof(mlan_ds_rate);
363 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
364 LEAVE();
365 return MLAN_STATUS_RESOURCE;
366 }
367 rate = (mlan_ds_rate *)(void *)pioctl_req->pbuf;
368 switch (rate->sub_command)
369 {
370 case MLAN_OID_RATE_CFG:
371 status = wlan_rate_ioctl_cfg(pmadapter, pioctl_req);
372 break;
373 default:
374 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
375 status = MLAN_STATUS_FAILURE;
376 break;
377 }
378 LEAVE();
379 return status;
380 }
381
382 /**
383 * @brief Get Tx power configuration
384 *
385 * @param pmadapter A pointer to mlan_adapter structure
386 * @param cmd_no Firmware command number used to retrieve power values
387 * @param pioctl_req A pointer to ioctl request buffer
388 *
389 * @return MLAN_STATUS_PENDING --success, otherwise fail
390 */
wlan_power_ioctl_get_power(IN pmlan_adapter pmadapter,IN t_u16 cmd_no,IN pmlan_ioctl_req pioctl_req)391 static mlan_status wlan_power_ioctl_get_power(IN pmlan_adapter pmadapter,
392 IN t_u16 cmd_no,
393 IN pmlan_ioctl_req pioctl_req)
394 {
395 mlan_status ret = MLAN_STATUS_SUCCESS;
396 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
397
398 ENTER();
399
400 /* Send request to firmware */
401 ret = wlan_prepare_cmd(pmpriv, cmd_no, HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req, MNULL);
402
403 if (ret == MLAN_STATUS_SUCCESS)
404 {
405 ret = MLAN_STATUS_PENDING;
406 }
407
408 LEAVE();
409 return ret;
410 }
411
412 /**
413 * @brief Set Tx power configuration
414 *
415 * @param pmadapter A pointer to mlan_adapter structure
416 * @param pioctl_req A pointer to ioctl request buffer
417 *
418 * @return MLAN_STATUS_PENDING --success, otherwise fail
419 */
wlan_power_ioctl_set_power(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)420 static mlan_status wlan_power_ioctl_set_power(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
421 {
422 mlan_ds_power_cfg *power = MNULL;
423 mlan_status ret = MLAN_STATUS_SUCCESS;
424
425 HostCmd_DS_TXPWR_CFG *txp_cfg = MNULL;
426 MrvlTypes_Power_Group_t *pg_tlv = MNULL;
427 Power_Group_t *pg = MNULL;
428 pmlan_callbacks pcb = &pmadapter->callbacks;
429 t_u8 *buf = MNULL;
430 t_u16 dbm = 0;
431 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
432
433 ENTER();
434
435 power = (mlan_ds_power_cfg *)(void *)pioctl_req->pbuf;
436 if (!power->param.power_cfg.is_power_auto)
437 {
438 dbm = (t_u16)power->param.power_cfg.power_level;
439 #if 0
440 if ((dbm < pmpriv->min_tx_power_level) ||
441 (dbm > pmpriv->max_tx_power_level)) {
442 PRINTM(MERROR,
443 "The set txpower value %d dBm is out of range (%d dBm-%d dBm)!\n",
444 dbm, pmpriv->min_tx_power_level, pmpriv->max_tx_power_level);
445 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
446 ret = MLAN_STATUS_FAILURE;
447 goto exit;
448 }
449 #endif
450 }
451
452 ret = pcb->moal_malloc(pmadapter->pmoal_handle, MRVDRV_SIZE_OF_CMD_BUFFER, MLAN_MEM_DEF, &buf);
453 if (ret != MLAN_STATUS_SUCCESS || (buf == MNULL))
454 {
455 PRINTM(MERROR, "ALLOC_CMD_BUF: Failed to allocate command buffer\n");
456 pioctl_req->status_code = MLAN_ERROR_NO_MEM;
457 ret = MLAN_STATUS_FAILURE;
458 goto exit;
459 }
460 (void)__memset(pmadapter, buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
461 txp_cfg = (HostCmd_DS_TXPWR_CFG *)(void *)buf;
462 txp_cfg->action = HostCmd_ACT_GEN_SET;
463 if (!power->param.power_cfg.is_power_auto)
464 {
465 txp_cfg->mode = 1;
466 pg_tlv = (MrvlTypes_Power_Group_t *)(void *)(buf + sizeof(HostCmd_DS_TXPWR_CFG));
467 pg_tlv->type = TLV_TYPE_POWER_GROUP;
468 pg_tlv->length = 4U * sizeof(Power_Group_t);
469 pg = (Power_Group_t *)(void *)(buf + sizeof(HostCmd_DS_TXPWR_CFG) + sizeof(MrvlTypes_Power_Group_t));
470 /* Power group for modulation class HR/DSSS */
471 pg->first_rate_code = 0x00;
472 pg->last_rate_code = 0x03;
473 pg->modulation_class = MOD_CLASS_HR_DSSS;
474 pg->power_step = (t_s8)0;
475 pg->power_min = (t_s8)dbm;
476 pg->power_max = (t_s8)dbm;
477 pg++;
478 /* Power group for modulation class OFDM */
479 pg->first_rate_code = 0x00;
480 pg->last_rate_code = 0x07;
481 pg->modulation_class = MOD_CLASS_OFDM;
482 pg->power_step = (t_s8)0;
483 pg->power_min = (t_s8)dbm;
484 pg->power_max = (t_s8)dbm;
485 pg++;
486 /* Power group for modulation class HTBW20 */
487 pg->first_rate_code = 0x00;
488 pg->last_rate_code = 0x20;
489 pg->modulation_class = MOD_CLASS_HT;
490 pg->power_step = (t_s8)0;
491 pg->power_min = (t_s8)dbm;
492 pg->power_max = (t_s8)dbm;
493 pg->ht_bandwidth = HT_BW_20;
494 pg++;
495 /* Power group for modulation class HTBW40 */
496 pg->first_rate_code = 0x00;
497 pg->last_rate_code = 0x20;
498 pg->modulation_class = MOD_CLASS_HT;
499 pg->power_step = (t_s8)0;
500 pg->power_min = (t_s8)dbm;
501 pg->power_max = (t_s8)dbm;
502 pg->ht_bandwidth = HT_BW_40;
503 }
504
505 /* Send request to firmware */
506 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TXPWR_CFG, HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req, buf);
507
508 if (ret == MLAN_STATUS_SUCCESS)
509 {
510 ret = MLAN_STATUS_PENDING;
511 }
512
513 (void)pcb->moal_mfree(pmadapter->pmoal_handle, buf);
514
515 exit:
516 LEAVE();
517 return ret;
518 }
519
520 /**
521 * @brief Get modulation class from rate index
522 *
523 * @param pmadapter A pointer to mlan_adapter structure
524 * @param rate_index Rate index
525 *
526 * @return 0 fail, otherwise return modulation class
527 */
wlan_get_modulation_class(pmlan_adapter pmadapter,int rate_index)528 static int wlan_get_modulation_class(pmlan_adapter pmadapter, int rate_index)
529 {
530 ENTER();
531 if (rate_index >= MLAN_RATE_INDEX_HRDSSS0 && rate_index <= MLAN_RATE_INDEX_HRDSSS3)
532 {
533 LEAVE();
534 return (int)MOD_CLASS_HR_DSSS;
535 }
536 else if (rate_index >= MLAN_RATE_INDEX_OFDM0 && rate_index <= MLAN_RATE_INDEX_OFDM7)
537 {
538 LEAVE();
539 return (int)MOD_CLASS_OFDM;
540 }
541 else if (rate_index <= MLAN_RATE_INDEX_MCS127)
542 {
543 LEAVE();
544 return (int)MOD_CLASS_HT;
545 }
546 else
547 { /* Do Nothing */
548 }
549 PRINTM(MERROR, "Invalid rate index = %d supplied!\n", rate_index);
550
551 LEAVE();
552 return 0;
553 }
554
555 /**
556 * @brief Set extended power configuration
557 *
558 * @param pmadapter A pointer to mlan_adapter structure
559 * @param pioctl_req A pointer to ioctl request buffer
560 *
561 * @return MLAN_STATUS_PENDING --success, otherwise fail
562 */
wlan_power_ioctl_set_power_ext(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)563 static mlan_status wlan_power_ioctl_set_power_ext(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
564 {
565 mlan_status ret = MLAN_STATUS_SUCCESS;
566 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
567 mlan_ds_power_cfg *power = MNULL;
568 pmlan_callbacks pcb = &pmadapter->callbacks;
569 t_u8 *buf = MNULL;
570 HostCmd_DS_TXPWR_CFG *txp_cfg = MNULL;
571 MrvlTypes_Power_Group_t *pg_tlv = MNULL;
572 Power_Group_t *pg = MNULL;
573 int mod_class;
574 t_u32 data[4] = {0};
575 t_u8 ht_bw;
576
577 ENTER();
578
579 power = (mlan_ds_power_cfg *)(void *)pioctl_req->pbuf;
580 ret = pcb->moal_malloc(pmadapter->pmoal_handle, MRVDRV_SIZE_OF_CMD_BUFFER, MLAN_MEM_DEF, &buf);
581 if (ret != MLAN_STATUS_SUCCESS || (buf == MNULL))
582 {
583 PRINTM(MERROR, "ALLOC_CMD_BUF: Failed to allocate command buffer\n");
584 pioctl_req->status_code = MLAN_ERROR_NO_MEM;
585 ret = MLAN_STATUS_FAILURE;
586 goto exit;
587 }
588 (void)__memset(pmadapter, buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
589 txp_cfg = (HostCmd_DS_TXPWR_CFG *)(void *)buf;
590 txp_cfg->action = HostCmd_ACT_GEN_SET;
591 (void)__memcpy(pmadapter, (t_u8 *)&data, (t_u8 *)power->param.power_ext.power_data, sizeof(data));
592 switch (power->param.power_ext.len)
593 {
594 case 1:
595 if (data[0] == 0xFFU)
596 {
597 txp_cfg->mode = 0;
598 }
599 else
600 {
601 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
602 ret = MLAN_STATUS_FAILURE;
603 }
604 break;
605 case 2:
606 case 4:
607 ht_bw = (data[0] & TX_RATE_HT_BW40_BIT) ? HT_BW_40 : HT_BW_20;
608 data[0] &= ~TX_RATE_HT_BW40_BIT;
609 if (!(mod_class = wlan_get_modulation_class(pmadapter, (int)data[0])))
610 {
611 pioctl_req->status_code = MLAN_ERROR_CMD_RESP_FAIL;
612 ret = MLAN_STATUS_FAILURE;
613 break;
614 }
615 if (ht_bw && mod_class != MOD_CLASS_HT)
616 {
617 pioctl_req->status_code = MLAN_ERROR_CMD_RESP_FAIL;
618 ret = MLAN_STATUS_FAILURE;
619 break;
620 }
621 txp_cfg->mode = 1;
622 pg_tlv = (MrvlTypes_Power_Group_t *)(void *)(buf + sizeof(HostCmd_DS_TXPWR_CFG));
623 pg_tlv->type = TLV_TYPE_POWER_GROUP;
624 pg_tlv->length = (t_u16)sizeof(Power_Group_t);
625 pg = (Power_Group_t *)(void *)(buf + sizeof(HostCmd_DS_TXPWR_CFG) + sizeof(MrvlTypes_Power_Group_t));
626 pg->modulation_class = (t_u8)mod_class;
627 pg->first_rate_code = (t_u8)data[0];
628 pg->last_rate_code = (t_u8)data[0];
629 if (mod_class == MOD_CLASS_OFDM)
630 {
631 pg->first_rate_code = (t_u8)(data[0] - MLAN_RATE_INDEX_OFDM0);
632 pg->last_rate_code = (t_u8)(data[0] - MLAN_RATE_INDEX_OFDM0);
633 }
634 else if (mod_class == MOD_CLASS_HT)
635 {
636 pg->first_rate_code = (t_u8)(data[0] - MLAN_RATE_INDEX_MCS0);
637 pg->last_rate_code = (t_u8)(data[0] - MLAN_RATE_INDEX_MCS0);
638 pg->ht_bandwidth = ht_bw;
639 }
640 else
641 {
642 /* Do Nothing */
643 }
644 pg->power_min = (t_s8)data[1];
645 pg->power_max = (t_s8)data[1];
646 if (power->param.power_ext.len == 4U)
647 {
648 pg->power_max = (t_s8)data[2];
649 pg->power_step = (t_s8)data[3];
650 }
651 break;
652 default:
653 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
654 ret = MLAN_STATUS_FAILURE;
655 break;
656 }
657 if (ret == MLAN_STATUS_FAILURE)
658 {
659 (void)pcb->moal_mfree(pmadapter->pmoal_handle, buf);
660 goto exit;
661 }
662
663 /* Send request to firmware */
664 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TXPWR_CFG, HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req, buf);
665 if (ret == MLAN_STATUS_SUCCESS)
666 {
667 ret = MLAN_STATUS_PENDING;
668 }
669 (void)pcb->moal_mfree(pmadapter->pmoal_handle, buf);
670
671 exit:
672 LEAVE();
673 return ret;
674 }
675
676 /**
677 * @brief Power configuration command handler
678 *
679 * @param pmadapter A pointer to mlan_adapter structure
680 * @param pioctl_req A pointer to ioctl request buffer
681 *
682 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
683 */
wlan_power_ioctl(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)684 static mlan_status wlan_power_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
685 {
686 mlan_status status = MLAN_STATUS_SUCCESS;
687 mlan_ds_power_cfg *power = MNULL;
688
689 ENTER();
690
691 if (pioctl_req->buf_len < sizeof(mlan_ds_power_cfg))
692 {
693 PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
694 pioctl_req->data_read_written = 0;
695 pioctl_req->buf_len_needed = sizeof(mlan_ds_power_cfg);
696 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
697 LEAVE();
698 return MLAN_STATUS_RESOURCE;
699 }
700 power = (mlan_ds_power_cfg *)(void *)pioctl_req->pbuf;
701 switch (power->sub_command)
702 {
703 case MLAN_OID_POWER_CFG:
704 if (pioctl_req->action == MLAN_ACT_GET)
705 {
706 status = wlan_power_ioctl_get_power(pmadapter, HostCmd_CMD_TXPWR_CFG, pioctl_req);
707 }
708 else
709 {
710 status = wlan_power_ioctl_set_power(pmadapter, pioctl_req);
711 }
712 break;
713 case MLAN_OID_POWER_CFG_EXT:
714 if (pioctl_req->action == MLAN_ACT_GET)
715 {
716 status = wlan_power_ioctl_get_power(pmadapter, HostCmd_CMD_TXPWR_CFG, pioctl_req);
717 }
718 else
719 {
720 status = wlan_power_ioctl_set_power_ext(pmadapter, pioctl_req);
721 }
722 break;
723 default:
724 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
725 status = MLAN_STATUS_FAILURE;
726 break;
727 }
728 LEAVE();
729 return status;
730 }
731
732 #if CONFIG_WMM_UAPSD
733 /**
734 * @brief Set/Get WMM QoS configuration
735 *
736 * @param pmadapter A pointer to mlan_adapter structure
737 * @param pioctl_req A pointer to ioctl request buffer
738 *
739 * @return MLAN_STATUS_SUCCESS --success
740 */
wlan_wmm_ioctl_qos(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)741 static mlan_status wlan_wmm_ioctl_qos(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
742 {
743 mlan_status ret = MLAN_STATUS_SUCCESS;
744 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
745 mlan_ds_wmm_cfg *wmm = MNULL;
746
747 ENTER();
748
749 wmm = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
750
751 if (pioctl_req->action == MLAN_ACT_GET)
752 wmm->param.qos_cfg = pmpriv->wmm_qosinfo;
753 else
754 {
755 pmpriv->wmm_qosinfo = wmm->param.qos_cfg;
756 }
757
758 pioctl_req->data_read_written = sizeof(t_u8) + MLAN_SUB_COMMAND_SIZE;
759
760 LEAVE();
761 return ret;
762 }
763
764 /**
765 * @brief WMM configuration handler
766 *
767 * @param pmadapter A pointer to mlan_adapter structure
768 * @param pioctl_req A pointer to ioctl request buffer
769 *
770 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
771 */
wlan_wmm_cfg_ioctl(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)772 static mlan_status wlan_wmm_cfg_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
773 {
774 mlan_status status = MLAN_STATUS_SUCCESS;
775 mlan_ds_wmm_cfg *wmm = MNULL;
776
777 ENTER();
778
779 if (pioctl_req->buf_len < sizeof(mlan_ds_wmm_cfg))
780 {
781 PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
782 pioctl_req->data_read_written = 0;
783 pioctl_req->buf_len_needed = sizeof(mlan_ds_wmm_cfg);
784 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
785 LEAVE();
786 return MLAN_STATUS_RESOURCE;
787 }
788 wmm = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
789 switch (wmm->sub_command)
790 {
791 case MLAN_OID_WMM_CFG_QOS:
792 status = wlan_wmm_ioctl_qos(pmadapter, pioctl_req);
793 break;
794 default:
795 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
796 status = MLAN_STATUS_FAILURE;
797 break;
798 }
799 LEAVE();
800 return status;
801 }
802 #endif
803
804 /**
805 * @brief Get Random charactor
806 *
807 * @param pmadapter A pointer to mlan_adapter structure
808 *
809 * @return random charactor
810 */
wlan_get_random_charactor(pmlan_adapter pmadapter)811 t_u8 wlan_get_random_charactor(pmlan_adapter pmadapter)
812 {
813 t_u32 sec, usec;
814 t_u32 ch_32 = 0;
815 t_u8 ch = 0;
816
817 ENTER();
818
819 sec = 10; // wmtime_time_get_posix();
820 usec = 0;
821
822 sec = (sec & 0xFFFFU) + (sec >> 16);
823 usec = (usec & 0xFFFFU) + (usec >> 16);
824 ch_32 = (((sec << 16) + usec) % 26U);
825 ch = (t_u8)ch_32 + (t_u8)'a';
826
827 LEAVE();
828 return ch;
829 }
830
831 #ifdef WPA
832 /**
833 * @brief Set WPA key
834 *
835 * @param pmadapter A pointer to mlan_adapter structure
836 * @param pioctl_req A pointer to ioctl request buffer
837 *
838 * @return MLAN_STATUS_PENDING --success, otherwise fail
839 */
wlan_sec_ioctl_set_wpa_key(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)840 static mlan_status wlan_sec_ioctl_set_wpa_key(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
841 {
842 mlan_status ret = MLAN_STATUS_SUCCESS;
843 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
844 mlan_ds_sec_cfg *sec = MNULL;
845 #ifndef KEY_PARAM_SET_V2
846 t_u8 broadcast_mac_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
847 t_u8 remove_key = MFALSE;
848 #endif /* KEY_PARAM_SET_V2 */
849
850 ENTER();
851
852 sec = (mlan_ds_sec_cfg *)(void *)pioctl_req->pbuf;
853 /* Current driver only supports key length of up to 32 bytes */
854 if (sec->param.encrypt_key.key_len > MLAN_MAX_KEY_LENGTH)
855 {
856 PRINTM(MERROR, "Key length is incorrect\n");
857 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
858 ret = MLAN_STATUS_FAILURE;
859 goto exit;
860 }
861
862 #ifndef KEY_PARAM_SET_V2
863 #ifdef ENABLE_WPA_NONE
864 if ((pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) && pmpriv->sec_info.wpa_enabled)
865 {
866 /*
867 * IBSS/WPA-None uses only one key (Group) for both receiving and
868 * sending unicast and multicast packets.
869 */
870 /* Send the key as PTK to firmware */
871 sec->param.encrypt_key.key_index = MLAN_KEY_INDEX_UNICAST;
872 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL, HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, MNULL,
873 &sec->param.encrypt_key);
874 if (ret)
875 goto exit;
876
877 /* Send the key as GTK to firmware */
878 sec->param.encrypt_key.key_index = ~MLAN_KEY_INDEX_UNICAST;
879 }
880 #endif /* ENABLE_WPA_NONE */
881 #endif /* KEY_PARAM_SET_V2 */
882
883 #if defined(ADHOCAES) || defined(ENABLE_IBSS_WPA2)
884 if (sec->param.encrypt_key.key_len == WPA_AES_KEY_LEN)
885 {
886 /** back up adhoc AES key */
887 #ifdef KEY_PARAM_SET_V2
888 (void)__memset(pmpriv->adapter, &pmpriv->aes_key, 0, sizeof(pmpriv->aes_key));
889 (void)__memcpy(pmpriv->adapter, (t_u8 *)&pmpriv->aes_key, (t_u8 *)&sec->param.encrypt_key,
890 sizeof(pmpriv->aes_key));
891 #else
892 (void)__memset(pmpriv->adapter, pmpriv->aes_key.key_param_set.key, 0,
893 sizeof(pmpriv->aes_key.key_param_set.key));
894 pmpriv->aes_key.key_param_set.key_len = sec->param.encrypt_key.key_len;
895 (void)__memcpy(pmpriv->adapter, pmpriv->aes_key.key_param_set.key, sec->param.encrypt_key.key_material,
896 pmpriv->aes_key.key_param_set.key_len);
897 #endif /* KEY_PARAM_SET_V2 */
898 }
899 #endif /* ADHOCAES || ENABLE_IBSS_WPA2 */
900
901 #ifdef ADHOCAES
902 /** only adhoc aes key_index = MLAN_KEY_INDEX_UNICAST */
903 if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS && sec->param.encrypt_key.key_len == WPA_AES_KEY_LEN &&
904 sec->param.encrypt_key.key_index & MLAN_KEY_INDEX_UNICAST)
905 {
906 t_u8 zero_key_material[WPA_AES_KEY_LEN];
907 (void)__memset(pmadapter, zero_key_material, 0, sizeof(zero_key_material));
908 if (__memcmp(pmadapter, sec->param.encrypt_key.key_material, zero_key_material, WPA_AES_KEY_LEN))
909 {
910 PRINTM(MINFO, "Adhoc AES Enabled.\n");
911 pmpriv->adhoc_aes_enabled = MTRUE;
912 #ifndef KEY_PARAM_SET_V2
913 remove_key = MFALSE;
914 #endif /* KEY_PARAM_SET_V2 */
915 }
916 else
917 {
918 PRINTM(MINFO, "Adhoc AES Disabled.\n");
919 pmpriv->adhoc_aes_enabled = MFALSE;
920 /** clear adhoc AES key */
921 #ifdef KEY_PARAM_SET_V2
922 pmpriv->aes_key.key_len = 0;
923 #else
924 remove_key = MTRUE;
925 pmpriv->aes_key.key_param_set.key_len = 0;
926 #endif /* KEY_PARAM_SET_V2 */
927 }
928 }
929 #endif /* ADHOCAES */
930
931 #ifdef KEY_PARAM_SET_V2
932 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL, HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
933 &sec->param.encrypt_key);
934 #else
935 if (__memcmp(pmadapter, sec->param.encrypt_key.mac_addr, broadcast_mac_addr, MLAN_MAC_ADDR_LENGTH))
936 {
937 sec->param.encrypt_key.key_index |= MLAN_KEY_INDEX_UNICAST;
938 }
939
940 #ifdef ENABLE_IBSS_WPA2
941 if ((pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) && (sec->param.encrypt_key.key_len == WPA_AES_KEY_LEN))
942 {
943 if (__memcmp(pmadapter, sec->param.encrypt_key.mac_addr, broadcast_mac_addr, MLAN_MAC_ADDR_LENGTH) == 0)
944 {
945 /* for IBSS RSN when GTK is to be downloaded for
946 * broadcast mac
947 * address,replace broadcast mac with self mac address*/
948 (void)__memcpy(pmadapter, sec->param.encrypt_key.mac_addr, pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH);
949 }
950 if (sec->param.encrypt_key.key_flags & KEY_FLAG_GROUP_KEY)
951 {
952 PRINTM(MINFO, "Received GTK for " MACSTR "\n", MAC2STR(sec->param.encrypt_key.mac_addr));
953 /* Send the key as GTK to firmware */
954 sec->param.encrypt_key.key_index = ~MLAN_KEY_INDEX_UNICAST;
955 }
956 }
957 #endif
958 if (remove_key == MTRUE)
959 {
960 /* Send request to firmware */
961 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL, HostCmd_ACT_GEN_SET, !(KEY_INFO_ENABLED),
962 (t_void *)pioctl_req, &sec->param.encrypt_key);
963 }
964 else
965 {
966 /* Send request to firmware */
967 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL, HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
968 (t_void *)pioctl_req, &sec->param.encrypt_key);
969 }
970 #endif /* KEY_PARAM_SET_V2 */
971
972 if (ret == MLAN_STATUS_SUCCESS)
973 {
974 ret = MLAN_STATUS_PENDING;
975 }
976
977 exit:
978 LEAVE();
979 return ret;
980 }
981 #endif /* WPA */
982
983 /**
984 * @brief Set security key(s)
985 *
986 * @param pmadapter A pointer to mlan_adapter structure
987 * @param pioctl_req A pointer to ioctl request buffer
988 *
989 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
990 */
wlan_sec_ioctl_encrypt_key(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)991 static mlan_status wlan_sec_ioctl_encrypt_key(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
992 {
993 mlan_status status = MLAN_STATUS_SUCCESS;
994 mlan_ds_sec_cfg *sec = MNULL;
995 ENTER();
996 sec = (mlan_ds_sec_cfg *)(void *)pioctl_req->pbuf;
997 if (pioctl_req->action == MLAN_ACT_SET)
998 {
999 #ifdef WAPI
1000 if (sec->param.encrypt_key.is_wapi_key)
1001 {
1002 status = wlan_sec_ioctl_set_wapi_key(pmadapter, pioctl_req);
1003 }
1004 else
1005 #endif
1006 #ifdef WPA
1007 if (sec->param.encrypt_key.key_len > MAX_WEP_KEY_SIZE)
1008 {
1009 status = wlan_sec_ioctl_set_wpa_key(pmadapter, pioctl_req);
1010 }
1011 #endif /* WPA */
1012 }
1013 else
1014 {
1015 /* fixme: enable when needed */
1016 /* status = wlan_sec_ioctl_get_key(pmadapter, pioctl_req); */
1017 }
1018 LEAVE();
1019 return status;
1020 }
1021
1022 /**
1023 * @brief Set/Get WPA passphrase from embedded supplicant
1024 *
1025 * @param pmadapter A pointer to mlan_adapter structure
1026 * @param pioctl_req A pointer to ioctl request buffer
1027 *
1028 * @return MLAN_STATUS_PENDING --success, otherwise fail
1029 */
wlan_sec_ioctl_passphrase(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1030 static mlan_status wlan_sec_ioctl_passphrase(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
1031 {
1032 mlan_status ret = MLAN_STATUS_SUCCESS;
1033 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1034 mlan_ds_sec_cfg *sec = MNULL;
1035 t_u16 cmd_action = 0;
1036 /* BSSDescriptor_t *pbss_desc; */
1037 /* int i = 0; */
1038
1039 ENTER();
1040
1041 sec = (mlan_ds_sec_cfg *)(void *)pioctl_req->pbuf;
1042 if (pioctl_req->action == MLAN_ACT_SET)
1043 {
1044 if (sec->param.passphrase.psk_type == MLAN_PSK_CLEAR)
1045 {
1046 cmd_action = HostCmd_ACT_GEN_REMOVE;
1047 }
1048 else
1049 {
1050 cmd_action = HostCmd_ACT_GEN_SET;
1051 }
1052 }
1053 else
1054 {
1055 if (sec->param.passphrase.psk_type == MLAN_PSK_QUERY)
1056 {
1057 if (sec->param.passphrase.ssid.ssid_len != 0U)
1058 {
1059 (void)__memset(pmadapter, &sec->param.passphrase.bssid, 0, MLAN_MAC_ADDR_LENGTH);
1060 }
1061 }
1062 cmd_action = HostCmd_ACT_GEN_GET;
1063 }
1064
1065 /* Send request to firmware */
1066 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SUPPLICANT_PMK, cmd_action, 0, (t_void *)pioctl_req,
1067 &sec->param.passphrase);
1068 if (ret == MLAN_STATUS_SUCCESS)
1069 {
1070 ret = MLAN_STATUS_PENDING;
1071 }
1072
1073 LEAVE();
1074 return ret;
1075 }
1076
1077 /**
1078 * @brief Set/Get WPA3 SAE password from embedded supplicant
1079 *
1080 * @param pmadapter A pointer to mlan_adapter structure
1081 * @param pioctl_req A pointer to ioctl request buffer
1082 *
1083 * @return MLAN_STATUS_PENDING --success, otherwise fail
1084 */
wlan_sec_ioctl_password(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1085 static mlan_status wlan_sec_ioctl_password(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
1086 {
1087 mlan_status ret = MLAN_STATUS_SUCCESS;
1088 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1089 mlan_ds_sec_cfg *sec = MNULL;
1090 t_u16 cmd_action = 0;
1091 /* BSSDescriptor_t *pbss_desc; */
1092 /* int i = 0; */
1093
1094 ENTER();
1095
1096 sec = (mlan_ds_sec_cfg *)(void *)pioctl_req->pbuf;
1097 if (pioctl_req->action == MLAN_ACT_SET)
1098 {
1099 if (sec->param.passphrase.psk_type == MLAN_PSK_CLEAR)
1100 {
1101 cmd_action = HostCmd_ACT_GEN_REMOVE;
1102 }
1103 else
1104 {
1105 cmd_action = HostCmd_ACT_GEN_SET;
1106 }
1107 }
1108 else
1109 {
1110 if (sec->param.passphrase.psk_type == MLAN_PSK_QUERY)
1111 {
1112 if (sec->param.passphrase.ssid.ssid_len != 0U)
1113 {
1114 (void)__memset(pmadapter, &sec->param.passphrase.bssid, 0, MLAN_MAC_ADDR_LENGTH);
1115 }
1116 }
1117 cmd_action = HostCmd_ACT_GEN_GET;
1118 }
1119
1120 /* Send request to firmware */
1121 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SUPPLICANT_PMK, cmd_action, 0, (t_void *)pioctl_req,
1122 &sec->param.passphrase);
1123 if (ret == MLAN_STATUS_SUCCESS)
1124 {
1125 ret = MLAN_STATUS_PENDING;
1126 }
1127
1128 LEAVE();
1129 return ret;
1130 }
1131
1132 /**
1133 * @brief Security configuration handler
1134 *
1135 * @param pmadapter A pointer to mlan_adapter structure
1136 * @param pioctl_req A pointer to ioctl request buffer
1137 *
1138 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
1139 */
wlan_sec_cfg_ioctl(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1140 static mlan_status wlan_sec_cfg_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
1141 {
1142 mlan_status status = MLAN_STATUS_SUCCESS;
1143 mlan_ds_sec_cfg *sec = MNULL;
1144
1145 ENTER();
1146
1147 if (pioctl_req->buf_len < sizeof(mlan_ds_sec_cfg))
1148 {
1149 PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
1150 pioctl_req->data_read_written = 0;
1151 pioctl_req->buf_len_needed = sizeof(mlan_ds_sec_cfg);
1152 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1153 LEAVE();
1154 return MLAN_STATUS_RESOURCE;
1155 }
1156 sec = (mlan_ds_sec_cfg *)(void *)pioctl_req->pbuf;
1157 switch (sec->sub_command)
1158 {
1159 case MLAN_OID_SEC_CFG_ENCRYPT_KEY:
1160 status = wlan_sec_ioctl_encrypt_key(pmadapter, pioctl_req);
1161 break;
1162 case MLAN_OID_SEC_CFG_PASSPHRASE:
1163 status = wlan_sec_ioctl_passphrase(pmadapter, pioctl_req);
1164 break;
1165 case MLAN_OID_SEC_CFG_PASSWORD:
1166 status = wlan_sec_ioctl_password(pmadapter, pioctl_req);
1167 break;
1168 default:
1169 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
1170 status = MLAN_STATUS_FAILURE;
1171 break;
1172 }
1173 LEAVE();
1174 return status;
1175 }
1176
1177 /**
1178 * @brief 11D configuration handler
1179 *
1180 * @param pmadapter A pointer to mlan_adapter structure
1181 * @param pioctl_req A pointer to ioctl request buffer
1182 *
1183 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
1184 */
wlan_11d_cfg_ioctl(IN mlan_private * pmpriv,IN pmlan_ioctl_req pioctl_req)1185 mlan_status wlan_11d_cfg_ioctl(IN mlan_private *pmpriv, IN pmlan_ioctl_req pioctl_req)
1186 {
1187 mlan_adapter *pmadapter = pmpriv->adapter;
1188 mlan_status status = MLAN_STATUS_SUCCESS;
1189 mlan_ds_11d_cfg *pcfg_11d = MNULL;
1190
1191 ENTER();
1192
1193 if (pioctl_req->buf_len < sizeof(mlan_ds_11d_cfg))
1194 {
1195 PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
1196 pioctl_req->data_read_written = 0;
1197 pioctl_req->buf_len_needed = sizeof(mlan_ds_11d_cfg);
1198 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1199 status = MLAN_STATUS_RESOURCE;
1200 goto exit;
1201 }
1202
1203 pcfg_11d = (mlan_ds_11d_cfg *)(void *)pioctl_req->pbuf;
1204 switch (pcfg_11d->sub_command)
1205 {
1206 case MLAN_OID_11D_DOMAIN_INFO:
1207 if (pmpriv->support_11d_APIs != NULL)
1208 {
1209 status = pmpriv->support_11d_APIs->wlan_11d_cfg_domain_info_p(pmadapter, pioctl_req);
1210 }
1211 break;
1212 default:
1213 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
1214 status = MLAN_STATUS_FAILURE;
1215 break;
1216 }
1217
1218 exit:
1219 LEAVE();
1220 return status;
1221 }
1222
1223 #if CONFIG_WPS2
1224 /**
1225 * @brief WPS configuration handler
1226 *
1227 * @param pmadapter A pointer to mlan_adapter structure
1228 * @param pioctl_req A pointer to ioctl request buffer
1229 *
1230 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
1231 */
wlan_wps_cfg_ioctl(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1232 static mlan_status wlan_wps_cfg_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
1233 {
1234 mlan_status status = MLAN_STATUS_SUCCESS;
1235 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1236 mlan_ds_wps_cfg *pwps = MNULL;
1237
1238 ENTER();
1239
1240 if (pioctl_req->buf_len < sizeof(mlan_ds_wps_cfg))
1241 {
1242 PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
1243 pioctl_req->data_read_written = 0;
1244 pioctl_req->buf_len_needed = sizeof(mlan_ds_wps_cfg);
1245 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1246 LEAVE();
1247 return MLAN_STATUS_RESOURCE;
1248 }
1249
1250 pwps = (mlan_ds_wps_cfg *)pioctl_req->pbuf;
1251 switch (pwps->sub_command)
1252 {
1253 case MLAN_OID_WPS_CFG_SESSION:
1254 if (pioctl_req->action == MLAN_ACT_SET)
1255 {
1256 if (pwps->param.wps_session == MLAN_WPS_CFG_SESSION_START)
1257 pmpriv->wps.session_enable = MTRUE;
1258 else
1259 pmpriv->wps.session_enable = MFALSE;
1260 }
1261 else
1262 {
1263 pwps->param.wps_session = (t_u32)pmpriv->wps.session_enable;
1264 pioctl_req->data_read_written = sizeof(t_u32);
1265 PRINTM(MINFO, "wpscfg GET=%d\n", pwps->param.wps_session);
1266 }
1267 break;
1268 default:
1269 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
1270 status = MLAN_STATUS_FAILURE;
1271 break;
1272 }
1273
1274 LEAVE();
1275 return status;
1276 }
1277 #endif /* CONFIG_WPS2 */
1278
1279 /**
1280 * @brief Set/Get region code
1281 *
1282 * @param pmadapter A pointer to mlan_adapter structure
1283 * @param pioctl_req A pointer to ioctl request buffer
1284 *
1285 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
1286 */
wlan_misc_ioctl_region(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1287 /* static */ mlan_status wlan_misc_ioctl_region(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
1288 {
1289 mlan_status ret = MLAN_STATUS_SUCCESS;
1290 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1291 mlan_ds_misc_cfg *misc = MNULL;
1292 int i;
1293
1294 ENTER();
1295
1296 misc = (mlan_ds_misc_cfg *)(void *)pioctl_req->pbuf;
1297 if (pioctl_req->action == MLAN_ACT_GET)
1298 {
1299 misc->param.region_code = pmadapter->region_code;
1300 }
1301 else
1302 {
1303 #ifdef OTP_CHANINFO
1304 if (pmadapter->otp_region && pmadapter->otp_region->force_reg)
1305 {
1306 (void)PRINTF(
1307 "ForceRegionRule is set in the on-chip OTP"
1308 " memory\r\n");
1309 LEAVE();
1310 return MLAN_STATUS_FAILURE;
1311 }
1312 #endif
1313 for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++)
1314 {
1315 /* Use the region code to search for the index */
1316 if (misc->param.region_code == region_code_index[i])
1317 {
1318 pmadapter->region_code = (t_u16)misc->param.region_code;
1319 break;
1320 }
1321 }
1322 /* It's unidentified region code */
1323 if (i >= MRVDRV_MAX_REGION_CODE)
1324 {
1325 PRINTM(MERROR, "Region Code not identified\n");
1326 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1327 LEAVE();
1328 return MLAN_STATUS_FAILURE;
1329 }
1330 pmadapter->cfp_code_bg = (t_u8)misc->param.region_code;
1331 pmadapter->cfp_code_a = (t_u8)misc->param.region_code;
1332 if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
1333 (t_u16)(pmadapter->config_bands | pmadapter->adhoc_start_band)) != MLAN_STATUS_SUCCESS)
1334 {
1335 pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
1336 ret = MLAN_STATUS_FAILURE;
1337 }
1338 }
1339 pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
1340
1341 LEAVE();
1342 return ret;
1343 }
1344
1345 #if CONFIG_GTK_REKEY_OFFLOAD
1346 /**
1347 * @brief Gtk Rekey Offload
1348 *
1349 * @param pmadapter A pointer to mlan_adapter structure
1350 * @param pioctl_req A pointer to ioctl request buffer
1351 *
1352 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
1353 */
wlan_misc_ioctl_gtk_rekey_offload(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1354 static mlan_status wlan_misc_ioctl_gtk_rekey_offload(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
1355 {
1356 mlan_status ret = MLAN_STATUS_SUCCESS;
1357 mlan_ds_misc_cfg *misc_cfg = MNULL;
1358 t_u16 cmd_action = 0;
1359 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1360
1361 ENTER();
1362 misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
1363 if (pioctl_req->action == MLAN_ACT_SET)
1364 cmd_action = HostCmd_ACT_GEN_SET;
1365 else if (pioctl_req->action == MLAN_ACT_CLEAR)
1366 cmd_action = HostCmd_ACT_GEN_REMOVE;
1367 else
1368 cmd_action = HostCmd_ACT_GEN_GET;
1369
1370 if (!pmpriv->wpa_is_gtk_set)
1371 {
1372 /* Store the gtk rekey data if it has already set gtk */
1373 (void)__memcpy(pmadapter, &pmpriv->gtk_rekey, &misc_cfg->param.gtk_rekey, sizeof(mlan_ds_misc_gtk_rekey_data));
1374 LEAVE();
1375 return ret;
1376 }
1377 /* Send request to firmware if it hasn't set gtk yet */
1378 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CONFIG_GTK_REKEY_OFFLOAD_CFG, cmd_action, 0, (t_void *)pioctl_req,
1379 &misc_cfg->param.gtk_rekey);
1380
1381 if (ret == MLAN_STATUS_SUCCESS)
1382 ret = MLAN_STATUS_PENDING;
1383
1384 LEAVE();
1385 return ret;
1386 }
1387 #endif
1388
1389 /**
1390 * @brief Get/Set subscribe event
1391 *
1392 * @param pmadapter A pointer to mlan_adapter structure
1393 * @param pioctl_req A pointer to ioctl request buffer
1394 *
1395 * @return MLAN_STATUS_PENDING -- success, otherwise fail
1396 */
wlan_misc_ioctl_subscribe_evt(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1397 mlan_status wlan_misc_ioctl_subscribe_evt(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
1398 {
1399 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1400 mlan_status ret = MLAN_STATUS_SUCCESS;
1401 mlan_ds_misc_cfg *misc = MNULL;
1402 t_u16 cmd_action = 0;
1403
1404 ENTER();
1405
1406 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
1407 if (pioctl_req->action == MLAN_ACT_SET)
1408 {
1409 cmd_action = HostCmd_ACT_GEN_SET;
1410 }
1411 else
1412 {
1413 cmd_action = HostCmd_ACT_GEN_GET;
1414 }
1415
1416 /* Send command to firmware */
1417 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT, cmd_action, 0, (t_void *)pioctl_req,
1418 &misc->param.subscribe_event);
1419
1420 if (ret == MLAN_STATUS_SUCCESS)
1421 ret = MLAN_STATUS_PENDING;
1422
1423 LEAVE();
1424 return ret;
1425 }
1426
1427 /**
1428 * @brief Miscellaneous configuration handler
1429 *
1430 * @param pmadapter A pointer to mlan_adapter structure
1431 * @param pioctl_req A pointer to ioctl request buffer
1432 *
1433 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
1434 */
wlan_misc_cfg_ioctl(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1435 static mlan_status wlan_misc_cfg_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
1436 {
1437 mlan_status status = MLAN_STATUS_SUCCESS;
1438 mlan_ds_misc_cfg *misc = MNULL;
1439
1440 ENTER();
1441
1442 if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg))
1443 {
1444 PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
1445 pioctl_req->data_read_written = 0;
1446 pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
1447 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1448 LEAVE();
1449 return MLAN_STATUS_RESOURCE;
1450 }
1451 if ((pioctl_req == MNULL) || (pioctl_req->pbuf == MNULL))
1452 {
1453 PRINTM(MERROR, "Request buffer not found!\n");
1454 LEAVE();
1455 return MLAN_STATUS_FAILURE;
1456 }
1457 misc = (mlan_ds_misc_cfg *)(void *)pioctl_req->pbuf;
1458 switch (misc->sub_command)
1459 {
1460 case MLAN_OID_MISC_REGION:
1461 status = wlan_misc_ioctl_region(pmadapter, pioctl_req);
1462 break;
1463 #if CONFIG_GTK_REKEY_OFFLOAD
1464 case MLAN_OID_MISC_CONFIG_GTK_REKEY_OFFLOAD:
1465 status = wlan_misc_ioctl_gtk_rekey_offload(pmadapter, pioctl_req);
1466 break;
1467 #endif
1468 #if CONFIG_ROAMING
1469 case MLAN_OID_MISC_SUBSCRIBE_EVENT:
1470 status = wlan_misc_ioctl_subscribe_evt(pmadapter, pioctl_req);
1471 break;
1472 #endif
1473 #ifdef WLAN_LOW_POWER_ENABLE
1474 case MLAN_OID_MISC_LOW_PWR_MODE:
1475 status = wlan_misc_ioctl_low_pwr_mode(pmadapter, pioctl_req);
1476 break;
1477 #endif // WLAN_LOW_POWER_ENABLE
1478 #if CONFIG_WIFI_CLOCKSYNC
1479 case MLAN_OID_MISC_GPIO_TSF_LATCH:
1480 status = wlan_misc_gpio_tsf_latch_config(pmadapter, pioctl_req);
1481 break;
1482 case MLAN_OID_MISC_GET_TSF_INFO:
1483 status = wlan_misc_get_tsf_info(pmadapter, pioctl_req);
1484 break;
1485 #endif /* CONFIG_WIFI_CLOCKSYNC */
1486 #if CONFIG_RF_TEST_MODE
1487 case MLAN_OID_MISC_RF_TEST_GENERIC:
1488 case MLAN_OID_MISC_RF_TEST_TX_CONT:
1489 case MLAN_OID_MISC_RF_TEST_CONFIG_TRIGGER_FRAME:
1490 case MLAN_OID_MISC_RF_TEST_TX_FRAME:
1491 case MLAN_OID_MISC_RF_TEST_HE_POWER:
1492 status = wlan_misc_ioctl_rf_test_cfg(pmadapter, pioctl_req);
1493 break;
1494 #endif /* CONFIG_RF_TEST_MODE */
1495 #if (CONFIG_WIFI_IND_RESET) && (CONFIG_WIFI_IND_DNLD)
1496 case MLAN_OID_MISC_IND_RST_CFG:
1497 status = wlan_misc_ioctl_ind_rst_cfg(pmadapter, pioctl_req);
1498 break;
1499 #endif
1500 default:
1501 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
1502
1503 status = MLAN_STATUS_FAILURE;
1504 break;
1505 }
1506 LEAVE();
1507 return status;
1508 }
1509
1510 #if CONFIG_11K_OFFLOAD
1511 /**
1512 * @brief 11k enable
1513 *
1514 * @param pmpriv A pointer to mlan_private structure
1515 * @param pioctl_buf A pointer to ioctl request buffer
1516 * @param enable_11k 11k enable flag.
1517 *
1518 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
1519 */
wlan_11k_enable(mlan_private * pmpriv,t_void * pioctl_buf,t_u8 enable_11k)1520 static mlan_status wlan_11k_enable(mlan_private *pmpriv, t_void *pioctl_buf, t_u8 enable_11k)
1521 {
1522 mlan_status ret = MLAN_STATUS_SUCCESS;
1523 HostCmd_OFFLOAD_FEATURE_CTRL fctrl;
1524
1525 ENTER();
1526
1527 (void)__memset(pmpriv->adapter, &fctrl, 0, sizeof(fctrl));
1528 fctrl.featureSelect = 0; /* Std feature */
1529
1530 /* enable or disable Neighbor AP list Report */
1531 fctrl.control.std.dot11k_nbor_support = enable_11k;
1532 /* enable or disable Traffic Stream Measurement*/
1533 fctrl.control.std.dot11k_tsm = enable_11k;
1534 /* enable or disable Link Measurement*/
1535 fctrl.control.std.dot11k_lm = enable_11k;
1536 /* enable or disable Radio Measurement (Beacon Report)*/
1537 fctrl.control.std.dot11k_rm = enable_11k;
1538
1539 /* enable 11v BSS Transition with 11k*/
1540 fctrl.control.std.dot11v_bss_trans = enable_11k;
1541
1542 /* enable or disable TPC report (Probe request) */
1543 fctrl.control.std.vowifi_probe_tpc_rpt = enable_11k;
1544
1545 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_OFFLOAD_FEATURE_CONTROL, HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_buf,
1546 &fctrl);
1547
1548 if (ret)
1549 {
1550 PRINTM(MERROR, "11K: Failed to %s 11K\n", (enable_11k) ? "enable" : "disable");
1551 }
1552
1553 LEAVE();
1554 return ret;
1555 }
1556
1557 /**
1558 * @brief 11k enable ioctl
1559 *
1560 * @param pmadapter A pointer to mlan_adapter structure
1561 * @param pioctl_req A pointer to ioctl request buffer
1562 *
1563 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
1564 */
wlan_11k_cfg_ioctl_enable(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1565 static mlan_status wlan_11k_cfg_ioctl_enable(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
1566 {
1567 mlan_status ret = MLAN_STATUS_SUCCESS;
1568 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1569 mlan_ds_11k_cfg *pcfg_11k = MNULL;
1570
1571 ENTER();
1572
1573 pcfg_11k = (mlan_ds_11k_cfg *)(void *)(pioctl_req->pbuf);
1574
1575 if (pioctl_req->action == MLAN_ACT_SET)
1576 {
1577 if (pmpriv->media_connected == MTRUE && pcfg_11k->param.enable_11k != pmpriv->enable_11k)
1578 {
1579 PRINTM(MERROR, "11K setting cannot be changed while connecting with AP.\n");
1580 ret = MLAN_STATUS_FAILURE;
1581 goto done;
1582 }
1583
1584 PRINTM(MINFO, "11K: 11kcfg SET=%d\n", pcfg_11k->param.enable_11k);
1585
1586 /* Compare with current settings */
1587 if (pmpriv->enable_11k != pcfg_11k->param.enable_11k)
1588 {
1589 ret = wlan_11k_enable(pmpriv, pioctl_req, pcfg_11k->param.enable_11k);
1590 if (ret == MLAN_STATUS_SUCCESS)
1591 ret = MLAN_STATUS_PENDING;
1592 }
1593 else
1594 {
1595 PRINTM(MINFO, "11K: same as current setting, do nothing\n");
1596 }
1597 }
1598 else
1599 {
1600 pcfg_11k->param.enable_11k = pmpriv->enable_11k;
1601 pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
1602 PRINTM(MINFO, "11K: 11kcfg GET=%d\n", pcfg_11k->param.enable_11k);
1603 }
1604 done:
1605 LEAVE();
1606 return ret;
1607 }
1608
1609 /**
1610 * @brief 11K cfg ioctl
1611 *
1612 * @param pmadapter A pointer to mlan_adapter structure
1613 * @param pioctl_req A pointer to ioctl request buffer
1614 *
1615 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
1616 */
wlan_11k_cfg_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1617 static mlan_status wlan_11k_cfg_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
1618 {
1619 mlan_status status = MLAN_STATUS_SUCCESS;
1620 mlan_ds_11k_cfg *ds_11kcfg = MNULL;
1621
1622 ENTER();
1623
1624 if (pioctl_req->buf_len < sizeof(mlan_ds_11k_cfg))
1625 {
1626 PRINTM(MWARN, "MLAN 11K IOCTL length is too short.\n");
1627 pioctl_req->data_read_written = 0;
1628 pioctl_req->buf_len_needed = sizeof(mlan_ds_11k_cfg);
1629 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1630 LEAVE();
1631 return MLAN_STATUS_RESOURCE;
1632 }
1633
1634 ds_11kcfg = (mlan_ds_11k_cfg *)(void *)pioctl_req->pbuf;
1635 switch (ds_11kcfg->sub_command)
1636 {
1637 case MLAN_OID_11K_CFG_ENABLE:
1638 status = wlan_11k_cfg_ioctl_enable(pmadapter, pioctl_req);
1639 break;
1640 default:
1641 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
1642 status = MLAN_STATUS_FAILURE;
1643 break;
1644 }
1645
1646 LEAVE();
1647 return status;
1648 }
1649 #endif
1650
1651 /**
1652 * @brief MLAN station ioctl handler
1653 *
1654 * @param adapter A pointer to mlan_adapter structure
1655 * @param pioctl_req A pointer to ioctl request buffer
1656 *
1657 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
1658 */
wlan_ops_sta_ioctl(t_void * adapter,pmlan_ioctl_req pioctl_req)1659 mlan_status wlan_ops_sta_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req)
1660 {
1661 pmlan_private pmpriv = MNULL;
1662 pmlan_adapter pmadapter = (pmlan_adapter)adapter;
1663 mlan_status status = MLAN_STATUS_SUCCESS;
1664
1665 ENTER();
1666
1667 if (pioctl_req != MNULL)
1668 {
1669 CHECK_BSS_TYPE(pioctl_req->bss_index, MLAN_STATUS_FAILURE);
1670 pmpriv = pmadapter->priv[pioctl_req->bss_index];
1671 }
1672 else
1673 {
1674 PRINTM(MERROR, "MLAN IOCTL information is not present\n");
1675 return MLAN_STATUS_FAILURE;
1676 }
1677
1678 switch (pioctl_req->req_id)
1679 {
1680 case MLAN_IOCTL_BSS:
1681 status = wlan_bss_ioctl(pmadapter, pioctl_req);
1682 break;
1683 case MLAN_IOCTL_RADIO_CFG:
1684 status = wlan_radio_ioctl(pmadapter, pioctl_req);
1685 break;
1686 #if (CONFIG_WIFI_RTS_THRESHOLD) || (CONFIG_WIFI_FRAG_THRESHOLD)
1687 case MLAN_IOCTL_SNMP_MIB:
1688 status = wlan_snmp_mib_ioctl(pmadapter, pioctl_req);
1689 break;
1690 #endif
1691 case MLAN_IOCTL_SEC_CFG:
1692 status = wlan_sec_cfg_ioctl(pmadapter, pioctl_req);
1693 break;
1694 case MLAN_IOCTL_RATE:
1695 status = wlan_rate_ioctl(pmadapter, pioctl_req);
1696 break;
1697 case MLAN_IOCTL_POWER_CFG:
1698 status = wlan_power_ioctl(pmadapter, pioctl_req);
1699 break;
1700 #if CONFIG_WMM_UAPSD
1701 case MLAN_IOCTL_WMM_CFG:
1702 status = wlan_wmm_cfg_ioctl(pmadapter, pioctl_req);
1703 break;
1704 #endif
1705 #if CONFIG_WPS2
1706 case MLAN_IOCTL_WPS_CFG:
1707 status = wlan_wps_cfg_ioctl(pmadapter, pioctl_req);
1708 break;
1709 #endif /* CONFIG_WPS2 */
1710 case MLAN_IOCTL_11N_CFG:
1711 status = wlan_11n_cfg_ioctl(pmadapter, pioctl_req);
1712 break;
1713 case MLAN_IOCTL_11D_CFG:
1714 if (pmpriv->support_11d_APIs != NULL)
1715 {
1716 status = pmpriv->support_11d_APIs->wlan_11d_cfg_ioctl_p(pmpriv, pioctl_req);
1717 }
1718 break;
1719 case MLAN_IOCTL_MISC_CFG:
1720 status = wlan_misc_cfg_ioctl(pmadapter, pioctl_req);
1721 break;
1722 #if CONFIG_11K_OFFLOAD
1723 case MLAN_IOCTL_11K_CFG:
1724 status = wlan_11k_cfg_ioctl(pmadapter, pioctl_req);
1725 break;
1726 #endif
1727 #if CONFIG_11AX
1728 case MLAN_IOCTL_11AX_CFG:
1729 status = wlan_11ax_cfg_ioctl(pmadapter, pioctl_req);
1730 break;
1731 #endif
1732 default:
1733 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
1734 status = MLAN_STATUS_FAILURE;
1735 break;
1736 }
1737 LEAVE();
1738 return status;
1739 }
1740