1 /** @file mlan_sta_ioctl.c
2 *
3 * @brief This file contains the functions for station ioctl.
4 *
5 *
6 * Copyright 2008-2022 NXP
7 *
8 * This software file (the File) is distributed by NXP
9 * under the terms of the GNU General Public License Version 2, June 1991
10 * (the License). You may use, redistribute and/or modify the File in
11 * accordance with the terms and conditions of the License, a copy of which
12 * is available by writing to the Free Software Foundation, Inc.,
13 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
14 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
15 *
16 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
18 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
19 * this warranty disclaimer.
20 *
21 */
22
23 /******************************************************
24 Change log:
25 10/21/2008: initial version
26 ******************************************************/
27
28 #include "mlan.h"
29 #include "mlan_join.h"
30 #include "mlan_util.h"
31 #include "mlan_fw.h"
32 #include "mlan_main.h"
33 #include "mlan_wmm.h"
34 #include "mlan_11n.h"
35 #include "mlan_11ac.h"
36 #include "mlan_11ax.h"
37 #include "mlan_11h.h"
38 #ifdef DRV_EMBEDDED_SUPPLICANT
39 #include "authenticator_api.h"
40 #endif
41
42 /********************************************************
43 Local Variables
44 ********************************************************/
45
46 /********************************************************
47 Global Variables
48 ********************************************************/
49
50 /********************************************************
51 Local Functions
52 ********************************************************/
53
54 /**
55 * @brief Get signal information
56 *
57 * @param pmadapter A pointer to mlan_adapter structure
58 * @param pioctl_req A pointer to ioctl request buffer
59 *
60 * @return MLAN_STATUS_PENDING --success, otherwise fail
61 */
wlan_get_info_signal(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)62 static mlan_status wlan_get_info_signal(pmlan_adapter pmadapter,
63 pmlan_ioctl_req pioctl_req)
64 {
65 pmlan_private pmpriv = MNULL;
66 mlan_status ret = MLAN_STATUS_SUCCESS;
67
68 ENTER();
69
70 if (pioctl_req != MNULL) {
71 pmpriv = pmadapter->priv[pioctl_req->bss_index];
72 } else {
73 PRINTM(MERROR, "MLAN IOCTL information is not present\n");
74 ret = MLAN_STATUS_FAILURE;
75 goto exit;
76 }
77
78 /* Check information buffer length of MLAN IOCTL */
79 if (pioctl_req->buf_len < sizeof(mlan_ds_get_signal)) {
80 PRINTM(MWARN,
81 "MLAN IOCTL information buffer length is too short.\n");
82 pioctl_req->data_read_written = 0;
83 pioctl_req->buf_len_needed = sizeof(mlan_ds_get_signal);
84 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
85 ret = MLAN_STATUS_RESOURCE;
86 goto exit;
87 }
88
89 /* Signal info can be obtained only if connected */
90 if (pmpriv->media_connected == MFALSE) {
91 PRINTM(MINFO, "Can not get signal in disconnected state\n");
92 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
93 ret = MLAN_STATUS_FAILURE;
94 goto exit;
95 }
96
97 /* Send request to firmware */
98 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RSSI_INFO,
99 HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
100 MNULL);
101
102 if (ret == MLAN_STATUS_SUCCESS)
103 ret = MLAN_STATUS_PENDING;
104
105 exit:
106 LEAVE();
107 return ret;
108 }
109
110 /**
111 * @brief Get signal information
112 *
113 * @param pmadapter A pointer to mlan_adapter structure
114 * @param pioctl_req A pointer to ioctl request buffer
115 *
116 * @return MLAN_STATUS_PENDING --success, otherwise fail
117 */
wlan_get_info_signal_ext(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)118 static mlan_status wlan_get_info_signal_ext(pmlan_adapter pmadapter,
119 pmlan_ioctl_req pioctl_req)
120 {
121 pmlan_private pmpriv = MNULL;
122 mlan_status ret = MLAN_STATUS_SUCCESS;
123 mlan_ds_get_info *info = MNULL;
124
125 ENTER();
126
127 if (pioctl_req != MNULL) {
128 pmpriv = pmadapter->priv[pioctl_req->bss_index];
129 } else {
130 PRINTM(MERROR, "MLAN IOCTL information is not present\n");
131 ret = MLAN_STATUS_FAILURE;
132 goto exit;
133 }
134 info = (mlan_ds_get_info *)pioctl_req->pbuf;
135
136 /* Check information buffer length of MLAN IOCTL */
137 if (pioctl_req->buf_len < sizeof(mlan_ds_get_info)) {
138 PRINTM(MWARN,
139 "MLAN IOCTL information buffer length is too short.\n");
140 pioctl_req->data_read_written = 0;
141 pioctl_req->buf_len_needed = sizeof(mlan_ds_get_info);
142 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
143 ret = MLAN_STATUS_RESOURCE;
144 goto exit;
145 }
146
147 /* Send request to firmware */
148 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RSSI_INFO_EXT,
149 HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
150 (t_void *)info);
151
152 if (ret == MLAN_STATUS_SUCCESS)
153 ret = MLAN_STATUS_PENDING;
154
155 exit:
156 LEAVE();
157 return ret;
158 }
159
160 /**
161 * @brief Get statistics information
162 *
163 * @param pmadapter A pointer to mlan_adapter structure
164 * @param pioctl_req A pointer to ioctl request buffer
165 *
166 * @return MLAN_STATUS_PENDING --success, otherwise fail
167 */
wlan_get_info_stats(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)168 static mlan_status wlan_get_info_stats(pmlan_adapter pmadapter,
169 pmlan_ioctl_req pioctl_req)
170 {
171 pmlan_private pmpriv = MNULL;
172 mlan_status ret = MLAN_STATUS_SUCCESS;
173
174 ENTER();
175
176 if (pioctl_req != MNULL) {
177 pmpriv = pmadapter->priv[pioctl_req->bss_index];
178 } else {
179 PRINTM(MERROR, "MLAN IOCTL information is not present\n");
180 ret = MLAN_STATUS_FAILURE;
181 goto exit;
182 }
183
184 /* Check information buffer length of MLAN IOCTL */
185 if (pioctl_req->buf_len < sizeof(mlan_ds_get_stats)) {
186 PRINTM(MWARN,
187 "MLAN IOCTL information buffer length is too short.\n");
188 pioctl_req->data_read_written = 0;
189 pioctl_req->buf_len_needed = sizeof(mlan_ds_get_stats);
190 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
191 ret = MLAN_STATUS_RESOURCE;
192 goto exit;
193 }
194
195 /* Send request to firmware */
196 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_GET_LOG,
197 HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
198 MNULL);
199
200 if (ret == MLAN_STATUS_SUCCESS)
201 ret = MLAN_STATUS_PENDING;
202
203 exit:
204 LEAVE();
205 return ret;
206 }
207
208 /**
209 * @brief Get sta channel information
210 *
211 * @param pmadapter A pointer to mlan_adapter structure
212 * @param pioctl_req A pointer to ioctl request buffer
213 *
214 * @return MLAN_STATUS_PENDING --success, otherwise fail
215 */
wlan_bss_ioctl_get_chan_info(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)216 static mlan_status wlan_bss_ioctl_get_chan_info(pmlan_adapter pmadapter,
217 pmlan_ioctl_req pioctl_req)
218 {
219 pmlan_private pmpriv = MNULL;
220 mlan_status ret = MLAN_STATUS_SUCCESS;
221
222 ENTER();
223
224 if (pioctl_req != MNULL) {
225 pmpriv = pmadapter->priv[pioctl_req->bss_index];
226 } else {
227 PRINTM(MERROR, "MLAN IOCTL information is not present\n");
228 ret = MLAN_STATUS_FAILURE;
229 goto exit;
230 }
231
232 /* Check information buffer length of MLAN IOCTL */
233 if (pioctl_req->buf_len < sizeof(chan_band_info)) {
234 PRINTM(MWARN,
235 "MLAN IOCTL information buffer length is too short.\n");
236 pioctl_req->data_read_written = 0;
237 pioctl_req->buf_len_needed = sizeof(chan_band_info);
238 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
239 ret = MLAN_STATUS_RESOURCE;
240 goto exit;
241 }
242
243 /* Send request to firmware */
244 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_STA_CONFIGURE,
245 HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
246 MNULL);
247
248 if (ret == MLAN_STATUS_SUCCESS)
249 ret = MLAN_STATUS_PENDING;
250
251 exit:
252 LEAVE();
253 return ret;
254 }
255
256 /**
257 * @brief Get BSS information
258 *
259 * @param pmadapter A pointer to mlan_adapter structure
260 * @param pioctl_req A pointer to ioctl request buffer
261 *
262 * @return MLAN_STATUS_SUCCESS --success
263 */
wlan_get_info_bss_info(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)264 static mlan_status wlan_get_info_bss_info(pmlan_adapter pmadapter,
265 pmlan_ioctl_req pioctl_req)
266 {
267 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
268 mlan_status ret = MLAN_STATUS_SUCCESS;
269 mlan_ds_get_info *info;
270 BSSDescriptor_t *pbss_desc;
271 t_s32 tbl_idx = 0;
272
273 ENTER();
274
275 /* Get current BSS info */
276 pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
277 info = (mlan_ds_get_info *)pioctl_req->pbuf;
278
279 /* BSS mode */
280 info->param.bss_info.bss_mode = pmpriv->bss_mode;
281
282 /* SSID */
283 memcpy_ext(pmadapter, &info->param.bss_info.ssid, &pbss_desc->ssid,
284 sizeof(mlan_802_11_ssid), sizeof(mlan_802_11_ssid));
285
286 /* BSSID */
287 memcpy_ext(pmadapter, &info->param.bss_info.bssid,
288 &pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH,
289 MLAN_MAC_ADDR_LENGTH);
290
291 /* Channel */
292 info->param.bss_info.bss_chan = pbss_desc->channel;
293
294 /* Beacon interval */
295 info->param.bss_info.beacon_interval = pbss_desc->beacon_period;
296
297 /* Band */
298 info->param.bss_info.bss_band = pbss_desc->bss_band;
299
300 /* Region code */
301 info->param.bss_info.region_code = pmadapter->region_code;
302
303 /* Scan table index if connected */
304 info->param.bss_info.scan_table_idx = 0;
305 info->param.bss_info.scan_block = pmadapter->scan_block;
306 if (pmpriv->media_connected == MTRUE) {
307 tbl_idx = wlan_find_ssid_in_list(pmpriv, &pbss_desc->ssid,
308 pbss_desc->mac_address,
309 pmpriv->bss_mode);
310 if (tbl_idx >= 0)
311 info->param.bss_info.scan_table_idx = tbl_idx;
312 }
313
314 /* Connection status */
315 info->param.bss_info.media_connected = pmpriv->media_connected;
316
317 /* Radio status */
318 info->param.bss_info.radio_on = pmadapter->radio_on;
319
320 /* Tx power information */
321 info->param.bss_info.max_power_level = pmpriv->max_tx_power_level;
322 info->param.bss_info.min_power_level = pmpriv->min_tx_power_level;
323
324 /* AdHoc state */
325 info->param.bss_info.adhoc_state = pmpriv->adhoc_state;
326
327 /* Last beacon NF */
328 info->param.bss_info.bcn_nf_last = pmpriv->bcn_nf_last;
329
330 /* wep status */
331 if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled)
332 info->param.bss_info.wep_status = MTRUE;
333 else
334 info->param.bss_info.wep_status = MFALSE;
335
336 info->param.bss_info.is_hs_configured = pmadapter->is_hs_configured;
337 info->param.bss_info.is_deep_sleep = pmadapter->is_deep_sleep;
338
339 /* Capability Info */
340 info->param.bss_info.capability_info = 0;
341 memcpy_ext(pmadapter, &info->param.bss_info.capability_info,
342 &pbss_desc->cap_info,
343 sizeof(info->param.bss_info.capability_info),
344 sizeof(info->param.bss_info.capability_info));
345
346 memset(pmadapter, &info->param.bss_info.ext_cap, 0, sizeof(ExtCap_t));
347 if (pbss_desc->pext_cap) {
348 memcpy_ext(pmadapter, &info->param.bss_info.ext_cap,
349 (t_u8 *)pbss_desc->pext_cap +
350 sizeof(IEEEtypes_Header_t),
351 pbss_desc->pext_cap->ieee_hdr.len,
352 sizeof(info->param.bss_info.ext_cap));
353 }
354
355 /* Listen Interval */
356 info->param.bss_info.listen_interval = pmpriv->listen_interval;
357
358 /* Association ID */
359 info->param.bss_info.assoc_id =
360 (t_u16)((IEEEtypes_AssocRsp_t *)pmpriv->assoc_rsp_buf)->a_id;
361
362 /* AP/Peer supported rates */
363 memset(pmadapter, info->param.bss_info.peer_supp_rates, 0,
364 sizeof(info->param.bss_info.peer_supp_rates));
365 memcpy_ext(pmadapter, info->param.bss_info.peer_supp_rates,
366 pbss_desc->supported_rates,
367 sizeof(pbss_desc->supported_rates),
368 sizeof(info->param.bss_info.peer_supp_rates));
369 if (pbss_desc->pmd_ie) {
370 info->param.bss_info.mdid = pbss_desc->pmd_ie->mdid;
371 info->param.bss_info.ft_cap = pbss_desc->pmd_ie->ft_cap;
372 }
373 pioctl_req->data_read_written =
374 sizeof(mlan_bss_info) + MLAN_SUB_COMMAND_SIZE;
375
376 LEAVE();
377 return ret;
378 }
379
380 /**
381 * @brief Get information handler
382 *
383 * @param pmadapter A pointer to mlan_adapter structure
384 * @param pioctl_req A pointer to ioctl request buffer
385 *
386 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
387 */
wlan_get_info_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)388 static mlan_status wlan_get_info_ioctl(pmlan_adapter pmadapter,
389 pmlan_ioctl_req pioctl_req)
390 {
391 mlan_status status = MLAN_STATUS_SUCCESS;
392 mlan_ds_get_info *pget_info = MNULL;
393 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
394
395 ENTER();
396
397 pget_info = (mlan_ds_get_info *)pioctl_req->pbuf;
398
399 switch (pget_info->sub_command) {
400 case MLAN_OID_GET_STATS:
401 status = wlan_get_info_stats(pmadapter, pioctl_req);
402 break;
403 case MLAN_OID_GET_SIGNAL:
404 status = wlan_get_info_signal(pmadapter, pioctl_req);
405 break;
406 case MLAN_OID_GET_SIGNAL_EXT:
407 status = wlan_get_info_signal_ext(pmadapter, pioctl_req);
408 break;
409 case MLAN_OID_GET_FW_INFO:
410 pioctl_req->data_read_written =
411 sizeof(mlan_fw_info) + MLAN_SUB_COMMAND_SIZE;
412 pget_info->param.fw_info.fw_ver = pmadapter->fw_release_number;
413 pget_info->param.fw_info.hotfix_version =
414 pmadapter->fw_hotfix_ver;
415 pget_info->param.fw_info.tx_buf_size = pmadapter->tx_buf_size;
416
417 memcpy_ext(pmadapter, &pget_info->param.fw_info.mac_addr,
418 pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH,
419 MLAN_MAC_ADDR_LENGTH);
420 pget_info->param.fw_info.fw_bands = pmadapter->fw_bands;
421 pget_info->param.fw_info.region_code = pmadapter->region_code;
422 if (pmadapter->otp_region && pmadapter->otp_region->force_reg)
423 pget_info->param.fw_info.force_reg = MTRUE;
424 else
425 pget_info->param.fw_info.force_reg = MFALSE;
426 pget_info->param.fw_info.ecsa_enable = pmadapter->ecsa_enable;
427 pget_info->param.fw_info.getlog_enable =
428 pmadapter->getlog_enable;
429 pget_info->param.fw_info.hw_dev_mcs_support =
430 pmadapter->hw_dev_mcs_support;
431 pget_info->param.fw_info.hw_dot_11n_dev_cap =
432 pmadapter->hw_dot_11n_dev_cap;
433 pget_info->param.fw_info.usr_dev_mcs_support =
434 pmpriv->usr_dev_mcs_support;
435 if (IS_FW_SUPPORT_NO_80MHZ(pmadapter))
436 pget_info->param.fw_info.prohibit_80mhz = MTRUE;
437 else
438 pget_info->param.fw_info.prohibit_80mhz = MFALSE;
439 pget_info->param.fw_info.hw_dot_11ac_mcs_support =
440 pmadapter->hw_dot_11ac_mcs_support;
441 pget_info->param.fw_info.hw_dot_11ac_dev_cap =
442 pmadapter->hw_dot_11ac_dev_cap;
443 pget_info->param.fw_info.usr_dot_11ac_dev_cap_bg =
444 pmpriv->usr_dot_11ac_dev_cap_bg;
445 pget_info->param.fw_info.usr_dot_11ac_mcs_support =
446 pmpriv->usr_dot_11ac_mcs_support;
447 pget_info->param.fw_info.usr_dot_11ac_dev_cap_a =
448 pmpriv->usr_dot_11ac_dev_cap_a;
449 pget_info->param.fw_info.uuid_lo = pmadapter->uuid_lo;
450 pget_info->param.fw_info.uuid_hi = pmadapter->uuid_hi;
451 pget_info->param.fw_info.hw_hecap_len = pmadapter->hw_hecap_len;
452 pget_info->param.fw_info.hw_2g_hecap_len =
453 pmadapter->hw_2g_hecap_len;
454 memcpy_ext(pmadapter, pget_info->param.fw_info.hw_he_cap,
455 pmadapter->hw_he_cap, pmadapter->hw_hecap_len,
456 sizeof(pget_info->param.fw_info.hw_he_cap));
457 memcpy_ext(pmadapter, pget_info->param.fw_info.hw_2g_he_cap,
458 pmadapter->hw_2g_he_cap, pmadapter->hw_2g_hecap_len,
459 sizeof(pget_info->param.fw_info.hw_2g_he_cap));
460 pget_info->param.fw_info.fw_supplicant_support =
461 IS_FW_SUPPORT_SUPPLICANT(pmadapter) ? 0x01 : 0x00;
462 pget_info->param.fw_info.antinfo = pmadapter->antinfo;
463 pget_info->param.fw_info.max_ap_assoc_sta =
464 pmadapter->max_sta_conn;
465 pget_info->param.fw_info.fw_roaming_support =
466 (pmadapter->fw_cap_info & FW_ROAMING_SUPPORT) ? 0x01 :
467 0x00;
468 pget_info->param.fw_info.fw_beacon_prot =
469 IS_FW_SUPPORT_BEACON_PROT(pmadapter) ? 0x01 : 0x00;
470 break;
471 case MLAN_OID_GET_BSS_INFO:
472 status = wlan_get_info_bss_info(pmadapter, pioctl_req);
473 break;
474 case MLAN_OID_GET_DEBUG_INFO:
475 status = wlan_get_info_debug_info(pmadapter, pioctl_req);
476 break;
477 case MLAN_OID_GET_VER_EXT:
478 status = wlan_get_info_ver_ext(pmadapter, pioctl_req);
479 break;
480 case MLAN_OID_LINK_STATS:
481 status = wlan_ioctl_link_statistic(pmpriv, pioctl_req);
482 break;
483 default:
484 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
485 status = MLAN_STATUS_FAILURE;
486 break;
487 }
488
489 LEAVE();
490 return status;
491 }
492
493 /**
494 * @brief Set/Get SNMP MIB handler
495 *
496 * @param pmadapter A pointer to mlan_adapter structure
497 * @param pioctl_req A pointer to ioctl request buffer
498 *
499 * @return MLAN_STATUS_PENDING --success, otherwise fail
500 */
wlan_snmp_mib_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)501 static mlan_status wlan_snmp_mib_ioctl(pmlan_adapter pmadapter,
502 pmlan_ioctl_req pioctl_req)
503 {
504 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
505 mlan_status ret = MLAN_STATUS_SUCCESS;
506 t_u16 cmd_action = 0;
507 t_u16 cmd_oid = 0;
508 mlan_ds_snmp_mib *mib = MNULL;
509 t_u32 value = 0;
510
511 ENTER();
512
513 if (pioctl_req->buf_len < sizeof(mlan_ds_snmp_mib)) {
514 PRINTM(MWARN,
515 "MLAN IOCTL information buffer length is too short.\n");
516 pioctl_req->data_read_written = 0;
517 pioctl_req->buf_len_needed = sizeof(mlan_ds_snmp_mib);
518 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
519 ret = MLAN_STATUS_RESOURCE;
520 goto exit;
521 }
522
523 mib = (mlan_ds_snmp_mib *)pioctl_req->pbuf;
524 if (pioctl_req->action == MLAN_ACT_SET)
525 cmd_action = HostCmd_ACT_GEN_SET;
526 else
527 cmd_action = HostCmd_ACT_GEN_GET;
528
529 switch (mib->sub_command) {
530 case MLAN_OID_SNMP_MIB_RTS_THRESHOLD:
531 value = mib->param.rts_threshold;
532 cmd_oid = RtsThresh_i;
533 break;
534 case MLAN_OID_SNMP_MIB_FRAG_THRESHOLD:
535 value = mib->param.frag_threshold;
536 cmd_oid = FragThresh_i;
537 break;
538 case MLAN_OID_SNMP_MIB_RETRY_COUNT:
539 value = mib->param.retry_count;
540 cmd_oid = ShortRetryLim_i;
541 break;
542 case MLAN_OID_SNMP_MIB_DTIM_PERIOD:
543 value = mib->param.dtim_period;
544 cmd_oid = DtimPeriod_i;
545 break;
546 case MLAN_OID_SNMP_MIB_SIGNALEXT_ENABLE:
547 value = mib->param.signalext_enable;
548 cmd_oid = SignalextEnable_i;
549 break;
550 case MLAN_OID_SNMP_MIB_CHAN_TRACK:
551 if (!IS_FW_SUPPORT_CHAN_TRACK(pmadapter)) {
552 goto exit;
553 }
554 value = mib->param.chan_track;
555 cmd_oid = ChanTrackParam_i;
556 break;
557 }
558
559 /* Send request to firmware */
560 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB, cmd_action,
561 cmd_oid, (t_void *)pioctl_req, &value);
562
563 if (ret == MLAN_STATUS_SUCCESS)
564 ret = MLAN_STATUS_PENDING;
565
566 exit:
567 LEAVE();
568 return ret;
569 }
570
571 /**
572 * @brief Radio command handler
573 *
574 * @param pmadapter A pointer to mlan_adapter structure
575 * @param pioctl_req A pointer to ioctl request buffer
576 *
577 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
578 */
wlan_radio_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)579 static mlan_status wlan_radio_ioctl(pmlan_adapter pmadapter,
580 pmlan_ioctl_req pioctl_req)
581 {
582 mlan_status status = MLAN_STATUS_SUCCESS;
583 mlan_ds_radio_cfg *radio_cfg = MNULL;
584
585 ENTER();
586
587 if (pioctl_req->buf_len < sizeof(mlan_ds_radio_cfg)) {
588 PRINTM(MWARN,
589 "MLAN IOCTL information buffer length is too short.\n");
590 pioctl_req->data_read_written = 0;
591 pioctl_req->buf_len_needed = sizeof(mlan_ds_radio_cfg);
592 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
593 LEAVE();
594 return MLAN_STATUS_RESOURCE;
595 }
596 radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
597 switch (radio_cfg->sub_command) {
598 case MLAN_OID_RADIO_CTRL:
599 status = wlan_radio_ioctl_radio_ctl(pmadapter, pioctl_req);
600 break;
601 case MLAN_OID_BAND_CFG:
602 status = wlan_radio_ioctl_band_cfg(pmadapter, pioctl_req);
603 break;
604 case MLAN_OID_ANT_CFG:
605 status = wlan_radio_ioctl_ant_cfg(pmadapter, pioctl_req);
606 break;
607 case MLAN_OID_REMAIN_CHAN_CFG:
608 status =
609 wlan_radio_ioctl_remain_chan_cfg(pmadapter, pioctl_req);
610 break;
611 case MLAN_OID_MIMO_SWITCH:
612 status =
613 wlan_radio_ioctl_mimo_switch_cfg(pmadapter, pioctl_req);
614 break;
615 default:
616 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
617 status = MLAN_STATUS_FAILURE;
618 break;
619 }
620
621 LEAVE();
622 return status;
623 }
624
625 /**
626 * @brief Set/Get MAC address
627 *
628 * @param pmadapter A pointer to mlan_adapter structure
629 * @param pioctl_req A pointer to ioctl request buffer
630 *
631 * @return MLAN_STATUS_PENDING --success, otherwise fail
632 */
wlan_bss_ioctl_mac_address(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)633 static mlan_status wlan_bss_ioctl_mac_address(pmlan_adapter pmadapter,
634 pmlan_ioctl_req pioctl_req)
635 {
636 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
637 mlan_ds_bss *bss = MNULL;
638 t_u16 cmd_action;
639 mlan_status ret = MLAN_STATUS_SUCCESS;
640
641 ENTER();
642
643 bss = (mlan_ds_bss *)pioctl_req->pbuf;
644 if (pioctl_req->action == MLAN_ACT_GET) {
645 cmd_action = HostCmd_ACT_GEN_GET;
646 } else {
647 cmd_action = HostCmd_ACT_GEN_SET;
648 memcpy_ext(pmadapter, pmpriv->curr_addr, &bss->param.mac_addr,
649 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
650 }
651
652 /* Send request to firmware */
653 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_MAC_ADDRESS,
654 cmd_action, 0, (t_void *)pioctl_req, MNULL);
655 if (ret == MLAN_STATUS_SUCCESS)
656 ret = MLAN_STATUS_PENDING;
657
658 LEAVE();
659 return ret;
660 }
661
662 /**
663 * @brief Set multicast list
664 *
665 * @param pmadapter A pointer to mlan_adapter structure
666 * @param pioctl_req A pointer to ioctl request buffer
667 *
668 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
669 * otherwise fail
670 */
wlan_bss_ioctl_set_multicast_list(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)671 static mlan_status wlan_bss_ioctl_set_multicast_list(pmlan_adapter pmadapter,
672 pmlan_ioctl_req pioctl_req)
673 {
674 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
675 mlan_ds_bss *bss = MNULL;
676 mlan_status ret = MLAN_STATUS_SUCCESS;
677 t_u16 old_pkt_filter;
678
679 ENTER();
680
681 old_pkt_filter = pmpriv->curr_pkt_filter;
682 bss = (mlan_ds_bss *)pioctl_req->pbuf;
683 if (pioctl_req->action == MLAN_ACT_GET) {
684 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
685 ret = MLAN_STATUS_FAILURE;
686 goto exit;
687 }
688 pioctl_req->data_read_written =
689 sizeof(mlan_multicast_list) + MLAN_SUB_COMMAND_SIZE;
690 if (bss->param.multicast_list.mode == MLAN_PROMISC_MODE) {
691 PRINTM(MINFO, "Enable Promiscuous mode\n");
692 pmpriv->curr_pkt_filter |= HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
693 pmpriv->curr_pkt_filter &=
694 ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
695 } else {
696 /* Multicast */
697 pmpriv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
698 if (bss->param.multicast_list.mode == MLAN_ALL_MULTI_MODE) {
699 PRINTM(MINFO, "Enabling All Multicast!\n");
700 pmpriv->curr_pkt_filter |=
701 HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
702 } else {
703 pmpriv->curr_pkt_filter &=
704 ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
705 if (bss->param.multicast_list.num_multicast_addr) {
706 PRINTM(MINFO, "Set multicast list=%d\n",
707 bss->param.multicast_list
708 .num_multicast_addr);
709 /* Set multicast addresses to firmware */
710 if (old_pkt_filter == pmpriv->curr_pkt_filter) {
711 /* Send request to firmware */
712 ret = wlan_prepare_cmd(
713 pmpriv,
714 HostCmd_CMD_MAC_MULTICAST_ADR,
715 HostCmd_ACT_GEN_SET, 0,
716 (t_void *)pioctl_req,
717 &bss->param.multicast_list);
718 if (ret == MLAN_STATUS_SUCCESS)
719 ret = MLAN_STATUS_PENDING;
720 } else {
721 /* Send request to firmware */
722 ret = wlan_prepare_cmd(
723 pmpriv,
724 HostCmd_CMD_MAC_MULTICAST_ADR,
725 HostCmd_ACT_GEN_SET, 0, MNULL,
726 &bss->param.multicast_list);
727 }
728 if (ret)
729 goto exit;
730 }
731 }
732 }
733 PRINTM(MINFO, "old_pkt_filter=0x%x, curr_pkt_filter=0x%x\n",
734 old_pkt_filter, pmpriv->curr_pkt_filter);
735 if (old_pkt_filter != pmpriv->curr_pkt_filter) {
736 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
737 HostCmd_ACT_GEN_SET, 0,
738 (t_void *)pioctl_req,
739 &pmpriv->curr_pkt_filter);
740 if (ret == MLAN_STATUS_SUCCESS)
741 ret = MLAN_STATUS_PENDING;
742 }
743
744 exit:
745 LEAVE();
746 return ret;
747 }
748
749 /**
750 * @brief Get channel list
751 *
752 * @param pmadapter A pointer to mlan_adapter structure
753 * @param pioctl_req A pointer to ioctl request buffer
754 *
755 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
756 */
wlan_bss_ioctl_get_channel_list(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)757 static mlan_status wlan_bss_ioctl_get_channel_list(pmlan_adapter pmadapter,
758 pmlan_ioctl_req pioctl_req)
759 {
760 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
761 mlan_ds_bss *bss = MNULL;
762 mlan_status ret = MLAN_STATUS_SUCCESS;
763 chan_freq_power_t *cfp;
764 t_u32 i, j;
765
766 ENTER();
767
768 bss = (mlan_ds_bss *)pioctl_req->pbuf;
769 if (pioctl_req->action != MLAN_ACT_GET) {
770 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
771 LEAVE();
772 return MLAN_STATUS_FAILURE;
773 }
774 if ((wlan_11d_is_enabled(pmpriv) && pmpriv->media_connected == MTRUE) &&
775 ((pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) ||
776 (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS &&
777 pmpriv->adhoc_state != ADHOC_STARTED))) {
778 t_u8 chan_no;
779 t_u16 band;
780
781 parsed_region_chan_11d_t *parsed_region_chan = MNULL;
782 parsed_region_chan_11d_t region_chan;
783
784 BSSDescriptor_t *pbss_desc =
785 &pmpriv->curr_bss_params.bss_descriptor;
786
787 memset(pmadapter, ®ion_chan, 0,
788 sizeof(parsed_region_chan_11d_t));
789
790 /*If country IE is present in the associated AP then return the
791 channel list from country IE
792 else return it from the learning table*/
793
794 if (wlan_11d_parse_domain_info(
795 pmadapter, &pbss_desc->country_info,
796 pbss_desc->bss_band,
797 ®ion_chan) == MLAN_STATUS_SUCCESS) {
798 parsed_region_chan = ®ion_chan;
799 } else {
800 parsed_region_chan = &pmadapter->parsed_region_chan;
801 }
802
803 PRINTM(MINFO, "no_of_chan=%d\n",
804 parsed_region_chan->no_of_chan);
805
806 for (i = 0;
807 (bss->param.chanlist.num_of_chan < MLAN_MAX_CHANNEL_NUM) &&
808 (i < parsed_region_chan->no_of_chan);
809 i++) {
810 chan_no = parsed_region_chan->chan_pwr[i].chan;
811 band = parsed_region_chan->chan_pwr[i].band;
812 PRINTM(MINFO, "band=%d, chan_no=%d\n", band, chan_no);
813 bss->param.chanlist.cf[bss->param.chanlist.num_of_chan]
814 .channel = (t_u32)chan_no;
815 bss->param.chanlist.cf[bss->param.chanlist.num_of_chan]
816 .freq = (t_u32)wlan_11d_chan_2_freq(
817 pmadapter, chan_no, band);
818 bss->param.chanlist.num_of_chan++;
819 }
820 } else {
821 for (j = 0;
822 (bss->param.chanlist.num_of_chan < MLAN_MAX_CHANNEL_NUM) &&
823 (j < MAX_REGION_CHANNEL_NUM);
824 j++) {
825 cfp = pmadapter->region_channel[j].pcfp;
826 for (i = 0; (bss->param.chanlist.num_of_chan <
827 MLAN_MAX_CHANNEL_NUM) &&
828 pmadapter->region_channel[j].valid && cfp &&
829 (i < pmadapter->region_channel[j].num_cfp);
830 i++) {
831 bss->param.chanlist
832 .cf[bss->param.chanlist.num_of_chan]
833 .channel = (t_u32)cfp->channel;
834 bss->param.chanlist
835 .cf[bss->param.chanlist.num_of_chan]
836 .freq = (t_u32)cfp->freq;
837 bss->param.chanlist.num_of_chan++;
838 cfp++;
839 }
840 }
841 }
842
843 PRINTM(MINFO, "num of channel=%d\n", bss->param.chanlist.num_of_chan);
844
845 LEAVE();
846 return ret;
847 }
848
849 /** Highest channel used in 2.4GHz band */
850 #define MAX_CHANNEL_BAND_B (14)
851
852 /** Highest frequency used in 2.4GHz band */
853 #define MAX_FREQUENCY_BAND_B (2484)
854
855 /**
856 * @brief Set/Get BSS channel
857 *
858 * @param pmadapter A pointer to mlan_adapter structure
859 * @param pioctl_req A pointer to ioctl request buffer
860 *
861 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
862 */
wlan_bss_ioctl_channel(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)863 static mlan_status wlan_bss_ioctl_channel(pmlan_adapter pmadapter,
864 pmlan_ioctl_req pioctl_req)
865 {
866 mlan_private *pmpriv = MNULL;
867 mlan_ds_bss *bss = MNULL;
868 mlan_status ret = MLAN_STATUS_SUCCESS;
869 chan_freq_power_t *cfp = MNULL;
870 ENTER();
871
872 if ((pioctl_req == MNULL) || (pioctl_req->pbuf == MNULL)) {
873 PRINTM(MERROR, "Request buffer not found!\n");
874 LEAVE();
875 return MLAN_STATUS_FAILURE;
876 }
877 pmpriv = pmadapter->priv[pioctl_req->bss_index];
878 bss = (mlan_ds_bss *)pioctl_req->pbuf;
879 if (pioctl_req->action == MLAN_ACT_GET) {
880 cfp = wlan_find_cfp_by_band_and_channel(
881 pmadapter, pmpriv->curr_bss_params.band,
882 (t_u16)pmpriv->curr_bss_params.bss_descriptor.channel);
883 if (cfp) {
884 bss->param.bss_chan.channel = cfp->channel;
885 bss->param.bss_chan.freq = cfp->freq;
886 } else {
887 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
888 ret = MLAN_STATUS_FAILURE;
889 }
890 pioctl_req->data_read_written =
891 sizeof(chan_freq) + MLAN_SUB_COMMAND_SIZE;
892 LEAVE();
893 return ret;
894 }
895 if (!bss->param.bss_chan.channel && !bss->param.bss_chan.freq) {
896 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
897 LEAVE();
898 return MLAN_STATUS_FAILURE;
899 }
900 if (pmadapter->adhoc_start_band & BAND_A)
901 pmadapter->adhoc_start_band = BAND_G | BAND_B;
902 if (bss->param.bss_chan.channel) {
903 if (bss->param.bss_chan.channel <= MAX_CHANNEL_BAND_B)
904 cfp = wlan_find_cfp_by_band_and_channel(
905 pmadapter, BAND_B,
906 (t_u16)bss->param.bss_chan.channel);
907 if (!cfp) {
908 cfp = wlan_find_cfp_by_band_and_channel(
909 pmadapter, BAND_A,
910 (t_u16)bss->param.bss_chan.channel);
911 if (cfp) {
912 pmadapter->adhoc_start_band = BAND_A;
913 }
914 }
915 } else {
916 if (bss->param.bss_chan.freq <= MAX_FREQUENCY_BAND_B)
917 cfp = wlan_find_cfp_by_band_and_freq(
918 pmadapter, BAND_B, bss->param.bss_chan.freq);
919 if (!cfp) {
920 cfp = wlan_find_cfp_by_band_and_freq(
921 pmadapter, BAND_A, bss->param.bss_chan.freq);
922 if (cfp) {
923 pmadapter->adhoc_start_band = BAND_A;
924 }
925 }
926 }
927 if (!cfp || !cfp->channel) {
928 PRINTM(MERROR, "Invalid channel/freq\n");
929 if (pioctl_req)
930 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
931 LEAVE();
932 return MLAN_STATUS_FAILURE;
933 }
934 pmpriv->adhoc_channel = (t_u8)cfp->channel;
935 pmpriv->intf_state_11h.adhoc_auto_sel_chan = MFALSE;
936 bss->param.bss_chan.channel = cfp->channel;
937 bss->param.bss_chan.freq = cfp->freq;
938
939 LEAVE();
940 return ret;
941 }
942
943 /**
944 * @brief Set/Get BSS mode
945 *
946 * @param pmadapter A pointer to mlan_adapter structure
947 * @param pioctl_req A pointer to ioctl request buffer
948 *
949 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
950 * otherwise fail
951 */
wlan_bss_ioctl_mode(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)952 static mlan_status wlan_bss_ioctl_mode(pmlan_adapter pmadapter,
953 pmlan_ioctl_req pioctl_req)
954 {
955 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
956 mlan_ds_bss *bss = MNULL;
957 mlan_status ret = MLAN_STATUS_SUCCESS;
958 bss = (mlan_ds_bss *)pioctl_req->pbuf;
959
960 ENTER();
961
962 if (pioctl_req->action == MLAN_ACT_GET) {
963 bss->param.bss_mode = pmpriv->bss_mode;
964 pioctl_req->data_read_written =
965 sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
966 goto exit;
967 }
968
969 if ((pmpriv->bss_mode == bss->param.bss_mode) ||
970 (bss->param.bss_mode == MLAN_BSS_MODE_AUTO)) {
971 PRINTM(MINFO, "Already set to required mode! No change!\n");
972 pmpriv->bss_mode = bss->param.bss_mode;
973 goto exit;
974 }
975
976 if (pmpriv->bss_mode != MLAN_BSS_MODE_AUTO)
977 ret = wlan_disconnect(pmpriv, MNULL, MNULL);
978 else
979 ret = wlan_disconnect(pmpriv, pioctl_req, MNULL);
980
981 if (pmpriv->sec_info.authentication_mode != MLAN_AUTH_MODE_AUTO)
982 pmpriv->sec_info.authentication_mode = MLAN_AUTH_MODE_OPEN;
983 pmpriv->bss_mode = bss->param.bss_mode;
984 if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA)
985 pmpriv->port_ctrl_mode = MTRUE;
986 else
987 pmpriv->port_ctrl_mode = MFALSE;
988 if (pmpriv->bss_mode != MLAN_BSS_MODE_AUTO) {
989 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SET_BSS_MODE,
990 HostCmd_ACT_GEN_SET, 0,
991 (t_void *)pioctl_req, MNULL);
992 if (ret == MLAN_STATUS_SUCCESS)
993 ret = MLAN_STATUS_PENDING;
994 }
995 exit:
996 LEAVE();
997 return ret;
998 }
999
1000 /**
1001 * @brief Start BSS
1002 *
1003 * @param pmadapter A pointer to mlan_adapter structure
1004 * @param pioctl_req A pointer to ioctl request buffer
1005 *
1006 * @return MLAN_STATUS_PENDING --success, otherwise fail
1007 */
wlan_bss_ioctl_start(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1008 static mlan_status wlan_bss_ioctl_start(pmlan_adapter pmadapter,
1009 pmlan_ioctl_req pioctl_req)
1010 {
1011 mlan_status ret = MLAN_STATUS_SUCCESS;
1012 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1013 mlan_ds_bss *bss = (mlan_ds_bss *)pioctl_req->pbuf;
1014 t_s32 i = -1;
1015 t_u8 zero_mac[] = {0, 0, 0, 0, 0, 0};
1016
1017 ENTER();
1018
1019 if (pmadapter->enable_net_mon == CHANNEL_SPEC_SNIFFER_MODE) {
1020 PRINTM(MINFO,
1021 "Association is blocked in Channel Specified Network Monitor mode...\n");
1022 LEAVE();
1023 return MLAN_STATUS_FAILURE;
1024 }
1025 /* Before ASSOC REQ, If "port ctrl" mode is enabled,
1026 * move the port to CLOSED state */
1027 if (pmpriv->port_ctrl_mode == MTRUE) {
1028 PRINTM(MINFO, "bss_ioctl_start(): port_state=CLOSED\n");
1029 pmpriv->prior_port_status = pmpriv->port_open;
1030 pmpriv->port_open = MFALSE;
1031 }
1032 pmadapter->scan_block = MFALSE;
1033
1034 if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) {
1035 if (!bss->param.ssid_bssid.idx ||
1036 bss->param.ssid_bssid.idx > pmadapter->num_in_scan_table) {
1037 /* Search for the requested SSID in the scan table */
1038 if (bss->param.ssid_bssid.ssid.ssid_len) {
1039 if (memcmp(pmadapter,
1040 &bss->param.ssid_bssid.bssid,
1041 zero_mac, sizeof(zero_mac)))
1042 i = wlan_find_ssid_in_list(
1043 pmpriv,
1044 &bss->param.ssid_bssid.ssid,
1045 (t_u8 *)&bss->param.ssid_bssid
1046 .bssid,
1047 MLAN_BSS_MODE_INFRA);
1048 else
1049 i = wlan_find_ssid_in_list(
1050 pmpriv,
1051 &bss->param.ssid_bssid.ssid,
1052 MNULL, MLAN_BSS_MODE_INFRA);
1053 } else {
1054 i = wlan_find_bssid_in_list(
1055 pmpriv,
1056 (t_u8 *)&bss->param.ssid_bssid.bssid,
1057 MLAN_BSS_MODE_INFRA);
1058 }
1059 } else {
1060 /* use bsslist index number to assoicate */
1061 i = wlan_is_network_compatible(
1062 pmpriv, bss->param.ssid_bssid.idx - 1,
1063 pmpriv->bss_mode);
1064 }
1065 if (i >= 0) {
1066 /* block if upper-layer tries to reconnect before new
1067 * scan */
1068 if (wlan_11h_get_csa_closed_channel(pmpriv) ==
1069 (t_u8)pmadapter->pscan_table[i].channel) {
1070 PRINTM(MINFO,
1071 "Attempt to reconnect on csa_closed_chan(%d)\n",
1072 pmadapter->pscan_table[i].channel);
1073 pioctl_req->status_code =
1074 MLAN_ERROR_INVALID_PARAMETER;
1075 ret = MLAN_STATUS_FAILURE;
1076 goto start_ssid_done;
1077 }
1078 PRINTM(MINFO,
1079 "SSID found in scan list ... associating...\n");
1080 pmpriv->curr_bss_params.host_mlme =
1081 bss->param.ssid_bssid.host_mlme;
1082 memcpy_ext(pmpriv->adapter,
1083 &pmpriv->curr_bss_params.prev_bssid,
1084 &bss->param.ssid_bssid.prev_bssid,
1085 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
1086 /* Clear any past association response stored for
1087 * application retrieval */
1088 pmpriv->assoc_rsp_size = 0;
1089 pmpriv->curr_chan_flags =
1090 bss->param.ssid_bssid.channel_flags;
1091 if (IS_FW_SUPPORT_NO_80MHZ(pmadapter))
1092 pmpriv->curr_chan_flags |= CHAN_FLAGS_NO_80MHZ;
1093 ret = wlan_associate(pmpriv, pioctl_req,
1094 &pmadapter->pscan_table[i]);
1095 if (ret)
1096 goto start_ssid_done;
1097 } else { /* i >= 0 */
1098 PRINTM(MERROR,
1099 "SSID not found in scan list: ssid=%s, " MACSTR
1100 ", idx=%d\n",
1101 bss->param.ssid_bssid.ssid.ssid,
1102 MAC2STR(bss->param.ssid_bssid.bssid),
1103 (int)bss->param.ssid_bssid.idx);
1104 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1105 ret = MLAN_STATUS_FAILURE;
1106 goto start_ssid_done;
1107 }
1108 } else {
1109 /* Adhoc mode */
1110 /* If the requested SSID matches current SSID, return */
1111 if (bss->param.ssid_bssid.ssid.ssid_len &&
1112 (!wlan_ssid_cmp(pmadapter,
1113 &pmpriv->curr_bss_params.bss_descriptor.ssid,
1114 &bss->param.ssid_bssid.ssid))) {
1115 ret = MLAN_STATUS_SUCCESS;
1116 goto start_ssid_done;
1117 }
1118
1119 /* Exit Adhoc mode first */
1120 PRINTM(MINFO, "Sending Adhoc Stop\n");
1121 ret = wlan_disconnect(pmpriv, MNULL, MNULL);
1122 if (ret)
1123 goto start_ssid_done;
1124
1125 pmpriv->adhoc_is_link_sensed = MFALSE;
1126
1127 if (!bss->param.ssid_bssid.idx ||
1128 bss->param.ssid_bssid.idx > pmadapter->num_in_scan_table) {
1129 /* Search for the requested network in the scan table */
1130 if (bss->param.ssid_bssid.ssid.ssid_len) {
1131 i = wlan_find_ssid_in_list(
1132 pmpriv, &bss->param.ssid_bssid.ssid,
1133 MNULL, MLAN_BSS_MODE_IBSS);
1134 } else {
1135 i = wlan_find_bssid_in_list(
1136 pmpriv,
1137 (t_u8 *)&bss->param.ssid_bssid.bssid,
1138 MLAN_BSS_MODE_IBSS);
1139 }
1140 } else {
1141 /* use bsslist index number to assoicate */
1142 i = wlan_is_network_compatible(
1143 pmpriv, bss->param.ssid_bssid.idx - 1,
1144 pmpriv->bss_mode);
1145 }
1146
1147 if (i >= 0) {
1148 PRINTM(MINFO,
1149 "Network found in scan list ... joining ...\n");
1150 pmpriv->curr_chan_flags =
1151 bss->param.ssid_bssid.channel_flags;
1152 ret = wlan_adhoc_join(pmpriv, pioctl_req,
1153 &pmadapter->pscan_table[i]);
1154 if (ret)
1155 goto start_ssid_done;
1156 } else { /* i >= 0 */
1157 PRINTM(MINFO,
1158 "Network not found in the list, "
1159 "creating adhoc with ssid = %s\n",
1160 bss->param.ssid_bssid.ssid.ssid);
1161 pmpriv->curr_chan_flags =
1162 bss->param.ssid_bssid.channel_flags;
1163 ret = wlan_adhoc_start(pmpriv, pioctl_req,
1164 &bss->param.ssid_bssid.ssid);
1165 if (ret)
1166 goto start_ssid_done;
1167 }
1168 }
1169
1170 if (ret == MLAN_STATUS_SUCCESS)
1171 ret = MLAN_STATUS_PENDING;
1172
1173 start_ssid_done:
1174 LEAVE();
1175 return ret;
1176 }
1177
1178 /**
1179 * @brief Stop BSS
1180 *
1181 * @param pmadapter A pointer to mlan_adapter structure
1182 * @param pioctl_req A pointer to ioctl request buffer
1183 *
1184 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
1185 * otherwise fail
1186 */
wlan_bss_ioctl_stop(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1187 static mlan_status wlan_bss_ioctl_stop(pmlan_adapter pmadapter,
1188 pmlan_ioctl_req pioctl_req)
1189 {
1190 mlan_status ret = MLAN_STATUS_SUCCESS;
1191 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
1192 mlan_ds_bss *bss = (mlan_ds_bss *)pioctl_req->pbuf;
1193
1194 ENTER();
1195
1196 ret = wlan_disconnect(pmpriv, pioctl_req, &bss->param.deauth_param);
1197
1198 LEAVE();
1199 return ret;
1200 }
1201
1202 /**
1203 * @brief Set/Get IBSS channel
1204 *
1205 * @param pmadapter A pointer to mlan_adapter structure
1206 * @param pioctl_req A pointer to ioctl request buffer
1207 *
1208 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
1209 * otherwise fail
1210 */
wlan_bss_ioctl_ibss_channel(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1211 static mlan_status wlan_bss_ioctl_ibss_channel(pmlan_adapter pmadapter,
1212 pmlan_ioctl_req pioctl_req)
1213 {
1214 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1215 mlan_ds_bss *bss = MNULL;
1216 mlan_status ret = MLAN_STATUS_SUCCESS;
1217 t_u16 cmd_action;
1218
1219 ENTER();
1220
1221 bss = (mlan_ds_bss *)pioctl_req->pbuf;
1222 if (pioctl_req->action == MLAN_ACT_GET) {
1223 if (pmpriv->media_connected == MFALSE) {
1224 bss->param.bss_chan.channel = pmpriv->adhoc_channel;
1225 goto exit;
1226 }
1227 cmd_action = HostCmd_ACT_GEN_GET;
1228 } else {
1229 cmd_action = HostCmd_ACT_GEN_SET;
1230 pmpriv->adhoc_channel = (t_u8)bss->param.bss_chan.channel;
1231 pmpriv->intf_state_11h.adhoc_auto_sel_chan = MFALSE;
1232 }
1233
1234 /* Send request to firmware */
1235 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_RF_CHANNEL,
1236 cmd_action, 0, (t_void *)pioctl_req,
1237 &bss->param.bss_chan.channel);
1238 if (ret == MLAN_STATUS_SUCCESS)
1239 ret = MLAN_STATUS_PENDING;
1240
1241 exit:
1242 LEAVE();
1243 return ret;
1244 }
1245
1246 /**
1247 * @brief Set/Get Listen Interval
1248 *
1249 * @param pmadapter A pointer to mlan_adapter structure
1250 * @param pioctl_req A pointer to ioctl request buffer
1251 *
1252 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
1253 * otherwise fail
1254 */
wlan_bss_ioctl_listen_interval(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1255 static mlan_status wlan_bss_ioctl_listen_interval(pmlan_adapter pmadapter,
1256 pmlan_ioctl_req pioctl_req)
1257 {
1258 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1259 mlan_ds_bss *bss = MNULL;
1260
1261 ENTER();
1262
1263 bss = (mlan_ds_bss *)pioctl_req->pbuf;
1264 if (pioctl_req->action == MLAN_ACT_GET)
1265 bss->param.listen_interval = pmpriv->listen_interval;
1266 else
1267 pmpriv->listen_interval = bss->param.listen_interval;
1268
1269 LEAVE();
1270 return MLAN_STATUS_SUCCESS;
1271 }
1272
1273 /*
1274 * @brief Set/Get beacon interval
1275 *
1276 * @param pmadapter A pointer to mlan_adapter structure
1277 * @param pioctl_req A pointer to ioctl request buffer
1278 *
1279 * @return MLAN_STATUS_SUCCESS --success
1280 */
wlan_bss_ioctl_beacon_interval(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1281 static mlan_status wlan_bss_ioctl_beacon_interval(pmlan_adapter pmadapter,
1282 pmlan_ioctl_req pioctl_req)
1283 {
1284 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1285 mlan_ds_bss *bss = MNULL;
1286 mlan_status ret = MLAN_STATUS_SUCCESS;
1287 ENTER();
1288 bss = (mlan_ds_bss *)pioctl_req->pbuf;
1289 if (pioctl_req->action == MLAN_ACT_GET) {
1290 bss->param.bcn_interval = pmpriv->beacon_period;
1291 if (pmpriv->media_connected == MTRUE)
1292 bss->param.bcn_interval =
1293 pmpriv->curr_bss_params.bss_descriptor
1294 .beacon_period;
1295 } else
1296 pmpriv->beacon_period = (t_u16)bss->param.bcn_interval;
1297 pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
1298 LEAVE();
1299 return ret;
1300 }
1301
1302 /**
1303 * @brief Set/Get ATIM window
1304 *
1305 * @param pmadapter A pointer to mlan_adapter structure
1306 * @param pioctl_req A pointer to ioctl request buffer
1307 *
1308 * @return MLAN_STATUS_SUCCESS --success
1309 */
wlan_bss_ioctl_atim_window(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1310 static mlan_status wlan_bss_ioctl_atim_window(pmlan_adapter pmadapter,
1311 pmlan_ioctl_req pioctl_req)
1312 {
1313 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1314 mlan_ds_bss *bss = MNULL;
1315 mlan_status ret = MLAN_STATUS_SUCCESS;
1316 ENTER();
1317 bss = (mlan_ds_bss *)pioctl_req->pbuf;
1318 if (pioctl_req->action == MLAN_ACT_GET) {
1319 bss->param.atim_window = pmpriv->atim_window;
1320 if (pmpriv->media_connected == MTRUE)
1321 bss->param.atim_window =
1322 pmpriv->curr_bss_params.bss_descriptor
1323 .atim_window;
1324 } else
1325 pmpriv->atim_window = (t_u16)bss->param.atim_window;
1326
1327 pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
1328 LEAVE();
1329 return ret;
1330 }
1331
1332 /**
1333 * @brief Query embe
1334 *
1335 * @param priv A pointer to mlan_private structure
1336 * @param pioctl_req A pointer to ioctl request buffer
1337 *
1338 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
1339 */
wlan_query_passphrase(mlan_private * priv,pmlan_ioctl_req pioctl_req)1340 static mlan_status wlan_query_passphrase(mlan_private *priv,
1341 pmlan_ioctl_req pioctl_req)
1342 {
1343 mlan_adapter *pmadapter = priv->adapter;
1344 pmlan_callbacks pcb = &pmadapter->callbacks;
1345 mlan_ds_bss *bss = MNULL;
1346 mlan_ssid_bssid *ssid_bssid = MNULL;
1347 mlan_ds_sec_cfg *sec = MNULL;
1348 mlan_ds_passphrase *sec_pp;
1349 int i = 0;
1350 BSSDescriptor_t *pbss_desc;
1351 mlan_status ret = MLAN_STATUS_SUCCESS;
1352
1353 ENTER();
1354
1355 bss = (mlan_ds_bss *)pioctl_req->pbuf;
1356 ssid_bssid = &bss->param.ssid_bssid;
1357
1358 ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(mlan_ds_sec_cfg),
1359 MLAN_MEM_DEF, (t_u8 **)&sec);
1360 if (ret || !sec) {
1361 PRINTM(MERROR, "Could not allocate sec!\n");
1362 LEAVE();
1363 return ret;
1364 }
1365 memset(pmadapter, sec, 0, sizeof(mlan_ds_sec_cfg));
1366 sec_pp = (mlan_ds_passphrase *)&sec->param.passphrase;
1367 sec_pp->psk_type = MLAN_PSK_QUERY;
1368 if (ssid_bssid->ssid.ssid_len == 0) {
1369 i = wlan_find_bssid_in_list(priv, (t_u8 *)&ssid_bssid->bssid,
1370 MLAN_BSS_MODE_AUTO);
1371 if (i >= 0) {
1372 pbss_desc = &pmadapter->pscan_table[i];
1373 memcpy_ext(pmadapter, (t_u8 *)&sec_pp->ssid,
1374 &pbss_desc->ssid, sizeof(mlan_802_11_ssid),
1375 sizeof(mlan_802_11_ssid));
1376 } else
1377 memcpy_ext(pmadapter, (t_u8 *)&sec_pp->bssid,
1378 &ssid_bssid->bssid, MLAN_MAC_ADDR_LENGTH,
1379 MLAN_MAC_ADDR_LENGTH);
1380 } else {
1381 memcpy_ext(pmadapter, (t_u8 *)&sec_pp->ssid, &ssid_bssid->ssid,
1382 sizeof(mlan_802_11_ssid), sizeof(mlan_802_11_ssid));
1383 }
1384
1385 /* Send request to firmware */
1386 ret = wlan_prepare_cmd(priv, HostCmd_CMD_SUPPLICANT_PMK,
1387 HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
1388 (t_void *)sec);
1389 if (sec)
1390 pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)sec);
1391 LEAVE();
1392 return ret;
1393 }
1394
1395 /**
1396 * @brief Search for a BSS
1397 *
1398 * @param pmadapter A pointer to mlan_adapter structure
1399 * @param pioctl_req A pointer to ioctl request buffer
1400 *
1401 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
1402 * otherwise fail
1403 */
wlan_bss_ioctl_find_bss(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1404 static mlan_status wlan_bss_ioctl_find_bss(pmlan_adapter pmadapter,
1405 pmlan_ioctl_req pioctl_req)
1406 {
1407 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1408 mlan_status ret = MLAN_STATUS_SUCCESS;
1409 #ifdef DRV_EMBEDDED_SUPPLICANT
1410 mlan_ds_bss *bss = MNULL;
1411 mlan_ssid_bssid *ssid_bssid = MNULL;
1412 #endif
1413
1414 ENTER();
1415
1416 if (pmpriv->ewpa_query) {
1417 if (wlan_query_passphrase(pmpriv, pioctl_req) ==
1418 MLAN_STATUS_SUCCESS) {
1419 PRINTM(MINFO, "Find BSS ioctl: query passphrase\n");
1420 LEAVE();
1421 return MLAN_STATUS_PENDING;
1422 }
1423 }
1424 #ifdef DRV_EMBEDDED_SUPPLICANT
1425 if (!IS_FW_SUPPORT_SUPPLICANT(pmpriv->adapter)) {
1426 bss = (mlan_ds_bss *)pioctl_req->pbuf;
1427 ssid_bssid = &bss->param.ssid_bssid;
1428 supplicantQueryPassphraseAndEnable(pmpriv->psapriv,
1429 (t_u8 *)ssid_bssid);
1430 }
1431 #endif
1432
1433 ret = wlan_find_bss(pmpriv, pioctl_req);
1434
1435 LEAVE();
1436 return ret;
1437 }
1438
1439 /**
1440 * @brief Search for a BSS
1441 *
1442 * @param pmadapter A pointer to mlan_adapter structure
1443 * @param pioctl_req A pointer to ioctl request buffer
1444 *
1445 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
1446 * otherwise fail
1447 */
wlan_bss_ioctl_find_bssid(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1448 static mlan_status wlan_bss_ioctl_find_bssid(pmlan_adapter pmadapter,
1449 pmlan_ioctl_req pioctl_req)
1450 {
1451 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1452 mlan_ds_bss *bss = MNULL;
1453 mlan_status ret = MLAN_STATUS_SUCCESS;
1454 int i = 0;
1455
1456 ENTER();
1457 bss = (mlan_ds_bss *)pioctl_req->pbuf;
1458 i = wlan_find_bssid_in_list(pmpriv, (t_u8 *)&bss->param.bssid,
1459 MLAN_BSS_MODE_AUTO);
1460 if (i < 0) {
1461 PRINTM(MCMND, "Can not find bssid " MACSTR "\n",
1462 MAC2STR((t_u8 *)&bss->param.bssid));
1463 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1464 LEAVE();
1465 return MLAN_STATUS_FAILURE;
1466 }
1467 PRINTM(MCMND, "Find bssid " MACSTR "\n",
1468 MAC2STR((t_u8 *)&bss->param.bssid));
1469 LEAVE();
1470 return ret;
1471 }
1472
1473 /**
1474 * @brief Check if BSS channel is valid for Station's region
1475 *
1476 * @param pmadapter A pointer to mlan_adapter structure
1477 * @param pioctl_req A pointer to ioctl request buffer
1478 *
1479 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
1480 * otherwise fail
1481 */
1482 static mlan_status
wlan_bss_ioctl_bss_11d_check_channel(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1483 wlan_bss_ioctl_bss_11d_check_channel(pmlan_adapter pmadapter,
1484 pmlan_ioctl_req pioctl_req)
1485 {
1486 mlan_status ret = MLAN_STATUS_SUCCESS;
1487 mlan_ds_bss *bss = MNULL;
1488 mlan_ssid_bssid *ssid_bssid = MNULL;
1489
1490 ENTER();
1491
1492 bss = (mlan_ds_bss *)pioctl_req->pbuf;
1493 ssid_bssid = &bss->param.ssid_bssid;
1494
1495 PRINTM(MINFO, "ssid: %s idx:%d\n", ssid_bssid->ssid.ssid,
1496 ssid_bssid->idx);
1497 PRINTM(MINFO, "band:%d channel:%d\n", (t_u8)ssid_bssid->bss_band,
1498 (t_u32)ssid_bssid->channel);
1499
1500 /* check if this channel is supported in the region */
1501 if (!wlan_find_cfp_by_band_and_channel(pmadapter, ssid_bssid->bss_band,
1502 (t_u32)ssid_bssid->channel)) {
1503 PRINTM(MERROR, "Unsupported Channel for region 0x%x\n",
1504 pmadapter->region_code);
1505 ret = MLAN_STATUS_FAILURE;
1506 }
1507
1508 LEAVE();
1509 return ret;
1510 }
1511
1512 /**
1513 * @brief BSS command handler
1514 *
1515 * @param pmadapter A pointer to mlan_adapter structure
1516 * @param pioctl_req A pointer to ioctl request buffer
1517 *
1518 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
1519 */
wlan_bss_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1520 static mlan_status wlan_bss_ioctl(pmlan_adapter pmadapter,
1521 pmlan_ioctl_req pioctl_req)
1522 {
1523 mlan_status status = MLAN_STATUS_SUCCESS;
1524 mlan_ds_bss *bss = MNULL;
1525
1526 ENTER();
1527
1528 if (pioctl_req->buf_len < sizeof(mlan_ds_bss)) {
1529 PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
1530 pioctl_req->data_read_written = 0;
1531 pioctl_req->buf_len_needed = sizeof(mlan_ds_bss);
1532 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1533 LEAVE();
1534 return MLAN_STATUS_RESOURCE;
1535 }
1536
1537 bss = (mlan_ds_bss *)pioctl_req->pbuf;
1538
1539 switch (bss->sub_command) {
1540 case MLAN_OID_BSS_START:
1541 status = wlan_bss_ioctl_start(pmadapter, pioctl_req);
1542 break;
1543 case MLAN_OID_BSS_STOP:
1544 status = wlan_bss_ioctl_stop(pmadapter, pioctl_req);
1545 break;
1546 case MLAN_OID_BSS_MODE:
1547 status = wlan_bss_ioctl_mode(pmadapter, pioctl_req);
1548 break;
1549 case MLAN_OID_BSS_CHANNEL:
1550 status = wlan_bss_ioctl_channel(pmadapter, pioctl_req);
1551 break;
1552 case MLAN_OID_BSS_CHANNEL_LIST:
1553 status = wlan_bss_ioctl_get_channel_list(pmadapter, pioctl_req);
1554 break;
1555 case MLAN_OID_BSS_MAC_ADDR:
1556 status = wlan_bss_ioctl_mac_address(pmadapter, pioctl_req);
1557 break;
1558 case MLAN_OID_BSS_MULTICAST_LIST:
1559 status = wlan_bss_ioctl_set_multicast_list(pmadapter,
1560 pioctl_req);
1561 break;
1562 case MLAN_OID_BSS_FIND_BSS:
1563 status = wlan_bss_ioctl_find_bss(pmadapter, pioctl_req);
1564 break;
1565 case MLAN_OID_BSS_FIND_BSSID:
1566 status = wlan_bss_ioctl_find_bssid(pmadapter, pioctl_req);
1567 break;
1568 case MLAN_OID_IBSS_BCN_INTERVAL:
1569 status = wlan_bss_ioctl_beacon_interval(pmadapter, pioctl_req);
1570 break;
1571 case MLAN_OID_IBSS_ATIM_WINDOW:
1572 status = wlan_bss_ioctl_atim_window(pmadapter, pioctl_req);
1573 break;
1574 case MLAN_OID_IBSS_CHANNEL:
1575 status = wlan_bss_ioctl_ibss_channel(pmadapter, pioctl_req);
1576 break;
1577 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
1578 case MLAN_OID_BSS_ROLE:
1579 util_enqueue_list_tail(pmadapter->pmoal_handle,
1580 &pmadapter->ioctl_pending_q,
1581 (pmlan_linked_list)pioctl_req,
1582 pmadapter->callbacks.moal_spin_lock,
1583 pmadapter->callbacks.moal_spin_unlock);
1584 pmadapter->pending_ioctl = MTRUE;
1585 status = MLAN_STATUS_PENDING;
1586 break;
1587 #endif
1588 #ifdef WIFI_DIRECT_SUPPORT
1589 case MLAN_OID_WIFI_DIRECT_MODE:
1590 status = wlan_bss_ioctl_wifi_direct_mode(pmadapter, pioctl_req);
1591 break;
1592 #endif
1593 case MLAN_OID_BSS_LISTEN_INTERVAL:
1594 status = wlan_bss_ioctl_listen_interval(pmadapter, pioctl_req);
1595 break;
1596 case MLAN_OID_BSS_REMOVE:
1597 status = wlan_bss_ioctl_bss_remove(pmadapter, pioctl_req);
1598 break;
1599
1600 case MLAN_OID_BSS_11D_CHECK_CHANNEL:
1601 status = wlan_bss_ioctl_bss_11d_check_channel(pmadapter,
1602 pioctl_req);
1603 break;
1604 case MLAN_OID_BSS_CHAN_INFO:
1605 status = wlan_bss_ioctl_get_chan_info(pmadapter, pioctl_req);
1606 break;
1607 default:
1608 status = MLAN_STATUS_FAILURE;
1609 break;
1610 }
1611
1612 LEAVE();
1613 return status;
1614 }
1615
1616 /**
1617 * @brief Get supported rates
1618 *
1619 * @param pmadapter A pointer to mlan_adapter structure
1620 * @param pioctl_req A pointer to ioctl request buffer
1621 *
1622 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
1623 */
1624 static mlan_status
wlan_rate_ioctl_get_supported_rate(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1625 wlan_rate_ioctl_get_supported_rate(pmlan_adapter pmadapter,
1626 pmlan_ioctl_req pioctl_req)
1627 {
1628 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1629 mlan_ds_rate *rate = MNULL;
1630 mlan_status ret = MLAN_STATUS_SUCCESS;
1631
1632 ENTER();
1633 if (pioctl_req->action != MLAN_ACT_GET) {
1634 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
1635 LEAVE();
1636 return MLAN_STATUS_FAILURE;
1637 }
1638 rate = (mlan_ds_rate *)pioctl_req->pbuf;
1639 if (rate->param.rate_band_cfg.config_bands &&
1640 rate->param.rate_band_cfg.bss_mode)
1641 wlan_get_active_data_rates(
1642 pmpriv, rate->param.rate_band_cfg.bss_mode,
1643 rate->param.rate_band_cfg.config_bands,
1644 rate->param.rates);
1645 else
1646 wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode,
1647 (pmpriv->bss_mode ==
1648 MLAN_BSS_MODE_INFRA) ?
1649 pmpriv->config_bands :
1650 pmadapter->adhoc_start_band,
1651 rate->param.rates);
1652 pioctl_req->data_read_written =
1653 MLAN_SUPPORTED_RATES + MLAN_SUB_COMMAND_SIZE;
1654 LEAVE();
1655 return ret;
1656 }
1657
1658 /**
1659 * @brief Rate command handler
1660 *
1661 * @param pmadapter A pointer to mlan_adapter structure
1662 * @param pioctl_req A pointer to ioctl request buffer
1663 *
1664 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
1665 * otherwise fail
1666 */
wlan_rate_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1667 static mlan_status wlan_rate_ioctl(pmlan_adapter pmadapter,
1668 pmlan_ioctl_req pioctl_req)
1669 {
1670 mlan_status status = MLAN_STATUS_SUCCESS;
1671 mlan_ds_rate *rate = MNULL;
1672
1673 ENTER();
1674
1675 if (pioctl_req->buf_len < sizeof(mlan_ds_rate)) {
1676 PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
1677 pioctl_req->data_read_written = 0;
1678 pioctl_req->buf_len_needed = sizeof(mlan_ds_rate);
1679 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1680 LEAVE();
1681 return MLAN_STATUS_RESOURCE;
1682 }
1683 rate = (mlan_ds_rate *)pioctl_req->pbuf;
1684 switch (rate->sub_command) {
1685 case MLAN_OID_RATE_CFG:
1686 status = wlan_rate_ioctl_cfg(pmadapter, pioctl_req);
1687 break;
1688 case MLAN_OID_GET_DATA_RATE:
1689 status = wlan_rate_ioctl_get_data_rate(pmadapter, pioctl_req);
1690 break;
1691 case MLAN_OID_SUPPORTED_RATES:
1692 status = wlan_rate_ioctl_get_supported_rate(pmadapter,
1693 pioctl_req);
1694 break;
1695 default:
1696 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
1697 status = MLAN_STATUS_FAILURE;
1698 break;
1699 }
1700 LEAVE();
1701 return status;
1702 }
1703
1704 /**
1705 * @brief Get Tx power configuration
1706 *
1707 * @param pmadapter A pointer to mlan_adapter structure
1708 * @param cmd_no Firmware command number used to retrieve power values
1709 * @param pioctl_req A pointer to ioctl request buffer
1710 *
1711 * @return MLAN_STATUS_PENDING --success, otherwise fail
1712 */
wlan_power_ioctl_get_power(pmlan_adapter pmadapter,t_u16 cmd_no,pmlan_ioctl_req pioctl_req)1713 static mlan_status wlan_power_ioctl_get_power(pmlan_adapter pmadapter,
1714 t_u16 cmd_no,
1715 pmlan_ioctl_req pioctl_req)
1716 {
1717 mlan_status ret = MLAN_STATUS_SUCCESS;
1718 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1719
1720 ENTER();
1721
1722 /* Send request to firmware */
1723 ret = wlan_prepare_cmd(pmpriv, cmd_no, HostCmd_ACT_GEN_GET, 0,
1724 (t_void *)pioctl_req, MNULL);
1725
1726 if (ret == MLAN_STATUS_SUCCESS)
1727 ret = MLAN_STATUS_PENDING;
1728
1729 LEAVE();
1730 return ret;
1731 }
1732
1733 /**
1734 * @brief Set Tx power configuration
1735 *
1736 * @param pmadapter A pointer to mlan_adapter structure
1737 * @param pioctl_req A pointer to ioctl request buffer
1738 *
1739 * @return MLAN_STATUS_PENDING --success, otherwise fail
1740 */
wlan_power_ioctl_set_power(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1741 static mlan_status wlan_power_ioctl_set_power(pmlan_adapter pmadapter,
1742 pmlan_ioctl_req pioctl_req)
1743 {
1744 mlan_ds_power_cfg *power = MNULL;
1745 mlan_status ret = MLAN_STATUS_SUCCESS;
1746
1747 HostCmd_DS_TXPWR_CFG *txp_cfg = MNULL;
1748 MrvlTypes_Power_Group_t *pg_tlv = MNULL;
1749 Power_Group_t *pg = MNULL;
1750 pmlan_callbacks pcb = &pmadapter->callbacks;
1751 t_u8 *buf = MNULL;
1752 t_s8 dbm = 0;
1753 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1754
1755 ENTER();
1756
1757 power = (mlan_ds_power_cfg *)pioctl_req->pbuf;
1758 if (!power->param.power_cfg.is_power_auto) {
1759 dbm = (t_s8)power->param.power_cfg.power_level;
1760 if ((dbm < pmpriv->min_tx_power_level) ||
1761 (dbm > pmpriv->max_tx_power_level)) {
1762 PRINTM(MERROR,
1763 "The set txpower value %d dBm is out of range (%d dBm-%d dBm)!\n",
1764 dbm, pmpriv->min_tx_power_level,
1765 pmpriv->max_tx_power_level);
1766 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1767 ret = MLAN_STATUS_FAILURE;
1768 goto exit;
1769 }
1770 }
1771
1772 ret = pcb->moal_malloc(pmadapter->pmoal_handle,
1773 MRVDRV_SIZE_OF_CMD_BUFFER, MLAN_MEM_DEF, &buf);
1774 if (ret != MLAN_STATUS_SUCCESS || buf == MNULL) {
1775 PRINTM(MERROR,
1776 "ALLOC_CMD_BUF: Failed to allocate command buffer\n");
1777 pioctl_req->status_code = MLAN_ERROR_NO_MEM;
1778 ret = MLAN_STATUS_FAILURE;
1779 goto exit;
1780 }
1781 memset(pmadapter, buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
1782 txp_cfg = (HostCmd_DS_TXPWR_CFG *)buf;
1783 txp_cfg->action = HostCmd_ACT_GEN_SET;
1784 if (!power->param.power_cfg.is_power_auto) {
1785 txp_cfg->mode = 1;
1786 pg_tlv = (MrvlTypes_Power_Group_t
1787 *)(buf + sizeof(HostCmd_DS_TXPWR_CFG));
1788 pg_tlv->type = TLV_TYPE_POWER_GROUP;
1789 pg_tlv->length = 4 * sizeof(Power_Group_t);
1790 pg = (Power_Group_t *)(buf + sizeof(HostCmd_DS_TXPWR_CFG) +
1791 sizeof(MrvlTypes_Power_Group_t));
1792 /* Power group for modulation class HR/DSSS */
1793 pg->first_rate_code = 0x00;
1794 pg->last_rate_code = 0x03;
1795 pg->modulation_class = MOD_CLASS_HR_DSSS;
1796 pg->power_step = 0;
1797 pg->power_min = (t_s8)dbm;
1798 pg->power_max = (t_s8)dbm;
1799 pg++;
1800 /* Power group for modulation class OFDM */
1801 pg->first_rate_code = 0x00;
1802 pg->last_rate_code = 0x07;
1803 pg->modulation_class = MOD_CLASS_OFDM;
1804 pg->power_step = 0;
1805 pg->power_min = (t_s8)dbm;
1806 pg->power_max = (t_s8)dbm;
1807 pg++;
1808 /* Power group for modulation class HTBW20 */
1809 pg->first_rate_code = 0x00;
1810 pg->last_rate_code = 0x20;
1811 pg->modulation_class = MOD_CLASS_HT;
1812 pg->power_step = 0;
1813 pg->power_min = (t_s8)dbm;
1814 pg->power_max = (t_s8)dbm;
1815 pg->ht_bandwidth = HT_BW_20;
1816 pg++;
1817 /* Power group for modulation class HTBW40 */
1818 pg->first_rate_code = 0x00;
1819 pg->last_rate_code = 0x20;
1820 pg->modulation_class = MOD_CLASS_HT;
1821 pg->power_step = 0;
1822 pg->power_min = (t_s8)dbm;
1823 pg->power_max = (t_s8)dbm;
1824 pg->ht_bandwidth = HT_BW_40;
1825 }
1826
1827 /* Send request to firmware */
1828 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TXPWR_CFG,
1829 HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
1830 buf);
1831
1832 if (ret == MLAN_STATUS_SUCCESS)
1833 ret = MLAN_STATUS_PENDING;
1834
1835 if (buf)
1836 pcb->moal_mfree(pmadapter->pmoal_handle, buf);
1837
1838 exit:
1839 LEAVE();
1840 return ret;
1841 }
1842
1843 /**
1844 * @brief Set extended power configuration
1845 *
1846 * @param pmadapter A pointer to mlan_adapter structure
1847 * @param pioctl_req A pointer to ioctl request buffer
1848 *
1849 * @return MLAN_STATUS_PENDING --success, otherwise fail
1850 */
wlan_power_ioctl_set_power_ext(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1851 static mlan_status wlan_power_ioctl_set_power_ext(pmlan_adapter pmadapter,
1852 pmlan_ioctl_req pioctl_req)
1853 {
1854 mlan_status ret = MLAN_STATUS_SUCCESS;
1855 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1856 mlan_ds_power_cfg *power = MNULL;
1857 pmlan_callbacks pcb = &pmadapter->callbacks;
1858 t_u8 *buf = MNULL;
1859 HostCmd_DS_TXPWR_CFG *txp_cfg = MNULL;
1860 MrvlTypes_Power_Group_t *pg_tlv = MNULL;
1861 Power_Group_t *pg = MNULL;
1862 mlan_power_group *pwr_grp = MNULL;
1863
1864 ENTER();
1865
1866 power = (mlan_ds_power_cfg *)pioctl_req->pbuf;
1867 ret = pcb->moal_malloc(pmadapter->pmoal_handle,
1868 MRVDRV_SIZE_OF_CMD_BUFFER, MLAN_MEM_DEF, &buf);
1869 if (ret != MLAN_STATUS_SUCCESS || buf == MNULL) {
1870 PRINTM(MERROR,
1871 "ALLOC_CMD_BUF: Failed to allocate command buffer\n");
1872 pioctl_req->status_code = MLAN_ERROR_NO_MEM;
1873 ret = MLAN_STATUS_FAILURE;
1874 goto exit;
1875 }
1876 memset(pmadapter, buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
1877 txp_cfg = (HostCmd_DS_TXPWR_CFG *)buf;
1878 txp_cfg->action = HostCmd_ACT_GEN_SET;
1879 pwr_grp = &power->param.power_ext.power_group[0];
1880 if (pwr_grp->rate_format == TX_PWR_CFG_AUTO_CTRL_OFF)
1881 txp_cfg->mode = 0;
1882 else {
1883 txp_cfg->mode = 1;
1884
1885 pg_tlv = (MrvlTypes_Power_Group_t
1886 *)(buf + sizeof(HostCmd_DS_TXPWR_CFG));
1887 pg_tlv->type = TLV_TYPE_POWER_GROUP;
1888 pg_tlv->length = sizeof(Power_Group_t);
1889 pg = (Power_Group_t *)(buf + sizeof(HostCmd_DS_TXPWR_CFG) +
1890 sizeof(MrvlTypes_Power_Group_t));
1891 pg->ht_bandwidth = pwr_grp->bandwidth;
1892 pg->power_min = (t_s8)pwr_grp->power_min;
1893 pg->power_max = (t_s8)pwr_grp->power_max;
1894 pg->power_step = (t_s8)pwr_grp->power_step;
1895
1896 if (pwr_grp->rate_format == MLAN_RATE_FORMAT_LG) {
1897 if (pwr_grp->first_rate_ind <=
1898 MLAN_RATE_INDEX_HRDSSS3) {
1899 pg->modulation_class = MOD_CLASS_HR_DSSS;
1900 } else {
1901 pg->modulation_class = MOD_CLASS_OFDM;
1902 pwr_grp->first_rate_ind -=
1903 MLAN_RATE_INDEX_OFDM0;
1904 pwr_grp->last_rate_ind -= MLAN_RATE_INDEX_OFDM0;
1905 }
1906 pg->first_rate_code = (t_u8)pwr_grp->first_rate_ind;
1907 pg->last_rate_code = (t_u8)pwr_grp->last_rate_ind;
1908 } else if (pwr_grp->rate_format == MLAN_RATE_FORMAT_HT) {
1909 pg->modulation_class = MOD_CLASS_HT;
1910 pg->first_rate_code = (t_u8)pwr_grp->first_rate_ind;
1911 pg->last_rate_code = (t_u8)pwr_grp->last_rate_ind;
1912 } else if (pwr_grp->rate_format == MLAN_RATE_FORMAT_VHT) {
1913 pg->modulation_class = MOD_CLASS_VHT;
1914 pg->first_rate_code =
1915 (t_u8)((pwr_grp->first_rate_ind & 0xF) |
1916 ((pwr_grp->nss - 1) << 4));
1917 pg->last_rate_code =
1918 (t_u8)((pwr_grp->last_rate_ind & 0xF) |
1919 ((pwr_grp->nss - 1) << 4));
1920 } else {
1921 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1922 ret = MLAN_STATUS_FAILURE;
1923 }
1924 }
1925 if (ret == MLAN_STATUS_FAILURE) {
1926 if (buf)
1927 pcb->moal_mfree(pmadapter->pmoal_handle, buf);
1928 goto exit;
1929 }
1930
1931 /* Send request to firmware */
1932 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TXPWR_CFG,
1933 HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
1934 buf);
1935 if (ret == MLAN_STATUS_SUCCESS)
1936 ret = MLAN_STATUS_PENDING;
1937 if (buf)
1938 pcb->moal_mfree(pmadapter->pmoal_handle, buf);
1939
1940 exit:
1941 LEAVE();
1942 return ret;
1943 }
1944
1945 /**
1946 * @brief Power configuration command handler
1947 *
1948 * @param pmadapter A pointer to mlan_adapter structure
1949 * @param pioctl_req A pointer to ioctl request buffer
1950 *
1951 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
1952 */
wlan_power_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1953 static mlan_status wlan_power_ioctl(pmlan_adapter pmadapter,
1954 pmlan_ioctl_req pioctl_req)
1955 {
1956 mlan_status status = MLAN_STATUS_SUCCESS;
1957 mlan_ds_power_cfg *power = MNULL;
1958
1959 ENTER();
1960
1961 if (pioctl_req->buf_len < sizeof(mlan_ds_power_cfg)) {
1962 PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
1963 pioctl_req->data_read_written = 0;
1964 pioctl_req->buf_len_needed = sizeof(mlan_ds_power_cfg);
1965 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1966 LEAVE();
1967 return MLAN_STATUS_RESOURCE;
1968 }
1969 power = (mlan_ds_power_cfg *)pioctl_req->pbuf;
1970 switch (power->sub_command) {
1971 case MLAN_OID_POWER_CFG:
1972 if (pioctl_req->action == MLAN_ACT_GET)
1973 status = wlan_power_ioctl_get_power(
1974 pmadapter, HostCmd_CMD_TXPWR_CFG, pioctl_req);
1975 else
1976 status = wlan_power_ioctl_set_power(pmadapter,
1977 pioctl_req);
1978 break;
1979
1980 case MLAN_OID_POWER_CFG_EXT:
1981 if (pioctl_req->action == MLAN_ACT_GET)
1982 status = wlan_power_ioctl_get_power(
1983 pmadapter, HostCmd_CMD_TXPWR_CFG, pioctl_req);
1984 else
1985 status = wlan_power_ioctl_set_power_ext(pmadapter,
1986 pioctl_req);
1987 break;
1988 case MLAN_OID_POWER_LOW_POWER_MODE:
1989 status = wlan_power_ioctl_set_get_lpm(pmadapter, pioctl_req);
1990 break;
1991 default:
1992 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
1993 status = MLAN_STATUS_FAILURE;
1994 break;
1995 }
1996 LEAVE();
1997 return status;
1998 }
1999
2000 /**
2001 * @brief Set power save configurations
2002 *
2003 * @param pmadapter A pointer to mlan_adapter structure
2004 * @param pioctl_req A pointer to ioctl request buffer
2005 * @param ps_mode Power save mode
2006 *
2007 * @return MLAN_STATUS_PENDING --success, otherwise fail
2008 */
wlan_pm_ioctl_ps_mode(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req,t_u16 ps_mode)2009 static mlan_status wlan_pm_ioctl_ps_mode(pmlan_adapter pmadapter,
2010 pmlan_ioctl_req pioctl_req,
2011 t_u16 ps_mode)
2012 {
2013 mlan_status ret = MLAN_STATUS_SUCCESS;
2014 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2015 t_u16 sub_cmd;
2016
2017 ENTER();
2018
2019 if (pioctl_req->action == MLAN_ACT_SET) {
2020 sub_cmd = (pmadapter->ps_mode == Wlan802_11PowerModePSP) ?
2021 EN_AUTO_PS :
2022 DIS_AUTO_PS;
2023 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
2024 sub_cmd, BITMAP_STA_PS,
2025 (t_void *)pioctl_req, MNULL);
2026 if ((ret == MLAN_STATUS_SUCCESS) && (sub_cmd == DIS_AUTO_PS)) {
2027 ret = wlan_prepare_cmd(pmpriv,
2028 HostCmd_CMD_802_11_PS_MODE_ENH,
2029 GET_PS, 0, MNULL, MNULL);
2030 }
2031 } else {
2032 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
2033 GET_PS, 0, (t_void *)pioctl_req, MNULL);
2034 }
2035
2036 if (ret == MLAN_STATUS_SUCCESS)
2037 ret = MLAN_STATUS_PENDING;
2038
2039 LEAVE();
2040 return ret;
2041 }
2042
2043 /**
2044 * @brief Set/Get Inactivity timeout extend
2045 *
2046 * @param pmadapter A pointer to mlan_adapter structure
2047 * @param pioctl_req A pointer to ioctl request buffer
2048 *
2049 * @return MLAN_STATUS_PENDING --success, otherwise fail
2050 */
wlan_pm_ioctl_inactivity_timeout(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2051 static mlan_status wlan_pm_ioctl_inactivity_timeout(pmlan_adapter pmadapter,
2052 pmlan_ioctl_req pioctl_req)
2053 {
2054 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2055 mlan_ds_pm_cfg *pmcfg = MNULL;
2056 mlan_status ret = MLAN_STATUS_SUCCESS;
2057 t_u16 cmd_action = 0;
2058
2059 ENTER();
2060
2061 pmcfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
2062 cmd_action = HostCmd_ACT_GEN_GET;
2063 if (pioctl_req->action == MLAN_ACT_SET)
2064 cmd_action = HostCmd_ACT_GEN_SET;
2065
2066 /* Send request to firmware */
2067 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_INACTIVITY_TIMEOUT_EXT,
2068 cmd_action, 0, (t_void *)pioctl_req,
2069 (t_void *)&pmcfg->param.inactivity_to);
2070
2071 if (ret == MLAN_STATUS_SUCCESS)
2072 ret = MLAN_STATUS_PENDING;
2073
2074 LEAVE();
2075 return ret;
2076 }
2077
2078 /**
2079 * @brief Enable/Disable Auto Deep Sleep
2080 *
2081 * @param pmadapter A pointer to mlan_adapter structure
2082 * @param pioctl_req A pointer to ioctl request buffer
2083 *
2084 * @return MLAN_STATUS_PENDING --success, otherwise fail
2085 */
wlan_set_auto_deep_sleep(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2086 static mlan_status wlan_set_auto_deep_sleep(pmlan_adapter pmadapter,
2087 pmlan_ioctl_req pioctl_req)
2088 {
2089 mlan_status ret = MLAN_STATUS_SUCCESS;
2090 pmlan_private pmpriv =
2091 (pmlan_private)pmadapter->priv[pioctl_req->bss_index];
2092 mlan_ds_auto_ds auto_ds;
2093 t_u32 mode;
2094
2095 ENTER();
2096
2097 if (((mlan_ds_pm_cfg *)pioctl_req->pbuf)
2098 ->param.auto_deep_sleep.auto_ds == DEEP_SLEEP_ON) {
2099 auto_ds.auto_ds = DEEP_SLEEP_ON;
2100 PRINTM(MINFO, "Auto Deep Sleep: on\n");
2101 mode = EN_AUTO_PS;
2102 } else {
2103 auto_ds.auto_ds = DEEP_SLEEP_OFF;
2104 PRINTM(MINFO, "Auto Deep Sleep: off\n");
2105 mode = DIS_AUTO_PS;
2106 }
2107 if (((mlan_ds_pm_cfg *)pioctl_req->pbuf)->param.auto_deep_sleep.idletime)
2108 auto_ds.idletime = ((mlan_ds_pm_cfg *)pioctl_req->pbuf)
2109 ->param.auto_deep_sleep.idletime;
2110 else
2111 auto_ds.idletime = pmadapter->idle_time;
2112 /* note: the command could be queued and executed
2113 later if there is command in progress. */
2114 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
2115 (t_u16)mode, BITMAP_AUTO_DS,
2116 (t_void *)pioctl_req, &auto_ds);
2117 if (ret) {
2118 LEAVE();
2119 return ret;
2120 }
2121 ret = MLAN_STATUS_PENDING;
2122 LEAVE();
2123 return ret;
2124 }
2125
2126 /**
2127 * @brief Set/Get sleep period
2128 *
2129 * @param pmadapter A pointer to mlan_adapter structure
2130 * @param pioctl_req A pointer to ioctl request buffer
2131 *
2132 * @return MLAN_STATUS_PENDING --success, otherwise fail
2133 */
wlan_set_get_sleep_pd(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2134 static mlan_status wlan_set_get_sleep_pd(pmlan_adapter pmadapter,
2135 pmlan_ioctl_req pioctl_req)
2136 {
2137 mlan_status ret = MLAN_STATUS_SUCCESS;
2138 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
2139 mlan_ds_pm_cfg *pm_cfg = MNULL;
2140 t_u16 cmd_action = 0, sleep_pd = 0;
2141
2142 ENTER();
2143
2144 pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
2145 cmd_action = HostCmd_ACT_GEN_GET;
2146 if (pioctl_req->action == MLAN_ACT_SET) {
2147 cmd_action = HostCmd_ACT_GEN_SET;
2148 sleep_pd = (t_u16)pm_cfg->param.sleep_period;
2149 }
2150
2151 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SLEEP_PERIOD,
2152 cmd_action, 0, (t_void *)pioctl_req, &sleep_pd);
2153
2154 if (ret == MLAN_STATUS_SUCCESS)
2155 ret = MLAN_STATUS_PENDING;
2156
2157 LEAVE();
2158 return ret;
2159 }
2160
2161 /**
2162 * @brief Set/Get PS configuration parameter
2163 *
2164 * @param pmadapter A pointer to mlan_adapter structure
2165 * @param pioctl_req A pointer to ioctl request buffer
2166 *
2167 * @return MLAN_STATUS_SUCCESS --success
2168 */
wlan_set_get_ps_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2169 static mlan_status wlan_set_get_ps_cfg(pmlan_adapter pmadapter,
2170 pmlan_ioctl_req pioctl_req)
2171 {
2172 mlan_ds_pm_cfg *pm_cfg = MNULL;
2173
2174 ENTER();
2175
2176 pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
2177 if (pioctl_req->action == MLAN_ACT_GET) {
2178 pm_cfg->param.ps_cfg.ps_null_interval =
2179 (t_u32)pmadapter->null_pkt_interval;
2180 pm_cfg->param.ps_cfg.multiple_dtim_interval =
2181 (t_u32)pmadapter->multiple_dtim;
2182 pm_cfg->param.ps_cfg.listen_interval =
2183 (t_u32)pmadapter->local_listen_interval;
2184 pm_cfg->param.ps_cfg.bcn_miss_timeout =
2185 (t_u32)pmadapter->bcn_miss_time_out;
2186 pm_cfg->param.ps_cfg.delay_to_ps =
2187 (t_u32)pmadapter->delay_to_ps;
2188 pm_cfg->param.ps_cfg.ps_mode =
2189 (t_u32)pmadapter->enhanced_ps_mode;
2190 } else {
2191 if (pm_cfg->param.ps_cfg.ps_null_interval)
2192 pmadapter->null_pkt_interval =
2193 (t_u16)pm_cfg->param.ps_cfg.ps_null_interval;
2194 else
2195 pm_cfg->param.ps_cfg.ps_null_interval =
2196 (t_u32)pmadapter->null_pkt_interval;
2197 if (pm_cfg->param.ps_cfg.multiple_dtim_interval)
2198 pmadapter->multiple_dtim =
2199 (t_u16)pm_cfg->param.ps_cfg
2200 .multiple_dtim_interval;
2201 else
2202 pm_cfg->param.ps_cfg.multiple_dtim_interval =
2203 (t_u32)pmadapter->multiple_dtim;
2204 if (((t_s32)pm_cfg->param.ps_cfg.listen_interval) ==
2205 MRVDRV_LISTEN_INTERVAL_DISABLE)
2206 pmadapter->local_listen_interval = 0;
2207 else if (pm_cfg->param.ps_cfg.listen_interval)
2208 pmadapter->local_listen_interval =
2209 (t_u16)pm_cfg->param.ps_cfg.listen_interval;
2210 else
2211 pm_cfg->param.ps_cfg.listen_interval =
2212 (t_u32)pmadapter->local_listen_interval;
2213 if (pm_cfg->param.ps_cfg.bcn_miss_timeout)
2214 pmadapter->bcn_miss_time_out =
2215 (t_u16)pm_cfg->param.ps_cfg.bcn_miss_timeout;
2216 else
2217 pm_cfg->param.ps_cfg.bcn_miss_timeout =
2218 (t_u32)pmadapter->bcn_miss_time_out;
2219 if (pm_cfg->param.ps_cfg.delay_to_ps != DELAY_TO_PS_UNCHANGED)
2220 pmadapter->delay_to_ps =
2221 (t_u16)pm_cfg->param.ps_cfg.delay_to_ps;
2222 else
2223 pm_cfg->param.ps_cfg.delay_to_ps =
2224 (t_u32)pmadapter->delay_to_ps;
2225 if (pm_cfg->param.ps_cfg.ps_mode)
2226 pmadapter->enhanced_ps_mode =
2227 (t_u16)pm_cfg->param.ps_cfg.ps_mode;
2228 else
2229 pm_cfg->param.ps_cfg.ps_mode =
2230 (t_u32)pmadapter->enhanced_ps_mode;
2231 }
2232 pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
2233
2234 LEAVE();
2235 return MLAN_STATUS_SUCCESS;
2236 }
2237
2238 /**
2239 * @brief Set/Get PS configuration parameter
2240 *
2241 * @param pmadapter A pointer to mlan_adapter structure
2242 * @param pioctl_req A pointer to ioctl request buffer
2243 *
2244 * @return MLAN_STATUS_SUCCESS --success
2245 */
wlan_set_get_bcn_timeout(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2246 static mlan_status wlan_set_get_bcn_timeout(pmlan_adapter pmadapter,
2247 pmlan_ioctl_req pioctl_req)
2248 {
2249 mlan_status ret = MLAN_STATUS_SUCCESS;
2250 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2251 mlan_ds_pm_cfg *pm_cfg = MNULL;
2252
2253 ENTER();
2254
2255 pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
2256
2257 /* Send command to firmware */
2258 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
2259 EN_AUTO_PS, BITMAP_BCN_TMO, (t_void *)pioctl_req,
2260 &pm_cfg->param.bcn_timeout);
2261
2262 if (ret == MLAN_STATUS_SUCCESS)
2263 ret = MLAN_STATUS_PENDING;
2264
2265 LEAVE();
2266 return ret;
2267 }
2268
2269 /**
2270 * @brief Get/Set the sleep parameters
2271 *
2272 * @param pmadapter A pointer to mlan_adapter structure
2273 * @param pioctl_req A pointer to ioctl request buffer
2274 *
2275 * @return MLAN_STATUS_PENDING --success, otherwise fail
2276 */
wlan_set_get_sleep_params(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2277 static mlan_status wlan_set_get_sleep_params(pmlan_adapter pmadapter,
2278 pmlan_ioctl_req pioctl_req)
2279 {
2280 mlan_status ret = MLAN_STATUS_SUCCESS;
2281 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2282 mlan_ds_pm_cfg *pm_cfg = MNULL;
2283 t_u16 cmd_action = 0;
2284
2285 ENTER();
2286
2287 pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
2288 cmd_action = HostCmd_ACT_GEN_GET;
2289 if (pioctl_req->action == MLAN_ACT_SET)
2290 cmd_action = HostCmd_ACT_GEN_SET;
2291
2292 /* Send command to firmware */
2293 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SLEEP_PARAMS,
2294 cmd_action, 0, (t_void *)pioctl_req,
2295 &pm_cfg->param.sleep_params);
2296
2297 if (ret == MLAN_STATUS_SUCCESS)
2298 ret = MLAN_STATUS_PENDING;
2299
2300 LEAVE();
2301 return ret;
2302 }
2303
2304 /**
2305 * @brief config management frame wakeup filter
2306 *
2307 * @param pmadapter A pointer to mlan_adapter structure
2308 * @param pioctl_req A pointer to ioctl request buffer
2309 *
2310 * @return MLAN_STATUS_PENDING --success, otherwise fail
2311 */
wlan_config_mgmt_filter(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2312 mlan_status wlan_config_mgmt_filter(pmlan_adapter pmadapter,
2313 pmlan_ioctl_req pioctl_req)
2314 {
2315 mlan_status ret = MLAN_STATUS_SUCCESS;
2316 mlan_ds_pm_cfg *pm_cfg = MNULL;
2317 int i = 0;
2318
2319 ENTER();
2320
2321 memset(pmadapter, pmadapter->mgmt_filter, 0,
2322 sizeof(mlan_mgmt_frame_wakeup) * MAX_MGMT_FRAME_FILTER);
2323 pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
2324 if (pioctl_req->action == MLAN_ACT_SET) {
2325 for (i = 0; i < MAX_MGMT_FRAME_FILTER; i++)
2326 if (!pm_cfg->param.mgmt_filter[i].type)
2327 break;
2328 memcpy_ext(pmadapter, (t_u8 *)pmadapter->mgmt_filter,
2329 (t_u8 *)pm_cfg->param.mgmt_filter,
2330 (i + 1) * sizeof(mlan_mgmt_frame_wakeup),
2331 sizeof(pmadapter->mgmt_filter));
2332 } else if (pioctl_req->action == MLAN_ACT_GET)
2333 PRINTM(MERROR, "Get not support\n");
2334 LEAVE();
2335 return ret;
2336 }
2337
2338 /**
2339 * @brief Power save command handler
2340 *
2341 * @param pmadapter A pointer to mlan_adapter structure
2342 * @param pioctl_req A pointer to ioctl request buffer
2343 *
2344 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
2345 */
wlan_pm_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2346 static mlan_status wlan_pm_ioctl(pmlan_adapter pmadapter,
2347 pmlan_ioctl_req pioctl_req)
2348 {
2349 mlan_status status = MLAN_STATUS_SUCCESS;
2350 mlan_ds_pm_cfg *pm = MNULL;
2351
2352 ENTER();
2353
2354 if (pioctl_req->buf_len < sizeof(mlan_ds_pm_cfg)) {
2355 PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
2356 pioctl_req->data_read_written = 0;
2357 pioctl_req->buf_len_needed = sizeof(mlan_ds_pm_cfg);
2358 LEAVE();
2359 return MLAN_STATUS_RESOURCE;
2360 }
2361 pm = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
2362 switch (pm->sub_command) {
2363 case MLAN_OID_PM_CFG_IEEE_PS:
2364 switch (pioctl_req->action) {
2365 case MLAN_ACT_SET:
2366 /**Block ieee power save disable command when bt coex
2367 * enable*/
2368 if (pmadapter->coex_scan && !pm->param.ps_mode)
2369 break;
2370 if (pm->param.ps_mode)
2371 pmadapter->ps_mode = Wlan802_11PowerModePSP;
2372 else
2373 pmadapter->ps_mode = Wlan802_11PowerModeCAM;
2374 status = wlan_pm_ioctl_ps_mode(pmadapter, pioctl_req,
2375 pmadapter->ps_mode);
2376 break;
2377 case MLAN_ACT_GET:
2378 status = wlan_pm_ioctl_ps_mode(pmadapter, pioctl_req,
2379 pmadapter->ps_mode);
2380 break;
2381 default:
2382 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
2383 status = MLAN_STATUS_FAILURE;
2384 break;
2385 }
2386 break;
2387 case MLAN_OID_PM_CFG_HS_CFG:
2388 status = wlan_pm_ioctl_hscfg(pmadapter, pioctl_req);
2389 break;
2390 case MLAN_OID_PM_CFG_INACTIVITY_TO:
2391 status =
2392 wlan_pm_ioctl_inactivity_timeout(pmadapter, pioctl_req);
2393 break;
2394 case MLAN_OID_PM_CFG_DEEP_SLEEP:
2395 switch (pioctl_req->action) {
2396 case MLAN_ACT_SET:
2397 if (pmadapter->is_deep_sleep &&
2398 pm->param.auto_deep_sleep.auto_ds ==
2399 DEEP_SLEEP_ON) {
2400 PRINTM(MMSG,
2401 "Station already in enhanced deep sleep mode\n");
2402 status = MLAN_STATUS_FAILURE;
2403 break;
2404 } else if (!pmadapter->is_deep_sleep &&
2405 pm->param.auto_deep_sleep.auto_ds ==
2406 DEEP_SLEEP_OFF) {
2407 PRINTM(MMSG,
2408 "Station already not in enhanced deep sleep mode\n");
2409 status = MLAN_STATUS_FAILURE;
2410 break;
2411 }
2412 status =
2413 wlan_set_auto_deep_sleep(pmadapter, pioctl_req);
2414 break;
2415 case MLAN_ACT_GET:
2416 if (pmadapter->is_deep_sleep) {
2417 pm->param.auto_deep_sleep.auto_ds =
2418 DEEP_SLEEP_ON;
2419 pm->param.auto_deep_sleep.idletime =
2420 pmadapter->idle_time;
2421 } else
2422 pm->param.auto_deep_sleep.auto_ds =
2423 DEEP_SLEEP_OFF;
2424 break;
2425 default:
2426 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
2427 status = MLAN_STATUS_FAILURE;
2428 break;
2429 }
2430 break;
2431 case MLAN_OID_PM_CFG_PS_CFG:
2432 status = wlan_set_get_ps_cfg(pmadapter, pioctl_req);
2433 break;
2434 case MLAN_OID_PM_CFG_SLEEP_PD:
2435 status = wlan_set_get_sleep_pd(pmadapter, pioctl_req);
2436 break;
2437 case MLAN_OID_PM_CFG_SLEEP_PARAMS:
2438 status = wlan_set_get_sleep_params(pmadapter, pioctl_req);
2439 break;
2440 case MLAN_OID_PM_INFO:
2441 status = wlan_get_pm_info(pmadapter, pioctl_req);
2442 break;
2443 case MLAN_OID_PM_HS_WAKEUP_REASON:
2444 status = wlan_get_hs_wakeup_reason(pmadapter, pioctl_req);
2445 break;
2446 case MLAN_OID_PM_MGMT_FILTER:
2447 status = wlan_config_mgmt_filter(pmadapter, pioctl_req);
2448 break;
2449 case MLAN_OID_PM_CFG_BCN_TIMEOUT:
2450 status = wlan_set_get_bcn_timeout(pmadapter, pioctl_req);
2451 break;
2452 default:
2453 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
2454 status = MLAN_STATUS_FAILURE;
2455 break;
2456 }
2457 LEAVE();
2458 return status;
2459 }
2460
2461 /**
2462 * @brief Set/Get WPA IE
2463 *
2464 * @param priv A pointer to mlan_private structure
2465 * @param ie_data_ptr A pointer to IE
2466 * @param ie_len Length of the IE
2467 *
2468 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
2469 */
wlan_set_wpa_ie_helper(mlan_private * priv,t_u8 * ie_data_ptr,t_u16 ie_len)2470 static mlan_status wlan_set_wpa_ie_helper(mlan_private *priv, t_u8 *ie_data_ptr,
2471 t_u16 ie_len)
2472 {
2473 ENTER();
2474
2475 if (ie_len) {
2476 if (ie_len > sizeof(priv->wpa_ie)) {
2477 PRINTM(MERROR, "failed to copy, WPA IE is too big\n");
2478 LEAVE();
2479 return MLAN_STATUS_FAILURE;
2480 }
2481 memcpy_ext(priv->adapter, priv->wpa_ie, ie_data_ptr, ie_len,
2482 sizeof(priv->wpa_ie));
2483 priv->wpa_ie_len = (t_u8)ie_len;
2484 PRINTM(MIOCTL, "Set Wpa_ie_len=%d IE=%#x\n", priv->wpa_ie_len,
2485 priv->wpa_ie[0]);
2486 DBG_HEXDUMP(MCMD_D, "Wpa_ie", priv->wpa_ie, priv->wpa_ie_len);
2487 if (priv->wpa_ie[0] == WPA_IE) {
2488 priv->sec_info.wpa_enabled = MTRUE;
2489 } else if (priv->wpa_ie[0] == RSN_IE) {
2490 priv->sec_info.wpa2_enabled = MTRUE;
2491 } else {
2492 priv->sec_info.wpa_enabled = MFALSE;
2493 priv->sec_info.wpa2_enabled = MFALSE;
2494 }
2495 } else {
2496 memset(priv->adapter, priv->wpa_ie, 0, sizeof(priv->wpa_ie));
2497 priv->wpa_ie_len = 0;
2498 PRINTM(MINFO, "Reset Wpa_ie_len=%d IE=%#x\n", priv->wpa_ie_len,
2499 priv->wpa_ie[0]);
2500 priv->sec_info.wpa_enabled = MFALSE;
2501 priv->sec_info.wpa2_enabled = MFALSE;
2502 }
2503
2504 LEAVE();
2505 return MLAN_STATUS_SUCCESS;
2506 }
2507
2508 /**
2509 * @brief Set OSEN IE
2510 *
2511 * @param priv A pointer to mlan_private structure
2512 * @param ie_data_ptr A pointer to IE
2513 * @param ie_len Length of the IE
2514 *
2515 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
2516 */
wlan_set_osen_ie(mlan_private * priv,t_u8 * ie_data_ptr,t_u16 ie_len)2517 static mlan_status wlan_set_osen_ie(mlan_private *priv, t_u8 *ie_data_ptr,
2518 t_u16 ie_len)
2519 {
2520 ENTER();
2521 if (ie_len) {
2522 if (ie_len > sizeof(priv->osen_ie)) {
2523 PRINTM(MWARN, "failed to copy, WAPI IE is too big\n");
2524 LEAVE();
2525 return MLAN_STATUS_FAILURE;
2526 }
2527 memcpy_ext(priv->adapter, priv->osen_ie, ie_data_ptr, ie_len,
2528 sizeof(priv->osen_ie));
2529 priv->osen_ie_len = (t_u8)ie_len;
2530 PRINTM(MIOCTL, "Set osen_ie_len=%d IE=%#x\n", priv->osen_ie_len,
2531 priv->osen_ie[0]);
2532 DBG_HEXDUMP(MCMD_D, "osen_ie", priv->osen_ie,
2533 priv->osen_ie_len);
2534 priv->sec_info.osen_enabled = MTRUE;
2535 } else {
2536 memset(priv->adapter, priv->osen_ie, 0, sizeof(priv->osen_ie));
2537 priv->osen_ie_len = (t_u8)ie_len;
2538 PRINTM(MINFO, "Reset osen_ie_len=%d IE=%#x\n",
2539 priv->osen_ie_len, priv->osen_ie[0]);
2540 priv->sec_info.osen_enabled = MFALSE;
2541 }
2542 LEAVE();
2543 return MLAN_STATUS_SUCCESS;
2544 }
2545
2546 /**
2547 * @brief Set WAPI IE
2548 *
2549 * @param priv A pointer to mlan_private structure
2550 * @param ie_data_ptr A pointer to IE
2551 * @param ie_len Length of the IE
2552 *
2553 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
2554 */
wlan_set_wapi_ie(mlan_private * priv,t_u8 * ie_data_ptr,t_u16 ie_len)2555 static mlan_status wlan_set_wapi_ie(mlan_private *priv, t_u8 *ie_data_ptr,
2556 t_u16 ie_len)
2557 {
2558 ENTER();
2559 if (ie_len) {
2560 if (ie_len > sizeof(priv->wapi_ie)) {
2561 PRINTM(MWARN, "failed to copy, WAPI IE is too big\n");
2562 LEAVE();
2563 return MLAN_STATUS_FAILURE;
2564 }
2565 memcpy_ext(priv->adapter, priv->wapi_ie, ie_data_ptr, ie_len,
2566 sizeof(priv->wapi_ie));
2567 priv->wapi_ie_len = (t_u8)ie_len;
2568 PRINTM(MIOCTL, "Set wapi_ie_len=%d IE=%#x\n", priv->wapi_ie_len,
2569 priv->wapi_ie[0]);
2570 DBG_HEXDUMP(MCMD_D, "wapi_ie", priv->wapi_ie,
2571 priv->wapi_ie_len);
2572 if (priv->wapi_ie[0] == WAPI_IE)
2573 priv->sec_info.wapi_enabled = MTRUE;
2574 } else {
2575 memset(priv->adapter, priv->wapi_ie, 0, sizeof(priv->wapi_ie));
2576 priv->wapi_ie_len = (t_u8)ie_len;
2577 PRINTM(MINFO, "Reset wapi_ie_len=%d IE=%#x\n",
2578 priv->wapi_ie_len, priv->wapi_ie[0]);
2579 priv->sec_info.wapi_enabled = MFALSE;
2580 }
2581 LEAVE();
2582 return MLAN_STATUS_SUCCESS;
2583 }
2584
2585 /**
2586 * @brief Set/Get WAPI status
2587 *
2588 * @param pmadapter A pointer to mlan_adapter structure
2589 * @param pioctl_req A pointer to ioctl request buffer
2590 *
2591 * @return MLAN_STATUS_SUCCESS --success
2592 */
wlan_sec_ioctl_wapi_enable(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2593 static mlan_status wlan_sec_ioctl_wapi_enable(pmlan_adapter pmadapter,
2594 pmlan_ioctl_req pioctl_req)
2595 {
2596 mlan_status ret = MLAN_STATUS_SUCCESS;
2597 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2598 mlan_ds_sec_cfg *sec = MNULL;
2599 ENTER();
2600 sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
2601 if (pioctl_req->action == MLAN_ACT_GET) {
2602 if (pmpriv->wapi_ie_len)
2603 sec->param.wapi_enabled = MTRUE;
2604 else
2605 sec->param.wapi_enabled = MFALSE;
2606 } else {
2607 if (sec->param.wapi_enabled == MFALSE)
2608 wlan_set_wapi_ie(pmpriv, MNULL, 0);
2609 }
2610 pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
2611 LEAVE();
2612 return ret;
2613 }
2614
2615 /**
2616 * @brief Set WAPI key
2617 *
2618 * @param pmadapter A pointer to mlan_adapter structure
2619 * @param pioctl_req A pointer to ioctl request buffer
2620 *
2621 * @return MLAN_STATUS_PENDING --success, otherwise fail
2622 */
wlan_sec_ioctl_set_wapi_key(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2623 static mlan_status wlan_sec_ioctl_set_wapi_key(pmlan_adapter pmadapter,
2624 pmlan_ioctl_req pioctl_req)
2625 {
2626 mlan_status ret = MLAN_STATUS_SUCCESS;
2627 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2628 mlan_ds_sec_cfg *sec = MNULL;
2629 ENTER();
2630
2631 sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
2632 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
2633 HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
2634 (t_void *)pioctl_req, &sec->param.encrypt_key);
2635 if (ret == MLAN_STATUS_SUCCESS)
2636 ret = MLAN_STATUS_PENDING;
2637
2638 LEAVE();
2639 return ret;
2640 }
2641
2642 /**
2643 * @brief Set/Get Port Control status
2644 *
2645 * @param pmadapter A pointer to mlan_adapter structure
2646 * @param pioctl_req A pointer to ioctl request buffer
2647 *
2648 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
2649 */
wlan_sec_ioctl_port_ctrl_enable(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2650 static mlan_status wlan_sec_ioctl_port_ctrl_enable(pmlan_adapter pmadapter,
2651 pmlan_ioctl_req pioctl_req)
2652 {
2653 mlan_status ret = MLAN_STATUS_SUCCESS;
2654 mlan_ds_sec_cfg *sec = MNULL;
2655 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2656
2657 ENTER();
2658
2659 sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
2660 if (pioctl_req->action == MLAN_ACT_GET) {
2661 if (pmpriv->port_ctrl_mode)
2662 sec->param.port_ctrl_enabled = MTRUE;
2663 else
2664 sec->param.port_ctrl_enabled = MFALSE;
2665 } else {
2666 if (sec->param.port_ctrl_enabled) {
2667 pmpriv->port_ctrl_mode = MTRUE;
2668 pmpriv->port_open = MFALSE;
2669 } else {
2670 if (pmpriv->port_ctrl_mode == MTRUE) {
2671 pmpriv->port_ctrl_mode = MFALSE;
2672 /* Cleanup the bypass TX queue */
2673 wlan_cleanup_bypass_txq(pmpriv);
2674 }
2675 }
2676 }
2677 PRINTM(MINFO, "port_ctrl: port_ctrl_mode=%d port_open=%d\n",
2678 pmpriv->port_ctrl_mode, pmpriv->port_open);
2679
2680 LEAVE();
2681 return ret;
2682 }
2683
2684 /**
2685 * @brief Set/Get authentication mode
2686 *
2687 * @param pmadapter A pointer to mlan_adapter structure
2688 * @param pioctl_req A pointer to ioctl request buffer
2689 *
2690 * @return MLAN_STATUS_SUCCESS --success
2691 */
wlan_sec_ioctl_auth_mode(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2692 static mlan_status wlan_sec_ioctl_auth_mode(pmlan_adapter pmadapter,
2693 pmlan_ioctl_req pioctl_req)
2694 {
2695 mlan_status ret = MLAN_STATUS_SUCCESS;
2696 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2697 mlan_ds_sec_cfg *sec = MNULL;
2698 ENTER();
2699 sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
2700 if (pioctl_req->action == MLAN_ACT_GET)
2701 sec->param.auth_mode = pmpriv->sec_info.authentication_mode;
2702 else
2703 pmpriv->sec_info.authentication_mode = sec->param.auth_mode;
2704
2705 pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
2706 LEAVE();
2707 return ret;
2708 }
2709
2710 /**
2711 * @brief Set/Get encryption mode
2712 *
2713 * @param pmadapter A pointer to mlan_adapter structure
2714 * @param pioctl_req A pointer to ioctl request buffer
2715 *
2716 * @return MLAN_STATUS_SUCCESS --success
2717 */
wlan_sec_ioctl_encrypt_mode(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2718 static mlan_status wlan_sec_ioctl_encrypt_mode(pmlan_adapter pmadapter,
2719 pmlan_ioctl_req pioctl_req)
2720 {
2721 mlan_status ret = MLAN_STATUS_SUCCESS;
2722 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2723 mlan_ds_sec_cfg *sec = MNULL;
2724 ENTER();
2725 sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
2726 if (pioctl_req->action == MLAN_ACT_GET)
2727 sec->param.encrypt_mode = pmpriv->sec_info.encryption_mode;
2728 else
2729 pmpriv->sec_info.encryption_mode = sec->param.encrypt_mode;
2730
2731 pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
2732 LEAVE();
2733 return ret;
2734 }
2735
2736 /**
2737 * @brief Get Random charactor
2738 *
2739 * @param pmadapter A pointer to mlan_adapter structure
2740 *
2741 * @return random charactor
2742 */
wlan_get_random_charactor(pmlan_adapter pmadapter)2743 static t_u8 wlan_get_random_charactor(pmlan_adapter pmadapter)
2744 {
2745 t_u32 sec, usec;
2746 t_u8 ch = 0;
2747
2748 ENTER();
2749
2750 pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec,
2751 &usec);
2752 sec = (sec & 0xFFFF) + (sec >> 16);
2753 usec = (usec & 0xFFFF) + (usec >> 16);
2754 ch = (((sec << 16) + usec) % 26) + 'a';
2755 LEAVE();
2756 return ch;
2757 }
2758
2759 /**
2760 * @brief Set/Get WPA status
2761 *
2762 * @param pmadapter A pointer to mlan_adapter structure
2763 * @param pioctl_req A pointer to ioctl request buffer
2764 *
2765 * @return MLAN_STATUS_SUCCESS --success
2766 */
wlan_sec_ioctl_wpa_enable(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2767 static mlan_status wlan_sec_ioctl_wpa_enable(pmlan_adapter pmadapter,
2768 pmlan_ioctl_req pioctl_req)
2769 {
2770 mlan_status ret = MLAN_STATUS_SUCCESS;
2771 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2772 mlan_ds_sec_cfg *sec = MNULL;
2773 ENTER();
2774 sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
2775 if (pioctl_req->action == MLAN_ACT_GET) {
2776 if (pmpriv->wpa_ie_len)
2777 sec->param.wpa_enabled = MTRUE;
2778 else
2779 sec->param.wpa_enabled = MFALSE;
2780 } else {
2781 if (sec->param.wpa_enabled == MFALSE)
2782 wlan_set_wpa_ie_helper(pmpriv, MNULL, 0);
2783 }
2784 pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
2785 LEAVE();
2786 return ret;
2787 }
2788
2789 /**
2790 * @brief Set WEP keys
2791 *
2792 * @param pmadapter A pointer to mlan_adapter structure
2793 * @param pioctl_req A pointer to ioctl request buffer
2794 *
2795 * @return MLAN_STATUS_PENDING --success, otherwise fail
2796 */
wlan_sec_ioctl_set_wep_key(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2797 static mlan_status wlan_sec_ioctl_set_wep_key(pmlan_adapter pmadapter,
2798 pmlan_ioctl_req pioctl_req)
2799 {
2800 mlan_status ret = MLAN_STATUS_SUCCESS;
2801 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2802 mlan_ds_sec_cfg *sec = MNULL;
2803 mrvl_wep_key_t *pwep_key = MNULL;
2804 int index;
2805 int i = 0;
2806
2807 ENTER();
2808
2809 if (pmpriv->wep_key_curr_index >= MRVL_NUM_WEP_KEY)
2810 pmpriv->wep_key_curr_index = 0;
2811 pwep_key = &pmpriv->wep_key[pmpriv->wep_key_curr_index];
2812 sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
2813 if (sec->param.encrypt_key.key_index == MLAN_KEY_INDEX_DEFAULT) {
2814 index = pmpriv->wep_key_curr_index;
2815 sec->param.encrypt_key.key_index = index;
2816 } else {
2817 if (sec->param.encrypt_key.key_index >= MRVL_NUM_WEP_KEY) {
2818 if ((sec->param.encrypt_key.key_remove == MTRUE) &&
2819 (sec->param.encrypt_key.key_index <= 5)) {
2820 /* call firmware remove key */
2821 ret = wlan_prepare_cmd(
2822 pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
2823 HostCmd_ACT_GEN_SET, 0,
2824 (t_void *)pioctl_req,
2825 &sec->param.encrypt_key);
2826 if (ret == MLAN_STATUS_SUCCESS)
2827 ret = MLAN_STATUS_PENDING;
2828 goto exit;
2829 }
2830 PRINTM(MERROR, "Key_index is invalid\n");
2831 ret = MLAN_STATUS_FAILURE;
2832 goto exit;
2833 }
2834 index = sec->param.encrypt_key.key_index;
2835 }
2836
2837 if ((sec->param.encrypt_key.key_disable == MTRUE) ||
2838 (sec->param.encrypt_key.key_remove == MTRUE)) {
2839 pmpriv->sec_info.wep_status = Wlan802_11WEPDisabled;
2840 /* remove key */
2841 if (sec->param.encrypt_key.key_remove == MTRUE) {
2842 memset(pmadapter, &pmpriv->wep_key[index], 0,
2843 sizeof(mrvl_wep_key_t));
2844 /* call firmware remove key */
2845 ret = wlan_prepare_cmd(pmpriv,
2846 HostCmd_CMD_802_11_KEY_MATERIAL,
2847 HostCmd_ACT_GEN_SET, 0, MNULL,
2848 &sec->param.encrypt_key);
2849 if (ret)
2850 goto exit;
2851 }
2852 } else {
2853 if (sec->param.encrypt_key.key_len) {
2854 if ((sec->param.encrypt_key.key_len !=
2855 WEP_104_BIT_LEN) &&
2856 (sec->param.encrypt_key.key_len !=
2857 WEP_40_BIT_LEN)) {
2858 PRINTM(MERROR, "Invalid wep key len=%d\n",
2859 sec->param.encrypt_key.key_len);
2860 /* We will use random key to clear the key
2861 * buffer in FW */
2862 if (sec->param.encrypt_key.key_len <
2863 WEP_40_BIT_LEN)
2864 sec->param.encrypt_key.key_len =
2865 WEP_40_BIT_LEN;
2866 else
2867 sec->param.encrypt_key.key_len =
2868 WEP_104_BIT_LEN;
2869 for (i = 0;
2870 i < (int)sec->param.encrypt_key.key_len;
2871 i++)
2872 sec->param.encrypt_key.key_material[i] =
2873 wlan_get_random_charactor(
2874 pmadapter);
2875 }
2876 pwep_key = &pmpriv->wep_key[index];
2877 /* Cleanup */
2878 memset(pmadapter, pwep_key, 0, sizeof(mrvl_wep_key_t));
2879 /* Copy the key in the driver */
2880
2881 memcpy_ext(pmadapter, pwep_key->key_material,
2882 sec->param.encrypt_key.key_material,
2883 sec->param.encrypt_key.key_len,
2884 MRVL_KEY_BUFFER_SIZE_IN_BYTE);
2885 pwep_key->key_index = index;
2886 pwep_key->key_length = sec->param.encrypt_key.key_len;
2887 if (pmpriv->sec_info.wep_status !=
2888 Wlan802_11WEPEnabled) {
2889 /*
2890 * The status is set as Key Absent
2891 * so as to make sure we display the
2892 * keys when iwlist mlanX key is used
2893 */
2894 pmpriv->sec_info.wep_status =
2895 Wlan802_11WEPKeyAbsent;
2896 }
2897 }
2898 if (sec->param.encrypt_key.is_current_wep_key == MTRUE) {
2899 /* Copy the required key as the current key */
2900 pwep_key = &pmpriv->wep_key[index];
2901 if (!pwep_key->key_length) {
2902 if (pmpriv->sec_info.wpa_enabled ||
2903 pmpriv->sec_info.wpa2_enabled ||
2904 pmpriv->sec_info.wapi_enabled) {
2905 ret = MLAN_STATUS_SUCCESS;
2906 goto exit;
2907 }
2908 PRINTM(MERROR,
2909 "Key %d not set,so cannot enable it\n",
2910 index);
2911 pioctl_req->status_code =
2912 MLAN_ERROR_CMD_RESP_FAIL;
2913 ret = MLAN_STATUS_FAILURE;
2914 goto exit;
2915 }
2916 pmpriv->wep_key_curr_index = (t_u16)index;
2917 pmpriv->sec_info.wep_status = Wlan802_11WEPEnabled;
2918 }
2919 if (sec->param.encrypt_key.key_flags && pwep_key->key_length) {
2920 pmpriv->wep_key_curr_index = (t_u16)index;
2921 // Only do this if the key is an xmit key. If the key
2922 // is a group key, we might be in wpa/wep mixed mode in
2923 // which case we don't want to set wep_status =
2924 // Wlan802_11WEPEnabled because that enables WEP at the
2925 // MAC controller level and WPA stops working properly.
2926 if (sec->param.encrypt_key.key_flags &
2927 KEY_FLAG_SET_TX_KEY) {
2928 pmpriv->sec_info.wep_status =
2929 Wlan802_11WEPEnabled;
2930 }
2931 }
2932 }
2933 if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled)
2934 pmpriv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE;
2935 else
2936 pmpriv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
2937
2938 /* Send request to firmware */
2939 if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled &&
2940 pwep_key->key_length) {
2941 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
2942 HostCmd_ACT_GEN_SET, 0, MNULL,
2943 &pmpriv->curr_pkt_filter);
2944 if (ret)
2945 goto exit;
2946 if (!sec->param.encrypt_key.key_len) {
2947 sec->param.encrypt_key.key_index = pwep_key->key_index;
2948 sec->param.encrypt_key.key_len = pwep_key->key_length;
2949 memcpy_ext(pmadapter,
2950 sec->param.encrypt_key.key_material,
2951 pwep_key->key_material,
2952 sec->param.encrypt_key.key_len,
2953 MLAN_MAX_KEY_LENGTH);
2954 }
2955 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
2956 HostCmd_ACT_GEN_SET, 0,
2957 (t_void *)pioctl_req,
2958 &sec->param.encrypt_key);
2959 } else {
2960 if (pwep_key->key_length) {
2961 if (!sec->param.encrypt_key.key_len) {
2962 sec->param.encrypt_key.key_index =
2963 pwep_key->key_index;
2964 sec->param.encrypt_key.key_len =
2965 pwep_key->key_length;
2966 memcpy_ext(pmadapter,
2967 sec->param.encrypt_key.key_material,
2968 pwep_key->key_material,
2969 sec->param.encrypt_key.key_len,
2970 MLAN_MAX_KEY_LENGTH);
2971 }
2972 ret = wlan_prepare_cmd(pmpriv,
2973 HostCmd_CMD_802_11_KEY_MATERIAL,
2974 HostCmd_ACT_GEN_SET, 0, MNULL,
2975 &sec->param.encrypt_key);
2976 if (ret)
2977 goto exit;
2978 }
2979 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
2980 HostCmd_ACT_GEN_SET, 0,
2981 (t_void *)pioctl_req,
2982 &pmpriv->curr_pkt_filter);
2983 }
2984 if (ret == MLAN_STATUS_SUCCESS)
2985 ret = MLAN_STATUS_PENDING;
2986
2987 exit:
2988 LEAVE();
2989 return ret;
2990 }
2991
2992 /**
2993 * @brief Set WPA key
2994 *
2995 * @param pmadapter A pointer to mlan_adapter structure
2996 * @param pioctl_req A pointer to ioctl request buffer
2997 *
2998 * @return MLAN_STATUS_PENDING --success, otherwise fail
2999 */
wlan_sec_ioctl_set_wpa_key(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3000 static mlan_status wlan_sec_ioctl_set_wpa_key(pmlan_adapter pmadapter,
3001 pmlan_ioctl_req pioctl_req)
3002 {
3003 mlan_status ret = MLAN_STATUS_SUCCESS;
3004 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3005 mlan_ds_sec_cfg *sec = MNULL;
3006
3007 ENTER();
3008
3009 sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
3010 /* Current driver only supports key length of up to 32 bytes */
3011 if (sec->param.encrypt_key.key_len > MLAN_MAX_KEY_LENGTH) {
3012 PRINTM(MERROR, "Key length is incorrect\n");
3013 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3014 ret = MLAN_STATUS_FAILURE;
3015 goto exit;
3016 }
3017
3018 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
3019 HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
3020 &sec->param.encrypt_key);
3021
3022 if (ret == MLAN_STATUS_SUCCESS)
3023 ret = MLAN_STATUS_PENDING;
3024
3025 exit:
3026 LEAVE();
3027 return ret;
3028 }
3029
3030 /**
3031 * @brief Get security keys
3032 *
3033 * @param pmadapter A pointer to mlan_adapter structure
3034 * @param pioctl_req A pointer to ioctl request buffer
3035 *
3036 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
3037 */
wlan_sec_ioctl_get_key(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3038 static mlan_status wlan_sec_ioctl_get_key(pmlan_adapter pmadapter,
3039 pmlan_ioctl_req pioctl_req)
3040 {
3041 mlan_status ret = MLAN_STATUS_SUCCESS;
3042 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3043 mlan_ds_sec_cfg *sec = MNULL;
3044 int index;
3045 ENTER();
3046
3047 sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
3048
3049 if (pmpriv->wep_key_curr_index >= MRVL_NUM_WEP_KEY)
3050 pmpriv->wep_key_curr_index = 0;
3051
3052 if ((pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled) ||
3053 (pmpriv->sec_info.wep_status == Wlan802_11WEPKeyAbsent) ||
3054 pmpriv->sec_info.ewpa_enabled || pmpriv->sec_info.wpa_enabled ||
3055 pmpriv->sec_info.wpa2_enabled) {
3056 sec->param.encrypt_key.key_disable = MFALSE;
3057 } else {
3058 sec->param.encrypt_key.key_disable = MTRUE;
3059 }
3060 if (sec->param.encrypt_key.key_index == MLAN_KEY_INDEX_DEFAULT) {
3061 if ((pmpriv->wep_key[pmpriv->wep_key_curr_index].key_length) &&
3062 (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled)) {
3063 index = pmpriv->wep_key_curr_index;
3064 sec->param.encrypt_key.key_index =
3065 pmpriv->wep_key[index].key_index;
3066 memcpy_ext(pmadapter,
3067 sec->param.encrypt_key.key_material,
3068 pmpriv->wep_key[index].key_material,
3069 pmpriv->wep_key[index].key_length,
3070 MLAN_MAX_KEY_LENGTH);
3071 sec->param.encrypt_key.key_len =
3072 MIN(MLAN_MAX_KEY_LENGTH,
3073 pmpriv->wep_key[index].key_length);
3074 } else if ((pmpriv->sec_info.wpa_enabled) ||
3075 (pmpriv->sec_info.ewpa_enabled) ||
3076 (pmpriv->sec_info.wpa2_enabled) ||
3077 (pmpriv->sec_info.wapi_enabled)) {
3078 /* Return WPA enabled */
3079 sec->param.encrypt_key.key_disable = MFALSE;
3080 memcpy_ext(pmadapter,
3081 sec->param.encrypt_key.key_material,
3082 pmpriv->aes_key.key_material,
3083 pmpriv->aes_key.key_len,
3084 MLAN_MAX_KEY_LENGTH);
3085 sec->param.encrypt_key.key_len = MIN(
3086 MLAN_MAX_KEY_LENGTH, pmpriv->aes_key.key_len);
3087 } else {
3088 sec->param.encrypt_key.key_disable = MTRUE;
3089 }
3090 } else {
3091 index = sec->param.encrypt_key.key_index;
3092 if (pmpriv->wep_key[index].key_length) {
3093 sec->param.encrypt_key.key_index =
3094 pmpriv->wep_key[index].key_index;
3095 memcpy_ext(pmadapter,
3096 sec->param.encrypt_key.key_material,
3097 pmpriv->wep_key[index].key_material,
3098 pmpriv->wep_key[index].key_length,
3099 MLAN_MAX_KEY_LENGTH);
3100 sec->param.encrypt_key.key_len =
3101 MIN(MLAN_MAX_KEY_LENGTH,
3102 pmpriv->wep_key[index].key_length);
3103 } else if ((pmpriv->sec_info.wpa_enabled) ||
3104 (pmpriv->sec_info.ewpa_enabled) ||
3105 (pmpriv->sec_info.wpa2_enabled) ||
3106 (pmpriv->sec_info.wapi_enabled)) {
3107 /* Return WPA enabled */
3108 sec->param.encrypt_key.key_disable = MFALSE;
3109 } else {
3110 sec->param.encrypt_key.key_disable = MTRUE;
3111 }
3112 }
3113
3114 LEAVE();
3115 return ret;
3116 }
3117
3118 /**
3119 * @brief Set security key(s)
3120 *
3121 * @param pmadapter A pointer to mlan_adapter structure
3122 * @param pioctl_req A pointer to ioctl request buffer
3123 *
3124 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
3125 * otherwise fail
3126 */
wlan_sec_ioctl_encrypt_key(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3127 static mlan_status wlan_sec_ioctl_encrypt_key(pmlan_adapter pmadapter,
3128 pmlan_ioctl_req pioctl_req)
3129 {
3130 mlan_status status = MLAN_STATUS_SUCCESS;
3131 mlan_ds_sec_cfg *sec = MNULL;
3132 ENTER();
3133 sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
3134 if (pioctl_req->action == MLAN_ACT_SET) {
3135 if (sec->param.encrypt_key.is_wapi_key)
3136 status = wlan_sec_ioctl_set_wapi_key(pmadapter,
3137 pioctl_req);
3138 else if (sec->param.encrypt_key.key_len > MAX_WEP_KEY_SIZE)
3139 status = wlan_sec_ioctl_set_wpa_key(pmadapter,
3140 pioctl_req);
3141 else
3142 status = wlan_sec_ioctl_set_wep_key(pmadapter,
3143 pioctl_req);
3144 } else {
3145 status = wlan_sec_ioctl_get_key(pmadapter, pioctl_req);
3146 }
3147 LEAVE();
3148 return status;
3149 }
3150
3151 /**
3152 * @brief Query Encrpyt key
3153 *
3154 * @param pmadapter A pointer to mlan_adapter structure
3155 * @param pioctl_req A pointer to ioctl request buffer
3156 *
3157 * @return MLAN_STATUS_PENDING --success, otherwise fail
3158 */
wlan_sec_ioctl_query_key(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3159 static mlan_status wlan_sec_ioctl_query_key(pmlan_adapter pmadapter,
3160 pmlan_ioctl_req pioctl_req)
3161 {
3162 mlan_status ret = MLAN_STATUS_SUCCESS;
3163 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3164 mlan_ds_sec_cfg *sec = MNULL;
3165
3166 ENTER();
3167
3168 sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
3169 /* Current driver only supports get PTK/GTK */
3170 if (pmpriv->port_open &&
3171 (pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.wpa2_enabled ||
3172 pmpriv->sec_info.wapi_enabled)) {
3173 /* Send request to firmware */
3174 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
3175 HostCmd_ACT_GEN_GET, KEY_INFO_ENABLED,
3176 (t_void *)pioctl_req,
3177 &sec->param.encrypt_key);
3178
3179 if (ret == MLAN_STATUS_SUCCESS)
3180 ret = MLAN_STATUS_PENDING;
3181 }
3182 LEAVE();
3183 return ret;
3184 }
3185
3186 /**
3187 * @brief Set/Get esupplicant status
3188 *
3189 * @param pmadapter A pointer to mlan_adapter structure
3190 * @param pioctl_req A pointer to ioctl request buffer
3191 *
3192 * @return MLAN_STATUS_SUCCESS --success
3193 */
wlan_sec_ioctl_ewpa_enable(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3194 static mlan_status wlan_sec_ioctl_ewpa_enable(pmlan_adapter pmadapter,
3195 pmlan_ioctl_req pioctl_req)
3196 {
3197 mlan_status ret = MLAN_STATUS_SUCCESS;
3198 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3199 mlan_ds_sec_cfg *sec = MNULL;
3200 ENTER();
3201 sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
3202 if (pioctl_req->action == MLAN_ACT_GET) {
3203 sec->param.ewpa_enabled = pmpriv->sec_info.ewpa_enabled;
3204 } else {
3205 pmpriv->sec_info.ewpa_enabled = (t_u8)sec->param.ewpa_enabled;
3206 PRINTM(MINFO, "Set: ewpa_enabled = %d\n",
3207 (int)pmpriv->sec_info.ewpa_enabled);
3208 }
3209 pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
3210 LEAVE();
3211 return ret;
3212 }
3213
3214 /**
3215 * @brief Get esupplicant mode
3216 *
3217 * @param pmadapter A pointer to mlan_adapter structure
3218 * @param pioctl_req A pointer to ioctl request buffer
3219 *
3220 * @return MLAN_STATUS_PENDING --success, otherwise fail
3221 */
wlan_sec_ioctl_esupp_mode(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3222 static mlan_status wlan_sec_ioctl_esupp_mode(pmlan_adapter pmadapter,
3223 pmlan_ioctl_req pioctl_req)
3224 {
3225 mlan_status ret = MLAN_STATUS_SUCCESS;
3226 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3227 t_u16 cmd_action = 0;
3228 mlan_ds_sec_cfg *sec = MNULL;
3229
3230 ENTER();
3231
3232 sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
3233 if (pioctl_req->action == MLAN_ACT_SET) {
3234 cmd_action = HostCmd_ACT_GEN_SET;
3235 if (pmpriv->media_connected == MTRUE) {
3236 PRINTM(MERROR,
3237 "Cannot set esupplicant mode configuration while connected.\n");
3238 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3239 ret = MLAN_STATUS_FAILURE;
3240 goto exit;
3241 }
3242 if (!sec->param.esupp_mode.rsn_mode ||
3243 (sec->param.esupp_mode.rsn_mode & RSN_TYPE_VALID_BITS) !=
3244 sec->param.esupp_mode.rsn_mode) {
3245 PRINTM(MERROR, "Invalid RSN mode\n");
3246 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3247 ret = MLAN_STATUS_FAILURE;
3248 goto exit;
3249 }
3250 if (!sec->param.esupp_mode.act_paircipher ||
3251 (sec->param.esupp_mode.act_paircipher &
3252 EMBED_CIPHER_VALID_BITS) !=
3253 sec->param.esupp_mode.act_paircipher) {
3254 PRINTM(MERROR, "Invalid pairwise cipher\n");
3255 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3256 ret = MLAN_STATUS_FAILURE;
3257 goto exit;
3258 }
3259 if (!sec->param.esupp_mode.act_groupcipher ||
3260 (sec->param.esupp_mode.act_groupcipher &
3261 EMBED_CIPHER_VALID_BITS) !=
3262 sec->param.esupp_mode.act_groupcipher) {
3263 PRINTM(MERROR, "Invalid group cipher\n");
3264 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3265 ret = MLAN_STATUS_FAILURE;
3266 goto exit;
3267 }
3268 } else {
3269 cmd_action = HostCmd_ACT_GEN_GET_CURRENT;
3270 }
3271
3272 /* Send request to firmware */
3273 if (sec) {
3274 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SUPPLICANT_PROFILE,
3275 cmd_action, 0, (t_void *)pioctl_req,
3276 &sec->param.esupp_mode);
3277 } else {
3278 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SUPPLICANT_PROFILE,
3279 cmd_action, 0, (t_void *)pioctl_req,
3280 MNULL);
3281 }
3282 if (ret == MLAN_STATUS_SUCCESS)
3283 ret = MLAN_STATUS_PENDING;
3284
3285 exit:
3286 LEAVE();
3287 return ret;
3288 }
3289
3290 /**
3291 * @brief Security configuration handler
3292 *
3293 * @param pmadapter A pointer to mlan_adapter structure
3294 * @param pioctl_req A pointer to ioctl request buffer
3295 *
3296 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
3297 * otherwise fail
3298 */
wlan_sec_cfg_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3299 static mlan_status wlan_sec_cfg_ioctl(pmlan_adapter pmadapter,
3300 pmlan_ioctl_req pioctl_req)
3301 {
3302 mlan_status status = MLAN_STATUS_SUCCESS;
3303 mlan_ds_sec_cfg *sec = MNULL;
3304
3305 ENTER();
3306
3307 if (pioctl_req->buf_len < sizeof(mlan_ds_sec_cfg)) {
3308 PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
3309 pioctl_req->data_read_written = 0;
3310 pioctl_req->buf_len_needed = sizeof(mlan_ds_sec_cfg);
3311 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3312 LEAVE();
3313 return MLAN_STATUS_RESOURCE;
3314 }
3315 sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
3316 switch (sec->sub_command) {
3317 case MLAN_OID_SEC_CFG_AUTH_MODE:
3318 status = wlan_sec_ioctl_auth_mode(pmadapter, pioctl_req);
3319 break;
3320 case MLAN_OID_SEC_CFG_ENCRYPT_MODE:
3321 status = wlan_sec_ioctl_encrypt_mode(pmadapter, pioctl_req);
3322 break;
3323 case MLAN_OID_SEC_CFG_WPA_ENABLED:
3324 status = wlan_sec_ioctl_wpa_enable(pmadapter, pioctl_req);
3325 break;
3326 case MLAN_OID_SEC_CFG_WAPI_ENABLED:
3327 status = wlan_sec_ioctl_wapi_enable(pmadapter, pioctl_req);
3328 break;
3329 case MLAN_OID_SEC_CFG_PORT_CTRL_ENABLED:
3330 status = wlan_sec_ioctl_port_ctrl_enable(pmadapter, pioctl_req);
3331 break;
3332 case MLAN_OID_SEC_CFG_ENCRYPT_KEY:
3333 status = wlan_sec_ioctl_encrypt_key(pmadapter, pioctl_req);
3334 break;
3335 case MLAN_OID_SEC_QUERY_KEY:
3336 status = wlan_sec_ioctl_query_key(pmadapter, pioctl_req);
3337 break;
3338 case MLAN_OID_SEC_CFG_PASSPHRASE:
3339 status = wlan_sec_ioctl_passphrase(pmadapter, pioctl_req);
3340 break;
3341 case MLAN_OID_SEC_CFG_EWPA_ENABLED:
3342 status = wlan_sec_ioctl_ewpa_enable(pmadapter, pioctl_req);
3343 break;
3344 case MLAN_OID_SEC_CFG_ESUPP_MODE:
3345 status = wlan_sec_ioctl_esupp_mode(pmadapter, pioctl_req);
3346 break;
3347
3348 default:
3349 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3350 status = MLAN_STATUS_FAILURE;
3351 break;
3352 }
3353 LEAVE();
3354 return status;
3355 }
3356
3357 /**
3358 * @brief Append/Reset IE buffer.
3359 *
3360 * Pass an opaque block of data, expected to be IEEE IEs, to the driver
3361 * for eventual passthrough to the firmware in an associate/join
3362 * (and potentially start) command. This function is the main body
3363 * for both wlan_set_gen_ie_ioctl and wlan_set_gen_ie
3364 *
3365 * Data is appended to an existing buffer and then wrapped in a passthrough
3366 * TLV in the command API to the firmware. The firmware treats the data
3367 * as a transparent passthrough to the transmitted management frame.
3368 *
3369 * @param priv A pointer to mlan_private structure
3370 * @param ie_data_ptr A pointer to iwreq structure
3371 * @param ie_len Length of the IE or IE block passed in ie_data_ptr
3372 *
3373 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
3374 */
wlan_set_gen_ie_helper(mlan_private * priv,t_u8 * ie_data_ptr,t_u16 ie_len)3375 static mlan_status wlan_set_gen_ie_helper(mlan_private *priv, t_u8 *ie_data_ptr,
3376 t_u16 ie_len)
3377 {
3378 mlan_status ret = MLAN_STATUS_SUCCESS;
3379 IEEEtypes_VendorHeader_t *pvendor_ie;
3380 const t_u8 wpa_oui[] = {0x00, 0x50, 0xf2, 0x01};
3381 const t_u8 wps_oui[] = {0x00, 0x50, 0xf2, 0x04};
3382 const t_u8 osen_oui[] = {0x50, 0x6f, 0x9a, 0x12};
3383 t_u8 i = 0, temp[12] = {0};
3384
3385 ENTER();
3386
3387 /* If the passed length is zero, reset the buffer */
3388 if (!ie_len) {
3389 priv->gen_ie_buf_len = 0;
3390 priv->wps.session_enable = MFALSE;
3391 wlan_set_wpa_ie_helper(priv, MNULL, 0);
3392 wlan_set_wapi_ie(priv, MNULL, 0);
3393 wlan_set_osen_ie(priv, MNULL, 0);
3394 } else if (!ie_data_ptr) {
3395 /* MNULL check */
3396 ret = MLAN_STATUS_FAILURE;
3397 } else {
3398 pvendor_ie = (IEEEtypes_VendorHeader_t *)ie_data_ptr;
3399 if (pvendor_ie->element_id == EXT_CAPABILITY) {
3400 memcpy_ext(priv->adapter, temp, &priv->ext_cap,
3401 sizeof(priv->ext_cap), sizeof(temp));
3402 for (i = 0;
3403 i < MIN(sizeof(priv->ext_cap), pvendor_ie->len);
3404 i++)
3405 temp[i] |= ie_data_ptr[2 + i];
3406 memcpy_ext(priv->adapter, &priv->ext_cap, temp,
3407 sizeof(temp), sizeof(priv->ext_cap));
3408 } else
3409 /* Test to see if it is a WPA IE, if not, then it is a
3410 gen IE*/
3411 if (((pvendor_ie->element_id == WPA_IE) &&
3412 (!memcmp(priv->adapter, pvendor_ie->oui, wpa_oui,
3413 sizeof(wpa_oui)))) ||
3414 (pvendor_ie->element_id == RSN_IE)) {
3415 /* IE is a WPA/WPA2 IE so call set_wpa function */
3416 ret = wlan_set_wpa_ie_helper(priv, ie_data_ptr, ie_len);
3417 priv->wps.session_enable = MFALSE;
3418 } else if (pvendor_ie->element_id == WAPI_IE) {
3419 /* IE is a WAPI IE so call set_wapi function */
3420 ret = wlan_set_wapi_ie(priv, ie_data_ptr, ie_len);
3421 } else if ((pvendor_ie->element_id == VENDOR_SPECIFIC_221) &&
3422 (!memcmp(priv->adapter, pvendor_ie->oui, osen_oui,
3423 sizeof(osen_oui)))) {
3424 /* IE is a OSEN IE so call set_osen function */
3425 ret = wlan_set_osen_ie(priv, ie_data_ptr, ie_len);
3426
3427 } else if ((pvendor_ie->element_id == WPS_IE) &&
3428 (priv->wps.session_enable == MFALSE) &&
3429 (!memcmp(priv->adapter, pvendor_ie->oui, wps_oui,
3430 sizeof(wps_oui)))) {
3431 /*
3432 * Discard first two byte (Element ID and Length)
3433 * because they are not needed in the case of setting
3434 * WPS_IE
3435 */
3436 if (pvendor_ie->len > 4) {
3437 memcpy_ext(priv->adapter,
3438 (t_u8 *)&priv->wps.wps_ie,
3439 ie_data_ptr, ie_len,
3440 sizeof(IEEEtypes_VendorSpecific_t));
3441 HEXDUMP("wps_ie", (t_u8 *)&priv->wps.wps_ie,
3442 priv->wps.wps_ie.vend_hdr.len + 2);
3443 } else {
3444 /* Only wps oui exist, reset driver wps buffer
3445 */
3446 memset(priv->adapter, (t_u8 *)&priv->wps.wps_ie,
3447 0x00, sizeof(priv->wps.wps_ie));
3448 PRINTM(MINFO, "wps_ie cleared\n");
3449 }
3450 } else {
3451 /*
3452 * Verify that the passed length is not larger than
3453 * the available space remaining in the buffer
3454 */
3455 if (ie_len <
3456 (sizeof(priv->gen_ie_buf) - priv->gen_ie_buf_len)) {
3457 /* Test to see if it is a WPS IE, if so, enable
3458 * wps session flag */
3459 pvendor_ie =
3460 (IEEEtypes_VendorHeader_t *)ie_data_ptr;
3461 if ((pvendor_ie->element_id == WPS_IE) &&
3462 (!memcmp(priv->adapter, pvendor_ie->oui,
3463 wps_oui, sizeof(wps_oui)))) {
3464 priv->wps.session_enable = MTRUE;
3465 PRINTM(MINFO, "WPS Session Enabled.\n");
3466 }
3467
3468 /* Append the passed data to the end of
3469 * the genIeBuffer */
3470 memcpy_ext(priv->adapter,
3471 priv->gen_ie_buf +
3472 priv->gen_ie_buf_len,
3473 ie_data_ptr, ie_len,
3474 MRVDRV_GENIE_BUF_SIZE -
3475 priv->gen_ie_buf_len);
3476 /* Increment the stored buffer length by
3477 * the size passed */
3478 priv->gen_ie_buf_len += ie_len;
3479 } else {
3480 /* Passed data does not fit in the
3481 * remaining buffer space */
3482 ret = MLAN_STATUS_FAILURE;
3483 }
3484 }
3485 }
3486
3487 /* Return MLAN_STATUS_SUCCESS, or MLAN_STATUS_FAILURE for error case */
3488 LEAVE();
3489 return ret;
3490 }
3491
3492 /**
3493 * @brief Set/Get WWS mode
3494 *
3495 * @param pmadapter A pointer to mlan_adapter structure
3496 * @param pioctl_req A pointer to ioctl request buffer
3497 *
3498 * @return MLAN_STATUS_PENDING --success, otherwise fail
3499 */
wlan_misc_ioctl_wws_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3500 static mlan_status wlan_misc_ioctl_wws_cfg(pmlan_adapter pmadapter,
3501 pmlan_ioctl_req pioctl_req)
3502 {
3503 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
3504 mlan_status ret = MLAN_STATUS_SUCCESS;
3505 mlan_ds_misc_cfg *misc_cfg = MNULL;
3506 t_u16 cmd_action = 0;
3507 t_u32 enable = 0;
3508
3509 ENTER();
3510
3511 if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) {
3512 PRINTM(MWARN,
3513 "MLAN IOCTL information buffer length is too short.\n");
3514 pioctl_req->data_read_written = 0;
3515 pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
3516 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3517 ret = MLAN_STATUS_RESOURCE;
3518 goto exit;
3519 }
3520
3521 misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
3522 if (pioctl_req->action == MLAN_ACT_SET)
3523 cmd_action = HostCmd_ACT_GEN_SET;
3524 else
3525 cmd_action = HostCmd_ACT_GEN_GET;
3526
3527 enable = misc_cfg->param.wws_cfg;
3528
3529 /* Send request to firmware */
3530 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB, cmd_action,
3531 WwsMode_i, (t_void *)pioctl_req, &enable);
3532
3533 if (ret == MLAN_STATUS_SUCCESS)
3534 ret = MLAN_STATUS_PENDING;
3535
3536 exit:
3537 LEAVE();
3538 return ret;
3539 }
3540
3541 /**
3542 * @brief Set/Get 11D status
3543 *
3544 * @param pmadapter A pointer to mlan_adapter structure
3545 * @param pioctl_req A pointer to ioctl request buffer
3546 *
3547 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
3548 * otherwise fail
3549 */
wlan_11d_cfg_ioctl_enable(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3550 static mlan_status wlan_11d_cfg_ioctl_enable(pmlan_adapter pmadapter,
3551 pmlan_ioctl_req pioctl_req)
3552 {
3553 mlan_status ret = MLAN_STATUS_SUCCESS;
3554 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3555 mlan_ds_11d_cfg *pcfg_11d = MNULL;
3556
3557 ENTER();
3558
3559 pcfg_11d = (mlan_ds_11d_cfg *)pioctl_req->pbuf;
3560
3561 if (pioctl_req->action == MLAN_ACT_SET) {
3562 if (pmpriv->media_connected == MTRUE) {
3563 PRINTM(MIOCTL,
3564 "11D setting cannot be changed while interface is active.\n");
3565 ret = MLAN_STATUS_FAILURE;
3566 goto done;
3567 }
3568
3569 PRINTM(MINFO, "11D: 11dcfg SET=%d\n",
3570 pcfg_11d->param.enable_11d);
3571
3572 /* Compare with current settings */
3573 if (pmpriv->state_11d.user_enable_11d !=
3574 pcfg_11d->param.enable_11d) {
3575 ret = wlan_11d_enable(
3576 pmpriv, pioctl_req,
3577 (state_11d_t)pcfg_11d->param.enable_11d);
3578 if (ret == MLAN_STATUS_SUCCESS)
3579 ret = MLAN_STATUS_PENDING;
3580 } else {
3581 PRINTM(MINFO,
3582 "11D: same as current setting, do nothing\n");
3583 }
3584 } else {
3585 pcfg_11d->param.enable_11d =
3586 (t_u32)pmpriv->state_11d.user_enable_11d;
3587 pioctl_req->data_read_written =
3588 sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
3589 PRINTM(MINFO, "11D: 11dcfg GET=%d\n",
3590 pcfg_11d->param.enable_11d);
3591 }
3592
3593 done:
3594 LEAVE();
3595 return ret;
3596 }
3597
3598 /**
3599 * @brief Clear 11D chan table
3600 *
3601 * @param pmadapter A pointer to mlan_adapter structure
3602 * @param pioctl_req A pointer to ioctl request buffer
3603 *
3604 * @return MLAN_STATUS_SUCCESS --success
3605 */
wlan_11d_clr_chan_table(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3606 static mlan_status wlan_11d_clr_chan_table(pmlan_adapter pmadapter,
3607 pmlan_ioctl_req pioctl_req)
3608 {
3609 mlan_status ret = MLAN_STATUS_SUCCESS;
3610 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3611
3612 ENTER();
3613
3614 if (pioctl_req->action == MLAN_ACT_SET) {
3615 PRINTM(MINFO, "11D: 11dclrtbl SET\n");
3616
3617 if (wlan_11d_clear_parsedtable(pmpriv) == MLAN_STATUS_SUCCESS)
3618 PRINTM(MINFO,
3619 "11D: cleared parsed_region_chan (now no_of_chan=%d)\n",
3620 pmadapter->parsed_region_chan.no_of_chan);
3621 }
3622
3623 LEAVE();
3624 return ret;
3625 }
3626
3627 /**
3628 * @brief 11D configuration handler
3629 *
3630 * @param pmadapter A pointer to mlan_adapter structure
3631 * @param pioctl_req A pointer to ioctl request buffer
3632 *
3633 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
3634 * otherwise fail
3635 */
wlan_11d_cfg_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3636 static mlan_status wlan_11d_cfg_ioctl(pmlan_adapter pmadapter,
3637 pmlan_ioctl_req pioctl_req)
3638 {
3639 mlan_status status = MLAN_STATUS_SUCCESS;
3640 mlan_ds_11d_cfg *pcfg_11d = MNULL;
3641
3642 ENTER();
3643
3644 if (pioctl_req->buf_len < sizeof(mlan_ds_11d_cfg)) {
3645 PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
3646 pioctl_req->data_read_written = 0;
3647 pioctl_req->buf_len_needed = sizeof(mlan_ds_11d_cfg);
3648 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3649 status = MLAN_STATUS_RESOURCE;
3650 goto exit;
3651 }
3652
3653 pcfg_11d = (mlan_ds_11d_cfg *)pioctl_req->pbuf;
3654 switch (pcfg_11d->sub_command) {
3655 case MLAN_OID_11D_CFG_ENABLE:
3656 status = wlan_11d_cfg_ioctl_enable(pmadapter, pioctl_req);
3657 break;
3658 case MLAN_OID_11D_CLR_CHAN_TABLE:
3659 status = wlan_11d_clr_chan_table(pmadapter, pioctl_req);
3660 break;
3661 case MLAN_OID_11D_DOMAIN_INFO_EXT:
3662 status = wlan_11d_cfg_domain_info(pmadapter, pioctl_req);
3663 break;
3664 default:
3665 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3666 status = MLAN_STATUS_FAILURE;
3667 break;
3668 }
3669
3670 exit:
3671 LEAVE();
3672 return status;
3673 }
3674
3675 /**
3676 * @brief WPS configuration handler
3677 *
3678 * @param pmadapter A pointer to mlan_adapter structure
3679 * @param pioctl_req A pointer to ioctl request buffer
3680 *
3681 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
3682 */
wlan_wps_cfg_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3683 static mlan_status wlan_wps_cfg_ioctl(pmlan_adapter pmadapter,
3684 pmlan_ioctl_req pioctl_req)
3685 {
3686 mlan_status status = MLAN_STATUS_SUCCESS;
3687 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3688 mlan_ds_wps_cfg *pwps = MNULL;
3689
3690 ENTER();
3691
3692 if (pioctl_req->buf_len < sizeof(mlan_ds_wps_cfg)) {
3693 PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
3694 pioctl_req->data_read_written = 0;
3695 pioctl_req->buf_len_needed = sizeof(mlan_ds_wps_cfg);
3696 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3697 LEAVE();
3698 return MLAN_STATUS_RESOURCE;
3699 }
3700
3701 pwps = (mlan_ds_wps_cfg *)pioctl_req->pbuf;
3702 switch (pwps->sub_command) {
3703 case MLAN_OID_WPS_CFG_SESSION:
3704 if (pioctl_req->action == MLAN_ACT_SET) {
3705 if (pwps->param.wps_session ==
3706 MLAN_WPS_CFG_SESSION_START)
3707 pmpriv->wps.session_enable = MTRUE;
3708 else
3709 pmpriv->wps.session_enable = MFALSE;
3710 } else {
3711 pwps->param.wps_session =
3712 (t_u32)pmpriv->wps.session_enable;
3713 pioctl_req->data_read_written = sizeof(t_u32);
3714 PRINTM(MINFO, "wpscfg GET=%d\n",
3715 pwps->param.wps_session);
3716 }
3717 break;
3718 default:
3719 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3720 status = MLAN_STATUS_FAILURE;
3721 break;
3722 }
3723
3724 LEAVE();
3725 return status;
3726 }
3727
3728 /**
3729 * @brief register memory access handler
3730 *
3731 * @param pmadapter A pointer to mlan_adapter structure
3732 * @param pioctl_req A pointer to ioctl request buffer
3733 *
3734 * @return MLAN_STATUS_PENDING --success, otherwise fail
3735 */
wlan_reg_mem_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3736 static mlan_status wlan_reg_mem_ioctl(pmlan_adapter pmadapter,
3737 pmlan_ioctl_req pioctl_req)
3738 {
3739 mlan_status status = MLAN_STATUS_SUCCESS;
3740 mlan_ds_reg_mem *reg_mem = MNULL;
3741
3742 ENTER();
3743
3744 if (pioctl_req->buf_len < sizeof(mlan_ds_reg_mem)) {
3745 PRINTM(MWARN, "MLAN REG_MEM IOCTL length is too short\n");
3746 pioctl_req->data_read_written = 0;
3747 pioctl_req->buf_len_needed = sizeof(mlan_ds_reg_mem);
3748 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3749 LEAVE();
3750 return MLAN_STATUS_RESOURCE;
3751 }
3752 reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
3753 switch (reg_mem->sub_command) {
3754 case MLAN_OID_REG_RW:
3755 status = wlan_reg_mem_ioctl_reg_rw(pmadapter, pioctl_req);
3756 break;
3757 case MLAN_OID_EEPROM_RD:
3758 status = wlan_reg_mem_ioctl_read_eeprom(pmadapter, pioctl_req);
3759 break;
3760 case MLAN_OID_MEM_RW:
3761 status = wlan_reg_mem_ioctl_mem_rw(pmadapter, pioctl_req);
3762 break;
3763 default:
3764 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3765 status = MLAN_STATUS_FAILURE;
3766 break;
3767 }
3768 LEAVE();
3769 return status;
3770 }
3771
3772 /**
3773 * @brief 802.11h ad-hoc start channel check
3774 *
3775 * @param pmadapter A pointer to mlan_adapter structure
3776 * @param pioctl_req A pointer to ioctl request buffer
3777 *
3778 * @return MLAN_STATUS_PENDING --success, otherwise fail
3779 */
wlan_11h_channel_check_req(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3780 static mlan_status wlan_11h_channel_check_req(pmlan_adapter pmadapter,
3781 pmlan_ioctl_req pioctl_req)
3782 {
3783 pmlan_private pmpriv = MNULL;
3784 mlan_status ret = MLAN_STATUS_FAILURE;
3785 t_u8 chan_width = CHAN_BW_20MHZ;
3786 Band_Config_t bandcfg;
3787
3788 ENTER();
3789
3790 if (pioctl_req != MNULL) {
3791 pmpriv = pmadapter->priv[pioctl_req->bss_index];
3792 } else {
3793 PRINTM(MERROR, "MLAN IOCTL information is not present\n");
3794 LEAVE();
3795 return MLAN_STATUS_FAILURE;
3796 }
3797
3798 memset(pmadapter, &bandcfg, 0, sizeof(Band_Config_t));
3799 pmpriv->adhoc_state = ADHOC_STARTING;
3800
3801 if ((pmadapter->adhoc_start_band & BAND_A)) {
3802 if (pmpriv->intf_state_11h.adhoc_auto_sel_chan)
3803 pmpriv->adhoc_channel =
3804 wlan_11h_get_adhoc_start_channel(pmpriv);
3805
3806 /*
3807 * Check if the region and channel requires a channel
3808 * availability check.
3809 */
3810 if (wlan_11h_radar_detect_required(pmpriv,
3811 pmpriv->adhoc_channel) &&
3812 !wlan_11h_is_channel_under_nop(pmadapter,
3813 pmpriv->adhoc_channel)) {
3814 /*
3815 * Radar detection is required for this channel, make
3816 * sure 11h is activated in the firmware
3817 */
3818 ret = wlan_11h_activate(pmpriv, MNULL, MTRUE);
3819 ret = wlan_11h_config_master_radar_det(pmpriv, MTRUE);
3820 ret = wlan_11h_check_update_radar_det_state(pmpriv);
3821
3822 /* Check for radar on the channel */
3823 if ((pmadapter->chan_bandwidth ==
3824 CHANNEL_BW_40MHZ_ABOVE) ||
3825 (pmadapter->chan_bandwidth ==
3826 CHANNEL_BW_40MHZ_BELOW)) {
3827 chan_width = CHAN_BW_40MHZ;
3828 if (pmadapter->chanrpt_param_bandcfg) {
3829 bandcfg.chan2Offset =
3830 pmadapter->chan_bandwidth;
3831 }
3832 } else if (pmadapter->chan_bandwidth ==
3833 CHANNEL_BW_80MHZ)
3834 chan_width = CHAN_BW_80MHZ;
3835 if (pmadapter->chanrpt_param_bandcfg) {
3836 bandcfg.chanWidth = chan_width;
3837 bandcfg.chanBand = BAND_5GHZ;
3838 } else {
3839 *((t_u8 *)&bandcfg) = chan_width;
3840 }
3841
3842 ret = wlan_11h_issue_radar_detect(pmpriv, pioctl_req,
3843 pmpriv->adhoc_channel,
3844 bandcfg);
3845 if (ret == MLAN_STATUS_SUCCESS)
3846 ret = MLAN_STATUS_PENDING;
3847 }
3848 }
3849
3850 LEAVE();
3851 return ret;
3852 }
3853
3854 /**
3855 * @brief 802.11h set/get local power constraint
3856 *
3857 * @param pmadapter A pointer to mlan_adapter structure
3858 * @param pioctl_req A pointer to ioctl request buffer
3859 *
3860 * @return MLAN_STATUS_SUCCESS
3861 */
3862 static mlan_status
wlan_11h_ioctl_local_power_constraint(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3863 wlan_11h_ioctl_local_power_constraint(pmlan_adapter pmadapter,
3864 pmlan_ioctl_req pioctl_req)
3865 {
3866 mlan_ds_11h_cfg *ds_11hcfg = MNULL;
3867 t_s8 *plocalpower = &pmadapter->state_11h.usr_def_power_constraint;
3868
3869 ENTER();
3870
3871 ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
3872
3873 if (pioctl_req->action == MLAN_ACT_GET)
3874 ds_11hcfg->param.usr_local_power_constraint = *plocalpower;
3875 else
3876 *plocalpower = ds_11hcfg->param.usr_local_power_constraint;
3877
3878 LEAVE();
3879 return MLAN_STATUS_SUCCESS;
3880 }
3881
3882 /**
3883 * @brief 11h configuration handler
3884 *
3885 * @param pmadapter A pointer to mlan_adapter structure
3886 * @param pioctl_req A pointer to ioctl request buffer
3887 *
3888 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
3889 * otherwise fail
3890 */
wlan_11h_cfg_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3891 static mlan_status wlan_11h_cfg_ioctl(pmlan_adapter pmadapter,
3892 pmlan_ioctl_req pioctl_req)
3893 {
3894 mlan_status status = MLAN_STATUS_SUCCESS;
3895 mlan_ds_11h_cfg *ds_11hcfg = MNULL;
3896
3897 ENTER();
3898
3899 if (pioctl_req->buf_len < sizeof(mlan_ds_11h_cfg)) {
3900 PRINTM(MWARN, "MLAN 11H IOCTL length is too short.\n");
3901 pioctl_req->data_read_written = 0;
3902 pioctl_req->buf_len_needed = sizeof(mlan_ds_11h_cfg);
3903 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3904 LEAVE();
3905 return MLAN_STATUS_RESOURCE;
3906 }
3907 ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
3908
3909 switch (ds_11hcfg->sub_command) {
3910 case MLAN_OID_11H_CHANNEL_CHECK:
3911 status = wlan_11h_channel_check_req(pmadapter, pioctl_req);
3912 break;
3913 case MLAN_OID_11H_LOCAL_POWER_CONSTRAINT:
3914 status = wlan_11h_ioctl_local_power_constraint(pmadapter,
3915 pioctl_req);
3916 break;
3917 case MLAN_OID_11H_DFS_TESTING:
3918 status = wlan_11h_ioctl_dfs_testing(pmadapter, pioctl_req);
3919 break;
3920 case MLAN_OID_11H_DFS_W53_CFG:
3921 status = wlan_11h_ioctl_dfs_w53_cfg(pmadapter, pioctl_req);
3922 break;
3923 default:
3924 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3925 status = MLAN_STATUS_FAILURE;
3926 break;
3927 }
3928
3929 LEAVE();
3930 return status;
3931 }
3932
3933 /**
3934 * @brief Set/Get generic IE
3935 *
3936 * @param pmadapter A pointer to mlan_adapter structure
3937 * @param pioctl_req A pointer to ioctl request buffer
3938 *
3939 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
3940 */
wlan_misc_ioctl_gen_ie(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3941 static mlan_status wlan_misc_ioctl_gen_ie(pmlan_adapter pmadapter,
3942 pmlan_ioctl_req pioctl_req)
3943 {
3944 mlan_status ret = MLAN_STATUS_SUCCESS;
3945 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3946 mlan_ds_misc_cfg *misc = MNULL;
3947
3948 ENTER();
3949
3950 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
3951 switch (misc->param.gen_ie.type) {
3952 case MLAN_IE_TYPE_GEN_IE:
3953 if (pioctl_req->action == MLAN_ACT_GET) {
3954 misc->param.gen_ie.len = pmpriv->wpa_ie_len;
3955 memcpy_ext(pmadapter, misc->param.gen_ie.ie_data,
3956 pmpriv->wpa_ie, misc->param.gen_ie.len,
3957 MAX_IE_SIZE);
3958 } else {
3959 ret = wlan_set_gen_ie_helper(
3960 pmpriv, misc->param.gen_ie.ie_data,
3961 (t_u16)misc->param.gen_ie.len);
3962 }
3963 break;
3964 case MLAN_IE_TYPE_ARP_FILTER:
3965 memset(pmadapter, pmadapter->arp_filter, 0,
3966 sizeof(pmadapter->arp_filter));
3967 if (misc->param.gen_ie.len > ARP_FILTER_MAX_BUF_SIZE) {
3968 pmadapter->arp_filter_size = 0;
3969 PRINTM(MERROR, "Invalid ARP Filter Size\n");
3970 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3971 ret = MLAN_STATUS_FAILURE;
3972 } else if (misc->param.gen_ie.len <=
3973 sizeof(MrvlIEtypesHeader_t)) {
3974 pmadapter->arp_filter_size = 0;
3975 PRINTM(MINFO, "Clear ARP filter\n");
3976 } else {
3977 memcpy_ext(pmadapter, pmadapter->arp_filter,
3978 misc->param.gen_ie.ie_data,
3979 misc->param.gen_ie.len,
3980 ARP_FILTER_MAX_BUF_SIZE);
3981 pmadapter->arp_filter_size = misc->param.gen_ie.len;
3982 HEXDUMP("ArpFilter", pmadapter->arp_filter,
3983 pmadapter->arp_filter_size);
3984 }
3985 break;
3986 default:
3987 PRINTM(MERROR, "Invalid IE type\n");
3988 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3989 ret = MLAN_STATUS_FAILURE;
3990 }
3991 pioctl_req->data_read_written =
3992 sizeof(mlan_ds_misc_gen_ie) + MLAN_SUB_COMMAND_SIZE;
3993 LEAVE();
3994 return ret;
3995 }
3996
3997 /**
3998 * @brief Perform warm reset
3999 *
4000 * @param pmadapter A pointer to mlan_adapter structure
4001 * @param pioctl_req A pointer to ioctl request buffer
4002 *
4003 * @return MLAN_STATUS_PENDING --success, MLAN_STATUS_FAILURE
4004 */
wlan_misc_ioctl_warm_reset(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4005 mlan_status wlan_misc_ioctl_warm_reset(pmlan_adapter pmadapter,
4006 pmlan_ioctl_req pioctl_req)
4007 {
4008 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
4009 mlan_status ret = MLAN_STATUS_SUCCESS;
4010 pmlan_callbacks pcb = &pmadapter->callbacks;
4011 pmlan_buffer pmbuf;
4012 t_s32 i = 0;
4013 mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4014
4015 ENTER();
4016 mlan_block_rx_process(pmadapter, MTRUE);
4017
4018 /* Cancel all pending commands and complete ioctls */
4019 if (misc->param.fw_reload)
4020 wlan_cancel_all_pending_cmd(pmadapter, MTRUE);
4021
4022 /** Init all the head nodes and free all the locks here */
4023 for (i = 0; i < pmadapter->priv_num; i++)
4024 wlan_free_priv(pmadapter->priv[i]);
4025
4026 while ((pmbuf = (pmlan_buffer)util_dequeue_list(
4027 pmadapter->pmoal_handle, &pmadapter->rx_data_queue,
4028 pcb->moal_spin_lock, pcb->moal_spin_unlock))) {
4029 pmadapter->ops.data_complete(pmadapter, pmbuf,
4030 MLAN_STATUS_FAILURE);
4031 }
4032 pmadapter->rx_pkts_queued = 0;
4033
4034 /* Initialize adapter structure */
4035 wlan_init_adapter(pmadapter);
4036 pmadapter->hw_status = WlanHardwareStatusInitializing;
4037
4038 /* Initialize private structures */
4039 for (i = 0; i < pmadapter->priv_num; i++) {
4040 if (pmadapter->priv[i])
4041 wlan_init_priv(pmadapter->priv[i]);
4042 }
4043 mlan_block_rx_process(pmadapter, MFALSE);
4044
4045 if (misc->param.fw_reload != MTRUE) {
4046 /* Restart the firmware */
4047 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_FUNC_SHUTDOWN,
4048 HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
4049 if (ret)
4050 goto done;
4051 }
4052
4053 /* Issue firmware initialize commands for first BSS,
4054 * for other interfaces it will be called after getting
4055 * the last init command response of previous interface
4056 */
4057 pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
4058 if (!pmpriv) {
4059 ret = MLAN_STATUS_FAILURE;
4060 LEAVE();
4061 return ret;
4062 }
4063 ret = wlan_adapter_get_hw_spec(pmpriv->adapter);
4064 if (ret == MLAN_STATUS_FAILURE) {
4065 LEAVE();
4066 return ret;
4067 }
4068 ret = pmpriv->ops.init_cmd(pmpriv, MTRUE);
4069 if (ret == MLAN_STATUS_FAILURE) {
4070 LEAVE();
4071 return ret;
4072 }
4073 if (ret == MLAN_STATUS_PENDING)
4074 pmadapter->pwarm_reset_ioctl_req = pioctl_req;
4075 done:
4076 LEAVE();
4077 return ret;
4078 }
4079
4080 #ifdef SDIO
4081 /**
4082 * @brief Reconfigure SDIO multiport aggregation parameters
4083 *
4084 * @param pmadapter A pointer to mlan_adapter structure
4085 * @param pioctl_req A pointer to ioctl request buffer
4086 *
4087 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
4088 */
wlan_misc_ioctl_sdio_mpa_ctrl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4089 static mlan_status wlan_misc_ioctl_sdio_mpa_ctrl(pmlan_adapter pmadapter,
4090 pmlan_ioctl_req pioctl_req)
4091 {
4092 mlan_status ret = MLAN_STATUS_SUCCESS;
4093 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
4094 mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4095 mlan_ds_misc_sdio_mpa_ctrl *mpa_ctrl = MNULL;
4096
4097 ENTER();
4098
4099 mpa_ctrl = &misc->param.mpa_ctrl;
4100
4101 if (pioctl_req->action == MLAN_ACT_SET) {
4102 if (pmpriv->media_connected == MTRUE) {
4103 PRINTM(MMSG,
4104 "SDIO MPA CTRL: not allowed in connected state\n");
4105 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
4106 ret = MLAN_STATUS_FAILURE;
4107 goto exit;
4108 }
4109
4110 if (mpa_ctrl->tx_enable > 1) {
4111 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4112 ret = MLAN_STATUS_FAILURE;
4113 goto exit;
4114 }
4115
4116 if (mpa_ctrl->rx_enable > 1) {
4117 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4118 ret = MLAN_STATUS_FAILURE;
4119 goto exit;
4120 }
4121
4122 if (mpa_ctrl->tx_max_ports > SDIO_MP_AGGR_DEF_PKT_LIMIT) {
4123 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4124 ret = MLAN_STATUS_FAILURE;
4125 goto exit;
4126 }
4127
4128 if (mpa_ctrl->rx_max_ports > SDIO_MP_AGGR_DEF_PKT_LIMIT) {
4129 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4130 ret = MLAN_STATUS_FAILURE;
4131 goto exit;
4132 }
4133
4134 if (mpa_ctrl->tx_buf_size || mpa_ctrl->rx_buf_size) {
4135 wlan_free_sdio_mpa_buffers(pmadapter);
4136
4137 if (mpa_ctrl->tx_buf_size > 0)
4138 pmadapter->pcard_sd->mpa_tx.buf_size =
4139 mpa_ctrl->tx_buf_size;
4140
4141 if (mpa_ctrl->rx_buf_size > 0)
4142 pmadapter->pcard_sd->mpa_rx.buf_size =
4143 mpa_ctrl->rx_buf_size;
4144
4145 if (wlan_alloc_sdio_mpa_buffers(
4146 pmadapter,
4147 pmadapter->pcard_sd->mpa_tx.buf_size,
4148 pmadapter->pcard_sd->mpa_rx.buf_size) !=
4149 MLAN_STATUS_SUCCESS) {
4150 PRINTM(MERROR,
4151 "Failed to allocate sdio mp-a buffers\n");
4152 pioctl_req->status_code = MLAN_ERROR_NO_MEM;
4153 ret = MLAN_STATUS_FAILURE;
4154 goto exit;
4155 }
4156 }
4157
4158 if (mpa_ctrl->tx_max_ports > 0)
4159 pmadapter->pcard_sd->mpa_tx.pkt_aggr_limit =
4160 mpa_ctrl->tx_max_ports;
4161 if (mpa_ctrl->rx_max_ports > 0)
4162 pmadapter->pcard_sd->mpa_rx.pkt_aggr_limit =
4163 mpa_ctrl->rx_max_ports;
4164
4165 pmadapter->pcard_sd->mpa_tx.enabled = (t_u8)mpa_ctrl->tx_enable;
4166 pmadapter->pcard_sd->mpa_rx.enabled = (t_u8)mpa_ctrl->rx_enable;
4167
4168 } else {
4169 mpa_ctrl->tx_enable =
4170 (t_u16)pmadapter->pcard_sd->mpa_tx.enabled;
4171 mpa_ctrl->rx_enable =
4172 (t_u16)pmadapter->pcard_sd->mpa_rx.enabled;
4173 mpa_ctrl->tx_buf_size =
4174 (t_u16)pmadapter->pcard_sd->mpa_tx.buf_size;
4175 mpa_ctrl->rx_buf_size =
4176 (t_u16)pmadapter->pcard_sd->mpa_rx.buf_size;
4177 mpa_ctrl->tx_max_ports =
4178 (t_u16)pmadapter->pcard_sd->mpa_tx.pkt_aggr_limit;
4179 mpa_ctrl->rx_max_ports =
4180 (t_u16)pmadapter->pcard_sd->mpa_rx.pkt_aggr_limit;
4181 }
4182
4183 exit:
4184 LEAVE();
4185 return ret;
4186 }
4187 #endif
4188
4189 /**
4190 * @brief Set/Get system clock configuration
4191 *
4192 * @param pmadapter A pointer to mlan_adapter structure
4193 * @param pioctl_req A pointer to ioctl request buffer
4194 *
4195 * @return MLAN_STATUS_PENDING --success, otherwise fail
4196 */
wlan_misc_ioctl_sysclock(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4197 static mlan_status wlan_misc_ioctl_sysclock(pmlan_adapter pmadapter,
4198 pmlan_ioctl_req pioctl_req)
4199 {
4200 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4201 mlan_ds_misc_cfg *misc = MNULL;
4202 mlan_status ret = MLAN_STATUS_SUCCESS;
4203 t_u16 cmd_action = 0;
4204
4205 ENTER();
4206
4207 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4208 if (pioctl_req->action == MLAN_ACT_GET)
4209 cmd_action = HostCmd_ACT_GEN_GET;
4210 else
4211 cmd_action = HostCmd_ACT_GEN_SET;
4212
4213 /* Send request to firmware */
4214 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_ECL_SYSTEM_CLOCK_CONFIG,
4215 cmd_action, 0, (t_void *)pioctl_req,
4216 (t_void *)&misc->param.sys_clock);
4217
4218 if (ret == MLAN_STATUS_SUCCESS)
4219 ret = MLAN_STATUS_PENDING;
4220
4221 LEAVE();
4222 return ret;
4223 }
4224
4225 /**
4226 * @brief Get the associate response
4227 *
4228 * @param pmadapter A pointer to mlan_adapter structure
4229 * @param pioctl_req A pointer to ioctl request buffer
4230 *
4231 * @return MLAN_STATUS_SUCCESS --success
4232 */
wlan_misc_ioctl_get_assoc_rsp(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4233 static mlan_status wlan_misc_ioctl_get_assoc_rsp(pmlan_adapter pmadapter,
4234 pmlan_ioctl_req pioctl_req)
4235 {
4236 mlan_ds_misc_cfg *misc = MNULL;
4237 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4238 mlan_status ret = MLAN_STATUS_SUCCESS;
4239
4240 ENTER();
4241
4242 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4243 if ((pioctl_req->action == MLAN_ACT_GET) && pmpriv->assoc_rsp_size) {
4244 memcpy_ext(pmadapter, misc->param.assoc_resp.assoc_resp_buf,
4245 pmpriv->assoc_rsp_buf, pmpriv->assoc_rsp_size,
4246 ASSOC_RSP_BUF_SIZE);
4247 misc->param.assoc_resp.assoc_resp_len =
4248 MIN(ASSOC_RSP_BUF_SIZE, pmpriv->assoc_rsp_size);
4249 }
4250
4251 LEAVE();
4252 return ret;
4253 }
4254
4255 /**
4256 * @brief Get the associate request IEs
4257 *
4258 * @param pmadapter A pointer to mlan_adapter structure
4259 * @param pioctl_req A pointer to ioctl request buffer
4260 *
4261 * @return MLAN_STATUS_SUCCESS --success
4262 */
wlan_misc_ioctl_get_assoc_req(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4263 static mlan_status wlan_misc_ioctl_get_assoc_req(pmlan_adapter pmadapter,
4264 pmlan_ioctl_req pioctl_req)
4265 {
4266 mlan_ds_misc_cfg *misc = MNULL;
4267 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4268 mlan_status ret = MLAN_STATUS_SUCCESS;
4269
4270 ENTER();
4271
4272 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4273 if ((pioctl_req->action == MLAN_ACT_GET) && pmpriv->assoc_req_size) {
4274 memcpy_ext(pmadapter, misc->param.assoc_req.assoc_req_buf,
4275 pmpriv->assoc_req_buf, pmpriv->assoc_req_size,
4276 ASSOC_RSP_BUF_SIZE);
4277 misc->param.assoc_req.assoc_req_len =
4278 MIN(ASSOC_RSP_BUF_SIZE, pmpriv->assoc_req_size);
4279 }
4280
4281 LEAVE();
4282 return ret;
4283 }
4284
4285 /**
4286 * @brief Send function softreset command to firmware
4287 *
4288 * @param pmadapter A pointer to mlan_adapter structure
4289 * @param pioctl_req A pointer to ioctl request buffer
4290 *
4291 * @return MLAN_STATUS_PENDING --success, otherwise fail
4292 */
wlan_misc_ioctl_soft_reset(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4293 static mlan_status wlan_misc_ioctl_soft_reset(pmlan_adapter pmadapter,
4294 pmlan_ioctl_req pioctl_req)
4295 {
4296 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4297 mlan_status ret = MLAN_STATUS_SUCCESS;
4298
4299 ENTER();
4300 /* Send command to firmware */
4301 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SOFT_RESET,
4302 HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
4303 MNULL);
4304
4305 if (ret == MLAN_STATUS_SUCCESS)
4306 ret = MLAN_STATUS_PENDING;
4307 LEAVE();
4308 return ret;
4309 }
4310
4311 /**
4312 * @brief Get the thermal reading
4313 *
4314 * @param pmadapter A pointer to mlan_adapter structure
4315 * @param pioctl_req A pointer to ioctl request buffer
4316 *
4317 * @return MLAN_STATUS_PENDING -- success, otherwise fail
4318 */
wlan_misc_ioctl_thermal(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4319 static mlan_status wlan_misc_ioctl_thermal(pmlan_adapter pmadapter,
4320 pmlan_ioctl_req pioctl_req)
4321 {
4322 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4323 mlan_status ret = MLAN_STATUS_SUCCESS;
4324 t_u16 cmd_action = 0;
4325
4326 ENTER();
4327
4328 if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) {
4329 PRINTM(MWARN,
4330 "MLAN IOCTL information buffer length is too short.\n");
4331 pioctl_req->data_read_written = 0;
4332 pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
4333 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4334 LEAVE();
4335 return MLAN_STATUS_RESOURCE;
4336 }
4337
4338 if (pioctl_req->action == MLAN_ACT_SET) {
4339 PRINTM(MERROR, "Thermal reading setting is not allowed!\n");
4340 LEAVE();
4341 return MLAN_STATUS_FAILURE;
4342 } else {
4343 cmd_action = HostCmd_ACT_GEN_GET;
4344 }
4345
4346 /* Send command to firmware */
4347 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB, cmd_action,
4348 Thermal_i, (t_void *)pioctl_req, MNULL);
4349
4350 if (ret == MLAN_STATUS_SUCCESS)
4351 ret = MLAN_STATUS_PENDING;
4352
4353 LEAVE();
4354 return ret;
4355 }
4356
4357 /**
4358 * @brief Get/Set subscribe event
4359 *
4360 * @param pmadapter A pointer to mlan_adapter structure
4361 * @param pioctl_req A pointer to ioctl request buffer
4362 *
4363 * @return MLAN_STATUS_PENDING -- success, otherwise fail
4364 */
wlan_misc_ioctl_subscribe_evt(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4365 static mlan_status wlan_misc_ioctl_subscribe_evt(pmlan_adapter pmadapter,
4366 pmlan_ioctl_req pioctl_req)
4367 {
4368 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4369 mlan_status ret = MLAN_STATUS_SUCCESS;
4370 mlan_ds_misc_cfg *misc = MNULL;
4371 t_u16 cmd_action = 0;
4372
4373 ENTER();
4374
4375 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4376 if (pioctl_req->action == MLAN_ACT_SET)
4377 cmd_action = HostCmd_ACT_GEN_SET;
4378 else
4379 cmd_action = HostCmd_ACT_GEN_GET;
4380
4381 /* Send command to firmware */
4382 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
4383 cmd_action, 0, (t_void *)pioctl_req,
4384 &misc->param.subscribe_event);
4385
4386 if (ret == MLAN_STATUS_SUCCESS)
4387 ret = MLAN_STATUS_PENDING;
4388
4389 LEAVE();
4390 return ret;
4391 }
4392
4393 /**
4394 * @brief Get/Set fw auto reconnect
4395 *
4396 * @param pmadapter A pointer to mlan_adapter structure
4397 * @param pioctl_req A pointer to ioctl request buffer
4398 *
4399 * @return MLAN_STATUS_PENDING -- success, otherwise fail
4400 */
wlan_misc_ioctl_fw_auto_reconnect(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4401 static mlan_status wlan_misc_ioctl_fw_auto_reconnect(pmlan_adapter pmadapter,
4402 pmlan_ioctl_req pioctl_req)
4403 {
4404 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4405 mlan_status ret = MLAN_STATUS_SUCCESS;
4406 mlan_ds_misc_cfg *misc = MNULL;
4407 t_u16 cmd_action = 0;
4408
4409 ENTER();
4410
4411 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4412 if (pioctl_req->action == MLAN_ACT_SET)
4413 cmd_action = HostCmd_ACT_GEN_SET;
4414 else
4415 cmd_action = HostCmd_ACT_GEN_GET;
4416
4417 /* Send command to firmware */
4418 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_FW_AUTO_RECONNECT,
4419 cmd_action, 0, (t_void *)pioctl_req,
4420 &misc->param.fw_auto_reconnect);
4421
4422 if (ret == MLAN_STATUS_SUCCESS)
4423 ret = MLAN_STATUS_PENDING;
4424
4425 LEAVE();
4426 return ret;
4427 }
4428
4429 /**
4430 * @brief Set ARP filter based on IP address
4431 *
4432 * @param pmadapter A pointer to mlan_adapter structure
4433 * @param pioctl_req A pointer to ioctl request buffer
4434 * @param ipv4_addr ipv4 Address
4435 *
4436 * @return MLAN_STATUS_PENDING --success, otherwise fail
4437 */
wlan_ipaddr_arp_filter(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req,t_u32 ipv4_addr)4438 static mlan_status wlan_ipaddr_arp_filter(pmlan_adapter pmadapter,
4439 pmlan_ioctl_req pioctl_req,
4440 t_u32 ipv4_addr)
4441 {
4442 mlan_status ret = MLAN_STATUS_SUCCESS;
4443 pmlan_callbacks pcb = &pmadapter->callbacks;
4444 t_u8 *buf;
4445 arpfilter_header *arpfilter = MNULL;
4446 filter_entry *entry = MNULL;
4447 t_u32 len;
4448
4449 ENTER();
4450
4451 pcb->moal_malloc(pmadapter->pmoal_handle, MRVDRV_SIZE_OF_CMD_BUFFER,
4452 MLAN_MEM_DEF, &buf);
4453 if (!buf) {
4454 ret = MLAN_STATUS_FAILURE;
4455 goto done;
4456 }
4457
4458 /* Construct the ARP filter TLV */
4459 arpfilter = (arpfilter_header *)buf;
4460 arpfilter->type = wlan_cpu_to_le16(TLV_TYPE_ARP_FILTER);
4461
4462 if (ipv4_addr) {
4463 arpfilter->len = wlan_cpu_to_le16(sizeof(filter_entry) * 3);
4464 entry = (filter_entry *)(buf + sizeof(arpfilter_header));
4465 entry->addr_type = wlan_cpu_to_le16(ADDR_TYPE_BROADCAST);
4466 entry->eth_type = wlan_cpu_to_le16(ETHER_TYPE_ARP);
4467 entry->ipv4_addr = wlan_cpu_to_le32(ipv4_addr);
4468 entry++;
4469 entry->addr_type = wlan_cpu_to_le16(ADDR_TYPE_UNICAST);
4470 entry->eth_type = wlan_cpu_to_le16(ETHER_TYPE_ANY);
4471 entry->ipv4_addr = wlan_cpu_to_le32(IPV4_ADDR_ANY);
4472 entry++;
4473 entry->addr_type = wlan_cpu_to_le16(ADDR_TYPE_MULTICAST);
4474 entry->eth_type = wlan_cpu_to_le16(ETHER_TYPE_ANY);
4475 entry->ipv4_addr = wlan_cpu_to_le32(IPV4_ADDR_ANY);
4476 } else
4477 arpfilter->len = 0;
4478
4479 /* Update the total length */
4480 len = sizeof(arpfilter_header) + wlan_le16_to_cpu(arpfilter->len);
4481
4482 memset(pmadapter, pmadapter->arp_filter, 0,
4483 sizeof(pmadapter->arp_filter));
4484 if (len > ARP_FILTER_MAX_BUF_SIZE) {
4485 pmadapter->arp_filter_size = 0;
4486 PRINTM(MERROR, "Invalid ARP Filter Size\n");
4487 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4488 ret = MLAN_STATUS_FAILURE;
4489 } else if (len <= sizeof(MrvlIEtypesHeader_t)) {
4490 pmadapter->arp_filter_size = 0;
4491 PRINTM(MINFO, "Clear ARP filter\n");
4492 } else {
4493 memcpy_ext(pmadapter, pmadapter->arp_filter, buf, len,
4494 ARP_FILTER_MAX_BUF_SIZE);
4495 pmadapter->arp_filter_size = len;
4496 HEXDUMP("ArpFilter", pmadapter->arp_filter,
4497 pmadapter->arp_filter_size);
4498 }
4499
4500 done:
4501 if (buf)
4502 pcb->moal_mfree(pmadapter->pmoal_handle, buf);
4503 LEAVE();
4504 return ret;
4505 }
4506
4507 /**
4508 * @brief MEF configuration
4509 *
4510 * @param pmadapter A pointer to mlan_adapter structure
4511 * @param pioctl_req A pointer to ioctl request buffer
4512 *
4513 * @return MLAN_STATUS_PENDING --success, otherwise fail
4514 */
wlan_misc_ioctl_mef_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4515 static mlan_status wlan_misc_ioctl_mef_cfg(pmlan_adapter pmadapter,
4516 pmlan_ioctl_req pioctl_req)
4517 {
4518 mlan_status ret = MLAN_STATUS_SUCCESS;
4519 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4520 mlan_ds_misc_mef_cfg *mef_cfg =
4521 &((mlan_ds_misc_cfg *)pioctl_req->pbuf)->param.mef_cfg;
4522 pmlan_callbacks pcb = &pmadapter->callbacks;
4523 HostCmd_DS_GEN *hostcmd_hdr;
4524 HostCmd_DS_MEF_CFG *mefcmd;
4525 mlan_ds_misc_cmd *hostcmd = MNULL;
4526 t_u32 buf_len = 0;
4527 t_u8 *buf, *filter;
4528 t_u8 fltr_buf[] = {0x02, 0x00, 0x2f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
4529 0x01, 0x00, 0x5e, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00,
4530 0x01, 0x41, 0x06, 0x00, 0x00, 0x00, 0x01, 0xff, 0x01,
4531 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41, 0x45, 0x01,
4532 0x00, 0x00, 0x00, 0x01, 0x33, 0x33, 0x02, 0x02, 0x00,
4533 0x00, 0x00, 0x00, 0x01, 0x41, 0x45};
4534
4535 ENTER();
4536
4537 /* GET operation */
4538 if (pioctl_req->action == MLAN_ACT_GET) {
4539 /* TODO: need to store for get operation */
4540 goto done;
4541 }
4542
4543 ret = pcb->moal_malloc(pmadapter->pmoal_handle,
4544 sizeof(mlan_ds_misc_cmd), MLAN_MEM_DEF,
4545 (t_u8 **)&hostcmd);
4546
4547 if (ret != MLAN_STATUS_SUCCESS || hostcmd == MNULL) {
4548 PRINTM(MERROR, "Failed to allocate hostcmd buffer\n");
4549 pioctl_req->status_code = MLAN_ERROR_NO_MEM;
4550 ret = MLAN_STATUS_FAILURE;
4551 goto done;
4552 }
4553
4554 memset(pmpriv->adapter, hostcmd, 0, sizeof(mlan_ds_misc_cmd));
4555 buf = hostcmd->cmd;
4556
4557 /* Prepare hostcmd buffer */
4558 hostcmd_hdr = (HostCmd_DS_GEN *)(buf);
4559 hostcmd_hdr->command = wlan_cpu_to_le16(HostCmd_CMD_MEF_CFG);
4560 mefcmd = (HostCmd_DS_MEF_CFG *)(buf + S_DS_GEN);
4561 buf_len = S_DS_GEN;
4562
4563 switch (mef_cfg->sub_id) {
4564 case MEF_CFG_DISABLE:
4565 PRINTM(MINFO, "Disable MEF\n");
4566 mefcmd->criteria = wlan_cpu_to_le32(0);
4567 mefcmd->nentries = wlan_cpu_to_le16(0);
4568 buf_len += sizeof(HostCmd_DS_MEF_CFG);
4569 break;
4570 case MEF_CFG_RX_FILTER_ENABLE:
4571 PRINTM(MINFO, "Enable Rx filter\n");
4572 mefcmd->criteria = wlan_cpu_to_le32((MBIT(3) | MBIT(0)));
4573 mefcmd->nentries = wlan_cpu_to_le16(1);
4574 buf_len += sizeof(HostCmd_DS_MEF_CFG);
4575 filter = buf + buf_len;
4576 memcpy_ext(pmpriv->adapter, filter, fltr_buf, sizeof(fltr_buf),
4577 MRVDRV_SIZE_OF_CMD_BUFFER - buf_len);
4578 buf_len += sizeof(fltr_buf);
4579 break;
4580 case MEF_CFG_AUTO_ARP_RESP:
4581 PRINTM(MINFO, "Enable auto ARP response\n");
4582 /* TODO */
4583 break;
4584 case MEF_CFG_HOSTCMD:
4585 PRINTM(MINFO, "MEF hostcmd from MOAL\n");
4586 filter = buf + buf_len;
4587 memcpy_ext(pmpriv->adapter, filter, mef_cfg->param.cmd_buf.cmd,
4588 mef_cfg->param.cmd_buf.len,
4589 MRVDRV_SIZE_OF_CMD_BUFFER - buf_len);
4590 buf_len += mef_cfg->param.cmd_buf.len;
4591 break;
4592 default:
4593 PRINTM(MERROR, "Invalid sub ID parameter\n");
4594 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4595 ret = MLAN_STATUS_FAILURE;
4596 goto done;
4597 break;
4598 }
4599 hostcmd_hdr->size = wlan_cpu_to_le16(buf_len);
4600 hostcmd->len = buf_len;
4601
4602 /* Send command to firmware */
4603 ret = wlan_prepare_cmd(pmpriv, 0, 0, 0, (t_void *)pioctl_req,
4604 (t_void *)hostcmd);
4605 if (ret == MLAN_STATUS_SUCCESS)
4606 ret = MLAN_STATUS_PENDING;
4607
4608 done:
4609 if (hostcmd)
4610 pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)hostcmd);
4611
4612 LEAVE();
4613 return ret;
4614 }
4615
4616 /**
4617 * @brief ipaddr configuration
4618 *
4619 * @param pmadapter A pointer to mlan_adapter structure
4620 * @param pioctl_req A pointer to ioctl request buffer
4621 *
4622 * @return MLAN_STATUS_PENDING --success, otherwise fail
4623 */
wlan_misc_ioctl_ipaddr_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4624 static mlan_status wlan_misc_ioctl_ipaddr_cfg(pmlan_adapter pmadapter,
4625 pmlan_ioctl_req pioctl_req)
4626 {
4627 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4628 mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4629 mlan_status ret = MLAN_STATUS_SUCCESS;
4630 t_u32 ipv4_addr[MAX_IPADDR] = {0};
4631 int i = 0;
4632
4633 ENTER();
4634
4635 /* GET operation */
4636 if (pioctl_req->action == MLAN_ACT_GET) {
4637 memcpy_ext(pmadapter, misc->param.ipaddr_cfg.ip_addr,
4638 pmpriv->ip_addr, IPADDR_LEN, IPADDR_LEN);
4639 misc->param.ipaddr_cfg.op_code = pmpriv->op_code;
4640 goto done;
4641 }
4642 /* only one IP is supported in current firmware */
4643 for (i = 0; i < (int)misc->param.ipaddr_cfg.ip_addr_num; i++) {
4644 memcpy_ext(pmadapter, &ipv4_addr[i],
4645 misc->param.ipaddr_cfg.ip_addr[i], sizeof(t_u32),
4646 sizeof(t_u32));
4647 }
4648
4649 if (misc->param.ipaddr_cfg.op_code != MLAN_IPADDR_OP_IP_REMOVE &&
4650 !misc->param.ipaddr_cfg.ip_addr_num) {
4651 PRINTM(MERROR, "Invalid IPv4 address\n");
4652 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4653 ret = MLAN_STATUS_FAILURE;
4654 goto done;
4655 }
4656 if (misc->param.ipaddr_cfg.op_code & MLAN_IPADDR_OP_ARP_FILTER)
4657 ret = wlan_ipaddr_arp_filter(pmadapter, pioctl_req,
4658 ipv4_addr[0]);
4659 else if (pmpriv->op_code & MLAN_IPADDR_OP_ARP_FILTER)
4660 ret = wlan_ipaddr_arp_filter(pmadapter, pioctl_req, 0);
4661 if (ret == MLAN_STATUS_FAILURE)
4662 goto done;
4663
4664 /* Save the values in MLAN */
4665 if (pioctl_req->action == MLAN_ACT_SET) {
4666 pmpriv->op_code = misc->param.ipaddr_cfg.op_code;
4667 memcpy_ext(pmadapter, pmpriv->ip_addr,
4668 misc->param.ipaddr_cfg.ip_addr, IPADDR_LEN,
4669 IPADDR_LEN);
4670 }
4671
4672 done:
4673 LEAVE();
4674 return ret;
4675 }
4676
4677 /**
4678 * @brief CFP code configuration
4679 *
4680 * @param pmadapter A pointer to mlan_adapter structure
4681 * @param pioctl_req A pointer to ioctl request buffer
4682 *
4683 * @return MLAN_STATUS_PENDING --success, otherwise fail
4684 */
wlan_misc_ioctl_cfp_code_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4685 static mlan_status wlan_misc_ioctl_cfp_code_cfg(pmlan_adapter pmadapter,
4686 pmlan_ioctl_req pioctl_req)
4687 {
4688 mlan_status ret = MLAN_STATUS_SUCCESS;
4689 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4690 mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4691 mlan_ds_misc_cfp_code *cfp_code = MNULL;
4692 t_u32 region_bg = 0;
4693 t_u32 region_a = 0;
4694 int i;
4695
4696 ENTER();
4697
4698 cfp_code = &misc->param.cfp_code;
4699 if (pioctl_req->action == MLAN_ACT_SET) {
4700 if (pmadapter->otp_region && pmadapter->otp_region->force_reg) {
4701 PRINTM(MERROR,
4702 "ForceRegionRule is set in the on-chip OTP"
4703 "memory\n");
4704 ret = MLAN_STATUS_FAILURE;
4705 goto done;
4706 }
4707 /* Save the values in MLAN */
4708 if (!cfp_code->cfp_code_bg)
4709 cfp_code->cfp_code_bg = pmadapter->cfp_code_bg;
4710 for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
4711 /* Use the region code to search for the index */
4712 if (cfp_code->cfp_code_bg == region_code_index[i]) {
4713 region_bg = cfp_code->cfp_code_bg;
4714 break;
4715 }
4716 }
4717 if (!cfp_code->cfp_code_a)
4718 cfp_code->cfp_code_a = pmadapter->cfp_code_a;
4719 for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
4720 /* Use the region code to search for the index */
4721 if (cfp_code->cfp_code_a == region_code_index[i]) {
4722 region_a = cfp_code->cfp_code_a;
4723 break;
4724 }
4725 }
4726 if (!region_a) {
4727 for (i = 0; i < MRVDRV_MAX_CFP_CODE_A; i++) {
4728 /* Use the CFP code to search for the index */
4729 if (cfp_code->cfp_code_a == cfp_code_index_a[i])
4730 break;
4731 }
4732 if (i >= MRVDRV_MAX_CFP_CODE_A) {
4733 PRINTM(MERROR,
4734 "CFP Code not identified for A\n");
4735 pioctl_req->status_code =
4736 MLAN_ERROR_INVALID_PARAMETER;
4737 ret = MLAN_STATUS_FAILURE;
4738 goto done;
4739 }
4740 }
4741 pmadapter->cfp_code_bg = (t_u8)cfp_code->cfp_code_bg;
4742 pmadapter->cfp_code_a = (t_u8)cfp_code->cfp_code_a;
4743 if (region_bg && region_a && (region_bg == region_a))
4744 pmadapter->region_code = pmadapter->cfp_code_a;
4745 else
4746 pmadapter->region_code = 0;
4747 if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
4748 pmadapter->config_bands |
4749 pmadapter->adhoc_start_band)) {
4750 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4751 ret = MLAN_STATUS_FAILURE;
4752 goto done;
4753 }
4754 } else {
4755 /* GET operation */
4756 cfp_code->cfp_code_bg = pmadapter->cfp_code_bg;
4757 cfp_code->cfp_code_a = pmadapter->cfp_code_a;
4758 }
4759
4760 done:
4761 LEAVE();
4762 return ret;
4763 }
4764
4765 /**
4766 * @brief This function sets up country code and downloads CMD to FW
4767 *
4768 * @param pmadapter A pointer to mlan_adapter structure
4769 * @param pioctl_req Pointer to the IOCTL request buffer
4770 *
4771 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4772 */
wlan_misc_ioctl_country_code(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)4773 static mlan_status wlan_misc_ioctl_country_code(pmlan_adapter pmadapter,
4774 mlan_ioctl_req *pioctl_req)
4775 {
4776 mlan_status ret = MLAN_STATUS_SUCCESS;
4777 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4778 mlan_ds_misc_country_code *country_code = MNULL;
4779 mlan_ds_misc_cfg *cfg_misc = MNULL;
4780 t_u8 cfp_bg = 0, cfp_a = 0;
4781
4782 ENTER();
4783
4784 cfg_misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4785 country_code = &cfg_misc->param.country_code;
4786
4787 if (pioctl_req->action == MLAN_ACT_SET) {
4788 if (pmadapter->otp_region && pmadapter->otp_region->force_reg) {
4789 PRINTM(MERROR,
4790 "ForceRegionRule is set in the on-chip OTP"
4791 "memory\n");
4792 ret = MLAN_STATUS_FAILURE;
4793 goto done;
4794 }
4795 /* Update region code and table based on country code */
4796 if (wlan_misc_country_2_cfp_table_code(
4797 pmadapter, country_code->country_code, &cfp_bg,
4798 &cfp_a)) {
4799 PRINTM(MERROR, "Country code not found!\n");
4800 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4801 ret = MLAN_STATUS_FAILURE;
4802 goto done;
4803 }
4804 pmadapter->cfp_code_bg = cfp_bg;
4805 pmadapter->cfp_code_a = cfp_a;
4806 if (cfp_a)
4807 pmadapter->region_code = cfp_a;
4808 else if (cfp_bg)
4809 pmadapter->region_code = cfp_bg;
4810 else
4811 pmadapter->region_code = 0;
4812 if (wlan_set_regiontable(pmpriv, pmadapter->region_code,
4813 pmadapter->config_bands |
4814 pmadapter->adhoc_start_band)) {
4815 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4816 ret = MLAN_STATUS_FAILURE;
4817 goto done;
4818 }
4819 memcpy_ext(pmadapter, pmadapter->country_code,
4820 country_code->country_code, COUNTRY_CODE_LEN,
4821 COUNTRY_CODE_LEN);
4822 } else {
4823 /* GET operation */
4824 memcpy_ext(pmadapter, country_code->country_code,
4825 pmadapter->country_code, COUNTRY_CODE_LEN,
4826 COUNTRY_CODE_LEN);
4827 }
4828
4829 done:
4830 LEAVE();
4831 return ret;
4832 }
4833
4834 /**
4835 * @brief Configure MFPC and MFPR for management frame protection
4836 *
4837 * @param pmadapter A pointer to mlan_adapter structure
4838 * @param pioctl_req Pointer to the IOCTL request buffer
4839 *
4840 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4841 */
wlan_misc_pmfcfg(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)4842 static mlan_status wlan_misc_pmfcfg(pmlan_adapter pmadapter,
4843 mlan_ioctl_req *pioctl_req)
4844 {
4845 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
4846 mlan_status ret = MLAN_STATUS_SUCCESS;
4847 mlan_ds_misc_cfg *cfg_misc = MNULL;
4848 mlan_ds_misc_pmfcfg *pmfcfg;
4849
4850 cfg_misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4851 pmfcfg = &cfg_misc->param.pmfcfg;
4852
4853 if (pioctl_req->action == MLAN_ACT_SET) {
4854 pmpriv->pmfcfg.mfpc = pmfcfg->mfpc;
4855 pmpriv->pmfcfg.mfpr = pmfcfg->mfpr;
4856 } else {
4857 /* GET operation */
4858 pmfcfg->mfpc = pmpriv->pmfcfg.mfpc;
4859 pmfcfg->mfpr = pmpriv->pmfcfg.mfpr;
4860 }
4861
4862 LEAVE();
4863 return ret;
4864 }
4865
4866 /**
4867 * @brief HW ARB Cfg
4868 *
4869 * @param pmadapter A pointer to mlan_adapter structure
4870 * @param pioctl_req A pointer to ioctl request buffer
4871 *
4872 * @return MLAN_STATUS_PENDING --success, otherwise fail
4873 */
wlan_misc_ioctl_arb_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4874 mlan_status wlan_misc_ioctl_arb_cfg(pmlan_adapter pmadapter,
4875 pmlan_ioctl_req pioctl_req)
4876 {
4877 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4878 mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4879 mlan_status ret = MLAN_STATUS_SUCCESS;
4880 t_u16 cmd_action = 0;
4881
4882 ENTER();
4883
4884 if (pioctl_req->action == MLAN_ACT_SET)
4885 cmd_action = HostCmd_ACT_GEN_SET;
4886 else
4887 cmd_action = HostCmd_ACT_GEN_GET;
4888 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_ARB_CONFIG, cmd_action, 0,
4889 (t_void *)pioctl_req, &(pmisc->param.arb_cfg));
4890 if (ret == MLAN_STATUS_SUCCESS)
4891 ret = MLAN_STATUS_PENDING;
4892
4893 LEAVE();
4894 return ret;
4895 }
4896
4897 /**
4898 * @brief Save tp accounting command configurations.
4899 *
4900 * @param pmadapter A pointer to mlan_adapter structure
4901 * @param pioctl_req A pointer to ioctl request buffer
4902 *
4903 * @return MLAN_STATUS_PENDING --success, otherwise fail
4904 */
wlan_misc_ioctl_tp_state(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4905 mlan_status wlan_misc_ioctl_tp_state(pmlan_adapter pmadapter,
4906 pmlan_ioctl_req pioctl_req)
4907 {
4908 mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4909 mlan_status ret = MLAN_STATUS_SUCCESS;
4910
4911 ENTER();
4912
4913 pmadapter->tp_state_on = pmisc->param.tp_state.on;
4914 pmadapter->tp_state_drop_point = pmisc->param.tp_state.drop_point;
4915
4916 LEAVE();
4917 return ret;
4918 }
4919
wlan_misc_ioctl_ips_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4920 static mlan_status wlan_misc_ioctl_ips_cfg(pmlan_adapter pmadapter,
4921 pmlan_ioctl_req pioctl_req)
4922 {
4923 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
4924 mlan_ds_misc_cfg *misc = MNULL;
4925 t_u16 cmd_action = 0;
4926 mlan_status ret = MLAN_STATUS_SUCCESS;
4927
4928 ENTER();
4929
4930 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4931 cmd_action = HostCmd_ACT_GEN_SET;
4932
4933 /* Send request to firmware */
4934 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_IPS_CONFIG, cmd_action, 0,
4935 (t_void *)pioctl_req, &misc->param.ips_ctrl);
4936
4937 if (ret == MLAN_STATUS_SUCCESS)
4938 ret = MLAN_STATUS_PENDING;
4939
4940 LEAVE();
4941 return ret;
4942 }
4943
4944 /**
4945 * @brief IPv6 Router Advertisement offload configuration
4946 *
4947 * @param pmadapter A pointer to mlan_adapter structure
4948 * @param pioctl_req Pointer to the IOCTL request buffer
4949 *
4950 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4951 */
wlan_misc_ioctl_ipv6_ra_offload(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)4952 mlan_status wlan_misc_ioctl_ipv6_ra_offload(pmlan_adapter pmadapter,
4953 mlan_ioctl_req *pioctl_req)
4954 {
4955 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
4956 mlan_ds_misc_cfg *misc = MNULL;
4957 t_u16 cmd_action = 0;
4958 mlan_status ret = MLAN_STATUS_SUCCESS;
4959
4960 ENTER();
4961
4962 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4963 if (pioctl_req->action == MLAN_ACT_SET)
4964 cmd_action = HostCmd_ACT_GEN_SET;
4965 else if (pioctl_req->action == MLAN_ACT_GET)
4966 cmd_action = HostCmd_ACT_GEN_GET;
4967
4968 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_IPV6_RA_OFFLOAD_CFG,
4969 cmd_action, 0, (t_void *)pioctl_req,
4970 &misc->param.ipv6_ra_offload);
4971 if (ret == MLAN_STATUS_SUCCESS)
4972 ret = MLAN_STATUS_PENDING;
4973
4974 LEAVE();
4975 return ret;
4976 }
4977
4978 /**
4979 * @brief Gtk Rekey Offload
4980 *
4981 * @param pmadapter A pointer to mlan_adapter structure
4982 * @param pioctl_req A pointer to ioctl request buffer
4983 *
4984 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
4985 */
wlan_misc_ioctl_gtk_rekey_offload(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4986 static mlan_status wlan_misc_ioctl_gtk_rekey_offload(pmlan_adapter pmadapter,
4987 pmlan_ioctl_req pioctl_req)
4988 {
4989 mlan_status ret = MLAN_STATUS_SUCCESS;
4990 mlan_ds_misc_cfg *misc_cfg = MNULL;
4991 t_u16 cmd_action = 0;
4992 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4993
4994 ENTER();
4995 misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4996 if (pioctl_req->action == MLAN_ACT_SET)
4997 cmd_action = HostCmd_ACT_GEN_SET;
4998 else if (pioctl_req->action == MLAN_ACT_CLEAR)
4999 cmd_action = HostCmd_ACT_GEN_REMOVE;
5000 else
5001 cmd_action = HostCmd_ACT_GEN_GET;
5002
5003 if (!pmpriv->wpa_is_gtk_set) {
5004 /* Store the gtk rekey data if it has already set gtk */
5005 memcpy_ext(pmadapter, &pmpriv->gtk_rekey,
5006 &misc_cfg->param.gtk_rekey,
5007 sizeof(mlan_ds_misc_gtk_rekey_data),
5008 sizeof(mlan_ds_misc_gtk_rekey_data));
5009 LEAVE();
5010 return ret;
5011 }
5012 /* Send request to firmware if it hasn't set gtk yet */
5013 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG,
5014 cmd_action, 0, (t_void *)pioctl_req,
5015 &misc_cfg->param.gtk_rekey);
5016
5017 if (ret == MLAN_STATUS_SUCCESS)
5018 ret = MLAN_STATUS_PENDING;
5019
5020 LEAVE();
5021 return ret;
5022 }
5023
5024 /**
5025 * @brief enable/disable roam offload in firmware
5026 *
5027 * @param pmadapter A pointer to mlan_adapter structure
5028 * @param pioctl_req Pointer to the IOCTL request buffer
5029 *
5030 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
5031 */
wlan_misc_roam_offload(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)5032 static mlan_status wlan_misc_roam_offload(pmlan_adapter pmadapter,
5033 mlan_ioctl_req *pioctl_req)
5034 {
5035 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
5036 mlan_ds_misc_cfg *misc = MNULL;
5037 t_u16 cmd_action = 0;
5038 mlan_status ret = MLAN_STATUS_SUCCESS;
5039
5040 ENTER();
5041
5042 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
5043
5044 if (!(pmadapter->fw_cap_info & FW_ROAMING_SUPPORT)) {
5045 PRINTM(MERROR, "Firmware roaming not support\n");
5046 LEAVE();
5047 return MLAN_STATUS_FAILURE;
5048 }
5049
5050 if (!IS_FW_SUPPORT_SUPPLICANT(pmadapter)) {
5051 PRINTM(MERROR, "Embedded supplicant do not enable\n");
5052 LEAVE();
5053 return MLAN_STATUS_FAILURE;
5054 }
5055
5056 if ((misc->param.roam_offload.config_mode == ROAM_OFFLOAD_ENABLE) &&
5057 misc->param.roam_offload.userset_passphrase) {
5058 pmpriv->adapter->userset_passphrase =
5059 misc->param.roam_offload.userset_passphrase;
5060 if (!misc->param.roam_offload.enable) {
5061 LEAVE();
5062 return MLAN_STATUS_SUCCESS;
5063 }
5064 }
5065
5066 if (pioctl_req->action == MLAN_ACT_SET)
5067 cmd_action = HostCmd_ACT_GEN_SET;
5068 else {
5069 PRINTM(MERROR, "Unsupported cmd_action\n");
5070 LEAVE();
5071 return MLAN_STATUS_FAILURE;
5072 }
5073
5074 /* Send request to firmware */
5075 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_ROAM_OFFLOAD, cmd_action, 0,
5076 (t_void *)pioctl_req, &misc->param.roam_offload);
5077
5078 if (ret == MLAN_STATUS_SUCCESS)
5079 ret = MLAN_STATUS_PENDING;
5080
5081 LEAVE();
5082 return ret;
5083 }
5084
5085 /**
5086 * @brief set roam offload aplist to firmware
5087 *
5088 * @param pmadapter A pointer to mlan_adapter structure
5089 * @param pioctl_req Pointer to the IOCTL request buffer
5090 *
5091 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
5092 */
wlan_misc_roam_offload_aplist(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)5093 static mlan_status wlan_misc_roam_offload_aplist(pmlan_adapter pmadapter,
5094 mlan_ioctl_req *pioctl_req)
5095 {
5096 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
5097 mlan_ds_misc_cfg *misc = MNULL;
5098 t_u16 cmd_action = 0;
5099 mlan_status ret = MLAN_STATUS_SUCCESS;
5100
5101 ENTER();
5102
5103 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
5104
5105 if (pioctl_req->action == MLAN_ACT_SET)
5106 cmd_action = HostCmd_ACT_GEN_SET;
5107 else {
5108 PRINTM(MERROR, "Unsupported cmd_action\n");
5109 LEAVE();
5110 return MLAN_STATUS_FAILURE;
5111 }
5112
5113 /* Send request to firmware */
5114 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_ROAM_OFFLOAD, cmd_action, 0,
5115 (t_void *)pioctl_req, &misc->param.roam_offload);
5116
5117 if (ret == MLAN_STATUS_SUCCESS)
5118 ret = MLAN_STATUS_PENDING;
5119
5120 LEAVE();
5121 return ret;
5122 }
5123
5124 /**
5125 * @brief cloud keep alive
5126 *
5127 * @param pmadapter A pointer to mlan_adapter structure
5128 * @param pioctl_req Pointer to the IOCTL request buffer
5129 *
5130 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
5131 */
wlan_misc_cloud_keep_alive(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)5132 static mlan_status wlan_misc_cloud_keep_alive(pmlan_adapter pmadapter,
5133 mlan_ioctl_req *pioctl_req)
5134 {
5135 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
5136 mlan_ds_misc_cfg *misc = MNULL;
5137 t_u16 cmd_action = 0;
5138 mlan_status ret = MLAN_STATUS_SUCCESS;
5139
5140 ENTER();
5141
5142 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
5143
5144 if (pioctl_req->action == MLAN_ACT_SET)
5145 cmd_action = HostCmd_ACT_GEN_SET;
5146 else if (pioctl_req->action == MLAN_ACT_GET) {
5147 cmd_action = HostCmd_ACT_GEN_GET;
5148 } else if (pioctl_req->action == MLAN_ACT_RESET) {
5149 cmd_action = HostCmd_ACT_GEN_RESET;
5150 } else {
5151 cmd_action = HostCmd_ACT_GEN_REMOVE;
5152 }
5153
5154 /* Send request to firmware */
5155 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_AUTO_TX, cmd_action,
5156 OID_CLOUD_KEEP_ALIVE, (t_void *)pioctl_req,
5157 &misc->param.keep_alive);
5158
5159 if (ret == MLAN_STATUS_SUCCESS)
5160 ret = MLAN_STATUS_PENDING;
5161
5162 LEAVE();
5163 return ret;
5164 }
5165
5166 /**
5167 * @brief Miscellaneous configuration handler
5168 *
5169 * @param pmadapter A pointer to mlan_adapter structure
5170 * @param pioctl_req A pointer to ioctl request buffer
5171 *
5172 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
5173 * otherwise fail
5174 */
wlan_misc_cfg_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)5175 static mlan_status wlan_misc_cfg_ioctl(pmlan_adapter pmadapter,
5176 pmlan_ioctl_req pioctl_req)
5177 {
5178 mlan_status status = MLAN_STATUS_SUCCESS;
5179 mlan_ds_misc_cfg *misc = MNULL;
5180
5181 ENTER();
5182
5183 if ((pioctl_req == MNULL) || (pioctl_req->pbuf == MNULL)) {
5184 PRINTM(MERROR, "Request buffer not found!\n");
5185 LEAVE();
5186 return MLAN_STATUS_FAILURE;
5187 }
5188 if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) {
5189 PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
5190 pioctl_req->data_read_written = 0;
5191 pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
5192 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
5193 LEAVE();
5194 return MLAN_STATUS_RESOURCE;
5195 }
5196 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
5197 switch (misc->sub_command) {
5198 case MLAN_OID_MISC_GEN_IE:
5199 status = wlan_misc_ioctl_gen_ie(pmadapter, pioctl_req);
5200 break;
5201 case MLAN_OID_MISC_REGION:
5202 status = wlan_misc_ioctl_region(pmadapter, pioctl_req);
5203 break;
5204 case MLAN_OID_MISC_WARM_RESET:
5205 PRINTM(MCMND, "Request WARM RESET\n");
5206 util_enqueue_list_tail(pmadapter->pmoal_handle,
5207 &pmadapter->ioctl_pending_q,
5208 (pmlan_linked_list)pioctl_req,
5209 pmadapter->callbacks.moal_spin_lock,
5210 pmadapter->callbacks.moal_spin_unlock);
5211 pmadapter->pending_ioctl = MTRUE;
5212 status = MLAN_STATUS_PENDING;
5213 break;
5214 #ifdef SDIO
5215 case MLAN_OID_MISC_SDIO_MPA_CTRL:
5216 status = wlan_misc_ioctl_sdio_mpa_ctrl(pmadapter, pioctl_req);
5217 break;
5218 #endif
5219 case MLAN_OID_MISC_HOST_CMD:
5220 status = wlan_misc_ioctl_host_cmd(pmadapter, pioctl_req);
5221 break;
5222 case MLAN_OID_MISC_SYS_CLOCK:
5223 status = wlan_misc_ioctl_sysclock(pmadapter, pioctl_req);
5224 break;
5225 case MLAN_OID_MISC_WWS:
5226 status = wlan_misc_ioctl_wws_cfg(pmadapter, pioctl_req);
5227 break;
5228 case MLAN_OID_MISC_ASSOC_RSP:
5229 status = wlan_misc_ioctl_get_assoc_rsp(pmadapter, pioctl_req);
5230 break;
5231 case MLAN_OID_MISC_ASSOC_REQ:
5232 status = wlan_misc_ioctl_get_assoc_req(pmadapter, pioctl_req);
5233 break;
5234 case MLAN_OID_MISC_INIT_SHUTDOWN:
5235 status = wlan_misc_ioctl_init_shutdown(pmadapter, pioctl_req);
5236 break;
5237 case MLAN_OID_MISC_SOFT_RESET:
5238 status = wlan_misc_ioctl_soft_reset(pmadapter, pioctl_req);
5239 break;
5240 case MLAN_OID_MISC_CUSTOM_IE:
5241 status = wlan_misc_ioctl_custom_ie_list(pmadapter, pioctl_req,
5242 MTRUE);
5243 break;
5244 case MLAN_OID_MISC_TDLS_CONFIG:
5245 status = wlan_misc_ioctl_tdls_config(pmadapter, pioctl_req);
5246 break;
5247 case MLAN_OID_MISC_TDLS_OPER:
5248 status = wlan_misc_ioctl_tdls_oper(pmadapter, pioctl_req);
5249 break;
5250 case MLAN_OID_MISC_GET_TDLS_IES:
5251 status = wlan_misc_ioctl_tdls_get_ies(pmadapter, pioctl_req);
5252 break;
5253 case MLAN_OID_MISC_TDLS_CS_CHANNEL:
5254 status = wlan_misc_ioctl_tdls_cs_channel(pmadapter, pioctl_req);
5255 break;
5256 case MLAN_OID_MISC_TDLS_IDLE_TIME:
5257 status = wlan_misc_ioctl_tdls_idle_time(pmadapter, pioctl_req);
5258 break;
5259
5260 case MLAN_OID_MISC_NET_MONITOR:
5261 status = wlan_misc_ioctl_net_monitor(pmadapter, pioctl_req);
5262 break;
5263 case MLAN_OID_MISC_MAC_CONTROL:
5264 status = wlan_misc_ioctl_mac_control(pmadapter, pioctl_req);
5265 break;
5266 case MLAN_OID_MISC_MEF_CFG:
5267 status = wlan_misc_ioctl_mef_cfg(pmadapter, pioctl_req);
5268 break;
5269 case MLAN_OID_MISC_RX_MGMT_IND:
5270 status = wlan_reg_rx_mgmt_ind(pmadapter, pioctl_req);
5271 break;
5272 #ifdef DEBUG_LEVEL1
5273 case MLAN_OID_MISC_DRVDBG:
5274 status = wlan_set_drvdbg(pmadapter, pioctl_req);
5275 break;
5276 #endif
5277 case MLAN_OID_MISC_IP_ADDR:
5278 status = wlan_misc_ioctl_ipaddr_cfg(pmadapter, pioctl_req);
5279 break;
5280 case MLAN_OID_MISC_CFP_CODE:
5281 status = wlan_misc_ioctl_cfp_code_cfg(pmadapter, pioctl_req);
5282 break;
5283 case MLAN_OID_MISC_COUNTRY_CODE:
5284 status = wlan_misc_ioctl_country_code(pmadapter, pioctl_req);
5285 break;
5286 case MLAN_OID_MISC_THERMAL:
5287 status = wlan_misc_ioctl_thermal(pmadapter, pioctl_req);
5288 break;
5289 case MLAN_OID_MISC_SUBSCRIBE_EVENT:
5290 status = wlan_misc_ioctl_subscribe_evt(pmadapter, pioctl_req);
5291 break;
5292 case MLAN_OID_MISC_HOTSPOT_CFG:
5293 status = wlan_misc_hotspot_cfg(pmadapter, pioctl_req);
5294 break;
5295 case MLAN_OID_MISC_OTP_USER_DATA:
5296 status = wlan_misc_otp_user_data(pmadapter, pioctl_req);
5297 break;
5298 case MLAN_OID_MISC_AUTO_ASSOC:
5299 status = wlan_misc_ioctl_fw_auto_reconnect(pmadapter,
5300 pioctl_req);
5301 break;
5302 #ifdef USB
5303 case MLAN_OID_MISC_USB_AGGR_CTRL:
5304 status = wlan_misc_ioctl_usb_aggr_ctrl(pmadapter, pioctl_req);
5305 break;
5306 #endif
5307 case MLAN_OID_MISC_AGGR_CTRL:
5308 status = wlan_misc_ioctl_aggr_ctrl(pmadapter, pioctl_req);
5309 break;
5310 case MLAN_OID_MISC_TXCONTROL:
5311 status = wlan_misc_ioctl_txcontrol(pmadapter, pioctl_req);
5312 break;
5313 #ifdef STA_SUPPORT
5314 case MLAN_OID_MISC_EXT_CAP_CFG:
5315 status = wlan_misc_ext_capa_cfg(pmadapter, pioctl_req);
5316 break;
5317 #endif
5318 case MLAN_OID_MISC_PMFCFG:
5319 status = wlan_misc_pmfcfg(pmadapter, pioctl_req);
5320 break;
5321 #ifdef RX_PACKET_COALESCE
5322 case MLAN_OID_MISC_RX_PACKET_COALESCE:
5323 status = wlan_misc_ioctl_rx_pkt_coalesce_config(pmadapter,
5324 pioctl_req);
5325 break;
5326 #endif
5327 case MLAN_OID_MISC_LOW_PWR_MODE:
5328 status = wlan_misc_ioctl_low_pwr_mode(pmadapter, pioctl_req);
5329 break;
5330 case MLAN_OID_MISC_PMIC_CFG:
5331 status = wlan_misc_ioctl_pmic_configure(pmadapter, pioctl_req);
5332 break;
5333 case MLAN_OID_MISC_CWMODE_CTRL:
5334 status = wlan_misc_ioctl_cwmode_ctrl(pmadapter, pioctl_req);
5335 break;
5336 case MLAN_OID_MISC_MEF_FLT_CFG:
5337 status = wlan_misc_ioctl_mef_flt_cfg(pmadapter, pioctl_req);
5338 break;
5339 case MLAN_OID_MISC_DFS_REAPTER_MODE:
5340 status =
5341 wlan_misc_ioctl_dfs_repeater_cfg(pmadapter, pioctl_req);
5342 break;
5343 case MLAN_OID_MISC_COALESCE_CFG:
5344 status = wlan_misc_ioctl_coalesce_cfg(pmadapter, pioctl_req);
5345 break;
5346 case MLAN_OID_MISC_GET_SENSOR_TEMP:
5347 status = wlan_misc_ioctl_get_sensor_temp(pmadapter, pioctl_req);
5348 break;
5349 case MLAN_OID_MISC_OPER_CLASS:
5350 status = wlan_misc_ioctl_oper_class(pmadapter, pioctl_req);
5351 break;
5352 case MLAN_OID_MISC_OPER_CLASS_CHECK:
5353 status = wlan_misc_ioctl_operclass_validation(pmadapter,
5354 pioctl_req);
5355 break;
5356 case MLAN_OID_MISC_IPV6_RA_OFFLOAD:
5357 status = wlan_misc_ioctl_ipv6_ra_offload(pmadapter, pioctl_req);
5358 break;
5359 case MLAN_OID_MISC_GTK_REKEY_OFFLOAD:
5360 status = wlan_misc_ioctl_gtk_rekey_offload(pmadapter,
5361 pioctl_req);
5362 break;
5363 case MLAN_OID_MISC_IND_RST_CFG:
5364 status = wlan_misc_ioctl_ind_rst_cfg(pmadapter, pioctl_req);
5365 break;
5366 case MLAN_OID_MISC_MC_AGGR_CFG:
5367 status = wlan_misc_ioctl_mc_aggr_cfg(pmadapter, pioctl_req);
5368 break;
5369 case MLAN_OID_MISC_CH_LOAD:
5370 status = wlan_misc_ioctl_ch_load(pmadapter, pioctl_req);
5371 break;
5372 case MLAN_OID_MISC_CH_LOAD_RESULTS:
5373 status = wlan_misc_ioctl_ch_load_results(pmadapter, pioctl_req);
5374 break;
5375 case MLAN_OID_MISC_GET_TSF:
5376 status = wlan_misc_ioctl_get_tsf(pmadapter, pioctl_req);
5377 break;
5378 case MLAN_OID_MISC_ROAM_OFFLOAD:
5379 status = wlan_misc_roam_offload(pmadapter, pioctl_req);
5380 break;
5381 case MLAN_OID_MISC_ROAM_OFFLOAD_APLIST:
5382 status = wlan_misc_roam_offload_aplist(pmadapter, pioctl_req);
5383 break;
5384 case MLAN_OID_MISC_GET_CHAN_REGION_CFG:
5385 status = wlan_misc_chan_reg_cfg(pmadapter, pioctl_req);
5386 break;
5387 case MLAN_OID_MISC_CLOUD_KEEP_ALIVE:
5388 status = wlan_misc_cloud_keep_alive(pmadapter, pioctl_req);
5389 break;
5390 case MLAN_OID_MISC_DYN_BW:
5391 status = wlan_misc_ioctl_dyn_bw(pmadapter, pioctl_req);
5392 break;
5393 case MLAN_OID_MISC_FW_DUMP_EVENT:
5394 status = wlan_misc_ioctl_fw_dump_event(pmadapter, pioctl_req);
5395 break;
5396 case MLAN_OID_MISC_PER_PKT_CFG:
5397 status = wlan_misc_per_pkt_cfg(pmadapter, pioctl_req);
5398 break;
5399 case MLAN_OID_MISC_ROBUSTCOEX:
5400 status = wlan_misc_robustcoex(pmadapter, pioctl_req);
5401 break;
5402 case MLAN_OID_MISC_DMCS_CONFIG:
5403 status = wlan_misc_dmcs_config(pmadapter, pioctl_req);
5404 break;
5405 case MLAN_OID_MISC_GET_TX_RX_HISTOGRAM:
5406 status = wlan_get_tx_rx_histogram(pmadapter, pioctl_req);
5407 break;
5408 case MLAN_OID_MISC_BOOT_SLEEP:
5409 status = wlan_misc_bootsleep(pmadapter, pioctl_req);
5410 break;
5411 case MLAN_OID_MISC_CFP_INFO:
5412 status = wlan_get_cfpinfo(pmadapter, pioctl_req);
5413 break;
5414 #if defined(PCIE)
5415 case MLAN_OID_MISC_SSU:
5416 if (pmadapter->ssu_buf)
5417 status = MLAN_STATUS_FAILURE;
5418 else
5419 status = wlan_misc_ssu(pmadapter, pioctl_req);
5420 break;
5421 #endif
5422 case MLAN_OID_MISC_CSI:
5423 status = wlan_misc_csi(pmadapter, pioctl_req);
5424 break;
5425 case MLAN_OID_MISC_HAL_PHY_CFG:
5426 status = wlan_misc_hal_phy_cfg(pmadapter, pioctl_req);
5427 break;
5428 case MLAN_OID_MISC_GPIO_TSF_LATCH:
5429 status = wlan_misc_gpio_tsf_latch_config(pmadapter, pioctl_req);
5430 break;
5431 case MLAN_OID_MISC_GET_TSF_INFO:
5432 status = wlan_misc_get_tsf_info(pmadapter, pioctl_req);
5433 break;
5434 case MLAN_OID_MISC_RX_ABORT_CFG:
5435 status = wlan_misc_ioctl_rxabortcfg(pmadapter, pioctl_req);
5436 break;
5437 case MLAN_OID_MISC_RX_ABORT_CFG_EXT:
5438 status = wlan_misc_ioctl_rxabortcfg_ext(pmadapter, pioctl_req);
5439 break;
5440 case MLAN_OID_MISC_TX_AMPDU_PROT_MODE:
5441 status = wlan_misc_ioctl_tx_ampdu_prot_mode(pmadapter,
5442 pioctl_req);
5443 break;
5444 case MLAN_OID_MISC_DOT11MC_UNASSOC_FTM_CFG:
5445 status = wlan_misc_ioctl_dot11mc_unassoc_ftm_cfg(pmadapter,
5446 pioctl_req);
5447 break;
5448 case MLAN_OID_MISC_RATE_ADAPT_CFG:
5449 status = wlan_misc_ioctl_rate_adapt_cfg(pmadapter, pioctl_req);
5450 break;
5451 case MLAN_OID_MISC_CCK_DESENSE_CFG:
5452 status = wlan_misc_ioctl_cck_desense_cfg(pmadapter, pioctl_req);
5453 break;
5454 case MLAN_OID_MISC_GET_REGIONPWR_CFG:
5455 status = wlan_get_rgchnpwr_cfg(pmadapter, pioctl_req);
5456 break;
5457 case MLAN_OID_MISC_GET_CHAN_TRPC_CFG:
5458 status = wlan_get_chan_trpc_cfg(pmadapter, pioctl_req);
5459 break;
5460 case MLAN_OID_MISC_RF_TEST_GENERIC:
5461 case MLAN_OID_MISC_RF_TEST_TX_CONT:
5462 case MLAN_OID_MISC_RF_TEST_TX_FRAME:
5463 case MLAN_OID_MISC_RF_TEST_HE_POWER:
5464 status = wlan_misc_ioctl_rf_test_cfg(pmadapter, pioctl_req);
5465 break;
5466 case MLAN_OID_MISC_ARB_CONFIG:
5467 status = wlan_misc_ioctl_arb_cfg(pmadapter, pioctl_req);
5468 break;
5469 case MLAN_OID_MISC_RANGE_EXT:
5470 status = wlan_misc_ioctl_range_ext(pmadapter, pioctl_req);
5471 break;
5472 case MLAN_OID_MISC_TP_STATE:
5473 status = wlan_misc_ioctl_tp_state(pmadapter, pioctl_req);
5474 break;
5475 case MLAN_OID_MISC_IPS_CFG:
5476 status = wlan_misc_ioctl_ips_cfg(pmadapter, pioctl_req);
5477 break;
5478 default:
5479 if (pioctl_req)
5480 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
5481 status = MLAN_STATUS_FAILURE;
5482 break;
5483 }
5484 LEAVE();
5485 return status;
5486 }
5487
5488 /**
5489 * @brief Set/Get scan configuration parameter
5490 *
5491 * @param pmadapter A pointer to mlan_adapter structure
5492 * @param pioctl_req A pointer to ioctl request buffer
5493 * @param action Set/Get
5494 *
5495 * @return MLAN_STATUS_SUCCESS --success
5496 */
wlan_set_get_scan_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req,t_u32 action)5497 static mlan_status wlan_set_get_scan_cfg(pmlan_adapter pmadapter,
5498 pmlan_ioctl_req pioctl_req,
5499 t_u32 action)
5500 {
5501 mlan_ds_scan *scan = MNULL;
5502
5503 ENTER();
5504
5505 scan = (mlan_ds_scan *)pioctl_req->pbuf;
5506 if (action == MLAN_ACT_SET) {
5507 if (scan->param.scan_cfg.scan_type)
5508 pmadapter->scan_type =
5509 (t_u8)scan->param.scan_cfg.scan_type;
5510 if (scan->param.scan_cfg.scan_mode)
5511 pmadapter->scan_mode = scan->param.scan_cfg.scan_mode;
5512 if (scan->param.scan_cfg.scan_probe)
5513 pmadapter->scan_probes =
5514 (t_u16)scan->param.scan_cfg.scan_probe;
5515 if (scan->param.scan_cfg.scan_time.specific_scan_time)
5516 pmadapter->specific_scan_time =
5517 (t_u16)scan->param.scan_cfg.scan_time
5518 .specific_scan_time;
5519 if (scan->param.scan_cfg.scan_time.active_scan_time)
5520 pmadapter->active_scan_time =
5521 (t_u16)scan->param.scan_cfg.scan_time
5522 .active_scan_time;
5523 if (scan->param.scan_cfg.scan_time.passive_scan_time)
5524 pmadapter->passive_scan_time =
5525 (t_u16)scan->param.scan_cfg.scan_time
5526 .passive_scan_time;
5527 if (scan->param.scan_cfg.passive_to_active_scan)
5528 pmadapter->passive_to_active_scan =
5529 scan->param.scan_cfg.passive_to_active_scan;
5530 if (scan->param.scan_cfg.ext_scan)
5531 pmadapter->ext_scan = scan->param.scan_cfg.ext_scan - 1;
5532 pmadapter->scan_chan_gap = scan->param.scan_cfg.scan_chan_gap;
5533 }
5534 scan->param.scan_cfg.scan_type = (t_u32)pmadapter->scan_type;
5535 scan->param.scan_cfg.scan_mode = pmadapter->scan_mode;
5536 scan->param.scan_cfg.scan_probe = (t_u32)pmadapter->scan_probes;
5537 scan->param.scan_cfg.scan_time.specific_scan_time =
5538 (t_u32)pmadapter->specific_scan_time;
5539 scan->param.scan_cfg.scan_time.active_scan_time =
5540 (t_u32)pmadapter->active_scan_time;
5541 scan->param.scan_cfg.scan_time.passive_scan_time =
5542 (t_u32)pmadapter->passive_scan_time;
5543 scan->param.scan_cfg.passive_to_active_scan =
5544 pmadapter->passive_to_active_scan;
5545 scan->param.scan_cfg.ext_scan = pmadapter->ext_scan + 1;
5546 scan->param.scan_cfg.scan_chan_gap = pmadapter->scan_chan_gap;
5547 pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
5548
5549 LEAVE();
5550 return MLAN_STATUS_SUCCESS;
5551 }
5552
5553 /**
5554 * @brief Set/Get scan
5555 *
5556 * @param pmadapter A pointer to mlan_adapter structure
5557 * @param pioctl_req A pointer to ioctl request buffer
5558 *
5559 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
5560 * otherwise fail
5561 */
wlan_scan_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)5562 static mlan_status wlan_scan_ioctl(pmlan_adapter pmadapter,
5563 pmlan_ioctl_req pioctl_req)
5564 {
5565 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
5566 mlan_status status = MLAN_STATUS_SUCCESS;
5567 mlan_ds_scan *pscan;
5568
5569 ENTER();
5570
5571 pscan = (mlan_ds_scan *)pioctl_req->pbuf;
5572 if (pscan->sub_command == MLAN_OID_SCAN_CONFIG ||
5573 pscan->sub_command == MLAN_OID_SCAN_BGSCAN_CONFIG)
5574 goto start_config;
5575 if (pmadapter->scan_processing && pioctl_req->action == MLAN_ACT_SET &&
5576 pscan->sub_command != MLAN_OID_SCAN_CANCEL) {
5577 PRINTM(MINFO, "Scan already in process...\n");
5578 LEAVE();
5579 return status;
5580 }
5581
5582 if (pmadapter->enable_net_mon == CHANNEL_SPEC_SNIFFER_MODE) {
5583 PRINTM(MINFO,
5584 "Scan is blocked in Channel Specified Network Monitor mode...\n");
5585 LEAVE();
5586 return MLAN_STATUS_FAILURE;
5587 }
5588
5589 if (pmadapter->scan_block && pioctl_req->action == MLAN_ACT_SET) {
5590 PRINTM(MERROR, "Scan is blocked during association...\n");
5591 LEAVE();
5592 return MLAN_STATUS_FAILURE;
5593 }
5594 start_config:
5595 /* Set scan */
5596 if (pioctl_req->action == MLAN_ACT_SET) {
5597 switch (pscan->sub_command) {
5598 case MLAN_OID_SCAN_NORMAL:
5599 status = wlan_scan_networks(pmpriv, pioctl_req, MNULL);
5600 break;
5601 case MLAN_OID_SCAN_SPECIFIC_SSID:
5602 status = wlan_scan_specific_ssid(
5603 pmpriv, pioctl_req,
5604 &pscan->param.scan_req.scan_ssid);
5605 break;
5606 case MLAN_OID_SCAN_USER_CONFIG:
5607 status = wlan_scan_networks(
5608 pmpriv, pioctl_req,
5609 (wlan_user_scan_cfg *)
5610 pscan->param.user_scan.scan_cfg_buf);
5611 break;
5612 case MLAN_OID_SCAN_CONFIG:
5613 status = wlan_set_get_scan_cfg(pmadapter, pioctl_req,
5614 MLAN_ACT_SET);
5615 break;
5616 case MLAN_OID_SCAN_CANCEL:
5617 status = wlan_cancel_pending_scan_cmd(pmadapter,
5618 pioctl_req);
5619 break;
5620 case MLAN_OID_SCAN_TABLE_FLUSH:
5621 status = wlan_flush_scan_table(pmadapter);
5622 break;
5623 case MLAN_OID_SCAN_BGSCAN_CONFIG:
5624 /* Send request to firmware */
5625 status = wlan_prepare_cmd(
5626 pmpriv, HostCmd_CMD_802_11_BG_SCAN_CONFIG,
5627 HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
5628 pscan->param.user_scan.scan_cfg_buf);
5629 break;
5630 default:
5631 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
5632 status = MLAN_STATUS_FAILURE;
5633 break;
5634 }
5635
5636 if ((status == MLAN_STATUS_SUCCESS) &&
5637 (pscan->sub_command != MLAN_OID_SCAN_TABLE_FLUSH) &&
5638 (pscan->sub_command != MLAN_OID_SCAN_CANCEL) &&
5639 (pscan->sub_command != MLAN_OID_SCAN_CONFIG)) {
5640 PRINTM(MINFO,
5641 "wlan_scan_ioctl: return MLAN_STATUS_PENDING\n");
5642 status = MLAN_STATUS_PENDING;
5643 }
5644 }
5645 /* Get scan */
5646 else {
5647 if (pscan->sub_command == MLAN_OID_SCAN_CONFIG) {
5648 status = wlan_set_get_scan_cfg(pmadapter, pioctl_req,
5649 MLAN_ACT_GET);
5650 } else if (pscan->sub_command ==
5651 MLAN_OID_SCAN_GET_CURRENT_BSS) {
5652 pscan->param.scan_resp.num_in_scan_table =
5653 pmadapter->num_in_scan_table;
5654 pscan->param.scan_resp.pscan_table =
5655 (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor;
5656 pioctl_req->data_read_written =
5657 sizeof(mlan_scan_resp) + MLAN_SUB_COMMAND_SIZE;
5658 } else {
5659 if (pmadapter->bgscan_reported) {
5660 pmadapter->bgscan_reported = MFALSE;
5661 /* Clear the previous scan result */
5662 memset(pmadapter, pmadapter->pscan_table, 0x00,
5663 sizeof(BSSDescriptor_t) *
5664 MRVDRV_MAX_BSSID_LIST);
5665 pmadapter->num_in_scan_table = 0;
5666 pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
5667 status = wlan_prepare_cmd(
5668 pmpriv,
5669 HostCmd_CMD_802_11_BG_SCAN_QUERY,
5670 HostCmd_ACT_GEN_GET, 0,
5671 (t_void *)pioctl_req, MNULL);
5672 if (status == MLAN_STATUS_SUCCESS) {
5673 PRINTM(MINFO,
5674 "wlan_scan_ioctl: return MLAN_STATUS_PENDING\n");
5675 status = MLAN_STATUS_PENDING;
5676 }
5677 } else {
5678 pscan->param.scan_resp.pscan_table =
5679 (t_u8 *)pmadapter->pscan_table;
5680 pscan->param.scan_resp.num_in_scan_table =
5681 pmadapter->num_in_scan_table;
5682 pscan->param.scan_resp.age_in_secs =
5683 pmadapter->age_in_secs;
5684 pioctl_req->data_read_written =
5685 sizeof(mlan_scan_resp) +
5686 MLAN_SUB_COMMAND_SIZE;
5687 pscan->param.scan_resp.pchan_stats =
5688 (t_u8 *)pmadapter->pchan_stats;
5689 pscan->param.scan_resp.num_in_chan_stats =
5690 pmadapter->num_in_chan_stats;
5691 }
5692 }
5693 }
5694
5695 LEAVE();
5696 return status;
5697 }
5698
5699 /********************************************************
5700 Global Functions
5701 ********************************************************/
5702
5703 /**
5704 * @brief Set ewpa mode
5705 *
5706 * @param priv A pointer to mlan_private structure
5707 * @param psec_pp A pointer to mlan_ds_passphrase structure
5708 *
5709 * @return MLAN_STATUS_SUCCESS
5710 */
wlan_set_ewpa_mode(mlan_private * priv,mlan_ds_passphrase * psec_pp)5711 mlan_status wlan_set_ewpa_mode(mlan_private *priv, mlan_ds_passphrase *psec_pp)
5712 {
5713 ENTER();
5714
5715 if ((psec_pp->psk_type == MLAN_PSK_PASSPHRASE &&
5716 psec_pp->psk.passphrase.passphrase_len > 0) ||
5717 (psec_pp->psk_type == MLAN_PSK_PMK))
5718 priv->sec_info.ewpa_enabled = MTRUE;
5719 else
5720 priv->sec_info.ewpa_enabled = MFALSE;
5721
5722 PRINTM(MINFO, "Set ewpa mode = %d\n", priv->sec_info.ewpa_enabled);
5723
5724 LEAVE();
5725 return MLAN_STATUS_SUCCESS;
5726 }
5727
5728 /**
5729 * @brief Search for a BSS
5730 *
5731 * @param pmpriv A pointer to mlan_private structure
5732 * @param pioctl_req A pointer to ioctl request buffer
5733 *
5734 * @return MLAN_STATUS_SUCCESS --success, otherwise
5735 * fail
5736 */
wlan_find_bss(mlan_private * pmpriv,pmlan_ioctl_req pioctl_req)5737 mlan_status wlan_find_bss(mlan_private *pmpriv, pmlan_ioctl_req pioctl_req)
5738 {
5739 mlan_adapter *pmadapter = pmpriv->adapter;
5740 mlan_ds_bss *bss = MNULL;
5741 mlan_status ret = MLAN_STATUS_SUCCESS;
5742 t_u8 zero_mac[] = {0, 0, 0, 0, 0, 0};
5743 t_u8 mac[MLAN_MAC_ADDR_LENGTH];
5744 int i = 0;
5745 BSSDescriptor_t *pbss_desc = MNULL;
5746
5747 ENTER();
5748
5749 bss = (mlan_ds_bss *)pioctl_req->pbuf;
5750
5751 if (memcmp(pmadapter, &bss->param.ssid_bssid.bssid, zero_mac,
5752 sizeof(zero_mac))) {
5753 if (bss->param.ssid_bssid.ssid.ssid_len) /* ssid & bssid */
5754 i = wlan_find_ssid_in_list(
5755 pmpriv, &bss->param.ssid_bssid.ssid,
5756 (t_u8 *)&bss->param.ssid_bssid.bssid,
5757 pmpriv->bss_mode);
5758 else
5759 i = wlan_find_bssid_in_list(
5760 pmpriv, (t_u8 *)&bss->param.ssid_bssid.bssid,
5761 pmpriv->bss_mode);
5762 if (i < 0) {
5763 memcpy_ext(pmadapter, mac, &bss->param.ssid_bssid.bssid,
5764 sizeof(mac), MLAN_MAC_ADDR_LENGTH);
5765 PRINTM(MIOCTL, "Can not find bssid " MACSTR "\n",
5766 MAC2STR(mac));
5767 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
5768 LEAVE();
5769 return MLAN_STATUS_FAILURE;
5770 }
5771 pbss_desc = &pmadapter->pscan_table[i];
5772 memcpy_ext(pmadapter, &bss->param.ssid_bssid.ssid,
5773 &pbss_desc->ssid, sizeof(mlan_802_11_ssid),
5774 sizeof(mlan_802_11_ssid));
5775 bss->param.ssid_bssid.rssi = pbss_desc->rssi;
5776 bss->param.ssid_bssid.channel = (t_u16)pbss_desc->channel;
5777
5778 bss->param.ssid_bssid.bss_band = pbss_desc->bss_band;
5779 /* index in bss list,start from 1 */
5780 bss->param.ssid_bssid.idx = i + 1;
5781 } else if (bss->param.ssid_bssid.ssid.ssid_len) {
5782 i = wlan_find_ssid_in_list(pmpriv, &bss->param.ssid_bssid.ssid,
5783 MNULL, pmpriv->bss_mode);
5784 if (i < 0) {
5785 PRINTM(MIOCTL, "Can not find ssid %s\n",
5786 bss->param.ssid_bssid.ssid.ssid);
5787 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
5788 LEAVE();
5789 return MLAN_STATUS_FAILURE;
5790 }
5791 pbss_desc = &pmadapter->pscan_table[i];
5792 memcpy_ext(pmadapter, (t_u8 *)&bss->param.ssid_bssid.bssid,
5793 (t_u8 *)&pbss_desc->mac_address,
5794 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
5795 bss->param.ssid_bssid.rssi = pbss_desc->rssi;
5796 bss->param.ssid_bssid.channel = (t_u16)pbss_desc->channel;
5797
5798 bss->param.ssid_bssid.bss_band = pbss_desc->bss_band;
5799 /* index in bss list, start from 1 */
5800 bss->param.ssid_bssid.idx = i + 1;
5801 } else {
5802 ret = wlan_find_best_network(pmpriv, &bss->param.ssid_bssid);
5803 }
5804
5805 if (pbss_desc) {
5806 /**if rsn do not have ft akm, don't set ft cap and ft md*/
5807 if (pbss_desc->pmd_ie &&
5808 wlan_ft_akm_is_used(pmpriv, (t_u8 *)pbss_desc->prsn_ie)) {
5809 bss->param.ssid_bssid.ft_md = pbss_desc->pmd_ie->mdid;
5810 bss->param.ssid_bssid.ft_cap =
5811 pbss_desc->pmd_ie->ft_cap;
5812 }
5813 }
5814
5815 LEAVE();
5816 return ret;
5817 }
5818
5819 /**
5820 * @brief MLAN station ioctl handler
5821 *
5822 * @param adapter A pointer to mlan_adapter structure
5823 * @param pioctl_req A pointer to ioctl request buffer
5824 *
5825 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
5826 * otherwise fail
5827 */
wlan_ops_sta_ioctl(t_void * adapter,pmlan_ioctl_req pioctl_req)5828 mlan_status wlan_ops_sta_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req)
5829 {
5830 pmlan_adapter pmadapter = (pmlan_adapter)adapter;
5831 mlan_status status = MLAN_STATUS_SUCCESS;
5832
5833 ENTER();
5834
5835 switch (pioctl_req->req_id) {
5836 case MLAN_IOCTL_SCAN:
5837 status = wlan_scan_ioctl(pmadapter, pioctl_req);
5838 break;
5839 case MLAN_IOCTL_BSS:
5840 status = wlan_bss_ioctl(pmadapter, pioctl_req);
5841 break;
5842 case MLAN_IOCTL_RADIO_CFG:
5843 status = wlan_radio_ioctl(pmadapter, pioctl_req);
5844 break;
5845 case MLAN_IOCTL_SNMP_MIB:
5846 status = wlan_snmp_mib_ioctl(pmadapter, pioctl_req);
5847 break;
5848 case MLAN_IOCTL_GET_INFO:
5849 status = wlan_get_info_ioctl(pmadapter, pioctl_req);
5850 break;
5851 case MLAN_IOCTL_SEC_CFG:
5852 status = wlan_sec_cfg_ioctl(pmadapter, pioctl_req);
5853 break;
5854 case MLAN_IOCTL_RATE:
5855 status = wlan_rate_ioctl(pmadapter, pioctl_req);
5856 break;
5857 case MLAN_IOCTL_POWER_CFG:
5858 status = wlan_power_ioctl(pmadapter, pioctl_req);
5859 break;
5860 case MLAN_IOCTL_PM_CFG:
5861 status = wlan_pm_ioctl(pmadapter, pioctl_req);
5862 break;
5863 case MLAN_IOCTL_WMM_CFG:
5864 status = wlan_wmm_cfg_ioctl(pmadapter, pioctl_req);
5865 break;
5866 case MLAN_IOCTL_WPS_CFG:
5867 status = wlan_wps_cfg_ioctl(pmadapter, pioctl_req);
5868 break;
5869 case MLAN_IOCTL_11N_CFG:
5870 status = wlan_11n_cfg_ioctl(pmadapter, pioctl_req);
5871 break;
5872 case MLAN_IOCTL_11D_CFG:
5873 status = wlan_11d_cfg_ioctl(pmadapter, pioctl_req);
5874 break;
5875 case MLAN_IOCTL_REG_MEM:
5876 status = wlan_reg_mem_ioctl(pmadapter, pioctl_req);
5877 break;
5878 case MLAN_IOCTL_MISC_CFG:
5879 status = wlan_misc_cfg_ioctl(pmadapter, pioctl_req);
5880 break;
5881 case MLAN_IOCTL_11H_CFG:
5882 status = wlan_11h_cfg_ioctl(pmadapter, pioctl_req);
5883 break;
5884 case MLAN_IOCTL_11AC_CFG:
5885 status = wlan_11ac_cfg_ioctl(pmadapter, pioctl_req);
5886 break;
5887 case MLAN_IOCTL_11AX_CFG:
5888 status = wlan_11ax_cfg_ioctl(pmadapter, pioctl_req);
5889 break;
5890 default:
5891 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
5892 status = MLAN_STATUS_FAILURE;
5893 break;
5894 }
5895 LEAVE();
5896 return status;
5897 }
5898