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