1 /*
2 * Copyright 2023, Cypress Semiconductor Corporation (an Infineon company)
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 /** @file
19 * Implements user functions for controlling the Wi-Fi system
20 *
21 * This file provides end-user functions which allow actions such as scanning for
22 * Wi-Fi networks, joining Wi-Fi networks, getting the MAC address, etc
23 *
24 */
25
26 #include "whd_version.h"
27 #include "whd_chip_constants.h"
28 #include "whd_cdc_bdc.h"
29 #include "whd_thread_internal.h"
30 #include "whd_debug.h"
31 #include "whd_utils.h"
32 #include "whd_wifi_api.h"
33 #include "whd_buffer_api.h"
34 #include "whd_wlioctl.h"
35 #include "whd_types.h"
36 #include "whd_types_int.h"
37
38 /******************************************************
39 * Constants
40 ******************************************************/
41 #define WL_CHANSPEC_CHAN_MASK (0x00ff)
42 #define CHSPEC_CHANNEL(chspec) ( (uint8_t)( (chspec) & WL_CHANSPEC_CHAN_MASK ) )
43 #define CH20MHZ_CHSPEC(channel) (chanspec_t)( (chanspec_t)(channel) | GET_C_VAR(whd_driver, CHANSPEC_BW_20) | \
44 GET_C_VAR(whd_driver, CHANSPEC_CTL_SB_NONE) | \
45 ( ( (channel) <= CH_MAX_2G_CHANNEL ) ? GET_C_VAR(whd_driver, \
46 CHANSPEC_BAND_2G) \
47 : GET_C_VAR(whd_driver, CHANSPEC_BAND_5G) ) )
48
49 #define MAX_SUPPORTED_MCAST_ENTRIES (10)
50 #define WLC_EVENT_MSG_LINK (0x01)
51
52 #define JOIN_ASSOCIATED (uint32_t)(1 << 0)
53 #define JOIN_AUTHENTICATED (uint32_t)(1 << 1)
54 #define JOIN_LINK_READY (uint32_t)(1 << 2)
55 #define JOIN_SECURITY_COMPLETE (uint32_t)(1 << 3)
56 #define JOIN_SSID_SET (uint32_t)(1 << 4)
57 #define JOIN_NO_NETWORKS (uint32_t)(1 << 5)
58 #define JOIN_EAPOL_KEY_M1_TIMEOUT (uint32_t)(1 << 6)
59 #define JOIN_EAPOL_KEY_M3_TIMEOUT (uint32_t)(1 << 7)
60 #define JOIN_EAPOL_KEY_G1_TIMEOUT (uint32_t)(1 << 8)
61 #define JOIN_EAPOL_KEY_FAILURE (uint32_t)(1 << 9)
62
63 #define JOIN_SECURITY_FLAGS_MASK (JOIN_SECURITY_COMPLETE | JOIN_EAPOL_KEY_M1_TIMEOUT | JOIN_EAPOL_KEY_M3_TIMEOUT | \
64 JOIN_EAPOL_KEY_G1_TIMEOUT | JOIN_EAPOL_KEY_FAILURE)
65
66 #define DEFAULT_JOIN_ATTEMPT_TIMEOUT (9000) /* Overall join attempt timeout in milliseconds.(FW will do "full scan"[~2.8 seconds] + "psk-to-pmk"[2.x seconds] + "join"[5 seconds timer in FW]) */
67 #define DEFAULT_EAPOL_KEY_PACKET_TIMEOUT (2500) /* Timeout when waiting for EAPOL key packet M1 or M3 in milliseconds.*/
68 /* Some APs may be slow to provide M1 and 1000 ms is not long enough for edge of cell. */
69 #ifndef DEFAULT_PM2_SLEEP_RET_TIME
70 #define DEFAULT_PM2_SLEEP_RET_TIME (200)
71 #endif
72
73 #define PM2_SLEEP_RET_TIME_MIN (10) /* Minimum return-to-sleep in milliseconds */
74 #define PM2_SLEEP_RET_TIME_MAX (2000) /* Maximum return-to-sleep in milliseconds */
75 #define NULL_FRAMES_WITH_PM_SET_LIMIT (100) /* NULL_FRAMES_WITH_PM_SET_LIMIT */
76 #define RSPEC_KBPS_MASK (0x7f)
77 #define RSPEC_500KBPS(rate) ( (rate) & RSPEC_KBPS_MASK )
78 #define RSPEC_TO_KBPS(rate) (RSPEC_500KBPS( (rate) ) * (uint32_t)500)
79 #define UNSIGNED_CHAR_TO_CHAR(uch) ( (uch) & 0x7f )
80 #define ETHER_ISMULTI(ea) ( ( (const uint8_t *)(ea) )[0] & 1 )
81
82 #define KEY_MAX_LEN (64) /* Maximum key length */
83 #define KEY_MIN_LEN (8) /* Minimum key length */
84 #define BT_CTRL_REG_ADDR (0x18000c7c)
85 #define HOST_CTRL_REG_ADDR (0x18000d6c)
86 #define BT_BUF_REG_ADDR (0x18000c78)
87 /******************************************************
88 * Local Structures
89 ******************************************************/
90
91 #pragma pack(1)
92
93 typedef struct
94 {
95 uint32_t entry_count;
96 whd_mac_t macs[1];
97 } mcast_list_t;
98
99 typedef struct
100 {
101 int32_t rssi;
102 whd_mac_t macs;
103 } client_rssi_t;
104
105 typedef struct
106 {
107 whd_sync_scan_result_t *aps;
108 uint32_t count;
109 uint32_t offset;
110 cy_semaphore_t scan_semaphore;
111 } whd_scan_userdata_t;
112
113 #pragma pack()
114
115 /******************************************************
116 * Static Variables
117 ******************************************************/
118
119 /* LOOK: !!!When adding events below, please modify whd_event_to_string!!! */
120 const whd_event_num_t join_events[] =
121 {
122 WLC_E_SET_SSID, WLC_E_LINK, WLC_E_AUTH, WLC_E_DEAUTH_IND, WLC_E_DISASSOC_IND, WLC_E_PSK_SUP, WLC_E_CSA_COMPLETE_IND,
123 WLC_E_NONE
124 };
125 static const whd_event_num_t scan_events[] = { WLC_E_ESCAN_RESULT, WLC_E_NONE };
126 static const whd_event_num_t auth_events[] =
127 { WLC_E_EXT_AUTH_REQ, WLC_E_EXT_AUTH_FRAME_RX, WLC_E_NONE };
128
129 /* Values are in 100's of Kbit/sec (1 = 100Kbit/s). Arranged as:
130 * [Bit index]
131 * [0] = 20Mhz only
132 * [0] = Long GI
133 * [1] = Short GI
134 * [1] = 40MHz support
135 * [0] = Long GI
136 * [1] = Short GI
137 */
138 static const uint16_t mcs_data_rate_lookup_table[32][2][2] =
139 {
140 [0] =
141 {
142 { 65, 72},
143 { 135, 150}
144 },
145 [1] =
146 {
147 { 130, 144},
148 { 270, 300}
149 },
150 [2] =
151 {
152 { 195, 217},
153 { 405, 450}
154 },
155 [3] =
156 {
157 { 260, 289},
158 { 540, 600}
159 },
160 [4] =
161 {
162 { 390, 433},
163 { 810, 900}
164 },
165 [5] =
166 {
167 { 520, 578},
168 { 1080, 1200}
169 },
170 [6] =
171 {
172 { 585, 650},
173 { 1215, 1350}
174 },
175 [7] =
176 {
177 { 650, 722},
178 { 1350, 1500}
179 },
180 [8] =
181 {
182 { 130, 144},
183 { 270, 300}
184 },
185 [9] =
186 {
187 { 260, 289},
188 { 540, 600}
189 },
190 [10] =
191 {
192 { 390, 433},
193 { 810, 900}
194 },
195 [11] =
196 {
197 { 520, 578},
198 { 1080, 1200}
199 },
200 [12] =
201 {
202 { 780, 867},
203 { 1620, 1800}
204 },
205 [13] =
206 {
207 { 1040, 1156},
208 { 2160, 2400}
209 },
210 [14] =
211 {
212 { 1170, 1300},
213 { 2430, 2700}
214 },
215 [15] =
216 {
217 { 1300, 1444},
218 { 2700, 3000}
219 },
220 [16] =
221 {
222 { 195, 217},
223 { 405, 450}
224 },
225 [17] =
226 {
227 { 390, 433},
228 { 810, 900}
229 },
230 [18] =
231 {
232 { 585, 650},
233 { 1215, 1350}
234 },
235 [19] =
236 {
237 { 780, 867},
238 { 1620, 1800}
239 },
240 [20] =
241 {
242 { 1170, 1300},
243 { 2430, 2700}
244 },
245 [21] =
246 {
247 { 1560, 1733},
248 { 3240, 3600}
249 },
250 [22] =
251 {
252 { 1755, 1950},
253 { 3645, 4050}
254 },
255 [23] =
256 {
257 { 1950, 2167},
258 { 4050, 4500}
259 },
260 [24] =
261 {
262 { 260, 288},
263 { 540, 600}
264 },
265 [25] =
266 {
267 { 520, 576},
268 { 1080, 1200}
269 },
270 [26] =
271 {
272 { 780, 868},
273 { 1620, 1800}
274 },
275 [27] =
276 {
277 { 1040, 1156},
278 { 2160, 2400}
279 },
280 [28] =
281 {
282 { 1560, 1732},
283 { 3240, 3600}
284 },
285 [29] =
286 {
287 { 2080, 2312},
288 { 4320, 4800}
289 },
290 [30] =
291 {
292 { 2340, 2600},
293 { 4860, 5400}
294 },
295 [31] =
296 {
297 { 2600, 2888},
298 { 5400, 6000}
299 },
300 };
301
302
303 /******************************************************
304 * Static Function prototypes
305 ******************************************************/
306 static void *whd_wifi_join_events_handler(whd_interface_t ifp, const whd_event_header_t *event_header,
307 const uint8_t *event_data, void *handler_user_data);
308 static void *whd_wifi_scan_events_handler(whd_interface_t ifp, const whd_event_header_t *event_header,
309 const uint8_t *event_data,
310 void *handler_user_data);
311 static uint32_t whd_wifi_prepare_join(whd_interface_t ifp,
312 whd_security_t security,
313 const uint8_t *security_key,
314 uint8_t key_length,
315 cy_semaphore_t *semaphore);
316 static uint32_t whd_wifi_check_join_status(whd_interface_t ifp);
317 static void whd_wifi_active_join_deinit(whd_interface_t ifp, cy_semaphore_t *stack_semaphore,
318 whd_result_t result);
319 static uint32_t whd_wifi_active_join_init(whd_interface_t ifp, whd_security_t auth_type,
320 const uint8_t *security_key, uint8_t key_length,
321 cy_semaphore_t *semaphore);
322
323 /** Sets the current EAPOL key timeout for the given interface
324 *
325 * @param interface : the interface for which we want to set the EAPOL key timeout
326 * eapol_key_timeout : EAPOL key timeout value
327 *
328 * @return WHD_SUCCESS : if success
329 * Error code : error code to indicate the type of error
330 */
331 static uint32_t whd_wifi_set_supplicant_key_timeout(whd_interface_t ifp, int32_t eapol_key_timeout);
332
333 /******************************************************
334 * Function definitions
335 ******************************************************/
336 uint32_t whd_get_bt_info(whd_driver_t whd_driver, whd_bt_info_t bt_info);
337
whd_channel_to_wl_band(whd_driver_t whd_driver,uint32_t channel)338 inline wl_chanspec_t whd_channel_to_wl_band(whd_driver_t whd_driver, uint32_t channel)
339 {
340 return ( ( (channel) <= CH_MAX_2G_CHANNEL ) ? (uint16_t)GET_C_VAR(whd_driver, CHANSPEC_BAND_2G) :
341 (uint16_t)GET_C_VAR(whd_driver, CHANSPEC_BAND_5G) );
342 }
343
whd_wifi_set_up(whd_interface_t ifp)344 uint32_t whd_wifi_set_up(whd_interface_t ifp)
345 {
346 whd_mac_t mac;
347 char version[200];
348 whd_driver_t whd_driver;
349
350 CHECK_IFP_NULL(ifp);
351
352 whd_driver = ifp->whd_driver;
353 if (whd_driver->internal_info.whd_wlan_status.state == WLAN_UP)
354 {
355 WPRINT_WHD_INFO( ("whd_wifi_set_up: already up.\n") );
356 return WHD_SUCCESS;
357 }
358
359 /* Send UP command */
360 CHECK_RETURN(whd_wifi_set_ioctl_buffer(ifp, WLC_UP, NULL, 0) );
361
362 if (whd_wifi_get_mac_address(ifp, &mac) == WHD_SUCCESS)
363 {
364 WPRINT_MACRO( ("WLAN MAC Address : %02X:%02X:%02X:%02X:%02X:%02X\n", mac.octet[0], mac.octet[1], mac.octet[2],
365 mac.octet[3], mac.octet[4], mac.octet[5]) );
366 }
367
368 if (whd_wifi_get_wifi_version(ifp, version, sizeof(version) ) == WHD_SUCCESS)
369 {
370 WPRINT_MACRO( ("WLAN Firmware : %s", version) );
371 }
372
373 /* minimize bootloader usage and start time from UART output */
374 if (whd_wifi_get_clm_version(ifp, version, sizeof(version) ) == WHD_SUCCESS)
375 {
376 WPRINT_MACRO( ("WLAN CLM : %s\n", version) );
377 }
378
379 WPRINT_MACRO( ("WHD VERSION : " WHD_VERSION) );
380 WPRINT_MACRO( (" : " WHD_BRANCH) );
381 #if defined(__ARMCC_VERSION)
382 WPRINT_MACRO( (" : ARM CLANG %u", __ARMCC_VERSION) );
383 #elif defined(__ICCARM__)
384 WPRINT_MACRO( (" : IAR %u", __VER__) );
385 #elif defined(__GNUC__)
386 WPRINT_MACRO( (" : GCC %u.%u", __GNUC__, __GNUC_MINOR__) );
387 #else
388 WPRINT_MACRO( (" : UNKNOWN CC") );
389 #endif
390 WPRINT_MACRO( (" : " WHD_DATE "\n") );
391
392 /* Update wlan status */
393 whd_driver->internal_info.whd_wlan_status.state = WLAN_UP;
394
395 return WHD_SUCCESS;
396 }
397
whd_wifi_set_down(whd_interface_t ifp)398 uint32_t whd_wifi_set_down(whd_interface_t ifp)
399 {
400 whd_driver_t whd_driver = ifp->whd_driver;
401
402 if (whd_driver->internal_info.whd_wlan_status.state != WLAN_UP)
403 {
404 WPRINT_WHD_INFO( ("whd_wifi_set_down: already down.\n") );
405 return WHD_INTERFACE_NOT_UP;
406 }
407
408 /* Send DOWN command */
409 CHECK_RETURN(whd_wifi_set_ioctl_buffer(ifp, WLC_DOWN, NULL, 0) );
410
411 /* Update wlan status */
412 whd_driver->internal_info.whd_wlan_status.state = WLAN_DOWN;
413
414 return WHD_SUCCESS;
415 }
416
whd_get_bt_info(whd_driver_t whd_driver,whd_bt_info_t bt_info)417 uint32_t whd_get_bt_info(whd_driver_t whd_driver, whd_bt_info_t bt_info)
418 {
419 whd_result_t result;
420 whd_interface_t ifp;
421 uint32_t addr = 0;
422
423 ifp = whd_get_primary_interface(whd_driver);
424
425 CHECK_IFP_NULL(ifp);
426
427 memset(bt_info, 0, sizeof(struct whd_bt_info) );
428 bt_info->bt_ctrl_reg_addr = BT_CTRL_REG_ADDR;
429 bt_info->host_ctrl_reg_addr = HOST_CTRL_REG_ADDR;
430 bt_info->bt_buf_reg_addr = BT_BUF_REG_ADDR;
431 result = whd_wifi_get_iovar_buffer(ifp, IOVAR_STR_BTADDR, (uint8_t *)&addr, sizeof(uint32_t) );
432 if (result == WHD_SUCCESS)
433 {
434 bt_info->wlan_buf_addr = addr;
435 }
436 return WHD_SUCCESS;
437 }
438
whd_wifi_set_channel(whd_interface_t ifp,uint32_t channel)439 uint32_t whd_wifi_set_channel(whd_interface_t ifp, uint32_t channel)
440 {
441 whd_buffer_t buffer;
442 uint32_t *data;
443 wl_chan_switch_t *chan_switch;
444 whd_driver_t whd_driver;
445
446 CHECK_IFP_NULL(ifp);
447
448 whd_driver = ifp->whd_driver;
449
450 CHECK_DRIVER_NULL(whd_driver);
451
452 /* Map P2P interface to either STA or AP interface depending if it's running as group owner or client */
453 if (ifp->role == WHD_P2P_ROLE)
454 {
455 if (whd_driver->internal_info.whd_wifi_p2p_go_is_up == WHD_TRUE)
456 {
457 ifp->role = WHD_AP_ROLE;
458 }
459 else
460 {
461 ifp->role = WHD_STA_ROLE;
462 }
463 }
464
465 switch (ifp->role)
466 {
467 case WHD_STA_ROLE:
468 data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, sizeof(uint32_t) );
469 CHECK_IOCTL_BUFFER(data);
470 *data = htod32(channel);
471 CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_GET, WLC_SET_CHANNEL, buffer, NULL) );
472 break;
473
474 case WHD_AP_ROLE:
475 chan_switch = (wl_chan_switch_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, sizeof(wl_chan_switch_t),
476 IOVAR_STR_CSA);
477 CHECK_IOCTL_BUFFER(chan_switch);
478 chan_switch->chspec =
479 ( wl_chanspec_t )(GET_C_VAR(whd_driver,
480 CHANSPEC_BW_20) | GET_C_VAR(whd_driver, CHANSPEC_CTL_SB_NONE) | channel);
481 chan_switch->chspec |= whd_channel_to_wl_band(whd_driver, channel);
482 chan_switch->chspec = htod16(chan_switch->chspec);
483 chan_switch->count = 1;
484 chan_switch->mode = 1;
485 chan_switch->reg = 0;
486 CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0) );
487 break;
488 case WHD_P2P_ROLE:
489 case WHD_INVALID_ROLE:
490 default:
491 whd_assert("Bad interface", 0 != 0);
492 return WHD_UNKNOWN_INTERFACE;
493 }
494
495 return WHD_SUCCESS;
496 }
497
whd_wifi_get_channel(whd_interface_t ifp,uint32_t * channel)498 uint32_t whd_wifi_get_channel(whd_interface_t ifp, uint32_t *channel)
499 {
500 whd_buffer_t buffer;
501 whd_buffer_t response;
502 channel_info_t *channel_info;
503 whd_driver_t whd_driver;
504
505 CHECK_IFP_NULL(ifp);
506
507 if (channel == NULL)
508 return WHD_BADARG;
509
510 whd_driver = ifp->whd_driver;
511
512 CHECK_DRIVER_NULL(whd_driver);
513
514 CHECK_IOCTL_BUFFER(whd_cdc_get_ioctl_buffer(whd_driver, &buffer, sizeof(channel_info_t) ) );
515
516 CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_GET, WLC_GET_CHANNEL, buffer, &response) );
517
518 channel_info = (channel_info_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response);
519 CHECK_PACKET_NULL(channel_info, WHD_NO_REGISTER_FUNCTION_POINTER);
520 *channel = (uint32_t)channel_info->hw_channel;
521 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
522 return WHD_SUCCESS;
523 }
524
whd_wifi_enable_supplicant(whd_interface_t ifp,whd_security_t auth_type)525 uint32_t whd_wifi_enable_supplicant(whd_interface_t ifp, whd_security_t auth_type)
526 {
527 whd_buffer_t buffer;
528 uint32_t *data;
529 uint32_t bss_index = 0;
530 whd_driver_t whd_driver;
531
532 CHECK_IFP_NULL(ifp);
533
534 whd_driver = ifp->whd_driver;
535
536 CHECK_DRIVER_NULL(whd_driver);
537
538 /* Map the interface to a BSS index */
539 bss_index = ifp->bsscfgidx;
540
541 /* Set supplicant variable - mfg app doesn't support these iovars, so don't care if return fails */
542 data = whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, "bsscfg:" IOVAR_STR_SUP_WPA);
543 CHECK_IOCTL_BUFFER(data);
544 data[0] = bss_index;
545 data[1] = (uint32_t)( ( ( (auth_type & WPA_SECURITY) != 0 ) ||
546 ( (auth_type & WPA2_SECURITY) != 0 ) ||
547 (auth_type & WPA3_SECURITY) != 0 ) ? 1 : 0 );
548 (void)whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0);
549
550 return WHD_SUCCESS;
551 }
552
whd_wifi_set_supplicant_key_timeout(whd_interface_t ifp,int32_t eapol_key_timeout)553 uint32_t whd_wifi_set_supplicant_key_timeout(whd_interface_t ifp, int32_t eapol_key_timeout)
554 {
555 whd_buffer_t buffer;
556 int32_t *data;
557 uint32_t bss_index = 0;
558 whd_driver_t whd_driver = (whd_driver_t)ifp->whd_driver;
559
560 /* Map the interface to a BSS index */
561 bss_index = ifp->bsscfgidx;
562
563 data = whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, "bsscfg:" IOVAR_STR_SUP_WPA_TMO);
564 CHECK_IOCTL_BUFFER(data);
565 data[0] = (int32_t)bss_index;
566 data[1] = eapol_key_timeout;
567 CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0) );
568
569 return WHD_SUCCESS;
570 }
571
whd_wifi_set_passphrase(whd_interface_t ifp,const uint8_t * security_key,uint8_t key_length)572 uint32_t whd_wifi_set_passphrase(whd_interface_t ifp, const uint8_t *security_key, uint8_t key_length)
573 {
574 whd_buffer_t buffer;
575 whd_driver_t whd_driver;
576 wsec_pmk_t *psk;
577
578 if (!ifp || !security_key || (key_length < KEY_MIN_LEN) || (key_length > KEY_MAX_LEN) )
579 {
580 WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n",
581 __func__, __LINE__) );
582 return WHD_WLAN_BADARG;
583 }
584
585 whd_driver = ifp->whd_driver;
586 CHECK_DRIVER_NULL(whd_driver);
587
588 psk = (wsec_pmk_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, sizeof(wsec_pmk_t) );
589 CHECK_IOCTL_BUFFER(psk);
590
591 memset(psk, 0, sizeof(wsec_pmk_t) );
592 memcpy(psk->key, security_key, key_length);
593 psk->key_len = htod16(key_length);
594 psk->flags = htod16( (uint16_t)WSEC_PASSPHRASE );
595
596 /* Delay required to allow radio firmware to be ready to receive PMK and avoid intermittent failure */
597 CHECK_RETURN(cy_rtos_delay_milliseconds(1) );
598
599 CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_WSEC_PMK, buffer, 0) );
600
601 return WHD_SUCCESS;
602 }
603
whd_wifi_sae_password(whd_interface_t ifp,const uint8_t * security_key,uint8_t key_length)604 uint32_t whd_wifi_sae_password(whd_interface_t ifp, const uint8_t *security_key, uint8_t key_length)
605 {
606 whd_buffer_t buffer;
607 whd_driver_t whd_driver;
608 wsec_sae_password_t *sae_password;
609
610 if (!ifp || !security_key || (key_length == 0) || (key_length > WSEC_MAX_SAE_PASSWORD_LEN) )
611 {
612 WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n",
613 __func__, __LINE__) );
614 return WHD_WLAN_BADARG;
615 }
616
617 whd_driver = ifp->whd_driver;
618 CHECK_DRIVER_NULL(whd_driver);
619
620 sae_password = (wsec_sae_password_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer,
621 sizeof(wsec_sae_password_t),
622 IOVAR_STR_SAE_PASSWORD);
623 CHECK_IOCTL_BUFFER(sae_password);
624 memset(sae_password, 0, sizeof(wsec_sae_password_t) );
625 memcpy(sae_password->password, security_key, key_length);
626 sae_password->password_len = htod16(key_length);
627 /* Delay required to allow radio firmware to be ready to receive PMK and avoid intermittent failure */
628 cy_rtos_delay_milliseconds(1);
629 CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0) );
630
631 return WHD_SUCCESS;
632 }
633
whd_wifi_enable_sup_set_passphrase(whd_interface_t ifp,const uint8_t * security_key_psk,uint8_t psk_length,whd_security_t auth_type)634 uint32_t whd_wifi_enable_sup_set_passphrase(whd_interface_t ifp, const uint8_t *security_key_psk, uint8_t psk_length,
635 whd_security_t auth_type)
636 {
637 whd_buffer_t buffer;
638 uint32_t *data;
639 uint32_t bss_index = 0;
640 whd_driver_t whd_driver;
641
642 CHECK_IFP_NULL(ifp);
643
644 whd_driver = ifp->whd_driver;
645
646 CHECK_DRIVER_NULL(whd_driver);
647
648 if ( (psk_length > (uint8_t)WSEC_MAX_PSK_LEN) ||
649 (psk_length < (uint8_t)WSEC_MIN_PSK_LEN) )
650 {
651 return WHD_INVALID_KEY;
652 }
653
654 /* Map the interface to a BSS index */
655 bss_index = ifp->bsscfgidx;
656
657 /* Set supplicant variable - mfg app doesn't support these iovars, so don't care if return fails */
658 data = whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, "bsscfg:" IOVAR_STR_SUP_WPA);
659 CHECK_IOCTL_BUFFER(data);
660 data[0] = bss_index;
661 data[1] = (uint32_t)( ( ( (auth_type & WPA_SECURITY) != 0 ) ||
662 ( (auth_type & WPA2_SECURITY) != 0 ) ||
663 (auth_type & WPA3_SECURITY) != 0 ) ? 1 : 0 );
664 (void)whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0);
665
666 CHECK_RETURN(whd_wifi_set_passphrase(ifp, security_key_psk, psk_length) );
667
668 return WHD_SUCCESS;
669 }
670
whd_wifi_set_pmk(whd_interface_t ifp,const uint8_t * security_key,uint8_t key_length)671 whd_result_t whd_wifi_set_pmk(whd_interface_t ifp, const uint8_t *security_key, uint8_t key_length)
672 {
673 whd_buffer_t buffer;
674 whd_driver_t whd_driver;
675 wsec_pmk_t *pmk;
676 uint32_t i;
677
678 if (!ifp || !security_key || (key_length != WSEC_PMK_LEN) )
679 {
680 WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n",
681 __func__, __LINE__) );
682 return WHD_WLAN_BADARG;
683 }
684
685 whd_driver = ifp->whd_driver;
686 CHECK_DRIVER_NULL(whd_driver);
687
688 pmk = (wsec_pmk_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, sizeof(wsec_pmk_t) );
689 CHECK_IOCTL_BUFFER(pmk);
690
691 memset(pmk, 0, sizeof(wsec_pmk_t) );
692 for (i = 0; i < key_length; i++)
693 {
694 snprintf( (char *)&pmk->key[2 * i], 3, "%02x", security_key[i] );
695 }
696 pmk->key_len = htod16(key_length << 1);
697 pmk->flags = htod16( (uint16_t)WSEC_PASSPHRASE );
698
699 /* Delay required to allow radio firmware to be ready to receive PMK and avoid intermittent failure */
700 CHECK_RETURN(cy_rtos_delay_milliseconds(1) );
701
702 CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_WSEC_PMK, buffer, 0) );
703
704 return WHD_SUCCESS;
705 }
706
whd_wifi_set_pmksa(whd_interface_t ifp,const pmkid_t * pmkid)707 whd_result_t whd_wifi_set_pmksa(whd_interface_t ifp, const pmkid_t *pmkid)
708 {
709 whd_buffer_t buffer;
710 whd_buffer_t response;
711 uint16_t cnt;
712 pmkid_list_t *orig_pmkid_list;
713 pmkid_list_t *new_pmkid_list;
714 whd_driver_t whd_driver;
715
716 if (!ifp || !pmkid)
717 {
718 WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n",
719 __func__, __LINE__) );
720 return WHD_WLAN_BADARG;
721 }
722
723 whd_driver = ifp->whd_driver;
724
725 CHECK_DRIVER_NULL(whd_driver);
726
727 /* Get the current pmkid_list list */
728 CHECK_IOCTL_BUFFER(whd_cdc_get_iovar_buffer(whd_driver, &buffer,
729 sizeof(uint32_t) + MAXPMKID *
730 sizeof(pmkid_t), IOVAR_STR_PMKID_INFO) );
731 CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) );
732
733 /* Verify address is not currently registered */
734 orig_pmkid_list = (pmkid_list_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response);
735 CHECK_PACKET_NULL(orig_pmkid_list, WHD_NO_REGISTER_FUNCTION_POINTER);
736 orig_pmkid_list->npmkid = dtoh32(orig_pmkid_list->npmkid);
737 for (cnt = 0; cnt < orig_pmkid_list->npmkid; ++cnt)
738 {
739 /* Check if any address matches */
740 if (!memcmp(pmkid->BSSID.octet, orig_pmkid_list->pmkid[cnt].BSSID.octet, sizeof(whd_mac_t) ) )
741 {
742 break;
743 }
744 }
745
746 if (cnt == MAXPMKID)
747 {
748 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
749 WPRINT_WHD_ERROR( ("Too manay PMKSA entrie cached %" PRIu32 "\n", orig_pmkid_list->npmkid) );
750 return WHD_WLAN_NORESOURCE;
751 }
752
753 /* Add Extra Space for New PMKID and write the new multicast list */
754 if (cnt == orig_pmkid_list->npmkid)
755 {
756 new_pmkid_list = (pmkid_list_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer,
757 ( uint16_t )(sizeof(uint32_t) +
758 (orig_pmkid_list->npmkid + 1) *
759 sizeof(pmkid_t) ), IOVAR_STR_PMKID_INFO);
760 CHECK_IOCTL_BUFFER(new_pmkid_list);
761 new_pmkid_list->npmkid = orig_pmkid_list->npmkid + 1;
762 memcpy(new_pmkid_list->pmkid, orig_pmkid_list->pmkid, orig_pmkid_list->npmkid * sizeof(pmkid_t) );
763 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
764 memcpy(&new_pmkid_list->pmkid[new_pmkid_list->npmkid - 1], pmkid, sizeof(pmkid_t) );
765 new_pmkid_list->npmkid = htod32(new_pmkid_list->npmkid);
766 }
767 else
768 /* Replace Old PMKID for New PMKID under same BSSID and write the new multicast list */
769 {
770 new_pmkid_list = (pmkid_list_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer,
771 ( uint16_t )(sizeof(uint32_t) +
772 (orig_pmkid_list->npmkid) *
773 sizeof(pmkid_t) ), IOVAR_STR_PMKID_INFO);
774 CHECK_IOCTL_BUFFER(new_pmkid_list);
775 new_pmkid_list->npmkid = orig_pmkid_list->npmkid;
776 memcpy(new_pmkid_list->pmkid, orig_pmkid_list->pmkid, orig_pmkid_list->npmkid * sizeof(pmkid_t) );
777 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
778 memcpy(&new_pmkid_list->pmkid[cnt], pmkid, sizeof(pmkid_t) );
779 new_pmkid_list->npmkid = htod32(new_pmkid_list->npmkid);
780 }
781 RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) );
782 }
783
whd_wifi_pmkid_clear(whd_interface_t ifp)784 whd_result_t whd_wifi_pmkid_clear(whd_interface_t ifp)
785 {
786 whd_buffer_t buffer;
787 whd_driver_t whd_driver = (whd_driver_t)ifp->whd_driver;
788
789 CHECK_IOCTL_BUFFER(whd_cdc_get_iovar_buffer(whd_driver, &buffer,
790 0, IOVAR_STR_PMKID_CLEAR) );
791 CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0) );
792
793 return WHD_SUCCESS;
794 }
795
whd_wifi_set_roam_time_threshold(whd_interface_t ifp,uint32_t roam_time_threshold)796 whd_result_t whd_wifi_set_roam_time_threshold(whd_interface_t ifp, uint32_t roam_time_threshold)
797 {
798 if (!ifp || !roam_time_threshold)
799 {
800 WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n",
801 __func__, __LINE__) );
802 return WHD_WLAN_BADARG;
803 }
804
805 return whd_wifi_set_iovar_value(ifp, IOVAR_STR_ROAM_TIME_THRESH, roam_time_threshold);
806 }
807
whd_wifi_get_roam_time_threshold(whd_interface_t ifp,uint32_t * roam_time_threshold)808 whd_result_t whd_wifi_get_roam_time_threshold(whd_interface_t ifp, uint32_t *roam_time_threshold)
809 {
810 CHECK_IFP_NULL(ifp);
811
812 return whd_wifi_get_iovar_value(ifp, IOVAR_STR_ROAM_TIME_THRESH, roam_time_threshold);
813 }
814
whd_wifi_get_rssi(whd_interface_t ifp,int32_t * rssi)815 uint32_t whd_wifi_get_rssi(whd_interface_t ifp, int32_t *rssi)
816 {
817 CHECK_IFP_NULL(ifp);
818
819 if (rssi == NULL)
820 return WHD_BADARG;
821 if (ifp->role == WHD_STA_ROLE)
822 {
823 return whd_wifi_get_ioctl_buffer(ifp, WLC_GET_RSSI, (uint8_t *)rssi, sizeof(*rssi) );
824 }
825 return WHD_BADARG;
826 }
827
whd_wifi_get_ap_client_rssi(whd_interface_t ifp,int32_t * rssi,const whd_mac_t * client_mac)828 uint32_t whd_wifi_get_ap_client_rssi(whd_interface_t ifp, int32_t *rssi, const whd_mac_t *client_mac)
829 {
830 whd_buffer_t buffer;
831 whd_buffer_t response;
832 uint8_t *data = NULL;
833 client_rssi_t *client_rssi;
834 whd_driver_t whd_driver = ifp->whd_driver;
835
836 /* WLAN expects buffer size to be 4-byte aligned */
837 client_rssi =
838 (client_rssi_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, ROUND_UP(sizeof(client_rssi_t),
839 sizeof(uint32_t) ) );
840 CHECK_IOCTL_BUFFER(client_rssi);
841
842 memcpy(&client_rssi->macs, client_mac, sizeof(*client_mac) );
843 client_rssi->rssi = 0;
844
845 CHECK_RETURN_UNSUPPORTED_OK(whd_cdc_send_ioctl(ifp, CDC_GET, WLC_GET_RSSI, buffer, &response) );
846 data = whd_buffer_get_current_piece_data_pointer(whd_driver, response);
847 CHECK_PACKET_NULL(data, WHD_NO_REGISTER_FUNCTION_POINTER);
848 memcpy(rssi, data, sizeof(int32_t) );
849 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
850
851 return WHD_SUCCESS;
852 }
853
854 /** Callback for join events
855 * This is called when the WLC_E_SET_SSID event is received,
856 * indicating that the system has joined successfully.
857 * Wakes the thread which was doing the join, allowing it to resume.
858 */
whd_wifi_join_events_handler(whd_interface_t ifp,const whd_event_header_t * event_header,const uint8_t * event_data,void * handler_user_data)859 static void *whd_wifi_join_events_handler(whd_interface_t ifp, const whd_event_header_t *event_header,
860 const uint8_t *event_data,
861 void *handler_user_data)
862 {
863 cy_semaphore_t *semaphore = (cy_semaphore_t *)handler_user_data;
864 whd_bool_t join_attempt_complete = WHD_FALSE;
865 whd_driver_t whd_driver = ifp->whd_driver;
866 whd_result_t result;
867
868 UNUSED_PARAMETER(event_data);
869
870 if (event_header->bsscfgidx >= WHD_INTERFACE_MAX)
871 {
872 WPRINT_WHD_DEBUG( ("%s: event_header: Bad interface\n", __FUNCTION__) );
873 return NULL;
874 }
875
876 switch (event_header->event_type)
877 {
878 case WLC_E_PSK_SUP:
879 /* Ignore WLC_E_PSK_SUP event if link is not up */
880 if ( (whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] & JOIN_LINK_READY) != 0 )
881 {
882 if (event_header->status == WLC_SUP_KEYED)
883 {
884 /* Successful WPA key exchange */
885 whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] &= ~JOIN_SECURITY_FLAGS_MASK;
886 whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] |= JOIN_SECURITY_COMPLETE;
887 }
888 else
889 {
890 /* join has completed with an error */
891 join_attempt_complete = WHD_TRUE;
892 if ( (event_header->status == WLC_SUP_KEYXCHANGE_WAIT_M1) &&
893 (event_header->reason == WLC_E_SUP_WPA_PSK_TMO) )
894 {
895 /* A timeout waiting for M1 may occur at the edge of the cell or if the AP is particularly slow. */
896 WPRINT_WHD_DEBUG( ("Supplicant M1 timeout event\n") );
897 whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] |= JOIN_EAPOL_KEY_M1_TIMEOUT;
898 }
899 else if ( (event_header->status == WLC_SUP_KEYXCHANGE_WAIT_M3) &&
900 (event_header->reason == WLC_E_SUP_WPA_PSK_TMO) )
901 {
902 /* A timeout waiting for M3 is an indicator that the passphrase may be incorrect. */
903 WPRINT_WHD_DEBUG( ("Supplicant M3 timeout event\n") );
904 whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] |= JOIN_EAPOL_KEY_M3_TIMEOUT;
905 }
906 else if ( (event_header->status == WLC_SUP_KEYXCHANGE_WAIT_G1) &&
907 (event_header->reason == WLC_E_SUP_WPA_PSK_TMO) )
908 {
909 /* A timeout waiting for G1 (group key) may occur at the edge of the cell. */
910 WPRINT_WHD_DEBUG( ("Supplicant G1 timeout event\n") );
911 whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] |= JOIN_EAPOL_KEY_G1_TIMEOUT;
912 }
913 else
914 {
915 WPRINT_WHD_DEBUG( ("Unsuccessful supplicant event; status=0x%" PRIu32 "\n",
916 event_header->status) );
917 /* Unknown failure during EAPOL key handshake */
918 whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] |= JOIN_EAPOL_KEY_FAILURE;
919 }
920 }
921 }
922 break;
923
924 case WLC_E_SET_SSID:
925 if (event_header->status == WLC_E_STATUS_SUCCESS)
926 {
927 /* SSID has been successfully set. */
928 whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] |= JOIN_SSID_SET;
929 }
930 /* We don't bail out on this event or things like WPS won't work if the AP is rebooting after configuration */
931 else if (event_header->status == WLC_E_STATUS_NO_NETWORKS)
932 {
933 whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] |= JOIN_NO_NETWORKS;
934 }
935 else
936 {
937 join_attempt_complete = WHD_TRUE;
938 }
939 break;
940
941 case WLC_E_LINK:
942 if ( (event_header->flags & WLC_EVENT_MSG_LINK) != 0 )
943 {
944 whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] |= JOIN_LINK_READY;
945 }
946 else
947 {
948 whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] &= ~JOIN_LINK_READY;
949 }
950 break;
951
952 case WLC_E_DEAUTH_IND:
953 case WLC_E_DISASSOC_IND:
954 whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] &=
955 ~(JOIN_AUTHENTICATED | JOIN_LINK_READY);
956 break;
957
958 case WLC_E_AUTH:
959 if (event_header->status == WLC_E_STATUS_SUCCESS)
960 {
961 whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] |= JOIN_AUTHENTICATED;
962 }
963 else if (event_header->status == WLC_E_STATUS_UNSOLICITED)
964 {
965 WPRINT_WHD_DEBUG( ("Ignore UNSOLICITED pkt event\n") );
966 }
967 else
968 {
969 /* We cannot authenticate. Perhaps we're blocked or at the edge of a cell. */
970 join_attempt_complete = WHD_TRUE;
971 }
972 break;
973
974 case WLC_E_CSA_COMPLETE_IND:
975 if (event_header->datalen >= sizeof(wl_chan_switch_t) )
976 {
977 wl_chan_switch_t *wl_csa = (wl_chan_switch_t *)event_data;
978 UNUSED_PARAMETER(wl_csa);
979 WPRINT_WHD_INFO( ("CSA event => chan %d\n", (dtoh16(wl_csa->chspec) & 0xff) ) );
980 }
981 break;
982
983 /* Note - These are listed to keep gcc pedantic checking happy */
984 case WLC_E_RRM:
985 case WLC_E_NONE:
986 case WLC_E_ROAM:
987 case WLC_E_JOIN:
988 case WLC_E_START:
989 case WLC_E_AUTH_IND:
990 case WLC_E_DEAUTH:
991 case WLC_E_ASSOC:
992 case WLC_E_ASSOC_IND:
993 case WLC_E_REASSOC:
994 case WLC_E_REASSOC_IND:
995 case WLC_E_DISASSOC:
996 case WLC_E_QUIET_START:
997 case WLC_E_QUIET_END:
998 case WLC_E_BEACON_RX:
999 case WLC_E_MIC_ERROR:
1000 case WLC_E_NDIS_LINK:
1001 case WLC_E_TXFAIL:
1002 case WLC_E_PMKID_CACHE:
1003 case WLC_E_RETROGRADE_TSF:
1004 case WLC_E_PRUNE:
1005 case WLC_E_AUTOAUTH:
1006 case WLC_E_EAPOL_MSG:
1007 case WLC_E_SCAN_COMPLETE:
1008 case WLC_E_ADDTS_IND:
1009 case WLC_E_DELTS_IND:
1010 case WLC_E_BCNSENT_IND:
1011 case WLC_E_BCNRX_MSG:
1012 case WLC_E_BCNLOST_MSG:
1013 case WLC_E_ROAM_PREP:
1014 case WLC_E_PFN_NET_FOUND:
1015 case WLC_E_PFN_NET_LOST:
1016 case WLC_E_RESET_COMPLETE:
1017 case WLC_E_JOIN_START:
1018 case WLC_E_ROAM_START:
1019 case WLC_E_ASSOC_START:
1020 case WLC_E_IBSS_ASSOC:
1021 case WLC_E_RADIO:
1022 case WLC_E_PSM_WATCHDOG:
1023 case WLC_E_CCX_ASSOC_START:
1024 case WLC_E_CCX_ASSOC_ABORT:
1025 case WLC_E_PROBREQ_MSG:
1026 case WLC_E_SCAN_CONFIRM_IND:
1027 case WLC_E_COUNTRY_CODE_CHANGED:
1028 case WLC_E_EXCEEDED_MEDIUM_TIME:
1029 case WLC_E_ICV_ERROR:
1030 case WLC_E_UNICAST_DECODE_ERROR:
1031 case WLC_E_MULTICAST_DECODE_ERROR:
1032 case WLC_E_TRACE:
1033 case WLC_E_BTA_HCI_EVENT:
1034 case WLC_E_IF:
1035 case WLC_E_PFN_BEST_BATCHING:
1036 case WLC_E_RSSI:
1037 case WLC_E_EXTLOG_MSG:
1038 case WLC_E_ACTION_FRAME:
1039 case WLC_E_ACTION_FRAME_COMPLETE:
1040 case WLC_E_PRE_ASSOC_IND:
1041 case WLC_E_PRE_REASSOC_IND:
1042 case WLC_E_CHANNEL_ADOPTED:
1043 case WLC_E_AP_STARTED:
1044 case WLC_E_DFS_AP_STOP:
1045 case WLC_E_DFS_AP_RESUME:
1046 case WLC_E_WAI_STA_EVENT:
1047 case WLC_E_WAI_MSG:
1048 case WLC_E_ESCAN_RESULT:
1049 case WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE:
1050 case WLC_E_PROBRESP_MSG:
1051 case WLC_E_P2P_PROBREQ_MSG:
1052 case WLC_E_DCS_REQUEST:
1053 case WLC_E_FIFO_CREDIT_MAP:
1054 case WLC_E_ACTION_FRAME_RX:
1055 case WLC_E_WAKE_EVENT:
1056 case WLC_E_RM_COMPLETE:
1057 case WLC_E_HTSFSYNC:
1058 case WLC_E_OVERLAY_REQ:
1059 case WLC_E_EXCESS_PM_WAKE_EVENT:
1060 case WLC_E_PFN_SCAN_NONE:
1061 case WLC_E_PFN_SCAN_ALLGONE:
1062 case WLC_E_GTK_PLUMBED:
1063 case WLC_E_ASSOC_IND_NDIS:
1064 case WLC_E_REASSOC_IND_NDIS:
1065 case WLC_E_ASSOC_REQ_IE:
1066 case WLC_E_ASSOC_RESP_IE:
1067 case WLC_E_ASSOC_RECREATED:
1068 case WLC_E_ACTION_FRAME_RX_NDIS:
1069 case WLC_E_AUTH_REQ:
1070 case WLC_E_TDLS_PEER_EVENT:
1071 case WLC_E_SPEEDY_RECREATE_FAIL:
1072 case WLC_E_NATIVE:
1073 case WLC_E_PKTDELAY_IND:
1074 case WLC_E_AWDL_AW:
1075 case WLC_E_AWDL_ROLE:
1076 case WLC_E_AWDL_EVENT:
1077 case WLC_E_NIC_AF_TXS:
1078 case WLC_E_NAN:
1079 case WLC_E_BEACON_FRAME_RX:
1080 case WLC_E_SERVICE_FOUND:
1081 case WLC_E_GAS_FRAGMENT_RX:
1082 case WLC_E_GAS_COMPLETE:
1083 case WLC_E_P2PO_ADD_DEVICE:
1084 case WLC_E_P2PO_DEL_DEVICE:
1085 case WLC_E_WNM_STA_SLEEP:
1086 case WLC_E_TXFAIL_THRESH:
1087 case WLC_E_PROXD:
1088 case WLC_E_IBSS_COALESCE:
1089 case WLC_E_AWDL_RX_PRB_RESP:
1090 case WLC_E_AWDL_RX_ACT_FRAME:
1091 case WLC_E_AWDL_WOWL_NULLPKT:
1092 case WLC_E_AWDL_PHYCAL_STATUS:
1093 case WLC_E_AWDL_OOB_AF_STATUS:
1094 case WLC_E_AWDL_SCAN_STATUS:
1095 case WLC_E_AWDL_AW_START:
1096 case WLC_E_AWDL_AW_END:
1097 case WLC_E_AWDL_AW_EXT:
1098 case WLC_E_AWDL_PEER_CACHE_CONTROL:
1099 case WLC_E_CSA_START_IND:
1100 case WLC_E_CSA_DONE_IND:
1101 case WLC_E_CSA_FAILURE_IND:
1102 case WLC_E_CCA_CHAN_QUAL:
1103 case WLC_E_BSSID:
1104 case WLC_E_TX_STAT_ERROR:
1105 case WLC_E_BCMC_CREDIT_SUPPORT:
1106 case WLC_E_PSTA_PRIMARY_INTF_IND:
1107 case WLC_E_P2P_DISC_LISTEN_COMPLETE:
1108 case WLC_E_BT_WIFI_HANDOVER_REQ:
1109 case WLC_E_SPW_TXINHIBIT:
1110 case WLC_E_FBT_AUTH_REQ_IND:
1111 case WLC_E_RSSI_LQM:
1112 case WLC_E_PFN_GSCAN_FULL_RESULT:
1113 case WLC_E_PFN_SWC:
1114 case WLC_E_AUTHORIZED:
1115 case WLC_E_PROBREQ_MSG_RX:
1116 case WLC_E_PFN_SCAN_COMPLETE:
1117 case WLC_E_RMC_EVENT:
1118 case WLC_E_DPSTA_INTF_IND:
1119 case WLC_E_ULP:
1120 case WLC_E_LAST:
1121 default:
1122 whd_assert("Received event which was not registered\n", 0 != 0);
1123 break;
1124 }
1125
1126 if (whd_wifi_is_ready_to_transceive(ifp) == WHD_SUCCESS)
1127 {
1128 join_attempt_complete = WHD_TRUE;
1129 }
1130
1131 if (join_attempt_complete == WHD_TRUE)
1132 {
1133 if (semaphore != NULL)
1134 {
1135 result = cy_rtos_get_semaphore(&whd_driver->internal_info.active_join_mutex, CY_RTOS_NEVER_TIMEOUT,
1136 WHD_FALSE);
1137 if (result != WHD_SUCCESS)
1138 {
1139 WPRINT_WHD_ERROR( ("Get semaphore failed in %s at %d \n", __func__, __LINE__) );
1140 }
1141 if (whd_driver->internal_info.active_join_semaphore != NULL)
1142 {
1143 whd_assert("Unexpected semaphore\n", whd_driver->internal_info.active_join_semaphore == semaphore);
1144 result = cy_rtos_set_semaphore(whd_driver->internal_info.active_join_semaphore, WHD_FALSE);
1145 if (result != WHD_SUCCESS)
1146 {
1147 WPRINT_WHD_ERROR( ("Set semaphore failed in %s at %d \n", __func__, __LINE__) );
1148 }
1149 }
1150 result = cy_rtos_set_semaphore(&whd_driver->internal_info.active_join_mutex, WHD_FALSE);
1151 if (result != WHD_SUCCESS)
1152 {
1153 WPRINT_WHD_ERROR( ("Set semaphore failed in %s at %d \n", __func__, __LINE__) );
1154 }
1155 }
1156 return NULL;
1157 }
1158 else
1159 {
1160 return handler_user_data;
1161 }
1162 }
1163
1164 /* Do any needed preparation prior to launching a join */
whd_wifi_active_join_init(whd_interface_t ifp,whd_security_t auth_type,const uint8_t * security_key,uint8_t key_length,cy_semaphore_t * semaphore)1165 static uint32_t whd_wifi_active_join_init(whd_interface_t ifp, whd_security_t auth_type, const uint8_t *security_key,
1166 uint8_t key_length, cy_semaphore_t *semaphore)
1167 {
1168 whd_driver_t whd_driver = ifp->whd_driver;
1169
1170 if (whd_driver->internal_info.active_join_mutex_initted == WHD_FALSE)
1171 {
1172 CHECK_RETURN(cy_rtos_init_semaphore(&whd_driver->internal_info.active_join_mutex, 1, 0) );
1173 whd_driver->internal_info.active_join_mutex_initted = WHD_TRUE;
1174 CHECK_RETURN(cy_rtos_set_semaphore(&whd_driver->internal_info.active_join_mutex, WHD_FALSE) );
1175 }
1176
1177 CHECK_RETURN(cy_rtos_get_semaphore(&whd_driver->internal_info.active_join_mutex, CY_RTOS_NEVER_TIMEOUT,
1178 WHD_FALSE) );
1179 whd_driver->internal_info.active_join_semaphore = semaphore;
1180 CHECK_RETURN(cy_rtos_set_semaphore(&whd_driver->internal_info.active_join_mutex, WHD_FALSE) );
1181
1182 CHECK_RETURN(whd_wifi_prepare_join(ifp, auth_type, security_key, key_length, semaphore) );
1183 return WHD_SUCCESS;
1184 }
1185
whd_wifi_prepare_join(whd_interface_t ifp,whd_security_t auth_type,const uint8_t * security_key,uint8_t key_length,cy_semaphore_t * semaphore)1186 static uint32_t whd_wifi_prepare_join(whd_interface_t ifp, whd_security_t auth_type,
1187 const uint8_t *security_key, uint8_t key_length,
1188 cy_semaphore_t *semaphore)
1189 {
1190 whd_buffer_t buffer;
1191 uint32_t auth_mfp = WL_MFP_NONE;
1192 whd_result_t retval = WHD_SUCCESS;
1193 whd_result_t check_result = WHD_SUCCESS;
1194 uint32_t *data;
1195 uint32_t *wpa_auth;
1196 uint32_t bss_index = 0;
1197 uint32_t auth;
1198 whd_driver_t whd_driver = ifp->whd_driver;
1199 uint16_t event_entry = 0xFF;
1200
1201 (void)bss_index;
1202 if ( (auth_type == WHD_SECURITY_WPA2_FBT_ENT) || (auth_type == WHD_SECURITY_IBSS_OPEN) ||
1203 (auth_type == WHD_SECURITY_WPA2_FBT_PSK) )
1204 {
1205 return WHD_UNKNOWN_SECURITY_TYPE;
1206 }
1207 else if ( (auth_type & WEP_ENABLED) != 0 )
1208 {
1209 return WHD_WEP_NOT_ALLOWED;
1210 }
1211 if ( ( ( (key_length > (uint8_t)WSEC_MAX_PSK_LEN) || (key_length < (uint8_t)WSEC_MIN_PSK_LEN) ) &&
1212 ( (auth_type == WHD_SECURITY_WPA_TKIP_PSK) || (auth_type == WHD_SECURITY_WPA_AES_PSK) ||
1213 (auth_type == WHD_SECURITY_WPA2_AES_PSK) || (auth_type == WHD_SECURITY_WPA2_AES_PSK_SHA256) ||
1214 (auth_type == WHD_SECURITY_WPA2_TKIP_PSK) || (auth_type == WHD_SECURITY_WPA2_MIXED_PSK) ) ) ||
1215 ( (key_length > (uint8_t)WSEC_MAX_SAE_PASSWORD_LEN) &&
1216 ( (auth_type == WHD_SECURITY_WPA3_SAE) || (auth_type == WHD_SECURITY_WPA3_WPA2_PSK) ) ) )
1217 {
1218 return WHD_INVALID_KEY;
1219 }
1220
1221 (void)auth_type, (void)security_key, (void)key_length, (void)semaphore;
1222
1223 /* Clear the current join status */
1224 whd_driver->internal_info.whd_join_status[ifp->bsscfgidx] = 0;
1225
1226 /* Setting wsec will overwrite mfp setting in older branches, store value before setting wsec */
1227 CHECK_RETURN(whd_wifi_get_iovar_value(ifp, IOVAR_STR_MFP, &auth_mfp) );
1228
1229 /* Set Wireless Security Type */
1230 CHECK_RETURN(whd_wifi_set_ioctl_value(ifp, WLC_SET_WSEC, (uint32_t)(auth_type & 0xFF) ) );
1231
1232 /* Enable Roaming in FW by default */
1233 CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_ROAM_OFF, 0) );
1234
1235 /* Map the interface to a BSS index */
1236 bss_index = ifp->bsscfgidx;
1237
1238 /* Set supplicant variable - mfg app doesn't support these iovars, so don't care if return fails */
1239 data = whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, "bsscfg:" IOVAR_STR_SUP_WPA);
1240 CHECK_IOCTL_BUFFER(data);
1241 data[0] = htod32(bss_index);
1242 data[1] =
1243 htod32( ( uint32_t )( ( ( (auth_type & WPA_SECURITY) != 0 ) || ( (auth_type & WPA2_SECURITY) != 0 ) ||
1244 (auth_type & WPA3_SECURITY) != 0 ) ? 1 : 0 ) );
1245 (void)whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0);
1246
1247 /* Set the EAPOL version to whatever the AP is using (-1) */
1248 data = whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, "bsscfg:" IOVAR_STR_SUP_WPA2_EAPVER);
1249 CHECK_IOCTL_BUFFER(data);
1250 data[0] = htod32(bss_index);
1251 data[1] = htod32( ( uint32_t )-1 );
1252 (void)whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0);
1253
1254 /* Send WPA Key */
1255 switch (auth_type)
1256 {
1257 case WHD_SECURITY_OPEN:
1258 case WHD_SECURITY_WPS_SECURE:
1259 break;
1260
1261 case WHD_SECURITY_WPA_TKIP_PSK:
1262 case WHD_SECURITY_WPA_AES_PSK:
1263 case WHD_SECURITY_WPA_MIXED_PSK:
1264 case WHD_SECURITY_WPA2_AES_PSK:
1265 case WHD_SECURITY_WPA2_AES_PSK_SHA256:
1266 case WHD_SECURITY_WPA2_TKIP_PSK:
1267 case WHD_SECURITY_WPA2_MIXED_PSK:
1268 case WHD_SECURITY_WPA2_WPA_AES_PSK:
1269 case WHD_SECURITY_WPA2_WPA_MIXED_PSK:
1270 /* Set the EAPOL key packet timeout value, otherwise unsuccessful supplicant events aren't reported. If the IOVAR is unsupported then continue. */
1271 CHECK_RETURN_UNSUPPORTED_CONTINUE(whd_wifi_set_supplicant_key_timeout(ifp,
1272 DEFAULT_EAPOL_KEY_PACKET_TIMEOUT) );
1273 CHECK_RETURN(whd_wifi_set_passphrase(ifp, security_key, key_length) );
1274 break;
1275
1276 case WHD_SECURITY_WPA3_SAE:
1277 case WHD_SECURITY_WPA3_WPA2_PSK:
1278 if (auth_type == WHD_SECURITY_WPA3_WPA2_PSK)
1279 {
1280 CHECK_RETURN(whd_wifi_enable_sup_set_passphrase(ifp, security_key, key_length, auth_type) );
1281 }
1282 /* Set the EAPOL key packet timeout value, otherwise unsuccessful supplicant events aren't reported. If the IOVAR is unsupported then continue. */
1283 CHECK_RETURN_UNSUPPORTED_CONTINUE(whd_wifi_set_supplicant_key_timeout(ifp,
1284 DEFAULT_EAPOL_KEY_PACKET_TIMEOUT) );
1285 if (whd_driver->chip_info.fwcap_flags & (1 << WHD_FWCAP_SAE) )
1286 {
1287 CHECK_RETURN(whd_wifi_sae_password(ifp, security_key, key_length) );
1288 }
1289 else
1290 {
1291 /* Disable Roaming in FW, becuase our wpa3_external_supplicant's limitation.
1292 If FW report WLC_E_EXT_AUTH_REQ during roaming, Host already called whd_wifi_stop_external_auth_request. */
1293 CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_ROAM_OFF, 1) );
1294 }
1295 break;
1296
1297 case WHD_SECURITY_WPA_TKIP_ENT:
1298 case WHD_SECURITY_WPA_AES_ENT:
1299 case WHD_SECURITY_WPA_MIXED_ENT:
1300 case WHD_SECURITY_WPA2_TKIP_ENT:
1301 case WHD_SECURITY_WPA2_AES_ENT:
1302 case WHD_SECURITY_WPA2_MIXED_ENT:
1303 /* Disable eapol timer by setting to value 0 */
1304 CHECK_RETURN_UNSUPPORTED_CONTINUE(whd_wifi_set_supplicant_key_timeout(ifp, 0) );
1305 break;
1306 #if 0
1307 case WHD_SECURITY_WPA2_FBT_ENT:
1308 /* Disable eapol timer by setting to value 0 */
1309 CHECK_RETURN_UNSUPPORTED_CONTINUE(whd_wifi_set_supplicant_key_timeout(ifp, 0) );
1310 break;
1311 #endif
1312 case WHD_SECURITY_FORCE_32_BIT:
1313 case WHD_SECURITY_UNKNOWN:
1314 default:
1315 whd_assert("whd_wifi_prepare_join: Unsupported security type\n", 0 != 0);
1316 break;
1317 }
1318 /* Set infrastructure mode */
1319 CHECK_RETURN(whd_wifi_set_ioctl_value(ifp, WLC_SET_INFRA, ( (auth_type & IBSS_ENABLED) == 0 ) ? 1 : 0) );
1320
1321 if ( (auth_type == WHD_SECURITY_WPA3_SAE) || (auth_type == WHD_SECURITY_WPA3_WPA2_PSK) )
1322 {
1323 auth = WL_AUTH_SAE;
1324 }
1325 else
1326 {
1327 auth = WL_AUTH_OPEN_SYSTEM;
1328 }
1329 CHECK_RETURN(whd_wifi_set_ioctl_value(ifp, WLC_SET_AUTH, auth) );
1330
1331 /* From PMF cert test plan,
1332 * 2.2 Out of Box Requirements
1333 * When WPA2 security is enabled on the DUT, then by defaults the DUT shall:
1334 * Enable Robust Management Frame Protection Capable (MFPC) functionality
1335 */
1336 if (auth_type == WHD_SECURITY_WPA3_SAE)
1337 {
1338 auth_mfp = WL_MFP_REQUIRED;
1339 }
1340 else if ( (auth_type == WHD_SECURITY_WPA3_WPA2_PSK) || (auth_type & WPA2_SECURITY) )
1341 {
1342 auth_mfp = WL_MFP_CAPABLE;
1343 }
1344
1345 check_result = whd_wifi_set_iovar_value(ifp, IOVAR_STR_MFP, auth_mfp);
1346 if (check_result != WHD_SUCCESS)
1347 {
1348 WPRINT_WHD_DEBUG( ("Older chipsets might not support MFP..Ignore result\n") );
1349 }
1350
1351 /* Set WPA authentication mode */
1352 wpa_auth = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)4);
1353 CHECK_IOCTL_BUFFER(wpa_auth);
1354
1355 switch (auth_type)
1356 {
1357 #if 0
1358 case WHD_SECURITY_IBSS_OPEN:
1359 /* IBSS does not get authenticated onto an AP */
1360 whd_driver->internal_info.whd_join_status[ifp->bsscfgidx] |= JOIN_AUTHENTICATED;
1361 #endif
1362 /* intentional fall-thru */
1363 /* Disables Eclipse static analysis warning */
1364 /* no break */
1365 /* Fall-Through */
1366 case WHD_SECURITY_OPEN:
1367 case WHD_SECURITY_WPS_SECURE:
1368 *wpa_auth = WPA_AUTH_DISABLED;
1369 /* Open Networks do not have to complete security */
1370 whd_driver->internal_info.whd_join_status[ifp->bsscfgidx] |= JOIN_SECURITY_COMPLETE;
1371 break;
1372
1373 case WHD_SECURITY_WPA_TKIP_PSK:
1374 case WHD_SECURITY_WPA_AES_PSK:
1375 case WHD_SECURITY_WPA_MIXED_PSK:
1376 *wpa_auth = (uint32_t)WPA_AUTH_PSK;
1377 break;
1378
1379 case WHD_SECURITY_WPA2_AES_PSK:
1380 case WHD_SECURITY_WPA2_TKIP_PSK:
1381 case WHD_SECURITY_WPA2_MIXED_PSK:
1382 case WHD_SECURITY_WPA2_WPA_AES_PSK:
1383 case WHD_SECURITY_WPA2_WPA_MIXED_PSK:
1384 *wpa_auth = (uint32_t)WPA2_AUTH_PSK;
1385 break;
1386
1387 case WHD_SECURITY_WPA2_AES_PSK_SHA256:
1388 *wpa_auth = (uint32_t)WPA2_AUTH_PSK_SHA256;
1389 break;
1390
1391 case WHD_SECURITY_WPA3_SAE:
1392 case WHD_SECURITY_WPA3_WPA2_PSK:
1393 *wpa_auth = (uint32_t)WPA3_AUTH_SAE_PSK;
1394 break;
1395
1396 case WHD_SECURITY_WPA_TKIP_ENT:
1397 case WHD_SECURITY_WPA_AES_ENT:
1398 case WHD_SECURITY_WPA_MIXED_ENT:
1399 *wpa_auth = (uint32_t)WPA_AUTH_UNSPECIFIED;
1400 break;
1401
1402 case WHD_SECURITY_WPA2_TKIP_ENT:
1403 case WHD_SECURITY_WPA2_AES_ENT:
1404 case WHD_SECURITY_WPA2_MIXED_ENT:
1405 *wpa_auth = (uint32_t)WPA2_AUTH_UNSPECIFIED;
1406 break;
1407 #if 0
1408 case WHD_SECURITY_WPA2_FBT_ENT:
1409 *wpa_auth = ( uint32_t )(WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_FT);
1410 break;
1411 #endif
1412 case WHD_SECURITY_UNKNOWN:
1413 case WHD_SECURITY_FORCE_32_BIT:
1414 default:
1415 WPRINT_WHD_DEBUG( ("Unsupported Security type\n") );
1416 *wpa_auth = WPA_AUTH_DISABLED;
1417 break;
1418 }
1419 *wpa_auth = htod32(*wpa_auth);
1420 CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_WPA_AUTH, buffer, 0) );
1421
1422 if (ifp->event_reg_list[WHD_JOIN_EVENT_ENTRY] != WHD_EVENT_NOT_REGISTERED)
1423 {
1424 whd_wifi_deregister_event_handler(ifp, ifp->event_reg_list[WHD_JOIN_EVENT_ENTRY]);
1425 ifp->event_reg_list[WHD_JOIN_EVENT_ENTRY] = WHD_EVENT_NOT_REGISTERED;
1426 }
1427
1428 CHECK_RETURN(whd_management_set_event_handler(ifp, join_events, whd_wifi_join_events_handler, (void *)semaphore,
1429 &event_entry) );
1430 if (event_entry >= WHD_EVENT_ENTRY_MAX)
1431 {
1432 WPRINT_WHD_ERROR( ("Join events registration failed in function %s and line %d", __func__, __LINE__) );
1433 return WHD_UNFINISHED;
1434 }
1435 ifp->event_reg_list[WHD_JOIN_EVENT_ENTRY] = event_entry;
1436 whd_assert("Set join Event handler failed\n", retval == WHD_SUCCESS);
1437
1438 return WHD_SUCCESS;
1439 }
1440
1441 /* do any needed tear down after join
1442 * @param stack_semaphore - semaphore used to control execution if client_semaphore is NULL
1443 * @param client_semaphore - semaphore used to control execution if client passes this in
1444 */
whd_wifi_active_join_deinit(whd_interface_t ifp,cy_semaphore_t * stack_semaphore,whd_result_t result)1445 static void whd_wifi_active_join_deinit(whd_interface_t ifp, cy_semaphore_t *stack_semaphore, whd_result_t result)
1446 {
1447 whd_driver_t whd_driver = ifp->whd_driver;
1448 whd_result_t val;
1449 /* deinit join specific variables, with protection from mutex */
1450
1451 val = cy_rtos_get_semaphore(&whd_driver->internal_info.active_join_mutex, CY_RTOS_NEVER_TIMEOUT, WHD_FALSE);
1452 if (val != WHD_SUCCESS)
1453 WPRINT_WHD_ERROR( ("Get semaphore failed in %s at %d \n", __func__, __LINE__) );
1454
1455 whd_driver->internal_info.active_join_semaphore = NULL;
1456
1457 cy_rtos_deinit_semaphore(stack_semaphore);
1458
1459 if (WHD_SUCCESS != result)
1460 {
1461 WPRINT_WHD_INFO( ("Failed join (err %" PRIu32 ")\n", result) );
1462 ifp->role = WHD_INVALID_ROLE;
1463 }
1464
1465 val = cy_rtos_set_semaphore(&whd_driver->internal_info.active_join_mutex, WHD_FALSE);
1466 if (val != WHD_SUCCESS)
1467 WPRINT_WHD_ERROR( ("Get semaphore failed in %s at %d \n", __func__, __LINE__) );
1468
1469 /* we forced the chip to be up during join, now let it sleep */
1470 WHD_WLAN_LET_SLEEP(whd_driver);
1471 }
1472
whd_wifi_join_wait_for_complete(whd_interface_t ifp,cy_semaphore_t * semaphore)1473 static uint32_t whd_wifi_join_wait_for_complete(whd_interface_t ifp, cy_semaphore_t *semaphore)
1474 {
1475 whd_result_t result;
1476 uint32_t start_time;
1477 uint32_t current_time;
1478 whd_bool_t done = WHD_FALSE;
1479
1480 cy_rtos_get_time(&start_time);
1481
1482 while (!done)
1483 {
1484 result = cy_rtos_get_semaphore(semaphore, DEFAULT_JOIN_ATTEMPT_TIMEOUT / 10, WHD_FALSE);
1485 whd_assert("Get semaphore failed", (result == CY_RSLT_SUCCESS) || (result == CY_RTOS_TIMEOUT) );
1486 REFERENCE_DEBUG_ONLY_VARIABLE(result);
1487
1488 result = whd_wifi_is_ready_to_transceive(ifp);
1489 if (result == WHD_SUCCESS)
1490 {
1491 break;
1492 }
1493
1494 cy_rtos_get_time(¤t_time);
1495 done = (whd_bool_t)( (current_time - start_time) >= DEFAULT_JOIN_ATTEMPT_TIMEOUT );
1496 }
1497
1498 if (result != WHD_SUCCESS)
1499 {
1500 CHECK_RETURN(whd_wifi_leave(ifp) );
1501 WPRINT_WHD_INFO( ("%s: not ready to transceive (err %" PRIu32 "); left network\n", __func__, result) );
1502 }
1503
1504 return result;
1505 }
1506
whd_wifi_check_join_status(whd_interface_t ifp)1507 static uint32_t whd_wifi_check_join_status(whd_interface_t ifp)
1508 {
1509 whd_driver_t whd_driver = ifp->whd_driver;
1510
1511 if ( (uint32_t)ifp->bsscfgidx >= WHD_INTERFACE_MAX )
1512 {
1513 WPRINT_WHD_ERROR( ("%s: Bad interface %d\n", __FUNCTION__, ifp->bsscfgidx) );
1514 return WHD_INVALID_JOIN_STATUS;
1515 }
1516 switch (whd_driver->internal_info.whd_join_status[ifp->bsscfgidx])
1517 {
1518 case JOIN_NO_NETWORKS:
1519 return WHD_NETWORK_NOT_FOUND;
1520
1521 case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_EAPOL_KEY_M1_TIMEOUT:
1522 return WHD_EAPOL_KEY_PACKET_M1_TIMEOUT;
1523
1524 case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_EAPOL_KEY_M3_TIMEOUT:
1525 case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_SSID_SET | JOIN_EAPOL_KEY_M3_TIMEOUT:
1526 return WHD_EAPOL_KEY_PACKET_M3_TIMEOUT;
1527
1528 case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_EAPOL_KEY_G1_TIMEOUT:
1529 case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_SSID_SET | JOIN_EAPOL_KEY_G1_TIMEOUT:
1530 return WHD_EAPOL_KEY_PACKET_G1_TIMEOUT;
1531
1532 case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_EAPOL_KEY_FAILURE:
1533 case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_SSID_SET | JOIN_EAPOL_KEY_FAILURE:
1534 return WHD_EAPOL_KEY_FAILURE;
1535
1536 case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_SSID_SET | JOIN_SECURITY_COMPLETE:
1537 return WHD_SUCCESS;
1538
1539 case 0:
1540 case JOIN_SECURITY_COMPLETE: /* For open/WEP */
1541 return WHD_NOT_AUTHENTICATED;
1542
1543 case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_SECURITY_COMPLETE:
1544 return WHD_JOIN_IN_PROGRESS;
1545
1546 case JOIN_AUTHENTICATED | JOIN_LINK_READY:
1547 case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_SSID_SET:
1548 return WHD_NOT_KEYED;
1549
1550 default:
1551 return WHD_INVALID_JOIN_STATUS;
1552 }
1553 }
1554
whd_wifi_join_specific(whd_interface_t ifp,const whd_scan_result_t * ap,const uint8_t * security_key,uint8_t key_length)1555 uint32_t whd_wifi_join_specific(whd_interface_t ifp, const whd_scan_result_t *ap, const uint8_t *security_key,
1556 uint8_t key_length)
1557 {
1558 whd_buffer_t buffer;
1559 cy_semaphore_t join_semaphore;
1560 whd_result_t result;
1561 wl_extjoin_params_t *ext_join_params;
1562 wl_join_params_t *join_params;
1563 whd_security_t security = ap->security;
1564 uint16_t wl_band_for_channel = 0;
1565 whd_driver_t whd_driver;
1566
1567 CHECK_IFP_NULL(ifp);
1568
1569 whd_driver = ifp->whd_driver;
1570
1571 CHECK_DRIVER_NULL(whd_driver);
1572
1573 /* Keep WLAN awake while joining */
1574 WHD_WLAN_KEEP_AWAKE(whd_driver);
1575 ifp->role = WHD_STA_ROLE;
1576
1577 if (ap->bss_type == WHD_BSS_TYPE_MESH)
1578 {
1579 return WHD_UNSUPPORTED;
1580 }
1581
1582 if (ap->bss_type == WHD_BSS_TYPE_ADHOC)
1583 {
1584 security |= IBSS_ENABLED;
1585 }
1586
1587 if (NULL_MAC(ap->BSSID.octet) )
1588 {
1589 WPRINT_WHD_ERROR( ("NULL address is not allowed/valid\n") );
1590 return WHD_BADARG;
1591 }
1592
1593 if (BROADCAST_ID(ap->BSSID.octet) )
1594 {
1595 WPRINT_WHD_ERROR( ("Broadcast address is not allowed/valid in join with specific BSSID of AP\n") );
1596 return WHD_BADARG;
1597 }
1598
1599 if ( (ap->SSID.length == 0) || (ap->SSID.length > (size_t)SSID_NAME_SIZE) )
1600 {
1601 WPRINT_WHD_ERROR( ("%s: failure: SSID length error\n", __func__) );
1602 return WHD_WLAN_BADSSIDLEN;
1603 }
1604
1605 CHECK_RETURN(cy_rtos_init_semaphore(&join_semaphore, 1, 0) );
1606 result = whd_wifi_active_join_init(ifp, security, security_key, key_length, &join_semaphore);
1607
1608 if (result == WHD_SUCCESS)
1609 {
1610 /* Check if soft AP is running, if so, move its current channel to the the destination AP */
1611 if ( (ifp->role == WHD_AP_ROLE) && (whd_wifi_is_ready_to_transceive(ifp) == WHD_SUCCESS) )
1612 {
1613 uint32_t current_softap_channel = 0;
1614 CHECK_RETURN(whd_wifi_get_channel(ifp, ¤t_softap_channel) );
1615 if (current_softap_channel != ap->channel)
1616 {
1617 CHECK_RETURN(whd_wifi_set_channel(ifp, ap->channel) );
1618 WPRINT_WHD_DEBUG( ("WARN: moving soft-AP channel from %" PRIu32 " to %d due to STA join\n",
1619 current_softap_channel, ap->channel) );
1620 cy_rtos_delay_milliseconds(100);
1621 }
1622 }
1623
1624 else
1625 {
1626 if (ap->bss_type == WHD_BSS_TYPE_ADHOC)
1627 {
1628 CHECK_RETURN(whd_wifi_set_channel(ifp, ap->channel) );
1629 }
1630 }
1631
1632 /* Join network */
1633 ext_join_params =
1634 (wl_extjoin_params_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, sizeof(wl_extjoin_params_t), "join");
1635 CHECK_IOCTL_BUFFER(ext_join_params);
1636 memset(ext_join_params, 0, sizeof(wl_extjoin_params_t) );
1637
1638 ext_join_params->ssid.SSID_len = ap->SSID.length;
1639 DISABLE_COMPILER_WARNING(diag_suppress = Pa039)
1640 memcpy(ext_join_params->ssid.SSID, ap->SSID.value, ext_join_params->ssid.SSID_len);
1641 ENABLE_COMPILER_WARNING(diag_suppress = Pa039)
1642 memcpy(&ext_join_params->assoc_params.bssid, &ap->BSSID, sizeof(whd_mac_t) );
1643 ext_join_params->scan_params.scan_type = 0;
1644 ext_join_params->scan_params.active_time = -1;
1645 ext_join_params->scan_params.home_time = -1;
1646 ext_join_params->scan_params.nprobes = -1;
1647 ext_join_params->scan_params.passive_time = -1;
1648 ext_join_params->assoc_params.bssid_cnt = 0;
1649 if (ap->channel)
1650 {
1651 ext_join_params->assoc_params.chanspec_num = (uint32_t)1;
1652 ext_join_params->assoc_params.chanspec_list[0] =
1653 (wl_chanspec_t)htod16( (ap->channel |
1654 GET_C_VAR(whd_driver, CHANSPEC_BW_20) | GET_C_VAR(whd_driver,
1655 CHANSPEC_CTL_SB_NONE) ) );
1656
1657 /* set band properly */
1658 wl_band_for_channel = whd_channel_to_wl_band(whd_driver, ap->channel);
1659
1660 ext_join_params->assoc_params.chanspec_list[0] |= wl_band_for_channel;
1661 }
1662 result = whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0);
1663
1664 WPRINT_WHD_INFO( ("%s: set_ssid result (err %" PRIu32 "); left network\n", __func__, result) );
1665
1666 /* Some firmware, e.g. for 4390, does not support the join IOVAR, so use the older IOCTL call instead */
1667 if (result == WHD_WLAN_UNSUPPORTED)
1668 {
1669 join_params =
1670 (wl_join_params_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, sizeof(wl_join_params_t) );
1671 CHECK_IOCTL_BUFFER(join_params);
1672 memset(join_params, 0, sizeof(wl_join_params_t) );
1673 DISABLE_COMPILER_WARNING(diag_suppress = Pa039)
1674 memcpy(&join_params->ssid, &ext_join_params->ssid, sizeof(wlc_ssid_t) );
1675 ENABLE_COMPILER_WARNING(diag_suppress = Pa039)
1676 memcpy(&join_params->params.bssid, &ap->BSSID, sizeof(whd_mac_t) );
1677 join_params->params.bssid_cnt = 0;
1678 if (ap->channel)
1679 {
1680 join_params->params.chanspec_num = (uint32_t)1;
1681 join_params->params.chanspec_list[0] =
1682 (wl_chanspec_t)htod16( (ap->channel |
1683 GET_C_VAR(whd_driver,
1684 CHANSPEC_BW_20) | GET_C_VAR(whd_driver, CHANSPEC_CTL_SB_NONE) ) );
1685
1686 /* set band properly */
1687 join_params->params.chanspec_list[0] |= wl_band_for_channel;
1688 }
1689 result = whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_SSID, buffer, 0);
1690 }
1691
1692 if (result == WHD_SUCCESS)
1693 {
1694
1695 uint16_t chip_id = whd_chip_get_chip_id(whd_driver);
1696
1697 CHECK_RETURN(whd_wifi_join_wait_for_complete(ifp, &join_semaphore) );
1698
1699 if (chip_id == 0x4373)
1700 {
1701 /* For 11 AC MAX throughput set the frame burst and MPDU per AMPDU */
1702 CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_MPDU_PER_AMPDU, 16) );
1703 }
1704
1705 }
1706 else
1707 {
1708 WPRINT_WHD_INFO( ("%s:3 not ready to transceive (err %" PRIu32 "); left network\n", __func__, result) );
1709 }
1710 }
1711 else
1712 {
1713 WPRINT_WHD_INFO( ("%s: active join init failed: (%" PRIu32 ")\n", __FUNCTION__, result) );
1714 }
1715 /* clean up from the join attempt */
1716 whd_wifi_active_join_deinit(ifp, &join_semaphore, result);
1717
1718 CHECK_RETURN(result);
1719
1720 return WHD_SUCCESS;
1721 }
1722
whd_wifi_join(whd_interface_t ifp,const whd_ssid_t * ssid,whd_security_t auth_type,const uint8_t * security_key,uint8_t key_length)1723 uint32_t whd_wifi_join(whd_interface_t ifp, const whd_ssid_t *ssid, whd_security_t auth_type,
1724 const uint8_t *security_key, uint8_t key_length)
1725 {
1726 cy_semaphore_t join_sema;
1727 whd_result_t result;
1728 whd_buffer_t buffer;
1729 wlc_ssid_t *ssid_params;
1730 whd_driver_t whd_driver;
1731
1732 CHECK_IFP_NULL(ifp);
1733
1734 whd_driver = ifp->whd_driver;
1735
1736 CHECK_DRIVER_NULL(whd_driver);
1737
1738 if (ssid == NULL)
1739 {
1740 WPRINT_WHD_ERROR( ("%s: failure: ssid is null\n", __func__) );
1741 return WHD_BADARG;
1742 }
1743
1744 if ( (ssid->length == 0) || (ssid->length > (size_t)SSID_NAME_SIZE) )
1745 {
1746 WPRINT_WHD_ERROR( ("%s: failure: SSID length error\n", __func__) );
1747 return WHD_WLAN_BADSSIDLEN;
1748 }
1749
1750 /* Keep WLAN awake while joining */
1751 WHD_WLAN_KEEP_AWAKE(whd_driver);
1752 ifp->role = WHD_STA_ROLE;
1753
1754 CHECK_RETURN(cy_rtos_init_semaphore(&join_sema, 1, 0) );
1755 result = whd_wifi_active_join_init(ifp, auth_type, security_key, key_length, &join_sema);
1756
1757 if (result == WHD_SUCCESS)
1758 {
1759 /* Join network */
1760 ssid_params = (struct wlc_ssid *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, sizeof(wlc_ssid_t) );
1761 CHECK_IOCTL_BUFFER(ssid_params);
1762 memset(ssid_params, 0, sizeof(wlc_ssid_t) );
1763 ssid_params->SSID_len = htod32(ssid->length);
1764 memcpy(ssid_params->SSID, ssid->value, ssid_params->SSID_len);
1765 result = whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_SSID, buffer, 0);
1766
1767 if (result == WHD_SUCCESS)
1768 {
1769 CHECK_RETURN(whd_wifi_join_wait_for_complete(ifp, &join_sema) );
1770 }
1771 }
1772
1773 /* clean up from the join attempt */
1774 whd_wifi_active_join_deinit(ifp, &join_sema, result);
1775
1776 return result;
1777 }
1778
whd_wifi_leave(whd_interface_t ifp)1779 uint32_t whd_wifi_leave(whd_interface_t ifp)
1780 {
1781 whd_result_t result = WHD_SUCCESS;
1782 whd_driver_t whd_driver;
1783
1784 CHECK_IFP_NULL(ifp);
1785
1786 whd_driver = ifp->whd_driver;
1787
1788 CHECK_DRIVER_NULL(whd_driver);
1789
1790 /* If interface is greater than max return error */
1791 if (ifp->bsscfgidx >= WHD_INTERFACE_MAX)
1792 {
1793 WPRINT_WHD_ERROR( ("%s: Bad interface 2\n", __FUNCTION__) );
1794 return WHD_BADARG;
1795 }
1796 if (ifp->event_reg_list[WHD_JOIN_EVENT_ENTRY] != WHD_EVENT_NOT_REGISTERED)
1797 {
1798 CHECK_RETURN(whd_wifi_deregister_event_handler(ifp, ifp->event_reg_list[WHD_JOIN_EVENT_ENTRY]) );
1799 ifp->event_reg_list[WHD_JOIN_EVENT_ENTRY] = WHD_EVENT_NOT_REGISTERED;
1800 }
1801
1802 /* Disassociate from AP */
1803 result = whd_wifi_set_ioctl_buffer(ifp, WLC_DISASSOC, NULL, 0);
1804
1805 if (result != WHD_SUCCESS)
1806 {
1807 WPRINT_WHD_DEBUG( ("whd_sdpcm_send_ioctl(WLC_DISASSOC) failed:%" PRIu32 "\r\n", result) );
1808 }
1809
1810 whd_driver->internal_info.whd_join_status[ifp->bsscfgidx] = 0;
1811 ifp->role = WHD_INVALID_ROLE;
1812
1813 if (whd_driver->internal_info.active_join_mutex_initted == WHD_TRUE)
1814 {
1815 cy_rtos_deinit_semaphore(&whd_driver->internal_info.active_join_mutex);
1816 whd_driver->internal_info.active_join_mutex_initted = WHD_FALSE;
1817 }
1818 if (whd_driver->internal_info.active_join_semaphore)
1819 {
1820 cy_rtos_deinit_semaphore(whd_driver->internal_info.active_join_semaphore);
1821 whd_driver->internal_info.active_join_semaphore = NULL;
1822 }
1823
1824
1825 return WHD_SUCCESS;
1826 }
1827
1828 /** Handles scan result events
1829 *
1830 * This function receives scan record events, and parses them into a better format, then passes the results
1831 * to the user application.
1832 *
1833 * @param event_header : The event details
1834 * @param event_data : The data for the event which contains the scan result structure
1835 * @param handler_user_data: data which will be passed to user application
1836 *
1837 * @returns : handler_user_data parameter
1838 *
1839 */
whd_wifi_scan_events_handler(whd_interface_t ifp,const whd_event_header_t * event_header,const uint8_t * event_data,void * handler_user_data)1840 static void *whd_wifi_scan_events_handler(whd_interface_t ifp, const whd_event_header_t *event_header,
1841 const uint8_t *event_data,
1842 void *handler_user_data)
1843 {
1844 whd_scan_result_t *record;
1845 wl_escan_result_t *eresult;
1846 wl_bss_info_t *bss_info;
1847 uint16_t chanspec;
1848 uint32_t version;
1849 whd_tlv8_header_t *cp;
1850 uint32_t len;
1851 uint16_t ie_offset;
1852 uint32_t bss_info_length;
1853 country_info_ie_fixed_portion_t *country_info_ie;
1854 rsn_ie_fixed_portion_t *rsnie;
1855 wpa_ie_fixed_portion_t *wpaie = NULL;
1856 rsnx_ie_t *rsnxie = NULL;
1857 uint8_t rate_num;
1858 ht_capabilities_ie_t *ht_capabilities_ie = NULL;
1859 uint32_t count_tmp = 0;
1860 uint16_t temp16;
1861 uint16_t bss_count;
1862 whd_driver_t whd_driver = ifp->whd_driver;
1863
1864 if (whd_driver->internal_info.scan_result_callback == NULL)
1865 {
1866 return handler_user_data;
1867 }
1868
1869 if (event_header->status == WLC_E_STATUS_SUCCESS)
1870 {
1871 whd_driver->internal_info.scan_result_callback(NULL, handler_user_data, WHD_SCAN_COMPLETED_SUCCESSFULLY);
1872 whd_driver->internal_info.scan_result_callback = NULL;
1873 whd_wifi_deregister_event_handler(ifp, ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY]);
1874 ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY] = WHD_EVENT_NOT_REGISTERED;
1875 return handler_user_data;
1876 }
1877 if ( (event_header->status == WLC_E_STATUS_NEWSCAN) || (event_header->status == WLC_E_STATUS_NEWASSOC) ||
1878 (event_header->status == WLC_E_STATUS_ABORT) )
1879 {
1880 whd_driver->internal_info.scan_result_callback(NULL, handler_user_data, WHD_SCAN_ABORTED);
1881 whd_driver->internal_info.scan_result_callback = NULL;
1882 whd_wifi_deregister_event_handler(ifp, ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY]);
1883 ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY] = WHD_EVENT_NOT_REGISTERED;
1884 return handler_user_data;
1885 }
1886
1887 if (event_header->status != WLC_E_STATUS_PARTIAL)
1888 {
1889 return handler_user_data;
1890 }
1891
1892 eresult = (wl_escan_result_t *)event_data;
1893 bss_info = &eresult->bss_info[0];
1894 bss_count = dtoh16(eresult->bss_count);
1895
1896 version = dtoh32(WHD_READ_32(&bss_info->version) );
1897 whd_minor_assert("wl_bss_info_t has wrong version", version == WL_BSS_INFO_VERSION);
1898
1899 /* PNO bss info doesn't contain the correct bss info version */
1900 if (version != WL_BSS_INFO_VERSION)
1901 {
1902 whd_minor_assert("Invalid bss_info version returned by firmware\n", version != WL_BSS_INFO_VERSION);
1903
1904 return handler_user_data;
1905 }
1906
1907 whd_minor_assert("More than one result returned by firmware", bss_count == 1);
1908 if (bss_count != 1)
1909 {
1910 return handler_user_data;
1911 }
1912
1913 /*
1914 * check the SSID length and bssinfo ie offset for buffer overflow
1915 */
1916 bss_info->ie_offset = dtoh16(bss_info->ie_offset);
1917 bss_info->ie_length = dtoh32(bss_info->ie_length);
1918 if ( (bss_info->SSID_len > sizeof(bss_info->SSID) ) || (bss_info->ie_offset < sizeof(wl_bss_info_t) ) ||
1919 (bss_info->ie_offset > (sizeof(wl_bss_info_t) + bss_info->ie_length) ) )
1920 {
1921 WPRINT_WHD_ERROR( ("Invalid bss length check %s: SSID_len:%d,ie_len:%" PRIu32 ",ie_off:%d\n", __FUNCTION__,
1922 bss_info->SSID_len, bss_info->ie_length, bss_info->ie_offset) );
1923 whd_minor_assert(" bss length check failed\n", bss_info->SSID_len != sizeof(bss_info->SSID) );
1924 return handler_user_data;
1925 }
1926
1927 /* Safe to access *whd_scan_result_ptr, as whd_scan_result_ptr == NULL case is handled above */
1928 record = (whd_scan_result_t *)(whd_driver->internal_info.whd_scan_result_ptr);
1929
1930 /* Clear the last scan result data */
1931 memset(record, 0, sizeof(whd_scan_result_t) );
1932
1933 /*
1934 * Totally ignore off channel results. This can only happen with DSSS (1 and 2 Mb). It is better to
1935 * totally ignore it when it happens. It is hard to argue it is "significant" given that it can't
1936 * happen in 5G with OFDM (or other 2G modulations). This is left here so that it could be
1937 * passed as a scan result for debugging only.
1938 */
1939 if (!(bss_info->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) )
1940 {
1941 record->flags |= WHD_SCAN_RESULT_FLAG_RSSI_OFF_CHANNEL;
1942 /* Comment out this return statement to pass along an off channel result for debugging */
1943 return handler_user_data;
1944 }
1945
1946 /* Copy the SSID into the output record structure */
1947 record->SSID.length = (uint8_t)MIN_OF(sizeof(record->SSID.value), bss_info->SSID_len);
1948 memset(record->SSID.value, 0, sizeof(record->SSID.value) );
1949 memcpy(record->SSID.value, bss_info->SSID, record->SSID.length);
1950
1951 /* Copy the BSSID into the output record structure */
1952 memcpy( (void *)record->BSSID.octet, (const void *)bss_info->BSSID.octet, sizeof(bss_info->BSSID.octet) );
1953
1954 /* Copy the RSSI into the output record structure */
1955 record->signal_strength = ( int16_t )dtoh16( (WHD_READ_16(&bss_info->RSSI) ) );
1956
1957 /* Find maximum data rate and put it in the output record structure */
1958 record->max_data_rate = 0;
1959 count_tmp = WHD_READ_32(&bss_info->rateset.count);
1960 if (count_tmp > 16)
1961 {
1962 count_tmp = 16;
1963 }
1964
1965 #ifdef WPRINT_ENABLE_WHD_DEBUG
1966 /* print out scan results info */
1967 {
1968 char ea_buf[WHD_ETHER_ADDR_STR_LEN];
1969 char ssid_buf[SSID_NAME_SIZE + 1];
1970
1971 WPRINT_WHD_DEBUG( ("Scan result: channel=%d signal=%d ssid=%s bssid=%s\n", record->channel,
1972 record->signal_strength,
1973 whd_ssid_to_string(record->SSID.value, record->SSID.length, ssid_buf,
1974 (uint8_t)sizeof(ssid_buf) ),
1975 whd_ether_ntoa( (const uint8_t *)bss_info->BSSID.octet, ea_buf, sizeof(ea_buf) ) ) );
1976 }
1977 #endif /* WPRINT_ENABLE_WHD_DEBUG */
1978
1979 for (rate_num = 0; rate_num < count_tmp; rate_num++)
1980 {
1981 uint32_t rate = RSPEC_TO_KBPS(bss_info->rateset.rates[rate_num]);
1982 if (record->max_data_rate < rate)
1983 {
1984 record->max_data_rate = rate;
1985 }
1986 }
1987
1988 bss_info->capability = dtoh16(bss_info->capability);
1989
1990 /* Write the BSS type into the output record structure */
1991 record->bss_type =
1992 ( (bss_info->capability & DOT11_CAP_ESS) !=
1993 0 ) ? WHD_BSS_TYPE_INFRASTRUCTURE : ( (bss_info->capability & DOT11_CAP_IBSS) !=
1994 0 ) ? WHD_BSS_TYPE_ADHOC : WHD_BSS_TYPE_UNKNOWN;
1995
1996 /* Determine the network security.
1997 * Some of this section has been copied from the standard broadcom host driver file wl/exe/wlu.c function wl_dump_wpa_rsn_ies
1998 */
1999
2000 ie_offset = WHD_READ_16(&bss_info->ie_offset);
2001 cp = (whd_tlv8_header_t *)( ( (uint8_t *)bss_info ) + ie_offset );
2002 len = WHD_READ_32(&bss_info->ie_length);
2003 bss_info_length = WHD_READ_32(&bss_info->length);
2004
2005 record->ie_ptr = (uint8_t *)cp;
2006 record->ie_len = len;
2007
2008 /* Validate the length of the IE section */
2009 if ( (ie_offset > bss_info_length) || (len > bss_info_length - ie_offset) )
2010 {
2011 whd_minor_assert("Invalid ie length", 1 == 0);
2012 return handler_user_data;
2013 }
2014
2015 /* Find an RSN IE (Robust-Security-Network Information-Element) */
2016 rsnie = (rsn_ie_fixed_portion_t *)whd_parse_dot11_tlvs(cp, len, DOT11_IE_ID_RSN);
2017
2018 /* Find a WPA IE */
2019 if (rsnie == NULL)
2020 {
2021 whd_tlv8_header_t *parse = cp;
2022 uint32_t parse_len = len;
2023 while ( (wpaie =
2024 (wpa_ie_fixed_portion_t *)whd_parse_tlvs(parse, parse_len, DOT11_IE_ID_VENDOR_SPECIFIC) ) != 0 )
2025 {
2026 if (whd_is_wpa_ie( (vendor_specific_ie_header_t *)wpaie, &parse, &parse_len ) != WHD_FALSE)
2027 {
2028 break;
2029 }
2030 }
2031 }
2032
2033 temp16 = WHD_READ_16(&bss_info->capability);
2034
2035 /* Check if AP is configured for RSN */
2036 if ( (rsnie != NULL) &&
2037 (rsnie->tlv_header.length >= RSN_IE_MINIMUM_LENGTH + rsnie->pairwise_suite_count * sizeof(uint32_t) ) )
2038 {
2039 uint16_t a;
2040 uint32_t group_key_suite;
2041 akm_suite_portion_t *akm_suites;
2042 DISABLE_COMPILER_WARNING(diag_suppress = Pa039)
2043 akm_suites = (akm_suite_portion_t *)&(rsnie->pairwise_suite_list[rsnie->pairwise_suite_count]);
2044 ENABLE_COMPILER_WARNING(diag_suppress = Pa039)
2045 for (a = 0; a < akm_suites->akm_suite_count; ++a)
2046 {
2047 uint32_t akm_suite_list_item = ntoh32(akm_suites->akm_suite_list[a]) & 0xFF;
2048 if (akm_suite_list_item == (uint32_t)WHD_AKM_PSK)
2049 {
2050 record->security |= WPA2_SECURITY;
2051 }
2052 if (akm_suite_list_item == (uint32_t)WHD_AKM_PSK_SHA256)
2053 {
2054 record->security |= WPA2_SECURITY;
2055 record->security |= WPA2_SHA256_SECURITY;
2056 }
2057 if (akm_suite_list_item == (uint32_t)WHD_AKM_SAE_SHA256)
2058 {
2059 record->security |= WPA3_SECURITY;
2060 }
2061 if (akm_suite_list_item == (uint32_t)WHD_AKM_8021X)
2062 {
2063 record->security |= WPA2_SECURITY;
2064 record->security |= ENTERPRISE_ENABLED;
2065 }
2066 if (akm_suite_list_item == (uint32_t)WHD_AKM_FT_8021X)
2067 {
2068 record->security |= WPA2_SECURITY;
2069 record->security |= FBT_ENABLED;
2070 record->security |= ENTERPRISE_ENABLED;
2071 }
2072 if (akm_suite_list_item == (uint32_t)WHD_AKM_FT_PSK)
2073 {
2074 record->security |= WPA2_SECURITY;
2075 record->security |= FBT_ENABLED;
2076 }
2077 }
2078
2079 group_key_suite = ntoh32(rsnie->group_key_suite) & 0xFF;
2080 /* Check the RSN contents to see if there are any references to TKIP cipher (2) in the group key or pairwise keys, */
2081 /* If so it must be mixed mode. */
2082 if (group_key_suite == (uint32_t)WHD_CIPHER_TKIP)
2083 {
2084 record->security |= TKIP_ENABLED;
2085 }
2086 if (group_key_suite == (uint32_t)WHD_CIPHER_CCMP_128)
2087 {
2088 record->security |= AES_ENABLED;
2089 }
2090
2091 for (a = 0; a < rsnie->pairwise_suite_count; ++a)
2092 {
2093 uint32_t pairwise_suite_list_item = ntoh32(rsnie->pairwise_suite_list[a]) & 0xFF;
2094 if (pairwise_suite_list_item == (uint32_t)WHD_CIPHER_TKIP)
2095 {
2096 record->security |= TKIP_ENABLED;
2097 }
2098
2099 if (pairwise_suite_list_item == (uint32_t)WHD_CIPHER_CCMP_128)
2100 {
2101 record->security |= AES_ENABLED;
2102 }
2103 }
2104 }
2105 /* Check if AP is configured for WPA */
2106 else if ( (wpaie != NULL) &&
2107 (wpaie->vendor_specific_header.tlv_header.length >=
2108 WPA_IE_MINIMUM_LENGTH + wpaie->unicast_suite_count * sizeof(uint32_t) ) )
2109 {
2110 uint16_t a;
2111 uint32_t group_key_suite;
2112 akm_suite_portion_t *akm_suites;
2113
2114 record->security = (whd_security_t)WPA_SECURITY;
2115 group_key_suite = ntoh32(wpaie->multicast_suite) & 0xFF;
2116 if (group_key_suite == (uint32_t)WHD_CIPHER_TKIP)
2117 {
2118 record->security |= TKIP_ENABLED;
2119 }
2120 if (group_key_suite == (uint32_t)WHD_CIPHER_CCMP_128)
2121 {
2122 record->security |= AES_ENABLED;
2123 }
2124
2125 akm_suites = (akm_suite_portion_t *)&(wpaie->unicast_suite_list[wpaie->unicast_suite_count]);
2126 for (a = 0; a < akm_suites->akm_suite_count; ++a)
2127 {
2128 uint32_t akm_suite_list_item = ntoh32(akm_suites->akm_suite_list[a]) & 0xFF;
2129 if (akm_suite_list_item == (uint32_t)WHD_AKM_8021X)
2130 {
2131 record->security |= ENTERPRISE_ENABLED;
2132 }
2133 }
2134
2135 for (a = 0; a < wpaie->unicast_suite_count; ++a)
2136 {
2137 if (wpaie->unicast_suite_list[a][3] == (uint32_t)WHD_CIPHER_CCMP_128)
2138 {
2139 record->security |= AES_ENABLED;
2140 }
2141 }
2142 }
2143 /* Check if AP is configured for WEP, that is, if the capabilities field indicates privacy, then security supports WEP */
2144 else if ( (temp16 & DOT11_CAP_PRIVACY) != 0 )
2145 {
2146 record->security = WHD_SECURITY_WEP_PSK;
2147 }
2148 else
2149 {
2150 /* Otherwise no security */
2151 record->security = WHD_SECURITY_OPEN;
2152 }
2153
2154 /* Find a RSNX IE */
2155 rsnxie = (rsnx_ie_t *)whd_parse_tlvs(cp, len, DOT11_IE_ID_RSNX);
2156 if ( (rsnxie != NULL) && (rsnxie->tlv_header.length == DOT11_RSNX_CAP_LEN) &&
2157 (rsnxie->data[0] & (1 << DOT11_RSNX_SAE_H2E) ) )
2158 {
2159 record->flags |= WHD_SCAN_RESULT_FLAG_SAE_H2E;
2160 }
2161
2162 /* Update the maximum data rate with 11n rates from the HT Capabilities IE */
2163 ht_capabilities_ie = (ht_capabilities_ie_t *)whd_parse_tlvs(cp, len, DOT11_IE_ID_HT_CAPABILITIES);
2164 if ( (ht_capabilities_ie != NULL) && (ht_capabilities_ie->tlv_header.length == HT_CAPABILITIES_IE_LENGTH) )
2165 {
2166 uint8_t a;
2167 uint8_t supports_40mhz =
2168 (ht_capabilities_ie->ht_capabilities_info & HT_CAPABILITIES_INFO_SUPPORTED_CHANNEL_WIDTH_SET) != 0 ? 1 : 0;
2169 uint8_t short_gi[2] =
2170 { (ht_capabilities_ie->ht_capabilities_info & HT_CAPABILITIES_INFO_SHORT_GI_FOR_20MHZ) != 0 ? 1 : 0,
2171 (ht_capabilities_ie->ht_capabilities_info & HT_CAPABILITIES_INFO_SHORT_GI_FOR_40MHZ) != 0 ? 1 : 0 };
2172
2173 /* Find highest bit from MCS info */
2174 for (a = 31; a != 0xFF; --a)
2175 {
2176 if ( (ht_capabilities_ie->rx_mcs[a / 8] & (1 << (a % 8) ) ) != 0 )
2177 {
2178 break;
2179 }
2180 }
2181 if (a != 0xFF)
2182 {
2183 record->max_data_rate =
2184 ( uint32_t )(100UL * mcs_data_rate_lookup_table[a][supports_40mhz][short_gi[supports_40mhz]]);
2185 }
2186 }
2187
2188 if (bss_info->flags & WL_BSS_FLAGS_FROM_BEACON)
2189 {
2190 record->flags |= WHD_SCAN_RESULT_FLAG_BEACON;
2191 }
2192
2193 /* Get the channel for pre-N and control channel for n/HT or later */
2194 chanspec = dtoh16(WHD_READ_16(&bss_info->chanspec) );
2195 if (bss_info->n_cap)
2196 {
2197 /* Check control channel first.The channel that chanspec reports is the center frequency which might not be the same as
2198 * the 20 MHz channel that the beacons is on (primary or control channel) if it's an 802.11n/AC 40MHz or wider channel.
2199 */
2200 record->channel = bss_info->ctl_ch;
2201 }
2202 else
2203 {
2204 /* 11 a/b/g and 20MHz bandwidth only */
2205 record->channel = ( ( uint8_t )(chanspec & WL_CHANSPEC_CHAN_MASK) );
2206 }
2207
2208 /* Find country info IE (Country-Information Information-Element) */
2209 country_info_ie = (country_info_ie_fixed_portion_t *)whd_parse_dot11_tlvs(cp, len, DOT11_IE_ID_COUNTRY);
2210 if ( (country_info_ie != NULL) && (country_info_ie->tlv_header.length >= COUNTRY_INFO_IE_MINIMUM_LENGTH) )
2211 {
2212 record->ccode[0] = UNSIGNED_CHAR_TO_CHAR(country_info_ie->ccode[0]);
2213 record->ccode[1] = UNSIGNED_CHAR_TO_CHAR(country_info_ie->ccode[1]);
2214 }
2215 record->band =
2216 ( (chanspec &
2217 GET_C_VAR(whd_driver,
2218 CHANSPEC_BAND_MASK) ) ==
2219 GET_C_VAR(whd_driver, CHANSPEC_BAND_2G) ? WHD_802_11_BAND_2_4GHZ : WHD_802_11_BAND_5GHZ );
2220
2221 whd_driver->internal_info.scan_result_callback(&whd_driver->internal_info.whd_scan_result_ptr, handler_user_data,
2222 WHD_SCAN_INCOMPLETE);
2223
2224 /* whd_driver->internal_info.scan_result_callback() can make whd_scan_result_ptr to NULL */
2225 if (whd_driver->internal_info.whd_scan_result_ptr == NULL)
2226 {
2227 whd_driver->internal_info.scan_result_callback(NULL, handler_user_data, WHD_SCAN_ABORTED);
2228 whd_driver->internal_info.scan_result_callback = NULL;
2229 whd_wifi_deregister_event_handler(ifp, ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY]);
2230 ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY] = WHD_EVENT_NOT_REGISTERED;
2231 }
2232
2233 return handler_user_data;
2234 }
2235
2236 /** Handles auth result events
2237 *
2238 * This function receives scan record events, and parses them into a better format, then passes the results
2239 * to the user application.
2240 *
2241 * @param event_header : The event details
2242 * @param event_data : The data for the event which contains the auth result structure
2243 * @param handler_user_data: data which will be passed to user application
2244 *
2245 * @returns : handler_user_data parameter
2246 *
2247 */
whd_wifi_auth_events_handler(whd_interface_t ifp,const whd_event_header_t * event_header,const uint8_t * event_data,void * handler_user_data)2248 static void *whd_wifi_auth_events_handler(whd_interface_t ifp, const whd_event_header_t *event_header,
2249 const uint8_t *event_data,
2250 void *handler_user_data)
2251 {
2252 whd_driver_t whd_driver = ifp->whd_driver;
2253 whd_scan_result_t *record;
2254
2255 if (whd_driver->internal_info.auth_result_callback == NULL)
2256 {
2257 WPRINT_WHD_ERROR( ("No set callback function in %s at %d \n", __func__, __LINE__) );
2258 return handler_user_data;
2259 }
2260 if (event_header->event_type == WLC_E_EXT_AUTH_REQ)
2261 {
2262 uint8_t flag = 0;
2263 if (whd_driver->internal_info.whd_scan_result_ptr)
2264 {
2265 record = (whd_scan_result_t *)(whd_driver->internal_info.whd_scan_result_ptr);
2266 if (record->flags & WHD_SCAN_RESULT_FLAG_SAE_H2E)
2267 flag = 1;
2268 else
2269 flag = 0;
2270
2271 }
2272 whd_driver->internal_info.auth_result_callback( (void *)event_data, sizeof(whd_auth_req_status_t),
2273 WHD_AUTH_EXT_REQ, &flag, handler_user_data );
2274 return handler_user_data;
2275 }
2276 else if (event_header->event_type == WLC_E_EXT_AUTH_FRAME_RX)
2277 {
2278 uint32_t mgmt_frame_len;
2279 wl_rx_mgmt_data_t *rxframe;
2280 uint8_t *frame;
2281
2282 mgmt_frame_len = event_header->datalen - sizeof(wl_rx_mgmt_data_t);
2283 rxframe = (wl_rx_mgmt_data_t *)event_data;
2284 frame = (uint8_t *)(rxframe + 1);
2285 whd_driver->internal_info.auth_result_callback( (void *)frame, mgmt_frame_len, WHD_AUTH_EXT_FRAME_RX, NULL,
2286 handler_user_data );
2287 return handler_user_data;
2288
2289 }
2290
2291 return handler_user_data;
2292 }
2293
whd_scan_count_handler(whd_scan_result_t ** result_ptr,void * user_data,whd_scan_status_t status)2294 static void whd_scan_count_handler(whd_scan_result_t **result_ptr, void *user_data, whd_scan_status_t status)
2295 {
2296 uint32_t result;
2297 whd_scan_userdata_t *scan_userdata = (whd_scan_userdata_t *)user_data;
2298
2299 /* finished scan, either successfully or through an abort */
2300 if (status != WHD_SCAN_INCOMPLETE)
2301 {
2302 DISABLE_COMPILER_WARNING(diag_suppress = Pa039)
2303 result = cy_rtos_set_semaphore(&scan_userdata->scan_semaphore, WHD_FALSE);
2304 ENABLE_COMPILER_WARNING(diag_suppress = Pa039)
2305 if (result != WHD_SUCCESS)
2306 WPRINT_WHD_ERROR( ("Set semaphore failed in %s at %d \n", __func__, __LINE__) );
2307 return;
2308 }
2309
2310 /* just count the available networks */
2311 scan_userdata->offset += 1;
2312
2313 memset(*result_ptr, 0, sizeof(whd_scan_result_t) );
2314 return;
2315 }
2316
whd_scan_result_handler(whd_scan_result_t ** result_ptr,void * user_data,whd_scan_status_t status)2317 static void whd_scan_result_handler(whd_scan_result_t **result_ptr, void *user_data, whd_scan_status_t status)
2318 {
2319 uint32_t result;
2320 whd_sync_scan_result_t *record;
2321 whd_scan_userdata_t *scan_userdata = (whd_scan_userdata_t *)user_data;
2322 whd_scan_result_t *current_result;
2323
2324 /* Safe to access *scan_userdata. This static function registered only from whd_wifi_scan_synch and
2325 * not exposed for general use. The user_data is valid when passed in from whd_wifi_scan_synch.
2326 */
2327
2328 /* finished scan, either successfully or through an abort */
2329 if (status != WHD_SCAN_INCOMPLETE)
2330 {
2331 DISABLE_COMPILER_WARNING(diag_suppress = Pa039)
2332 result = cy_rtos_set_semaphore(&scan_userdata->scan_semaphore, WHD_FALSE);
2333 ENABLE_COMPILER_WARNING(diag_suppress = Pa039)
2334 if (result != WHD_SUCCESS)
2335 WPRINT_WHD_ERROR( ("Set semaphore failed in %s at %d \n", __func__, __LINE__) );
2336 return;
2337 }
2338
2339 /* can't really keep anymore scan results */
2340 if (scan_userdata->offset == scan_userdata->count)
2341 {
2342 /*Offset and the count requested is reached. return with out saving the record details */
2343 memset(*result_ptr, 0, sizeof(whd_scan_result_t) );
2344 return;
2345 }
2346
2347 /* Safe to access *result_ptr as result_ptr should only be NULL if the scan has completed or
2348 * been aborted, which is handled above
2349 */
2350 current_result = (whd_scan_result_t *)(*result_ptr);
2351
2352 DISABLE_COMPILER_WARNING(diag_suppress = Pa039)
2353 /* Safe to access *scan_userdata, as noted above */
2354 record = (whd_sync_scan_result_t *)(&scan_userdata->aps[scan_userdata->offset]);
2355 ENABLE_COMPILER_WARNING(diag_suppress = Pa039)
2356
2357 /* Copy the SSID into the output record structure */
2358 record->SSID.length = current_result->SSID.length;
2359 memset(record->SSID.value, 0, sizeof(record->SSID.value) );
2360 memcpy(record->SSID.value, current_result->SSID.value, record->SSID.length);
2361
2362 /* Copy the BSSID into the output record structure */
2363 memcpy( (void *)record->BSSID.octet, (const void *)current_result->BSSID.octet,
2364 sizeof(current_result->BSSID.octet) );
2365
2366 record->security = current_result->security;
2367 record->signal_strength = current_result->signal_strength;
2368 record->channel = current_result->channel;
2369
2370 scan_userdata->offset += 1;
2371 memset(*result_ptr, 0, sizeof(whd_scan_result_t) );
2372 return;
2373 }
2374
whd_wifi_scan_synch(whd_interface_t ifp,whd_sync_scan_result_t * scan_result,uint32_t * count)2375 uint32_t whd_wifi_scan_synch(whd_interface_t ifp,
2376 whd_sync_scan_result_t *scan_result,
2377 uint32_t *count
2378 )
2379 {
2380 uint32_t result;
2381 whd_scan_result_t *scan_result_ptr;
2382 whd_scan_userdata_t scan_userdata;
2383 scan_userdata.count = *count;
2384 scan_userdata.aps = scan_result;
2385 scan_userdata.offset = 0;
2386
2387 if (!ifp || !scan_result)
2388 {
2389 WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n",
2390 __func__, __LINE__) );
2391 return WHD_WLAN_BADARG;
2392 }
2393
2394 DISABLE_COMPILER_WARNING(diag_suppress = Pa039)
2395 CHECK_RETURN(cy_rtos_init_semaphore(&scan_userdata.scan_semaphore, 1, 0) );
2396 ENABLE_COMPILER_WARNING(diag_suppress = Pa039)
2397
2398 whd_scan_result_callback_t handler = (*count == 0)
2399 ? whd_scan_count_handler : whd_scan_result_handler;
2400
2401 scan_result_ptr = (whd_scan_result_t *)whd_mem_malloc(sizeof(whd_scan_result_t) );
2402 if (scan_result_ptr == NULL)
2403 {
2404 goto error;
2405 }
2406 memset(scan_result_ptr, 0, sizeof(whd_scan_result_t) );
2407
2408 if (whd_wifi_scan(ifp, WHD_SCAN_TYPE_ACTIVE, WHD_BSS_TYPE_ANY, NULL, NULL, NULL, NULL,
2409 handler, (whd_scan_result_t *)scan_result_ptr, &scan_userdata) != WHD_SUCCESS)
2410 {
2411 WPRINT_WHD_INFO( ("Failed scan \n") );
2412 goto error;
2413 }
2414
2415 DISABLE_COMPILER_WARNING(diag_suppress = Pa039)
2416 result = cy_rtos_get_semaphore(&scan_userdata.scan_semaphore, CY_RTOS_NEVER_TIMEOUT, WHD_FALSE);
2417 ENABLE_COMPILER_WARNING(diag_suppress = Pa039)
2418 whd_assert("Get semaphore failed", (result == CY_RSLT_SUCCESS) || (result == CY_RTOS_TIMEOUT) );
2419
2420 DISABLE_COMPILER_WARNING(diag_suppress = Pa039)
2421 result = cy_rtos_deinit_semaphore(&scan_userdata.scan_semaphore);
2422 ENABLE_COMPILER_WARNING(diag_suppress = Pa039)
2423 if (WHD_SUCCESS != result)
2424 {
2425 WPRINT_WHD_INFO( ("Failed join (err %" PRIu32 ")\n", result) );
2426 }
2427 if (scan_result_ptr != NULL)
2428 {
2429 whd_mem_free(scan_result_ptr);
2430 scan_result_ptr = NULL;
2431 }
2432 *count = scan_userdata.offset;
2433
2434 return WHD_SUCCESS;
2435
2436 error:
2437 if (scan_result_ptr != NULL)
2438 {
2439 whd_mem_free(scan_result_ptr);
2440 scan_result_ptr = NULL;
2441 }
2442
2443 return WHD_MALLOC_FAILURE;
2444 }
2445
2446 /*
2447 * NOTE: search references of function wlu_get in wl/exe/wlu.c to find what format the returned IOCTL data is.
2448 */
whd_wifi_scan(whd_interface_t ifp,whd_scan_type_t scan_type,whd_bss_type_t bss_type,const whd_ssid_t * optional_ssid,const whd_mac_t * optional_mac,const uint16_t * optional_channel_list,const whd_scan_extended_params_t * optional_extended_params,whd_scan_result_callback_t callback,whd_scan_result_t * result_ptr,void * user_data)2449 uint32_t whd_wifi_scan(whd_interface_t ifp,
2450 whd_scan_type_t scan_type,
2451 whd_bss_type_t bss_type,
2452 const whd_ssid_t *optional_ssid,
2453 const whd_mac_t *optional_mac,
2454 const uint16_t *optional_channel_list,
2455 const whd_scan_extended_params_t *optional_extended_params,
2456 whd_scan_result_callback_t callback,
2457 whd_scan_result_t *result_ptr,
2458 void *user_data
2459 )
2460 {
2461 whd_buffer_t buffer;
2462 wl_escan_params_t *scan_params;
2463 uint16_t param_size = offsetof(wl_escan_params_t, params) + WL_SCAN_PARAMS_FIXED_SIZE;
2464 uint16_t channel_list_size = 0;
2465 whd_driver_t whd_driver = ifp->whd_driver;
2466 uint16_t event_entry = 0xFF;
2467
2468 whd_assert("Bad args", callback != NULL);
2469
2470 if ( (result_ptr == NULL) || (callback == NULL) )
2471 {
2472 return WHD_BADARG;
2473 }
2474
2475 if (!( (scan_type == WHD_SCAN_TYPE_ACTIVE) || (scan_type == WHD_SCAN_TYPE_PASSIVE) ||
2476 (scan_type == WHD_SCAN_TYPE_PROHIBITED_CHANNELS) || (scan_type == WHD_SCAN_TYPE_NO_BSSID_FILTER) ) )
2477 return WHD_BADARG;
2478
2479 if (!( (bss_type == WHD_BSS_TYPE_INFRASTRUCTURE) || (bss_type == WHD_BSS_TYPE_ADHOC) ||
2480 (bss_type == WHD_BSS_TYPE_ANY) ) )
2481 return WHD_BADARG;
2482
2483 /* Determine size of channel_list, and add it to the parameter size so correct sized buffer can be allocated */
2484 if (optional_channel_list != NULL)
2485 {
2486 /* Look for entry with channel number 0, which suggests the end of channel_list */
2487 for (channel_list_size = 0; optional_channel_list[channel_list_size] != 0; channel_list_size++)
2488 {
2489 }
2490 param_size = ( uint16_t )(param_size + channel_list_size * sizeof(uint16_t) );
2491 }
2492
2493 if (ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY] != WHD_EVENT_NOT_REGISTERED)
2494 {
2495 whd_wifi_deregister_event_handler(ifp, ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY]);
2496 ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY] = WHD_EVENT_NOT_REGISTERED;
2497 }
2498 CHECK_RETURN(whd_management_set_event_handler(ifp, scan_events, whd_wifi_scan_events_handler, user_data,
2499 &event_entry) );
2500 if (event_entry >= WHD_MAX_EVENT_SUBSCRIPTION)
2501 {
2502 WPRINT_WHD_ERROR( ("scan_events registration failed in function %s and line %d", __func__, __LINE__) );
2503 return WHD_UNFINISHED;
2504 }
2505 ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY] = event_entry;
2506 /* Allocate a buffer for the IOCTL message */
2507 scan_params = (wl_escan_params_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, param_size, IOVAR_STR_ESCAN);
2508 CHECK_IOCTL_BUFFER(scan_params);
2509
2510 /* Clear the scan parameters structure */
2511 memset(scan_params, 0, param_size);
2512
2513 /* Fill in the appropriate details of the scan parameters structure */
2514 scan_params->version = htod32(ESCAN_REQ_VERSION);
2515 scan_params->action = htod16(WL_SCAN_ACTION_START);
2516 scan_params->params.scan_type = (int8_t)scan_type;
2517 scan_params->params.bss_type = (int8_t)bss_type;
2518
2519 /* Fill out the SSID parameter if provided */
2520 if (optional_ssid != NULL)
2521 {
2522 scan_params->params.ssid.SSID_len = htod32(optional_ssid->length);
2523 memcpy(scan_params->params.ssid.SSID, optional_ssid->value, scan_params->params.ssid.SSID_len);
2524 }
2525
2526 /* Fill out the BSSID parameter if provided */
2527 if (optional_mac != NULL)
2528 {
2529 memcpy(scan_params->params.bssid.octet, optional_mac, sizeof(whd_mac_t) );
2530 }
2531 else
2532 {
2533 memset(scan_params->params.bssid.octet, 0xff, sizeof(whd_mac_t) );
2534 }
2535
2536 /* Fill out the extended parameters if provided */
2537 if (optional_extended_params != NULL)
2538 {
2539 scan_params->params.nprobes = (int32_t)htod32(optional_extended_params->number_of_probes_per_channel);
2540 scan_params->params.active_time =
2541 (int32_t)htod32(optional_extended_params->scan_active_dwell_time_per_channel_ms);
2542 scan_params->params.passive_time = (int32_t)htod32(
2543 optional_extended_params->scan_passive_dwell_time_per_channel_ms);
2544 scan_params->params.home_time = (int32_t)htod32(
2545 optional_extended_params->scan_home_channel_dwell_time_between_channels_ms);
2546 }
2547 else
2548 {
2549 scan_params->params.nprobes = (int32_t)htod32(-1);
2550 scan_params->params.active_time = (int32_t)htod32(-1);
2551 scan_params->params.passive_time = (int32_t)htod32(-1);
2552 scan_params->params.home_time = (int32_t)htod32(-1);
2553 }
2554
2555 /* Copy the channel list parameter if provided */
2556 if ( (channel_list_size > 0) && (optional_channel_list != NULL) )
2557 {
2558 int i;
2559
2560 for (i = 0; i < channel_list_size; i++)
2561 {
2562 scan_params->params.channel_list[i] = htod16(CH20MHZ_CHSPEC(optional_channel_list[i]) );
2563 }
2564 scan_params->params.channel_num = (int32_t)htod32(channel_list_size);
2565 }
2566
2567 whd_driver->internal_info.scan_result_callback = callback;
2568 whd_driver->internal_info.whd_scan_result_ptr = result_ptr;
2569
2570 /* Send the Incremental Scan IOVAR message - blocks until the response is received */
2571
2572 CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0) );
2573
2574 return WHD_SUCCESS;
2575 }
2576
whd_wifi_stop_scan(whd_interface_t ifp)2577 uint32_t whd_wifi_stop_scan(whd_interface_t ifp)
2578 {
2579 whd_buffer_t buffer;
2580 wl_escan_params_t *scan_params;
2581 whd_driver_t whd_driver;
2582
2583 CHECK_IFP_NULL(ifp);
2584 whd_driver = ifp->whd_driver;
2585 CHECK_DRIVER_NULL(whd_driver)
2586
2587 /* Allocate a buffer for the IOCTL message */
2588 scan_params = (wl_escan_params_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, sizeof(wl_escan_params_t),
2589 IOVAR_STR_ESCAN);
2590 CHECK_IOCTL_BUFFER(scan_params);
2591 /* Clear the scan parameters structure */
2592 memset(scan_params, 0, sizeof(wl_escan_params_t) );
2593
2594 /* Fill in the appropriate details of the scan parameters structure */
2595 scan_params->version = htod32(ESCAN_REQ_VERSION);
2596 scan_params->action = htod16(WL_SCAN_ACTION_ABORT);
2597
2598 /* Send the Scan IOVAR message to abort scan*/
2599 CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0) );
2600
2601 return WHD_SUCCESS;
2602 }
2603
whd_wifi_external_auth_request(whd_interface_t ifp,whd_auth_result_callback_t callback,void * result_ptr,void * user_data)2604 uint32_t whd_wifi_external_auth_request(whd_interface_t ifp,
2605 whd_auth_result_callback_t callback,
2606 void *result_ptr,
2607 void *user_data
2608 )
2609 {
2610 CHECK_IFP_NULL(ifp);
2611 whd_driver_t whd_driver = ifp->whd_driver;
2612 uint16_t event_entry = 0xFF;
2613
2614 whd_assert("Bad args", callback != NULL);
2615
2616 if (ifp->event_reg_list[WHD_AUTH_EVENT_ENTRY] != WHD_EVENT_NOT_REGISTERED)
2617 {
2618 whd_wifi_deregister_event_handler(ifp, ifp->event_reg_list[WHD_AUTH_EVENT_ENTRY]);
2619 ifp->event_reg_list[WHD_AUTH_EVENT_ENTRY] = WHD_EVENT_NOT_REGISTERED;
2620 }
2621 CHECK_RETURN(whd_management_set_event_handler(ifp, auth_events, whd_wifi_auth_events_handler, user_data,
2622 &event_entry) );
2623 if (event_entry >= WHD_MAX_EVENT_SUBSCRIPTION)
2624 {
2625 WPRINT_WHD_ERROR( ("auth_events registration failed in function %s and line %d", __func__, __LINE__) );
2626 return WHD_UNFINISHED;
2627 }
2628 ifp->event_reg_list[WHD_AUTH_EVENT_ENTRY] = event_entry;
2629
2630
2631 whd_driver->internal_info.auth_result_callback = callback;
2632
2633 return WHD_SUCCESS;
2634 }
2635
whd_wifi_stop_external_auth_request(whd_interface_t ifp)2636 uint32_t whd_wifi_stop_external_auth_request(whd_interface_t ifp)
2637 {
2638 whd_driver_t whd_driver;
2639
2640 CHECK_IFP_NULL(ifp);
2641 whd_driver = ifp->whd_driver;
2642 CHECK_DRIVER_NULL(whd_driver)
2643
2644 if (ifp->event_reg_list[WHD_AUTH_EVENT_ENTRY] != WHD_EVENT_NOT_REGISTERED)
2645 {
2646 whd_wifi_deregister_event_handler(ifp, ifp->event_reg_list[WHD_AUTH_EVENT_ENTRY]);
2647 ifp->event_reg_list[WHD_AUTH_EVENT_ENTRY] = WHD_EVENT_NOT_REGISTERED;
2648 }
2649 whd_driver->internal_info.auth_result_callback = NULL;
2650 return WHD_SUCCESS;
2651 }
2652
whd_wifi_deauth_sta(whd_interface_t ifp,whd_mac_t * mac,whd_dot11_reason_code_t reason)2653 uint32_t whd_wifi_deauth_sta(whd_interface_t ifp, whd_mac_t *mac, whd_dot11_reason_code_t reason)
2654 {
2655 whd_result_t result;
2656 scb_val_t *scb_val;
2657 whd_buffer_t buffer1;
2658 whd_driver_t whd_driver;
2659
2660 CHECK_IFP_NULL(ifp);
2661
2662 whd_driver = ifp->whd_driver;
2663
2664 if (mac == NULL)
2665 {
2666 uint8_t *buffer = NULL;
2667 whd_maclist_t *clients = NULL;
2668 const whd_mac_t *current;
2669 wl_bss_info_t ap_info;
2670 whd_security_t sec;
2671 uint32_t max_clients = 0;
2672 size_t size = 0;
2673
2674 result = whd_wifi_ap_get_max_assoc(ifp, &max_clients);
2675 if (result != WHD_SUCCESS)
2676 {
2677 WPRINT_WHD_ERROR( ("Failed to get max number of associated clients\n") );
2678 max_clients = 5;
2679 }
2680
2681 size = (sizeof(uint32_t) + (max_clients * sizeof(whd_mac_t) ) );
2682 buffer = whd_mem_calloc(1, size);
2683
2684 if (buffer == NULL)
2685 {
2686 WPRINT_WHD_ERROR( ("Unable to allocate memory for associated clients list, %s failed at line %d \n",
2687 __func__, __LINE__) );
2688 return WHD_MALLOC_FAILURE;
2689 }
2690
2691 clients = (whd_maclist_t *)buffer;
2692 clients->count = max_clients;
2693 memset(&ap_info, 0, sizeof(wl_bss_info_t) );
2694
2695 result = whd_wifi_get_associated_client_list(ifp, clients, (uint16_t)size);
2696 if (result != WHD_SUCCESS)
2697 {
2698 WPRINT_WHD_ERROR( ("Failed to get client list, %s failed at line %d \n", __func__, __LINE__) );
2699 whd_mem_free(buffer);
2700 return result;
2701 }
2702
2703 current = &clients->mac_list[0];
2704 result = whd_wifi_get_ap_info(ifp, &ap_info, &sec);
2705 if (result != WHD_SUCCESS)
2706 {
2707 WPRINT_WHD_ERROR( ("Function %s failed at line %d \n", __func__, __LINE__) );
2708 whd_mem_free(buffer);
2709 return result;
2710 }
2711
2712
2713 while ( (clients->count > 0) && (!(NULL_MAC(current->octet) ) ) )
2714 {
2715 if (memcmp(current->octet, &(ap_info.BSSID), sizeof(whd_mac_t) ) != 0)
2716 {
2717 WPRINT_WHD_INFO( ("Deauthenticating STA MAC: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", current->octet[0],
2718 current->octet[1], current->octet[2], current->octet[3], current->octet[4],
2719 current->octet[5]) );
2720
2721 scb_val = (scb_val_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer1, sizeof(scb_val_t) );
2722 if (scb_val == NULL)
2723 {
2724 WPRINT_WHD_ERROR( ("Buffer alloc failed in function %s at line %d \n", __func__, __LINE__) );
2725 whd_mem_free(buffer);
2726 return WHD_BUFFER_ALLOC_FAIL;
2727 }
2728 memset( (char *)scb_val, 0, sizeof(scb_val_t) );
2729 memcpy( (char *)&scb_val->ea, (char *)current, sizeof(whd_mac_t) );
2730 scb_val->val = (uint32_t)reason;
2731 result = whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SCB_DEAUTHENTICATE_FOR_REASON, buffer1, 0);
2732
2733 if (result != WHD_SUCCESS)
2734 {
2735 WPRINT_WHD_ERROR( ("Failed to deauth client\n") );
2736 }
2737 }
2738
2739 --clients->count;
2740 ++current;
2741 }
2742
2743 whd_mem_free(buffer);
2744
2745 return WHD_SUCCESS;
2746 }
2747
2748 scb_val = (scb_val_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer1, sizeof(scb_val_t) );
2749 CHECK_IOCTL_BUFFER(scb_val);
2750 memset( (char *)scb_val, 0, sizeof(scb_val_t) );
2751 memcpy( (char *)&scb_val->ea, (char *)mac, sizeof(whd_mac_t) );
2752 scb_val->val = (uint32_t)reason;
2753 CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SCB_DEAUTHENTICATE_FOR_REASON, buffer1, 0) );
2754
2755 return WHD_SUCCESS;
2756 }
2757
whd_wifi_get_mac_address(whd_interface_t ifp,whd_mac_t * mac)2758 uint32_t whd_wifi_get_mac_address(whd_interface_t ifp, whd_mac_t *mac)
2759 {
2760 whd_buffer_t buffer;
2761 whd_buffer_t response;
2762 whd_driver_t whd_driver;
2763
2764 CHECK_IFP_NULL(ifp);
2765
2766 if (mac == NULL)
2767 return WHD_BADARG;
2768
2769 whd_driver = ifp->whd_driver;
2770
2771 CHECK_DRIVER_NULL(whd_driver);
2772
2773 CHECK_IOCTL_BUFFER(whd_cdc_get_iovar_buffer(whd_driver, &buffer, sizeof(whd_mac_t), IOVAR_STR_CUR_ETHERADDR) );
2774
2775 CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) );
2776
2777 memcpy(mac, whd_buffer_get_current_piece_data_pointer(whd_driver, response), sizeof(whd_mac_t) );
2778 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
2779
2780 return WHD_SUCCESS;
2781 }
2782
whd_wifi_get_bssid(whd_interface_t ifp,whd_mac_t * bssid)2783 uint32_t whd_wifi_get_bssid(whd_interface_t ifp, whd_mac_t *bssid)
2784 {
2785 whd_buffer_t buffer;
2786 whd_buffer_t response;
2787 whd_result_t result;
2788 whd_driver_t whd_driver;
2789 uint8_t *data = NULL;
2790 CHECK_IFP_NULL(ifp);
2791
2792 if (bssid == NULL)
2793 return WHD_BADARG;
2794
2795 whd_driver = ifp->whd_driver;
2796
2797 CHECK_DRIVER_NULL(whd_driver);
2798
2799 if ( (ifp->role == WHD_STA_ROLE) || (ifp->role == WHD_AP_ROLE) )
2800 {
2801 memset(bssid, 0, sizeof(whd_mac_t) );
2802 CHECK_IOCTL_BUFFER(whd_cdc_get_ioctl_buffer(whd_driver, &buffer, sizeof(whd_mac_t) ) );
2803 if ( (result =
2804 whd_cdc_send_ioctl(ifp, CDC_GET, WLC_GET_BSSID, buffer, &response) ) == WHD_SUCCESS )
2805 {
2806 data = whd_buffer_get_current_piece_data_pointer(whd_driver, response);
2807 CHECK_PACKET_NULL(data, WHD_NO_REGISTER_FUNCTION_POINTER);
2808 memcpy(bssid->octet, data, sizeof(whd_mac_t) );
2809 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
2810 }
2811 return result;
2812 }
2813 else if (ifp->role == WHD_INVALID_ROLE)
2814 {
2815 WPRINT_WHD_ERROR( ("STA not associated with AP\n") );
2816 return WHD_WLAN_NOTASSOCIATED;
2817 }
2818 else
2819 {
2820 return WHD_UNSUPPORTED;
2821 }
2822 }
2823
whd_wifi_ap_get_max_assoc(whd_interface_t ifp,uint32_t * max_assoc)2824 uint32_t whd_wifi_ap_get_max_assoc(whd_interface_t ifp, uint32_t *max_assoc)
2825 {
2826 if (!ifp || !max_assoc)
2827 {
2828 WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n",
2829 __func__, __LINE__) );
2830 return WHD_WLAN_BADARG;
2831 }
2832
2833 return whd_wifi_get_iovar_value(ifp, IOVAR_STR_MAX_ASSOC, max_assoc);
2834 }
2835
whd_wifi_get_associated_client_list(whd_interface_t ifp,void * client_list_buffer,uint16_t buffer_length)2836 uint32_t whd_wifi_get_associated_client_list(whd_interface_t ifp, void *client_list_buffer, uint16_t buffer_length)
2837 {
2838 whd_buffer_t buffer;
2839 whd_buffer_t response;
2840 whd_result_t result;
2841 whd_maclist_t *data = NULL;
2842 uint8_t *pdata = NULL;
2843 whd_driver_t whd_driver;
2844
2845 CHECK_IFP_NULL(ifp);
2846
2847 whd_driver = ifp->whd_driver;
2848
2849 CHECK_DRIVER_NULL(whd_driver);
2850
2851 /* Check if soft AP interface is up, if not, return a count of 0 as a result */
2852 result = whd_wifi_is_ready_to_transceive(ifp);
2853 if ( (result == WHD_SUCCESS) && (ifp->role == WHD_AP_ROLE) )
2854 {
2855 data = (whd_maclist_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, buffer_length);
2856 CHECK_IOCTL_BUFFER(data);
2857 memset(data, 0, buffer_length);
2858 data->count = htod32( ( (whd_maclist_t *)client_list_buffer )->count );
2859
2860 CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_GET, WLC_GET_ASSOCLIST, buffer, &response) );
2861 pdata = whd_buffer_get_current_piece_data_pointer(whd_driver, response);
2862 CHECK_PACKET_NULL(pdata, WHD_NO_REGISTER_FUNCTION_POINTER);
2863 memcpy(client_list_buffer, (void *)pdata,
2864 (size_t)MIN_OF(whd_buffer_get_current_piece_size(whd_driver, response), buffer_length) );
2865
2866 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
2867 }
2868 else if (result == WHD_INTERFACE_NOT_UP)
2869 {
2870 /* not up, so can't have associated clients */
2871 ( (whd_maclist_t *)client_list_buffer )->count = 0;
2872 }
2873 else
2874 {
2875 WPRINT_WHD_ERROR( ("Invalid Interface\n") );
2876 return WHD_INVALID_INTERFACE;
2877 }
2878 return result;
2879 }
2880
whd_wifi_get_ap_info(whd_interface_t ifp,wl_bss_info_t * ap_info,whd_security_t * security)2881 uint32_t whd_wifi_get_ap_info(whd_interface_t ifp, wl_bss_info_t *ap_info, whd_security_t *security)
2882 {
2883 whd_buffer_t buffer;
2884 whd_buffer_t response;
2885 uint32_t *data;
2886 uint8_t *pdata = NULL;
2887 uint32_t security_value; /* hold misc security values */
2888 whd_driver_t whd_driver;
2889 CHECK_IFP_NULL(ifp);
2890
2891 if ( (ap_info == NULL) || (security == NULL) )
2892 return WHD_BADARG;
2893
2894 whd_driver = ifp->whd_driver;
2895
2896 CHECK_DRIVER_NULL(whd_driver);
2897 /* Read the BSS info */
2898 data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, WLC_IOCTL_SMLEN);
2899 CHECK_IOCTL_BUFFER(data);
2900 *data = WLC_IOCTL_SMLEN;
2901 CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_GET, WLC_GET_BSS_INFO, buffer, &response) );
2902 pdata = whd_buffer_get_current_piece_data_pointer(whd_driver, response);
2903 CHECK_PACKET_NULL(pdata, WHD_NO_REGISTER_FUNCTION_POINTER);
2904 memcpy(ap_info, (void *)(pdata + 4), sizeof(wl_bss_info_t) );
2905 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
2906
2907 /* Read the WSEC setting */
2908 CHECK_RETURN(whd_wifi_get_ioctl_value(ifp, WLC_GET_WSEC, &security_value) );
2909 security_value = security_value & SECURITY_MASK;
2910 *security = ( whd_security_t )(security_value);
2911
2912 if (*security == WHD_SECURITY_WEP_PSK)
2913 {
2914 /* Read the WEP auth setting */
2915 CHECK_RETURN(whd_wifi_get_ioctl_value(ifp, WLC_GET_AUTH, &security_value) );
2916
2917 if (security_value == SHARED_AUTH)
2918 {
2919 *security |= SHARED_ENABLED;
2920 }
2921 }
2922 else if ( (*security & (TKIP_ENABLED | AES_ENABLED) ) != 0 )
2923 {
2924 /* Read the WPA auth setting */
2925 CHECK_RETURN(whd_wifi_get_ioctl_value(ifp, WLC_GET_WPA_AUTH, &security_value) );
2926
2927 if (security_value == WPA2_AUTH_PSK)
2928 {
2929 *security |= WPA2_SECURITY;
2930 }
2931 else if (security_value == WPA_AUTH_PSK)
2932 {
2933 *security |= WPA_SECURITY;
2934 }
2935 }
2936 else if (*security != WHD_SECURITY_OPEN)
2937 {
2938 *security = WHD_SECURITY_UNKNOWN;
2939 WPRINT_WHD_ERROR( ("Unknown security type, %s failed at line %d \n", __func__, __LINE__) );
2940 return WHD_UNKNOWN_SECURITY_TYPE;
2941 }
2942
2943 return WHD_SUCCESS;
2944 }
2945
whd_wifi_enable_powersave(whd_interface_t ifp)2946 uint32_t whd_wifi_enable_powersave(whd_interface_t ifp)
2947 {
2948 whd_buffer_t buffer;
2949 uint32_t *data;
2950 whd_driver_t whd_driver;
2951 CHECK_IFP_NULL(ifp);
2952
2953 whd_driver = ifp->whd_driver;
2954
2955 CHECK_DRIVER_NULL(whd_driver);
2956
2957 /* Set legacy powersave mode - PM1 */
2958 data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)4);
2959 CHECK_IOCTL_BUFFER(data);
2960 *data = htod32( (uint32_t)PM1_POWERSAVE_MODE );
2961
2962 RETURN_WITH_ASSERT(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_PM, buffer, NULL) );
2963 }
2964
whd_wifi_get_powersave_mode(whd_interface_t ifp,uint32_t * value)2965 uint32_t whd_wifi_get_powersave_mode(whd_interface_t ifp, uint32_t *value)
2966 {
2967 whd_driver_t whd_driver;
2968
2969 CHECK_IFP_NULL(ifp);
2970
2971 if (value == NULL)
2972 return WHD_BADARG;
2973
2974 whd_driver = ifp->whd_driver;
2975
2976 CHECK_DRIVER_NULL(whd_driver);
2977
2978 return whd_wifi_get_ioctl_value(ifp, WLC_GET_PM, value);
2979 }
2980
whd_wifi_enable_powersave_with_throughput(whd_interface_t ifp,uint16_t return_to_sleep_delay_ms)2981 uint32_t whd_wifi_enable_powersave_with_throughput(whd_interface_t ifp, uint16_t return_to_sleep_delay_ms)
2982 {
2983 whd_buffer_t buffer;
2984 uint32_t *data;
2985 whd_driver_t whd_driver;
2986 uint16_t chip_id;
2987 CHECK_IFP_NULL(ifp);
2988
2989 whd_driver = ifp->whd_driver;
2990
2991 CHECK_DRIVER_NULL(whd_driver);
2992
2993 if (return_to_sleep_delay_ms < PM2_SLEEP_RET_TIME_MIN)
2994 {
2995 WPRINT_WHD_ERROR( ("Delay too short, %s failed at line %d \n", __func__, __LINE__) );
2996 return WHD_DELAY_TOO_SHORT;
2997 }
2998 else if (return_to_sleep_delay_ms > PM2_SLEEP_RET_TIME_MAX)
2999 {
3000 WPRINT_WHD_ERROR( ("Delay too long, %s failed at line %d \n", __func__, __LINE__) );
3001 return WHD_DELAY_TOO_LONG;
3002 }
3003
3004 /* Set the maximum time to wait before going back to sleep */
3005 CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_PM2_SLEEP_RET,
3006 (uint32_t)(return_to_sleep_delay_ms / 10) * 10) );
3007 chip_id = whd_chip_get_chip_id(whd_driver);
3008
3009 if (chip_id == 43362)
3010 {
3011 CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_PM_LIMIT, NULL_FRAMES_WITH_PM_SET_LIMIT) );
3012 }
3013
3014 /* set PM2 fast return to sleep powersave mode */
3015 data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)4);
3016 CHECK_IOCTL_BUFFER(data);
3017 *data = htod32( (uint32_t)PM2_POWERSAVE_MODE );
3018
3019 RETURN_WITH_ASSERT(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_PM, buffer, NULL) );
3020 }
3021
whd_wifi_disable_powersave(whd_interface_t ifp)3022 uint32_t whd_wifi_disable_powersave(whd_interface_t ifp)
3023 {
3024 whd_buffer_t buffer;
3025 whd_driver_t whd_driver;
3026
3027 CHECK_IFP_NULL(ifp);
3028
3029 whd_driver = ifp->whd_driver;
3030
3031 CHECK_DRIVER_NULL(whd_driver);
3032
3033 uint32_t *data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)4);
3034
3035 CHECK_IOCTL_BUFFER(data);
3036 *data = htod32( (uint32_t)NO_POWERSAVE_MODE );
3037 CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_PM, buffer, NULL) );
3038 return WHD_SUCCESS;
3039 }
3040
whd_wifi_register_multicast_address(whd_interface_t ifp,const whd_mac_t * mac)3041 uint32_t whd_wifi_register_multicast_address(whd_interface_t ifp, const whd_mac_t *mac)
3042 {
3043 whd_buffer_t buffer;
3044 whd_buffer_t response;
3045 uint16_t a;
3046 mcast_list_t *orig_mcast_list;
3047 mcast_list_t *new_mcast_list;
3048 whd_driver_t whd_driver;
3049
3050 if (!ifp || !mac || !ETHER_ISMULTI(mac) )
3051 {
3052 WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n",
3053 __func__, __LINE__) );
3054 return WHD_WLAN_BADARG;
3055 }
3056
3057 whd_driver = ifp->whd_driver;
3058
3059 CHECK_DRIVER_NULL(whd_driver);
3060
3061 /* Get the current multicast list */
3062 CHECK_IOCTL_BUFFER(whd_cdc_get_iovar_buffer(whd_driver, &buffer,
3063 sizeof(uint32_t) + MAX_SUPPORTED_MCAST_ENTRIES *
3064 sizeof(whd_mac_t), IOVAR_STR_MCAST_LIST) );
3065 CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) );
3066
3067 /* Verify address is not currently registered */
3068 orig_mcast_list = (mcast_list_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response);
3069 CHECK_PACKET_NULL(orig_mcast_list, WHD_NO_REGISTER_FUNCTION_POINTER);
3070 orig_mcast_list->entry_count = dtoh32(orig_mcast_list->entry_count);
3071 for (a = 0; a < orig_mcast_list->entry_count; ++a)
3072 {
3073 /* Check if any address matches */
3074 if (0 == memcmp(mac, &orig_mcast_list->macs[a], sizeof(whd_mac_t) ) )
3075 {
3076 /* A matching address has been found so we can stop now. */
3077 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
3078 return WHD_SUCCESS;
3079 }
3080 }
3081
3082 /* Add the provided address to the list and write the new multicast list */
3083 new_mcast_list = (mcast_list_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer,
3084 ( uint16_t )(sizeof(uint32_t) +
3085 (orig_mcast_list->entry_count + 1) *
3086 sizeof(whd_mac_t) ),
3087 IOVAR_STR_MCAST_LIST);
3088 CHECK_IOCTL_BUFFER(new_mcast_list);
3089 new_mcast_list->entry_count = orig_mcast_list->entry_count;
3090 memcpy(new_mcast_list->macs, orig_mcast_list->macs, orig_mcast_list->entry_count * sizeof(whd_mac_t) );
3091 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
3092 memcpy(&new_mcast_list->macs[new_mcast_list->entry_count], mac, sizeof(whd_mac_t) );
3093 ++new_mcast_list->entry_count;
3094 new_mcast_list->entry_count = htod32(new_mcast_list->entry_count);
3095 RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) );
3096
3097 }
3098
whd_wifi_unregister_multicast_address(whd_interface_t ifp,const whd_mac_t * mac)3099 uint32_t whd_wifi_unregister_multicast_address(whd_interface_t ifp, const whd_mac_t *mac)
3100 {
3101 whd_buffer_t buffer;
3102 whd_buffer_t response;
3103 uint16_t a;
3104 mcast_list_t *orig_mcast_list;
3105 whd_driver_t whd_driver;
3106
3107 if (!ifp || !mac || !ETHER_ISMULTI(mac) )
3108 {
3109 WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n",
3110 __func__, __LINE__) );
3111 return WHD_WLAN_BADARG;
3112 }
3113
3114 whd_driver = ifp->whd_driver;
3115
3116 CHECK_DRIVER_NULL(whd_driver);
3117
3118 /* Get the current multicast list */
3119 CHECK_IOCTL_BUFFER(whd_cdc_get_iovar_buffer(whd_driver, &buffer,
3120 sizeof(uint32_t) + MAX_SUPPORTED_MCAST_ENTRIES *
3121 sizeof(whd_mac_t), IOVAR_STR_MCAST_LIST) );
3122 CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) );
3123
3124 /* Find the address, assuming it is part of the list */
3125 orig_mcast_list = (mcast_list_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response);
3126 orig_mcast_list->entry_count = dtoh32(orig_mcast_list->entry_count);
3127 if (orig_mcast_list->entry_count != 0)
3128 {
3129 mcast_list_t *new_mcast_list = (mcast_list_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer,
3130 ( uint16_t )(sizeof(uint32_t) +
3131 (orig_mcast_list->
3132 entry_count - 1) *
3133 sizeof(whd_mac_t) ),
3134 IOVAR_STR_MCAST_LIST);
3135 CHECK_IOCTL_BUFFER(new_mcast_list);
3136
3137 for (a = 0; a < orig_mcast_list->entry_count; ++a)
3138 {
3139 WPRINT_WHD_INFO( ("MAC: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", orig_mcast_list->macs[a].octet[0],
3140 orig_mcast_list->macs[a].octet[1], orig_mcast_list->macs[a].octet[2],
3141 orig_mcast_list->macs[a].octet[3], orig_mcast_list->macs[a].octet[4],
3142 orig_mcast_list->macs[a].octet[5]) );
3143 if (0 == memcmp(mac, &orig_mcast_list->macs[a], sizeof(whd_mac_t) ) )
3144 {
3145 /* Copy the existing list up to the matching address */
3146 memcpy(new_mcast_list->macs, orig_mcast_list->macs, a * sizeof(whd_mac_t) );
3147
3148 /* Skip the current address and copy the remaining entries */
3149 memcpy(&new_mcast_list->macs[a], &orig_mcast_list->macs[a + 1],
3150 ( size_t )(orig_mcast_list->entry_count - a - 1) * sizeof(whd_mac_t) );
3151
3152 new_mcast_list->entry_count = orig_mcast_list->entry_count - 1;
3153 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
3154 new_mcast_list->entry_count = htod32(new_mcast_list->entry_count);
3155 RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) );
3156 }
3157 }
3158 /* There was something in the list, but the request MAC wasn't there */
3159 CHECK_RETURN(whd_buffer_release(whd_driver, buffer, WHD_NETWORK_TX) );
3160 }
3161 /* If we get here than the address wasn't in the list or the list was empty */
3162 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
3163 WPRINT_WHD_ERROR( ("whd_wifi_unregister_multicast_address address not registered yet \n") );
3164 return WHD_DOES_NOT_EXIST;
3165 }
3166
whd_wifi_set_listen_interval(whd_interface_t ifp,uint8_t listen_interval,whd_listen_interval_time_unit_t time_unit)3167 uint32_t whd_wifi_set_listen_interval(whd_interface_t ifp, uint8_t listen_interval,
3168 whd_listen_interval_time_unit_t time_unit)
3169 {
3170 uint8_t listen_interval_dtim;
3171
3172 CHECK_IFP_NULL(ifp);
3173
3174 switch (time_unit)
3175 {
3176 case WHD_LISTEN_INTERVAL_TIME_UNIT_DTIM:
3177 {
3178 listen_interval_dtim = listen_interval;
3179 break;
3180 }
3181 case WHD_LISTEN_INTERVAL_TIME_UNIT_BEACON:
3182 {
3183 /* If the wake interval measured in DTIMs is set to 0, the wake interval is measured in beacon periods */
3184 listen_interval_dtim = 0;
3185
3186 /* The wake period is measured in beacon periods, set the value as required */
3187 CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_LISTEN_INTERVAL_BEACON, listen_interval) );
3188 break;
3189 }
3190 default:
3191 WPRINT_WHD_ERROR( ("whd_wifi_set_listen_interval: Invalid Time unit specified \n") );
3192 return WHD_BADARG;
3193 }
3194
3195 CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_LISTEN_INTERVAL_DTIM, listen_interval_dtim) );
3196
3197 CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_LISTEN_INTERVAL_ASSOC, listen_interval) );
3198
3199 return WHD_SUCCESS;
3200
3201 }
3202
whd_wifi_get_listen_interval(whd_interface_t ifp,whd_listen_interval_t * li)3203 uint32_t whd_wifi_get_listen_interval(whd_interface_t ifp, whd_listen_interval_t *li)
3204 {
3205 whd_buffer_t buffer;
3206 whd_buffer_t response;
3207 int *data;
3208 uint8_t *pdata = NULL;
3209 whd_driver_t whd_driver;
3210
3211 CHECK_IFP_NULL(ifp);
3212
3213 if (li == NULL)
3214 return WHD_BADARG;
3215
3216 whd_driver = ifp->whd_driver;
3217
3218 CHECK_DRIVER_NULL(whd_driver);
3219
3220 data = (int *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, 4, IOVAR_STR_LISTEN_INTERVAL_BEACON);
3221 CHECK_IOCTL_BUFFER(data);
3222 memset(data, 0, 1);
3223 CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) );
3224 pdata = whd_buffer_get_current_piece_data_pointer(whd_driver, response);
3225 CHECK_PACKET_NULL(pdata, WHD_NO_REGISTER_FUNCTION_POINTER);
3226 memcpy( (uint8_t *)&(li->beacon), (char *)pdata, 1 );
3227 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
3228
3229 data = (int *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, 4, IOVAR_STR_LISTEN_INTERVAL_DTIM);
3230 CHECK_IOCTL_BUFFER(data);
3231 memset(data, 0, 1);
3232 CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) );
3233 pdata = whd_buffer_get_current_piece_data_pointer(whd_driver, response);
3234 CHECK_PACKET_NULL(pdata, WHD_NO_REGISTER_FUNCTION_POINTER);
3235 memcpy( (uint8_t *)&(li->dtim), (char *)pdata, 1 );
3236 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
3237
3238 data = (int *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, 4, IOVAR_STR_LISTEN_INTERVAL_ASSOC);
3239 CHECK_IOCTL_BUFFER(data);
3240 memset(data, 0, 4);
3241 CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) );
3242 pdata = whd_buffer_get_current_piece_data_pointer(whd_driver, response);
3243 CHECK_PACKET_NULL(pdata, WHD_NO_REGISTER_FUNCTION_POINTER);
3244 memcpy( (uint16_t *)&(li->assoc), (char *)pdata, 2 );
3245 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
3246
3247 return WHD_SUCCESS;
3248 }
3249
whd_wifi_is_ready_to_transceive(whd_interface_t ifp)3250 uint32_t whd_wifi_is_ready_to_transceive(whd_interface_t ifp)
3251 {
3252 whd_driver_t whd_driver;
3253
3254 CHECK_IFP_NULL(ifp);
3255
3256 whd_driver = ifp->whd_driver;
3257
3258 CHECK_DRIVER_NULL(whd_driver);
3259
3260 switch (ifp->role)
3261 {
3262 case WHD_AP_ROLE:
3263 return (whd_wifi_get_ap_is_up(whd_driver) == WHD_TRUE) ? WHD_SUCCESS : WHD_INTERFACE_NOT_UP;
3264
3265 case WHD_STA_ROLE:
3266 return whd_wifi_check_join_status(ifp);
3267
3268 /* Disables Eclipse static analysis warning */
3269 /* No break needed due to returns in all case paths */
3270 /* no break */
3271 /* Fall Through */
3272 case WHD_P2P_ROLE:
3273 case WHD_INVALID_ROLE:
3274
3275 default:
3276 return WHD_UNKNOWN_INTERFACE;
3277 }
3278 }
3279
whd_wifi_get_acparams(whd_interface_t ifp,edcf_acparam_t * acp)3280 uint32_t whd_wifi_get_acparams(whd_interface_t ifp, edcf_acparam_t *acp)
3281 {
3282 whd_buffer_t buffer;
3283 whd_buffer_t response;
3284 whd_driver_t whd_driver;
3285 uint8_t *pdata = NULL;
3286
3287 if (!ifp || !acp)
3288 {
3289 WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n",
3290 __func__, __LINE__) );
3291 return WHD_WLAN_BADARG;
3292 }
3293 whd_driver = ifp->whd_driver;
3294
3295 CHECK_DRIVER_NULL(whd_driver);
3296
3297 int *data = (int *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, 64, IOVAR_STR_AC_PARAMS_STA);
3298
3299 CHECK_IOCTL_BUFFER(data);
3300 memset(data, 0, 64);
3301 CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) );
3302 pdata = whd_buffer_get_current_piece_data_pointer(whd_driver, response);
3303 CHECK_PACKET_NULL(pdata, WHD_NO_REGISTER_FUNCTION_POINTER);
3304 memcpy( (char *)acp, (char *)pdata, (sizeof(edcf_acparam_t) * 4) );
3305 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
3306
3307 return WHD_SUCCESS;
3308 }
3309
whd_wifi_get_channels(whd_interface_t ifp,whd_list_t * channel_list)3310 uint32_t whd_wifi_get_channels(whd_interface_t ifp, whd_list_t *channel_list)
3311 {
3312 whd_buffer_t buffer;
3313 whd_buffer_t response;
3314 whd_list_t *list;
3315 whd_driver_t whd_driver;
3316 uint16_t buffer_length;
3317
3318 if (!ifp || !channel_list)
3319 {
3320 WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n",
3321 __func__, __LINE__) );
3322 return WHD_WLAN_BADARG;
3323 }
3324 if (!channel_list->count)
3325 {
3326 WPRINT_WHD_ERROR( ("channel_list->count is zero and max channel is %d in func %s at line %d \n",
3327 WL_NUMCHANNELS, __func__, __LINE__) );
3328 return WHD_WLAN_BADARG;
3329 }
3330
3331 whd_driver = ifp->whd_driver;
3332
3333 CHECK_DRIVER_NULL(whd_driver);
3334
3335 buffer_length = sizeof(uint32_t) * (WL_NUMCHANNELS + 1);
3336
3337 list = (whd_list_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, buffer_length);
3338 CHECK_IOCTL_BUFFER(list);
3339
3340 memset(list, 0, buffer_length);
3341 list->count = htod32(WL_NUMCHANNELS);
3342 CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_GET, WLC_GET_VALID_CHANNELS, buffer, &response) );
3343
3344 list = (whd_list_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response);
3345 memcpy(channel_list, list,
3346 (size_t)MIN_OF(whd_buffer_get_current_piece_size(whd_driver, response),
3347 (sizeof(uint32_t) * (channel_list->count + 1) ) ) );
3348
3349 whd_buffer_release(whd_driver, response, WHD_NETWORK_RX);
3350
3351 return WHD_SUCCESS;
3352 }
3353
whd_wifi_manage_custom_ie(whd_interface_t ifp,whd_custom_ie_action_t action,const uint8_t * oui,uint8_t subtype,const void * data,uint16_t length,uint16_t which_packets)3354 uint32_t whd_wifi_manage_custom_ie(whd_interface_t ifp, whd_custom_ie_action_t action, const uint8_t *oui,
3355 uint8_t subtype, const void *data, uint16_t length, uint16_t which_packets)
3356 {
3357 whd_buffer_t buffer;
3358 vndr_ie_setbuf_t *ie_setbuf;
3359 uint32_t *iovar_data;
3360 whd_driver_t whd_driver;
3361
3362 if (!ifp || !oui || !data)
3363 {
3364 WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n",
3365 __func__, __LINE__) );
3366 return WHD_WLAN_BADARG;
3367 }
3368
3369 /* VNDR_IE = OUI + subtype + data_length */
3370 if (VNDR_IE_MAX_LEN < WIFI_IE_OUI_LENGTH + 1 + length)
3371 {
3372 WPRINT_WHD_ERROR( ("Invalid length :%u in func %s\n", length, __func__) );
3373 return WHD_WLAN_BADARG;
3374 }
3375
3376 if (which_packets & VENDOR_IE_UNKNOWN)
3377 {
3378 WPRINT_WHD_ERROR( ("Unsupported packet ID(%x) in func %s\n", which_packets, __func__) );
3379 return WHD_WLAN_BADARG;
3380 }
3381
3382 whd_driver = ifp->whd_driver;
3383
3384 CHECK_DRIVER_NULL(whd_driver);
3385
3386 whd_assert("Bad Args", oui != NULL);
3387
3388 iovar_data =
3389 (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)(sizeof(vndr_ie_setbuf_t) + length + 4),
3390 "bsscfg:" IOVAR_STR_VENDOR_IE);
3391 CHECK_IOCTL_BUFFER(iovar_data);
3392 *iovar_data = ifp->bsscfgidx;
3393 ie_setbuf = (vndr_ie_setbuf_t *)(iovar_data + 1);
3394
3395 /* Copy the vndr_ie SET command ("add"/"del") to the buffer */
3396 if (action == WHD_ADD_CUSTOM_IE)
3397 {
3398 memcpy( (char *)ie_setbuf->cmd, "add", 3 );
3399 }
3400 else
3401 {
3402 memcpy( (char *)ie_setbuf->cmd, "del", 3 );
3403 }
3404 ie_setbuf->cmd[3] = 0;
3405
3406 /* Set the values */
3407 ie_setbuf->vndr_ie_buffer.iecount = (int32_t)htod32(1);
3408
3409 ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].pktflag = htod32(which_packets);
3410 ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = 0xdd;
3411 ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len =
3412 ( uint8_t )(length + sizeof(ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui) + 1); /* +1: one byte for sub type */
3413
3414 /* Stop lint warning about vndr_ie_list array element not yet being defined */
3415 memcpy(ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui, oui, (size_t)WIFI_IE_OUI_LENGTH);
3416
3417 ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data[0] = subtype;
3418
3419 memcpy(&ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data[1], data, length);
3420
3421 RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) );
3422 }
3423
whd_wifi_send_action_frame(whd_interface_t ifp,whd_af_params_t * af_params)3424 uint32_t whd_wifi_send_action_frame(whd_interface_t ifp, whd_af_params_t *af_params)
3425 {
3426 whd_buffer_t buffer;
3427 whd_af_params_t *af_frame;
3428 whd_driver_t whd_driver;
3429 CHECK_IFP_NULL(ifp);
3430
3431 whd_driver = ifp->whd_driver;
3432
3433 CHECK_DRIVER_NULL(whd_driver);
3434
3435 if ( (af_params == NULL) || (af_params->action_frame.len > ACTION_FRAME_SIZE) )
3436 {
3437 WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", __func__, __LINE__) );
3438 return WHD_WLAN_BADARG;
3439 }
3440
3441 af_frame = (whd_af_params_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, WL_WIFI_AF_PARAMS_SIZE,
3442 IOVAR_STR_ACTION_FRAME);
3443 CHECK_IOCTL_BUFFER (af_frame);
3444 memcpy(af_frame, af_params, WL_WIFI_AF_PARAMS_SIZE);
3445 RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) );
3446 }
3447
whd_wifi_send_auth_frame(whd_interface_t ifp,whd_auth_params_t * auth_params)3448 whd_result_t whd_wifi_send_auth_frame(whd_interface_t ifp, whd_auth_params_t *auth_params)
3449 {
3450 whd_buffer_t buffer;
3451 whd_auth_params_t *auth_frame;
3452 whd_driver_t whd_driver;
3453 uint16_t auth_frame_len;
3454 CHECK_IFP_NULL(ifp);
3455
3456 whd_driver = ifp->whd_driver;
3457
3458 CHECK_DRIVER_NULL(whd_driver);
3459
3460 if (auth_params == NULL)
3461 {
3462 WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", __func__, __LINE__) );
3463 return WHD_WLAN_BADARG;
3464 }
3465 /* FW doesn't need MAC Header Length */
3466 auth_params->len -= DOT11_MGMT_HDR_LEN;
3467 auth_frame_len = OFFSET(whd_auth_params_t, data) + auth_params->len;
3468 auth_frame = (whd_auth_params_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, auth_frame_len,
3469 IOVAR_STR_MGMT_FRAME);
3470 CHECK_IOCTL_BUFFER (auth_frame);
3471 memcpy(auth_frame, auth_params, OFFSET(whd_auth_params_t, data) );
3472 memcpy(auth_frame->data, &auth_params->data[DOT11_MGMT_HDR_LEN], auth_params->len);
3473 auth_frame->dwell_time = MGMT_AUTH_FRAME_DWELL_TIME;
3474 RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) );
3475 }
3476
whd_wifi_he_omi(whd_interface_t ifp,whd_he_omi_params_t * he_omi_params)3477 uint32_t whd_wifi_he_omi(whd_interface_t ifp, whd_he_omi_params_t *he_omi_params)
3478 {
3479 (void)ifp;
3480 (void)he_omi_params;
3481 return WHD_SUCCESS;
3482 }
3483
whd_wifi_bss_max_idle(whd_interface_t ifp,uint16_t period)3484 uint32_t whd_wifi_bss_max_idle(whd_interface_t ifp, uint16_t period)
3485 {
3486 (void)ifp;
3487 (void)period;
3488 return WHD_SUCCESS;
3489 }
3490
whd_wifi_itwt_setup(whd_interface_t ifp,whd_itwt_setup_params_t * twt_params)3491 uint32_t whd_wifi_itwt_setup(whd_interface_t ifp, whd_itwt_setup_params_t *twt_params)
3492 {
3493 (void)ifp;
3494 (void)twt_params;
3495 return WHD_SUCCESS;
3496 }
3497
whd_wifi_btwt_join(whd_interface_t ifp,whd_btwt_join_params_t * twt_params)3498 uint32_t whd_wifi_btwt_join(whd_interface_t ifp, whd_btwt_join_params_t *twt_params)
3499 {
3500 (void)ifp;
3501 (void)twt_params;
3502 return WHD_SUCCESS;
3503 }
3504
whd_wifi_twt_teardown(whd_interface_t ifp,whd_twt_teardown_params_t * twt_params)3505 uint32_t whd_wifi_twt_teardown(whd_interface_t ifp, whd_twt_teardown_params_t *twt_params)
3506 {
3507 (void)ifp;
3508 (void)twt_params;
3509 return WHD_SUCCESS;
3510 }
3511
whd_wifi_twt_information_frame(whd_interface_t ifp,whd_twt_information_params_t * twt_params)3512 uint32_t whd_wifi_twt_information_frame(whd_interface_t ifp, whd_twt_information_params_t *twt_params)
3513 {
3514 (void)ifp;
3515 (void)twt_params;
3516 return WHD_SUCCESS;
3517 }
3518
whd_wifi_btwt_config(whd_interface_t ifp,whd_btwt_config_params_t * twt_params)3519 uint32_t whd_wifi_btwt_config(whd_interface_t ifp, whd_btwt_config_params_t *twt_params)
3520 {
3521 (void)ifp;
3522 (void)twt_params;
3523 return WHD_SUCCESS;
3524 }
3525
whd_wifi_set_ioctl_value(whd_interface_t ifp,uint32_t ioctl,uint32_t value)3526 uint32_t whd_wifi_set_ioctl_value(whd_interface_t ifp, uint32_t ioctl, uint32_t value)
3527 {
3528 whd_buffer_t buffer;
3529 uint32_t *data;
3530 whd_driver_t whd_driver;
3531
3532 CHECK_IFP_NULL(ifp);
3533
3534 whd_driver = ifp->whd_driver;
3535
3536 CHECK_DRIVER_NULL(whd_driver);
3537
3538 data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)sizeof(value) );
3539 CHECK_IOCTL_BUFFER(data);
3540 *data = htod32(value);
3541 CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_SET, ioctl, buffer, 0) );
3542
3543 return WHD_SUCCESS;
3544 }
3545
whd_wifi_get_ioctl_value(whd_interface_t ifp,uint32_t ioctl,uint32_t * value)3546 uint32_t whd_wifi_get_ioctl_value(whd_interface_t ifp, uint32_t ioctl, uint32_t *value)
3547 {
3548 whd_buffer_t buffer;
3549 whd_buffer_t response;
3550 whd_driver_t whd_driver;
3551 uint8_t *data = NULL;
3552
3553 if (value == NULL)
3554 return WHD_BADARG;
3555
3556 CHECK_IFP_NULL(ifp);
3557
3558 whd_driver = ifp->whd_driver;
3559
3560 CHECK_DRIVER_NULL(whd_driver);
3561
3562 CHECK_IOCTL_BUFFER(whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)sizeof(*value) ) );
3563 CHECK_RETURN_UNSUPPORTED_OK(whd_cdc_send_ioctl(ifp, CDC_GET, ioctl, buffer, &response) );
3564 data = whd_buffer_get_current_piece_data_pointer(whd_driver, response);
3565 CHECK_PACKET_NULL(data, WHD_NO_REGISTER_FUNCTION_POINTER);
3566 *value = dtoh32(*(uint32_t *)data);
3567
3568 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
3569
3570 return WHD_SUCCESS;
3571 }
3572
whd_wifi_set_ioctl_buffer(whd_interface_t ifp,uint32_t ioctl,void * in_buffer,uint16_t in_buffer_length)3573 uint32_t whd_wifi_set_ioctl_buffer(whd_interface_t ifp, uint32_t ioctl, void *in_buffer, uint16_t in_buffer_length)
3574 {
3575 whd_buffer_t buffer;
3576 uint32_t *data;
3577 whd_driver_t whd_driver = ifp->whd_driver;
3578
3579 data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, in_buffer_length);
3580 CHECK_IOCTL_BUFFER(data);
3581
3582 memcpy(data, in_buffer, in_buffer_length);
3583
3584 CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_SET, ioctl, buffer, NULL) );
3585
3586 return WHD_SUCCESS;
3587 }
3588
whd_wifi_get_ioctl_buffer(whd_interface_t ifp,uint32_t ioctl,uint8_t * out_buffer,uint16_t out_length)3589 uint32_t whd_wifi_get_ioctl_buffer(whd_interface_t ifp, uint32_t ioctl, uint8_t *out_buffer, uint16_t out_length)
3590 {
3591 whd_buffer_t buffer;
3592 uint32_t *data;
3593 whd_buffer_t response;
3594 whd_result_t result;
3595 whd_driver_t whd_driver;
3596
3597 CHECK_IFP_NULL(ifp);
3598
3599 whd_driver = ifp->whd_driver;
3600 data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, out_length);
3601 CHECK_IOCTL_BUFFER(data);
3602 memcpy(data, out_buffer, out_length);
3603
3604 result = whd_cdc_send_ioctl(ifp, CDC_GET, ioctl, buffer, &response);
3605
3606 /* it worked: copy the result to the output buffer */
3607 if (WHD_SUCCESS == result)
3608 {
3609 data = (uint32_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response);
3610 CHECK_PACKET_NULL(data, WHD_NO_REGISTER_FUNCTION_POINTER);
3611 *data = dtoh32(*data);
3612 memcpy(out_buffer, data, out_length);
3613 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
3614 }
3615
3616 CHECK_RETURN(result);
3617
3618 return WHD_SUCCESS;
3619 }
3620
whd_wifi_set_iovar_void(whd_interface_t ifp,const char * iovar)3621 uint32_t whd_wifi_set_iovar_void(whd_interface_t ifp, const char *iovar)
3622 {
3623 whd_buffer_t buffer;
3624 whd_driver_t whd_driver = ifp->whd_driver;
3625
3626 whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)0, iovar);
3627
3628 return whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL);
3629 }
3630
whd_wifi_set_iovar_value(whd_interface_t ifp,const char * iovar,uint32_t value)3631 uint32_t whd_wifi_set_iovar_value(whd_interface_t ifp, const char *iovar, uint32_t value)
3632 {
3633 whd_buffer_t buffer;
3634 uint32_t *data;
3635 whd_driver_t whd_driver = ifp->whd_driver;
3636
3637 data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)sizeof(value), iovar);
3638 CHECK_IOCTL_BUFFER(data);
3639 *data = htod32(value);
3640 return whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL);
3641 }
3642
whd_wifi_get_iovar_value(whd_interface_t ifp,const char * iovar,uint32_t * value)3643 uint32_t whd_wifi_get_iovar_value(whd_interface_t ifp, const char *iovar, uint32_t *value)
3644 {
3645 whd_buffer_t buffer;
3646 whd_buffer_t response;
3647 whd_driver_t whd_driver = ifp->whd_driver;
3648 uint8_t *data = NULL;
3649
3650 if (value == NULL)
3651 return WHD_BADARG;
3652
3653 CHECK_IOCTL_BUFFER(whd_cdc_get_iovar_buffer(whd_driver, &buffer, 4, iovar) );
3654 CHECK_RETURN_UNSUPPORTED_OK(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) );
3655 data = whd_buffer_get_current_piece_data_pointer(whd_driver, response);
3656 CHECK_PACKET_NULL(data, WHD_NO_REGISTER_FUNCTION_POINTER);
3657 *value = dtoh32(*(uint32_t *)data);
3658 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
3659
3660 return WHD_SUCCESS;
3661 }
3662
whd_wifi_set_iovar_buffer(whd_interface_t ifp,const char * iovar,void * in_buffer,uint16_t in_buffer_length)3663 uint32_t whd_wifi_set_iovar_buffer(whd_interface_t ifp, const char *iovar, void *in_buffer, uint16_t in_buffer_length)
3664 {
3665 return whd_wifi_set_iovar_buffers(ifp, iovar, (const void **)&in_buffer, (const uint16_t *)&in_buffer_length, 1);
3666 }
3667
whd_wifi_get_iovar_buffer(whd_interface_t ifp,const char * iovar_name,uint8_t * out_buffer,uint16_t out_length)3668 uint32_t whd_wifi_get_iovar_buffer(whd_interface_t ifp, const char *iovar_name, uint8_t *out_buffer,
3669 uint16_t out_length)
3670 {
3671 uint32_t *data;
3672 whd_buffer_t buffer;
3673 whd_buffer_t response;
3674 whd_result_t result;
3675 whd_driver_t whd_driver = ifp->whd_driver;
3676
3677 data = whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)out_length, iovar_name);
3678 CHECK_IOCTL_BUFFER(data);
3679
3680 result = whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response);
3681
3682 /* it worked: copy the result to the output buffer */
3683 if (WHD_SUCCESS == result)
3684 {
3685 data = (uint32_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response);
3686 *data = dtoh32(*data);
3687 memcpy(out_buffer, data, out_length);
3688 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
3689 }
3690
3691 return result;
3692 }
3693
3694 /*
3695 * format an iovar buffer
3696 */
3697 static whd_result_t
whd_iovar_mkbuf(const char * name,char * data,uint32_t datalen,char * iovar_buf,uint16_t buflen)3698 whd_iovar_mkbuf(const char *name, char *data, uint32_t datalen, char *iovar_buf, uint16_t buflen)
3699 {
3700 uint32_t iovar_len;
3701
3702 iovar_len = strlen(name) + 1;
3703
3704 /* check for overflow */
3705 if ( (iovar_len + datalen) > buflen )
3706 {
3707 return WHD_BADARG;
3708 }
3709
3710 /* copy data to the buffer past the end of the iovar name string */
3711 if (datalen > 0)
3712 memmove(&iovar_buf[iovar_len], data, datalen);
3713
3714 /* copy the name to the beginning of the buffer */
3715 strncpy(iovar_buf, name, (iovar_len - 1) );
3716
3717 return WHD_SUCCESS;
3718 }
3719
whd_wifi_get_iovar_buffer_with_param(whd_interface_t ifp,const char * iovar_name,void * param,uint32_t paramlen,uint8_t * out_buffer,uint32_t out_length)3720 whd_result_t whd_wifi_get_iovar_buffer_with_param(whd_interface_t ifp, const char *iovar_name, void *param,
3721 uint32_t paramlen, uint8_t *out_buffer, uint32_t out_length)
3722 {
3723 uint32_t *data;
3724 whd_buffer_t buffer;
3725 whd_buffer_t response;
3726 whd_result_t result;
3727 whd_driver_t whd_driver;
3728
3729 if (!ifp || !iovar_name || !param || !out_buffer)
3730 {
3731 WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n",
3732 __func__, __LINE__) );
3733 return WHD_WLAN_BADARG;
3734 }
3735
3736 whd_driver = (whd_driver_t)ifp->whd_driver;
3737
3738 /* Format the input string */
3739 result = whd_iovar_mkbuf(iovar_name, param, paramlen, (char *)out_buffer, (uint16_t)out_length);
3740 if (result != WHD_SUCCESS)
3741 return result;
3742
3743 data = whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)out_length);
3744
3745 if (data == NULL)
3746 return WHD_WLAN_NOMEM;
3747
3748 memcpy(data, out_buffer, out_length);
3749
3750 result = (whd_result_t)whd_cdc_send_ioctl(ifp, CDC_GET, WLC_GET_VAR, buffer, &response);
3751
3752 if (result == WHD_SUCCESS)
3753 {
3754 memcpy(out_buffer, whd_buffer_get_current_piece_data_pointer(whd_driver, response),
3755 (size_t)MIN_OF(whd_buffer_get_current_piece_size(whd_driver, response), out_length) );
3756 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
3757 }
3758
3759 return result;
3760 }
3761
whd_wifi_set_iovar_buffers(whd_interface_t ifp,const char * iovar,const void ** in_buffers,const uint16_t * lengths,const uint8_t num_buffers)3762 uint32_t whd_wifi_set_iovar_buffers(whd_interface_t ifp, const char *iovar, const void **in_buffers,
3763 const uint16_t *lengths, const uint8_t num_buffers)
3764 {
3765 whd_buffer_t buffer;
3766 uint32_t *data;
3767 int tot_in_buffer_length = 0;
3768 uint8_t buffer_num = 0;
3769 whd_driver_t whd_driver = ifp->whd_driver;
3770
3771 /* get total length of all buffers: they will be copied into memory one after the other. */
3772 for (; buffer_num < num_buffers; buffer_num++)
3773 {
3774 tot_in_buffer_length += lengths[buffer_num];
3775 }
3776
3777 /* get a valid buffer */
3778 data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)tot_in_buffer_length, iovar);
3779 CHECK_IOCTL_BUFFER(data);
3780
3781 /* copy all data into buffer */
3782 for (buffer_num = 0; buffer_num < num_buffers; buffer_num++)
3783 {
3784 memcpy(data, in_buffers[buffer_num], lengths[buffer_num]);
3785 data += lengths[buffer_num];
3786 }
3787
3788 /* send iovar */
3789 return whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL);
3790 }
3791
whd_wifi_get_clm_version(whd_interface_t ifp,char * version,uint8_t length)3792 uint32_t whd_wifi_get_clm_version(whd_interface_t ifp, char *version, uint8_t length)
3793 {
3794 whd_result_t result;
3795
3796 CHECK_IFP_NULL(ifp);
3797
3798 if (version == NULL)
3799 return WHD_BADARG;
3800
3801 version[0] = '\0';
3802
3803 result = whd_wifi_get_iovar_buffer(ifp, IOVAR_STR_CLMVER, (uint8_t *)version, length);
3804 if ( (result == WHD_SUCCESS) && version[0] )
3805 {
3806 uint8_t version_length;
3807 char *p;
3808
3809 version_length = strlen(version);
3810
3811 /* -2 becase \0 termination needs a char and strlen doesn't include length of \0 */
3812 if (version_length > length - 2)
3813 version_length = length - 2;
3814 version[version_length + 1] = '\0';
3815
3816 /* Replace all newline/linefeed characters with space character */
3817 p = version;
3818 while ( (p = strchr(p, '\n') ) != NULL )
3819 {
3820 *p = ' ';
3821 }
3822 }
3823
3824 CHECK_RETURN(result);
3825 return WHD_SUCCESS;
3826 }
3827
whd_wifi_get_wifi_version(whd_interface_t ifp,char * buf,uint8_t length)3828 uint32_t whd_wifi_get_wifi_version(whd_interface_t ifp, char *buf, uint8_t length)
3829 {
3830 whd_result_t result;
3831 uint8_t ver_len;
3832
3833 CHECK_IFP_NULL(ifp);
3834
3835 if (buf == NULL)
3836 return WHD_BADARG;
3837
3838 result = whd_wifi_get_iovar_buffer(ifp, IOVAR_STR_VERSION, (uint8_t *)buf, length);
3839
3840 ver_len = strlen(buf);
3841
3842 if (ver_len > length - 2)
3843 ver_len = length - 2;
3844
3845 if ( (ver_len > 1) && (buf[ver_len + 1] == '\n') )
3846 {
3847 buf[ver_len + 1] = '\0';
3848 }
3849
3850 CHECK_RETURN(result);
3851 return WHD_SUCCESS;
3852 }
3853
whd_network_get_ifidx_from_ifp(whd_interface_t ifp,uint8_t * ifidx)3854 uint32_t whd_network_get_ifidx_from_ifp(whd_interface_t ifp, uint8_t *ifidx)
3855 {
3856 CHECK_IFP_NULL(ifp);
3857
3858 if (!ifidx)
3859 return WHD_BADARG;
3860
3861 *ifidx = ifp->ifidx;
3862
3863 return WHD_SUCCESS;
3864 }
3865
whd_network_get_bsscfgidx_from_ifp(whd_interface_t ifp,uint8_t * bsscfgidx)3866 uint32_t whd_network_get_bsscfgidx_from_ifp(whd_interface_t ifp, uint8_t *bsscfgidx)
3867 {
3868 CHECK_IFP_NULL(ifp);
3869
3870 if (!bsscfgidx)
3871 return WHD_BADARG;
3872
3873 *bsscfgidx = ifp->bsscfgidx;
3874
3875 return WHD_SUCCESS;
3876 }
3877
whd_wifi_ap_set_beacon_interval(whd_interface_t ifp,uint16_t interval)3878 uint32_t whd_wifi_ap_set_beacon_interval(whd_interface_t ifp, uint16_t interval)
3879 {
3880 CHECK_IFP_NULL(ifp);
3881
3882 CHECK_RETURN(whd_wifi_set_ioctl_value(ifp, WLC_SET_BCNPRD, interval) );
3883 return WHD_SUCCESS;
3884 }
3885
whd_wifi_ap_set_dtim_interval(whd_interface_t ifp,uint16_t interval)3886 uint32_t whd_wifi_ap_set_dtim_interval(whd_interface_t ifp, uint16_t interval)
3887 {
3888 CHECK_IFP_NULL(ifp);
3889
3890 CHECK_RETURN(whd_wifi_set_ioctl_value(ifp, WLC_SET_DTIMPRD, interval) );
3891 return WHD_SUCCESS;
3892 }
3893
whd_wifi_get_bss_info(whd_interface_t ifp,wl_bss_info_t * bi)3894 uint32_t whd_wifi_get_bss_info(whd_interface_t ifp, wl_bss_info_t *bi)
3895 {
3896 whd_buffer_t buffer, response;
3897 uint32_t result;
3898 uint8_t *data;
3899 whd_driver_t whd_driver;
3900
3901 CHECK_IFP_NULL(ifp);
3902
3903 whd_driver = ifp->whd_driver;
3904
3905 CHECK_DRIVER_NULL(whd_driver);
3906
3907 if (bi == NULL)
3908 return WHD_BADARG;
3909
3910 if (whd_cdc_get_ioctl_buffer(whd_driver, &buffer, WLC_IOCTL_SMLEN) == NULL)
3911 {
3912 WPRINT_WHD_INFO( ("%s: Unable to malloc WLC_GET_BSS_INFO buffer\n", __FUNCTION__) );
3913 return WHD_SUCCESS;
3914 }
3915 result = whd_cdc_send_ioctl(ifp, CDC_GET, WLC_GET_BSS_INFO, buffer, &response);
3916 if (result != WHD_SUCCESS)
3917 {
3918 WPRINT_WHD_INFO( ("%s: WLC_GET_BSS_INFO Failed\n", __FUNCTION__) );
3919 return result;
3920 }
3921 data = whd_buffer_get_current_piece_data_pointer(whd_driver, response);
3922 CHECK_PACKET_NULL(data, WHD_NO_REGISTER_FUNCTION_POINTER);
3923 memcpy(bi, data + 4, sizeof(wl_bss_info_t) );
3924
3925 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
3926
3927 return WHD_SUCCESS;
3928 }
3929
whd_wifi_set_coex_config(whd_interface_t ifp,whd_coex_config_t * coex_config)3930 uint32_t whd_wifi_set_coex_config(whd_interface_t ifp, whd_coex_config_t *coex_config)
3931 {
3932 CHECK_IFP_NULL(ifp);
3933
3934 if (coex_config == NULL)
3935 return WHD_BADARG;
3936
3937 return whd_wifi_set_iovar_buffer(ifp, IOVAR_STR_BTC_LESCAN_PARAMS, &coex_config->le_scan_params,
3938 sizeof(whd_btc_lescan_params_t) );
3939 }
3940
whd_wifi_set_auth_status(whd_interface_t ifp,whd_auth_req_status_t * params)3941 whd_result_t whd_wifi_set_auth_status(whd_interface_t ifp, whd_auth_req_status_t *params)
3942 {
3943 whd_buffer_t buffer;
3944 whd_driver_t whd_driver;
3945 whd_auth_req_status_t *auth_status;
3946
3947 CHECK_IFP_NULL(ifp);
3948
3949 whd_driver = ifp->whd_driver;
3950
3951 CHECK_DRIVER_NULL(whd_driver);
3952
3953 if (params == NULL)
3954 {
3955 WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", __func__, __LINE__) );
3956 return WHD_WLAN_BADARG;
3957 }
3958
3959 auth_status = (whd_auth_req_status_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, sizeof(whd_auth_req_status_t),
3960 IOVAR_STR_AUTH_STATUS);
3961 CHECK_IOCTL_BUFFER (auth_status);
3962 memcpy(auth_status, params, sizeof(whd_auth_req_status_t) );
3963 if (params->flags == DOT11_SC_SUCCESS)
3964 {
3965 auth_status->flags = WL_EXTAUTH_SUCCESS;
3966 }
3967 else
3968 {
3969 auth_status->flags = WL_EXTAUTH_FAIL;
3970 }
3971 RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) );
3972 }
3973
whd_wifi_get_fwcap(whd_interface_t ifp,uint32_t * value)3974 whd_result_t whd_wifi_get_fwcap(whd_interface_t ifp, uint32_t *value)
3975 {
3976 whd_driver_t whd_driver;
3977
3978 CHECK_IFP_NULL(ifp);
3979
3980 whd_driver = ifp->whd_driver;
3981
3982 CHECK_DRIVER_NULL(whd_driver);
3983
3984 *value = whd_driver->chip_info.fwcap_flags;
3985 return WHD_SUCCESS;
3986 }
3987
3988 /*
3989 * ARP Offload version
3990 * ARP version in the WLAN Firmware
3991 *
3992 * @param[in] ifp - whd interface Instance
3993 * @param[out] version - pointer to store version #
3994 *
3995 * @return @ref whd_result_t
3996 */
whd_arp_version(whd_interface_t ifp,uint32_t * value)3997 whd_result_t whd_arp_version(whd_interface_t ifp, uint32_t *value)
3998 {
3999 CHECK_IFP_NULL(ifp);
4000
4001 return whd_wifi_get_iovar_value(ifp, IOVAR_STR_ARP_VERSION, value);
4002 }
4003
whd_arp_peerage_get(whd_interface_t ifp,uint32_t * value)4004 whd_result_t whd_arp_peerage_get(whd_interface_t ifp, uint32_t *value)
4005 {
4006 CHECK_IFP_NULL(ifp);
4007
4008 return whd_wifi_get_iovar_value(ifp, IOVAR_STR_ARP_PEERAGE, value);
4009 }
4010
whd_arp_peerage_set(whd_interface_t ifp,uint32_t value)4011 whd_result_t whd_arp_peerage_set(whd_interface_t ifp, uint32_t value)
4012 {
4013 CHECK_IFP_NULL(ifp);
4014
4015 return whd_wifi_set_iovar_value(ifp, IOVAR_STR_ARP_PEERAGE, value);
4016 }
4017
whd_arp_arpoe_get(whd_interface_t ifp,uint32_t * value)4018 whd_result_t whd_arp_arpoe_get(whd_interface_t ifp, uint32_t *value)
4019 {
4020 CHECK_IFP_NULL(ifp);
4021
4022 return whd_wifi_get_iovar_value(ifp, IOVAR_STR_ARPOE, value);
4023 }
4024
whd_arp_arpoe_set(whd_interface_t ifp,uint32_t value)4025 whd_result_t whd_arp_arpoe_set(whd_interface_t ifp, uint32_t value)
4026 {
4027 CHECK_IFP_NULL(ifp);
4028
4029 return whd_wifi_set_iovar_value(ifp, IOVAR_STR_ARPOE, value);
4030 }
4031
whd_arp_cache_clear(whd_interface_t ifp)4032 whd_result_t whd_arp_cache_clear(whd_interface_t ifp)
4033 {
4034 whd_result_t whd_ret;
4035 CHECK_IFP_NULL(ifp);
4036
4037 whd_ret = whd_wifi_set_iovar_void(ifp, IOVAR_STR_ARP_TABLE_CLEAR);
4038 return whd_ret;
4039 }
4040
whd_arp_features_get(whd_interface_t ifp,uint32_t * features)4041 whd_result_t whd_arp_features_get(whd_interface_t ifp, uint32_t *features)
4042 {
4043 if ( (ifp == NULL) || (features == NULL) )
4044 {
4045 return WHD_BADARG;
4046 }
4047
4048 if (whd_wifi_get_iovar_buffer(ifp, IOVAR_STR_ARP_OL, (uint8_t *)features, sizeof(uint32_t) ) != WHD_SUCCESS)
4049 {
4050 WPRINT_WHD_ERROR( ("%s() failed to get arp_ol for features\n", __func__) );
4051 return WHD_IOCTL_FAIL;
4052 }
4053
4054 return WHD_SUCCESS;
4055 }
4056
whd_arp_features_set(whd_interface_t ifp,uint32_t features)4057 whd_result_t whd_arp_features_set(whd_interface_t ifp, uint32_t features)
4058 {
4059 CHECK_IFP_NULL(ifp);
4060
4061 return whd_wifi_set_iovar_buffer(ifp, IOVAR_STR_ARP_OL, (uint8_t *)&features, sizeof(features) );
4062 }
4063
whd_arp_features_print(uint32_t features,const char * title)4064 whd_result_t whd_arp_features_print(uint32_t features, const char *title)
4065 {
4066 if (title != NULL)
4067 {
4068 WPRINT_MACRO( ("%s\n", title) );
4069 }
4070 WPRINT_MACRO( (" features : 0x%x\n", (int)features) );
4071 WPRINT_MACRO( (" agent_enabled: (0x%x) %s\n", (int)(features & ARP_OL_AGENT),
4072 (features & ARP_OL_AGENT) ? "Enabled" : " disabled") );
4073 WPRINT_MACRO( (" snoop_enabled: (0x%x) %s\n", (int)(features & ARP_OL_SNOOP),
4074 (features & ARP_OL_SNOOP) ? "Enabled" : " disabled") );
4075 WPRINT_MACRO( (" host_auto_reply_enabled: (0x%x) %s\n", (int)(features & ARP_OL_HOST_AUTO_REPLY),
4076 (features & ARP_OL_HOST_AUTO_REPLY) ? "Enabled" : " disabled") );
4077 WPRINT_MACRO( (" peer_auto_reply_enabled: (0x%x) %s\n", (int)(features & ARP_OL_PEER_AUTO_REPLY),
4078 (features & ARP_OL_PEER_AUTO_REPLY) ? "Enabled" : " disabled") );
4079
4080 return WHD_SUCCESS;
4081 }
4082
whd_arp_hostip_list_add(whd_interface_t ifp,uint32_t * host_ipv4_list,uint32_t count)4083 whd_result_t whd_arp_hostip_list_add(whd_interface_t ifp, uint32_t *host_ipv4_list, uint32_t count)
4084 {
4085 uint32_t filled = 0;
4086 uint32_t current_ipv4_list[ARP_MULTIHOMING_MAX];
4087 CHECK_IFP_NULL(ifp);
4088
4089 whd_result_t whd_ret = WHD_SUCCESS;
4090 if (host_ipv4_list == NULL)
4091 {
4092 WPRINT_WHD_ERROR( ("%s() BAD ARGS ifp:%p host_ipv4_list:%u count %d\n", __func__, ifp, (int)host_ipv4_list,
4093 (int)count) );
4094 return WHD_BADARG;
4095 }
4096 /* check if unique */
4097 whd_ret = whd_arp_hostip_list_get(ifp, ARP_MULTIHOMING_MAX, current_ipv4_list, &filled);
4098 if ( (whd_ret == WHD_SUCCESS) && (filled > 0) )
4099 {
4100 uint32_t curr_index;
4101 uint32_t new_index;
4102
4103 for (curr_index = 0; curr_index < filled; curr_index++)
4104 {
4105 for (new_index = 0; new_index < count; new_index++)
4106 {
4107 WPRINT_WHD_DEBUG( ("%s() curr:%ld of %ld curr:0x%lx new:%ld of %ld:0x%lx\n", __func__, curr_index,
4108 filled, current_ipv4_list[curr_index],
4109 new_index, count, host_ipv4_list[new_index]) );
4110 if (current_ipv4_list[curr_index] == host_ipv4_list[new_index])
4111 {
4112 /* decrement count */
4113 count--;
4114 if (new_index < count)
4115 {
4116 /* copy next one down */
4117 WPRINT_WHD_DEBUG( ("move %ld (+1) of %ld \n", new_index, count) );
4118 host_ipv4_list[new_index] = host_ipv4_list[new_index + 1];
4119
4120 }
4121 break;
4122 }
4123 }
4124 }
4125 }
4126 else if (whd_ret != WHD_SUCCESS)
4127 {
4128 WPRINT_WHD_DEBUG( ("%s() whd_arp_hostip_list_get() failed:%d\n", __func__, (int)whd_ret) );
4129 }
4130
4131 if (count > 0)
4132 {
4133 uint32_t new_index;
4134 WPRINT_WHD_DEBUG( ("%s() whd_wifi_set_iovar_buffer( %p, %lx)\n", __func__, host_ipv4_list, count) );
4135 for (new_index = 0; new_index < count; new_index++)
4136 {
4137 WPRINT_WHD_DEBUG( (" 0x%lx\n", host_ipv4_list[new_index]) );
4138 }
4139 whd_ret = whd_wifi_set_iovar_buffer(ifp, IOVAR_STR_ARP_HOSTIP, host_ipv4_list, (count * sizeof(uint32_t) ) );
4140 if (whd_ret != WHD_SUCCESS)
4141 {
4142 WPRINT_WHD_ERROR( ("Failed to set arp_hostip 0x%x error:%d\n", (int)host_ipv4_list[0], (int)whd_ret) );
4143 }
4144 }
4145 return whd_ret;
4146 }
4147
whd_arp_hostip_list_add_string(whd_interface_t ifp,const char * ip_addr)4148 whd_result_t whd_arp_hostip_list_add_string(whd_interface_t ifp, const char *ip_addr)
4149 {
4150 /* convert string to uint32_t */
4151 uint32_t addr;
4152 CHECK_IFP_NULL(ifp);
4153
4154 whd_str_to_ip(ip_addr, strlen(ip_addr), &addr);
4155
4156 return whd_arp_hostip_list_add(ifp, &addr, 1);
4157 }
4158
whd_arp_hostip_list_clear_id(whd_interface_t ifp,uint32_t ipv4_addr)4159 whd_result_t whd_arp_hostip_list_clear_id(whd_interface_t ifp, uint32_t ipv4_addr)
4160 {
4161 whd_result_t whd_ret;
4162 uint32_t filled;
4163 uint32_t host_ipv4_list[ARP_MULTIHOMING_MAX];
4164 CHECK_IFP_NULL(ifp);
4165
4166 if (ipv4_addr == 0x00l)
4167 {
4168 return WHD_BADARG;
4169 }
4170 memset(host_ipv4_list, 0x00, sizeof(host_ipv4_list) );
4171 whd_ret = whd_arp_hostip_list_get(ifp, ARP_MULTIHOMING_MAX, host_ipv4_list, &filled);
4172 if ( (whd_ret == WHD_SUCCESS) && (filled > 0) )
4173 {
4174 uint32_t index;
4175
4176 /* clear the list in the WLAN processor */
4177 whd_ret = whd_wifi_set_iovar_void(ifp, IOVAR_STR_ARP_HOSTIP_CLEAR);
4178 if (whd_ret != WHD_SUCCESS)
4179 {
4180 WPRINT_WHD_ERROR( ("%d %s() whd_wifi_set_iovar_void() failed:%d\n", __LINE__, __func__, (int)whd_ret) );
4181 return whd_ret;
4182 }
4183
4184 /* remove the one address from the list and re-write arp_hostip list */
4185 for (index = 0; index < filled; index++)
4186 {
4187 WPRINT_WHD_DEBUG( ("%d %s() drop() 0x%lx == 0x%lx ? %s\n", __LINE__, __func__, host_ipv4_list[index],
4188 ipv4_addr, (host_ipv4_list[index] == ipv4_addr) ? "DROP" : "") );
4189 if (host_ipv4_list[index] == ipv4_addr)
4190 {
4191 uint32_t drop;
4192 /* drop this one, move rest up */
4193 for (drop = index; drop < (filled - 1); drop++)
4194 {
4195 host_ipv4_list[drop] = host_ipv4_list[drop + 1];
4196 }
4197 filled--;
4198 /* IP addresses must be added one at a time */
4199 for (drop = 0; drop < filled; drop++)
4200 {
4201 whd_ret = whd_arp_hostip_list_add(ifp, &host_ipv4_list[drop], sizeof(uint32_t) );
4202 }
4203 break;
4204 }
4205 }
4206 }
4207 else if (whd_ret != WHD_SUCCESS)
4208 {
4209 WPRINT_WHD_DEBUG( ("%s() whd_arp_hostip_list_get() failed:%d\n", __func__, (int)whd_ret) );
4210 }
4211 return WHD_SUCCESS;
4212 }
4213
whd_arp_hostip_list_clear_id_string(whd_interface_t ifp,const char * ip_addr)4214 whd_result_t whd_arp_hostip_list_clear_id_string(whd_interface_t ifp, const char *ip_addr)
4215 {
4216 /* convert string to uint32_t */
4217 uint32_t addr;
4218 CHECK_IFP_NULL(ifp);
4219
4220 whd_str_to_ip(ip_addr, strlen(ip_addr), &addr);
4221
4222 return whd_arp_hostip_list_clear_id(ifp, addr);
4223 }
4224
whd_arp_hostip_list_clear(whd_interface_t ifp)4225 whd_result_t whd_arp_hostip_list_clear(whd_interface_t ifp)
4226 {
4227 CHECK_IFP_NULL(ifp);
4228 return whd_wifi_set_iovar_void(ifp, IOVAR_STR_ARP_HOSTIP_CLEAR);
4229 }
4230
whd_arp_hostip_list_get(whd_interface_t ifp,uint32_t count,uint32_t * host_ipv4_list,uint32_t * filled)4231 whd_result_t whd_arp_hostip_list_get(whd_interface_t ifp, uint32_t count, uint32_t *host_ipv4_list, uint32_t *filled)
4232 {
4233 whd_result_t whd_ret = WHD_SUCCESS;
4234 uint32_t temp[ARP_MULTIHOMING_MAX];
4235 arp_ol_stats_t arp_stats; /* WL struct, not ours! */
4236 CHECK_IFP_NULL(ifp);
4237
4238 if ( (host_ipv4_list == NULL) || (filled == NULL) )
4239 {
4240 return WHD_BADARG;
4241 }
4242
4243 /* set up the buffer to retrieve the stats data */
4244 memset(&arp_stats, 0x00, sizeof(arp_ol_stats_t) );
4245 whd_ret = whd_wifi_get_iovar_buffer(ifp, "arp_stats", (uint8_t *)&arp_stats, sizeof(arp_ol_stats_t) );
4246 if (whd_ret != WHD_SUCCESS)
4247 {
4248 WPRINT_WHD_ERROR( ("%s() failed to get arp_stats\n", __func__) );
4249 return WHD_IOCTL_FAIL;
4250 }
4251
4252 *filled = 0;
4253 whd_ret = whd_wifi_get_iovar_buffer(ifp, IOVAR_STR_ARP_HOSTIP, (uint8_t *)&temp, sizeof(temp) );
4254 /* transfer the info */
4255 if (whd_ret == WHD_SUCCESS)
4256 {
4257 uint32_t index;
4258 for (index = 0; (index < count) && (index < arp_stats.host_ip_entries); index++)
4259 {
4260 /* only IPv4 !!! */
4261 if (htod32(temp[index]) != 0L)
4262 {
4263 host_ipv4_list[*filled] = temp[index];
4264 *filled = *filled + 1;
4265 }
4266 }
4267 }
4268 return whd_ret;
4269 }
4270
whd_arp_stats_clear(whd_interface_t ifp)4271 whd_result_t whd_arp_stats_clear(whd_interface_t ifp)
4272 {
4273 whd_result_t whd_ret;
4274 CHECK_IFP_NULL(ifp);
4275 whd_ret = whd_wifi_set_iovar_void(ifp, IOVAR_STR_ARP_STATS_CLEAR);
4276 return whd_ret;
4277 }
4278
whd_arp_stats_get(whd_interface_t ifp,whd_arp_stats_t * arp_stats)4279 whd_result_t whd_arp_stats_get(whd_interface_t ifp, whd_arp_stats_t *arp_stats)
4280 {
4281 whd_result_t whd_ret;
4282 uint32_t filled;
4283 static whd_arp_stats_t arp_stats_test; /* read twice to make sure we match */
4284 CHECK_IFP_NULL(ifp);
4285
4286 if (arp_stats == NULL)
4287 {
4288 return WHD_BADARG;
4289 }
4290
4291 /* set up the buffer to retreive the data */
4292 memcpy(&arp_stats_test, arp_stats, sizeof(whd_arp_stats_t) );
4293 memset(arp_stats, 0xFF, sizeof(whd_arp_stats_t) );
4294
4295 /* read multiple times to make sure we got valid data */
4296 do
4297 {
4298 /* get them until they match */
4299 whd_ret =
4300 whd_wifi_get_iovar_buffer(ifp, IOVAR_STR_ARP_STATS, (uint8_t *)&arp_stats->stats,
4301 sizeof(arp_ol_stats_t) );
4302 if (whd_ret != WHD_SUCCESS)
4303 {
4304 WPRINT_WHD_ERROR( ("%s() failed to get arp_stats\n", __func__) );
4305 return WHD_IOCTL_FAIL;
4306 }
4307 /* get all feature info in one call */
4308 whd_ret =
4309 whd_wifi_get_iovar_buffer(ifp, IOVAR_STR_ARP_OL, (uint8_t *)&arp_stats->features_enabled,
4310 sizeof(arp_stats->features_enabled) );
4311 if (whd_ret != WHD_SUCCESS)
4312 {
4313 WPRINT_WHD_ERROR( ("%s() failed to get arp_ol\n", __func__) );
4314 return WHD_IOCTL_FAIL;
4315 }
4316 whd_ret = whd_wifi_get_iovar_value(ifp, IOVAR_STR_ARP_VERSION, &(arp_stats->version) );
4317 if (whd_ret != WHD_SUCCESS)
4318 {
4319 WPRINT_WHD_ERROR( ("%s() failed to get arp_version\n", __func__) );
4320 return WHD_IOCTL_FAIL;
4321 }
4322 whd_ret = whd_wifi_get_iovar_value(ifp, IOVAR_STR_ARP_PEERAGE, &(arp_stats->peerage) );
4323 if (whd_ret != WHD_SUCCESS)
4324 {
4325 WPRINT_WHD_ERROR( ("%s() failed to get arp_peerage\n", __func__) );
4326 return WHD_IOCTL_FAIL;
4327 }
4328 whd_ret = whd_wifi_get_iovar_value(ifp, IOVAR_STR_ARPOE, &(arp_stats->arpoe) );
4329 if (whd_ret != WHD_SUCCESS)
4330 {
4331 WPRINT_WHD_ERROR( ("%s() failed to get some settings\n", __func__) );
4332 return WHD_IOCTL_FAIL;
4333 }
4334
4335 /* set endian correctly */
4336 arp_stats->stats.host_ip_entries = dtoh32(arp_stats->stats.host_ip_entries);
4337 arp_stats->stats.host_ip_overflow = dtoh32(arp_stats->stats.host_ip_overflow);
4338 arp_stats->stats.arp_table_entries = dtoh32(arp_stats->stats.arp_table_entries);
4339 arp_stats->stats.arp_table_overflow = dtoh32(arp_stats->stats.arp_table_overflow);
4340 arp_stats->stats.host_request = dtoh32(arp_stats->stats.host_request);
4341 arp_stats->stats.host_reply = dtoh32(arp_stats->stats.host_reply);
4342 arp_stats->stats.host_service = dtoh32(arp_stats->stats.host_service);
4343 arp_stats->stats.peer_request = dtoh32(arp_stats->stats.peer_request);
4344 arp_stats->stats.peer_request_drop = dtoh32(arp_stats->stats.peer_request_drop);
4345 arp_stats->stats.peer_reply = dtoh32(arp_stats->stats.peer_reply);
4346 arp_stats->stats.peer_reply_drop = dtoh32(arp_stats->stats.peer_reply_drop);
4347 arp_stats->stats.peer_service = dtoh32(arp_stats->stats.peer_service);
4348
4349 whd_ret = whd_arp_hostip_list_get(ifp, ARP_MULTIHOMING_MAX, arp_stats->host_ip_list, &filled);
4350 if (whd_ret != WHD_SUCCESS)
4351 {
4352 WPRINT_WHD_ERROR( ("%s() failed to get host_ip_list\n", __func__) );
4353 return WHD_IOCTL_FAIL;
4354 }
4355
4356 if (memcmp(&arp_stats_test, arp_stats, sizeof(whd_arp_stats_t) ) == 0)
4357 {
4358 break;
4359 }
4360
4361 memcpy(&arp_stats_test, arp_stats, sizeof(whd_arp_stats_t) );
4362 } while (1);
4363
4364 return whd_ret;
4365 }
4366
whd_arp_stats_print(whd_arp_stats_t * arp_stats,const char * title)4367 whd_result_t whd_arp_stats_print(whd_arp_stats_t *arp_stats, const char *title)
4368 {
4369 uint32_t index;
4370
4371 if (arp_stats == NULL)
4372 {
4373 return WHD_BADARG;
4374 }
4375
4376 if (title != NULL)
4377 {
4378 WPRINT_MACRO( ("%s\n", title) );
4379 }
4380 WPRINT_MACRO( (" version: 0x%lx\n", (unsigned long int)arp_stats->version) );
4381 WPRINT_MACRO( (" host_ip_entries: %d\n", (int)arp_stats->stats.host_ip_entries) );
4382 WPRINT_MACRO( (" host_ip_overflow: %d\n", (int)arp_stats->stats.host_ip_overflow) );
4383 WPRINT_MACRO( (" arp_table_entries: %d\n", (int)arp_stats->stats.arp_table_entries) );
4384 WPRINT_MACRO( (" arp_table_overflow: %d\n", (int)arp_stats->stats.arp_table_overflow) );
4385 WPRINT_MACRO( (" host_request: %d\n", (int)arp_stats->stats.host_request) );
4386 WPRINT_MACRO( (" host_reply: %d\n", (int)arp_stats->stats.host_reply) );
4387 WPRINT_MACRO( (" host_service: %d\n", (int)arp_stats->stats.host_service) );
4388 WPRINT_MACRO( (" peer_request: %d\n", (int)arp_stats->stats.peer_request) );
4389 WPRINT_MACRO( (" peer_request_drop: %d\n", (int)arp_stats->stats.peer_request_drop) );
4390 WPRINT_MACRO( (" peer_reply: %d\n", (int)arp_stats->stats.peer_reply) );
4391 WPRINT_MACRO( (" peer_reply_drop: %d\n", (int)arp_stats->stats.peer_reply_drop) );
4392 WPRINT_MACRO( (" peer_service: %d\n", (int)arp_stats->stats.peer_service) );
4393 WPRINT_MACRO( (" peerage: %d\n", (int)arp_stats->peerage) );
4394 WPRINT_MACRO( (" arpoe: %d %s\n", (int)arp_stats->arpoe,
4395 (arp_stats->arpoe != 0) ? "Enabled" : " disabled") );
4396
4397 whd_arp_features_print(arp_stats->features_enabled, NULL);
4398
4399 if (arp_stats->stats.host_ip_entries > 0)
4400 {
4401 WPRINT_MACRO( ("WLAN Device Host IP entries\n") );
4402 for (index = 0; index < arp_stats->stats.host_ip_entries; index++)
4403 {
4404 uint32_t ipv4_addr = arp_stats->host_ip_list[index];
4405 char ipv4_string[32];
4406 memset(ipv4_string, 0x00, sizeof(ipv4_string) );
4407 whd_ip4_to_string(&ipv4_addr, ipv4_string);
4408 WPRINT_MACRO( (" %d of %d IPV4: 0x%x %s\n", (int)index, (int)arp_stats->stats.host_ip_entries,
4409 (int)arp_stats->host_ip_list[index], ipv4_string) );
4410 }
4411 }
4412 return WHD_SUCCESS;
4413 }
4414
4415 whd_result_t
whd_wifi_toggle_packet_filter(whd_interface_t ifp,uint8_t filter_id,whd_bool_t enable)4416 whd_wifi_toggle_packet_filter(whd_interface_t ifp, uint8_t filter_id, whd_bool_t enable)
4417 {
4418 whd_buffer_t buffer;
4419 whd_driver_t whd_driver;
4420
4421 CHECK_IFP_NULL(ifp);
4422
4423 whd_driver = ifp->whd_driver;
4424 wl_pkt_filter_enable_t *data = (wl_pkt_filter_enable_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer,
4425 sizeof(wl_pkt_filter_enable_t),
4426 IOVAR_STR_PKT_FILTER_ENABLE);
4427 CHECK_IOCTL_BUFFER(data);
4428 data->id = (uint32_t)filter_id;
4429 data->enable = (uint32_t)enable;
4430 RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) );
4431 }
4432
4433 whd_result_t
whd_pf_enable_packet_filter(whd_interface_t ifp,uint8_t filter_id)4434 whd_pf_enable_packet_filter(whd_interface_t ifp, uint8_t filter_id)
4435 {
4436 return whd_wifi_toggle_packet_filter(ifp, filter_id, WHD_TRUE);
4437 }
4438
4439 whd_result_t
whd_pf_disable_packet_filter(whd_interface_t ifp,uint8_t filter_id)4440 whd_pf_disable_packet_filter(whd_interface_t ifp, uint8_t filter_id)
4441 {
4442 return whd_wifi_toggle_packet_filter(ifp, filter_id, WHD_FALSE);
4443 }
4444
4445 whd_result_t
whd_pf_add_packet_filter(whd_interface_t ifp,const whd_packet_filter_t * settings)4446 whd_pf_add_packet_filter(whd_interface_t ifp, const whd_packet_filter_t *settings)
4447 {
4448 wl_pkt_filter_t *packet_filter;
4449 whd_driver_t whd_driver;
4450 whd_buffer_t buffer;
4451 uint32_t buffer_length =
4452 (uint32_t)( (2 * (uint32_t)settings->mask_size) + WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN );
4453
4454 CHECK_IFP_NULL(ifp);
4455
4456 whd_driver = ifp->whd_driver;
4457
4458 packet_filter = (wl_pkt_filter_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)buffer_length,
4459 IOVAR_STR_PKT_FILTER_ADD);
4460 CHECK_IOCTL_BUFFER(packet_filter);
4461
4462 /* Copy filter entries */
4463 packet_filter->id = settings->id;
4464 packet_filter->type = 0;
4465 packet_filter->negate_match = settings->rule;
4466 packet_filter->u.pattern.offset = (uint32_t)settings->offset;
4467 packet_filter->u.pattern.size_bytes = settings->mask_size;
4468
4469 /* Copy mask */
4470 memcpy(packet_filter->u.pattern.mask_and_pattern, settings->mask, settings->mask_size);
4471
4472 /* Copy filter pattern */
4473 memcpy(packet_filter->u.pattern.mask_and_pattern + settings->mask_size, settings->pattern, settings->mask_size);
4474
4475 RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) );
4476 }
4477
4478 whd_result_t
whd_pf_remove_packet_filter(whd_interface_t ifp,uint8_t filter_id)4479 whd_pf_remove_packet_filter(whd_interface_t ifp, uint8_t filter_id)
4480 {
4481 whd_buffer_t buffer;
4482 whd_driver_t whd_driver;
4483 CHECK_IFP_NULL(ifp);
4484
4485 whd_driver = ifp->whd_driver;
4486
4487 uint32_t *data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, sizeof(uint32_t),
4488 IOVAR_STR_PKT_FILTER_DELETE);
4489 CHECK_IOCTL_BUFFER(data);
4490 *data = (uint32_t)filter_id;
4491 RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) );
4492 }
4493
4494 whd_result_t
whd_pf_get_packet_filter_stats(whd_interface_t ifp,uint8_t filter_id,whd_pkt_filter_stats_t * stats)4495 whd_pf_get_packet_filter_stats(whd_interface_t ifp, uint8_t filter_id, whd_pkt_filter_stats_t *stats)
4496 {
4497 whd_buffer_t buffer;
4498 whd_buffer_t response;
4499 whd_driver_t whd_driver;
4500 uint8_t *pdata;
4501
4502 CHECK_IFP_NULL(ifp);
4503
4504 whd_driver = ifp->whd_driver;
4505
4506 uint32_t *data =
4507 (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, sizeof(uint32_t) + sizeof(wl_pkt_filter_stats_t),
4508 IOVAR_STR_PKT_FILTER_STATS);
4509 CHECK_IOCTL_BUFFER(data);
4510
4511 memset(data, 0, sizeof(uint32_t) + sizeof(wl_pkt_filter_stats_t) );
4512 *data = (uint32_t)filter_id;
4513
4514 CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) );
4515 pdata = whd_buffer_get_current_piece_data_pointer(whd_driver, response);
4516 CHECK_PACKET_NULL(pdata, WHD_NO_REGISTER_FUNCTION_POINTER);
4517 memcpy( (char *)stats, (char *)pdata, (sizeof(wl_pkt_filter_stats_t) ) );
4518 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_TX) );
4519
4520 return WHD_SUCCESS;
4521 }
4522
4523 whd_result_t
whd_wifi_clear_packet_filter_stats(whd_interface_t ifp,uint32_t filter_id)4524 whd_wifi_clear_packet_filter_stats(whd_interface_t ifp, uint32_t filter_id)
4525 {
4526 RETURN_WITH_ASSERT(whd_wifi_set_iovar_value(ifp, IOVAR_STR_PKT_FILTER_CLEAR_STATS, (uint32_t)filter_id) );
4527 }
4528
4529 whd_result_t
whd_pf_get_packet_filter_mask_and_pattern(whd_interface_t ifp,uint8_t filter_id,uint32_t max_size,uint8_t * mask,uint8_t * pattern,uint32_t * size_out)4530 whd_pf_get_packet_filter_mask_and_pattern(whd_interface_t ifp, uint8_t filter_id, uint32_t max_size, uint8_t *mask,
4531 uint8_t *pattern, uint32_t *size_out)
4532 {
4533 whd_bool_t enabled_list;
4534 whd_driver_t whd_driver;
4535 CHECK_IFP_NULL(ifp);
4536
4537 whd_driver = ifp->whd_driver;
4538
4539 for (enabled_list = WHD_FALSE; enabled_list <= WHD_TRUE; enabled_list++)
4540 {
4541
4542 whd_buffer_t buffer;
4543 whd_buffer_t response;
4544 uint32_t *data;
4545 wl_pkt_filter_list_t *filter_list;
4546 wl_pkt_filter_t *filter_ptr;
4547 uint32_t i;
4548 wl_pkt_filter_t *in_filter;
4549
4550 data = whd_cdc_get_iovar_buffer(whd_driver, &buffer, PACKET_FILTER_LIST_BUFFER_MAX_LEN,
4551 IOVAR_STR_PKT_FILTER_LIST);
4552 CHECK_IOCTL_BUFFER(data);
4553 *data = (uint32_t)enabled_list;
4554
4555 CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) );
4556
4557 filter_list = (wl_pkt_filter_list_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response);
4558 filter_ptr = filter_list->filter;
4559 for (i = 0; i < filter_list->num; i++)
4560 {
4561 in_filter = filter_ptr;
4562
4563 if (in_filter->id == filter_id)
4564 {
4565 *size_out = MIN_OF(in_filter->u.pattern.size_bytes, max_size);
4566 memcpy (mask, in_filter->u.pattern.mask_and_pattern, *size_out);
4567 memcpy (pattern, in_filter->u.pattern.mask_and_pattern + in_filter->u.pattern.size_bytes, *size_out);
4568 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
4569 if (*size_out < in_filter->u.pattern.size_bytes)
4570 {
4571 return WHD_PARTIAL_RESULTS;
4572 }
4573 return WHD_SUCCESS;
4574 }
4575
4576 /* Update WL filter pointer */
4577 filter_ptr =
4578 (wl_pkt_filter_t *)( (char *)filter_ptr +
4579 (WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 *
4580 in_filter->u.pattern.size_bytes) );
4581
4582 /* WLAN returns word-aligned filter list */
4583 filter_ptr = (wl_pkt_filter_t *)ROUND_UP( (unsigned long)filter_ptr, 4 );
4584 }
4585 }
4586 return WHD_FILTER_NOT_FOUND;
4587 }
4588
4589 /* Set/Get TKO retry & interval parameters */
4590 whd_result_t
whd_tko_param(whd_interface_t ifp,whd_tko_retry_t * whd_retry,uint8_t set)4591 whd_tko_param(whd_interface_t ifp, whd_tko_retry_t *whd_retry, uint8_t set)
4592 {
4593 uint32_t len = 0;
4594 uint8_t *data = NULL;
4595 wl_tko_t *tko = NULL;
4596 whd_buffer_t buffer;
4597 whd_buffer_t response;
4598 wl_tko_param_t *wl_param_p = NULL;
4599 whd_result_t result = WHD_SUCCESS;
4600 whd_driver_t whd_driver;
4601 CHECK_IFP_NULL(ifp);
4602
4603 whd_driver = ifp->whd_driver;
4604
4605 len = (int)(WHD_PAYLOAD_MTU - strlen(IOVAR_STR_TKO) - 1);
4606 data = (uint8_t * )whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)len, IOVAR_STR_TKO);
4607 if (data == NULL)
4608 {
4609 WPRINT_WHD_ERROR( ("%s: Failed to get iovar buf\n", __func__) );
4610 return WHD_IOCTL_FAIL;
4611 }
4612
4613 tko = (wl_tko_t *)data;
4614 tko->subcmd_id = WL_TKO_SUBCMD_PARAM;
4615 tko->len = TKO_DATA_OFFSET;
4616 wl_param_p = (wl_tko_param_t *)tko->data;
4617 tko->len += sizeof(wl_tko_param_t);
4618
4619 tko->subcmd_id = htod16(tko->subcmd_id);
4620 tko->len = htod16(tko->len);
4621
4622 if (set)
4623 {
4624 /* SET parameters */
4625
4626 /* Set defaults if needed */
4627 wl_param_p->interval = whd_retry->tko_interval ==
4628 0 ? TCP_KEEPALIVE_OFFLOAD_INTERVAL_SEC : whd_retry->tko_interval;
4629 wl_param_p->retry_count = whd_retry->tko_retry_count ==
4630 0 ? TCP_KEEPALIVE_OFFLOAD_RETRY_COUNT : whd_retry->tko_retry_count;
4631 wl_param_p->retry_interval = whd_retry->tko_retry_interval ==
4632 0 ? TCP_KEEPALIVE_OFFLOAD_RETRY_INTERVAL_SEC : whd_retry->tko_retry_interval;
4633
4634 result = whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL);
4635 if (result != WHD_SUCCESS)
4636 {
4637 WPRINT_WHD_ERROR( ("%s: Cannot set params\n", __func__) );
4638 }
4639 }
4640 else
4641 {
4642 /* GET paramters */
4643 wl_tko_param_t tko_param_real;
4644
4645 result = whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response);
4646 if (result == WHD_SUCCESS)
4647 {
4648 wl_param_p = &tko_param_real;
4649 memcpy( (char *)wl_param_p,
4650 (char *)whd_buffer_get_current_piece_data_pointer(whd_driver, response) + TKO_DATA_OFFSET,
4651 (sizeof(wl_tko_param_t) ) );
4652 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_TX) );
4653
4654 /* Copy items from wl level struct to higher level struct */
4655 whd_retry->tko_interval = wl_param_p->interval;
4656 whd_retry->tko_retry_interval = wl_param_p->retry_interval;
4657 whd_retry->tko_retry_count = wl_param_p->retry_count;
4658 }
4659 else
4660 {
4661 WPRINT_WHD_ERROR( ("%s: Cannot get params.\n", __func__) );
4662 }
4663 }
4664
4665 return result;
4666 }
4667
4668 /* Query Status */
4669 whd_result_t
whd_tko_get_status(whd_interface_t ifp,whd_tko_status_t * whd_status)4670 whd_tko_get_status(whd_interface_t ifp, whd_tko_status_t *whd_status)
4671 {
4672 whd_result_t result = WHD_SUCCESS;
4673 uint32_t len = 0;
4674 uint8_t *data = NULL;
4675 wl_tko_t *tko = NULL;
4676 whd_buffer_t buffer;
4677 whd_buffer_t response;
4678 whd_driver_t whd_driver;
4679 CHECK_IFP_NULL(ifp);
4680
4681 whd_driver = ifp->whd_driver;
4682
4683 /* Get a buffer */
4684 len = (int)(100 - strlen(IOVAR_STR_TKO) - 1);
4685 data = (uint8_t * )whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)len, IOVAR_STR_TKO);
4686 CHECK_IOCTL_BUFFER(data);
4687
4688 /* Fill buffer with request */
4689 tko = (wl_tko_t *)data;
4690 tko->subcmd_id = WL_TKO_SUBCMD_STATUS;
4691 tko->len = TKO_DATA_OFFSET;
4692
4693 tko->len += sizeof(wl_tko_status_t);
4694
4695 tko->subcmd_id = htod16(tko->subcmd_id);
4696 tko->len = htod16(tko->len);
4697
4698 /* Make request and get result */
4699 result = whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response);
4700 if (result != WHD_SUCCESS)
4701 {
4702 WPRINT_WHD_ERROR( ("%s: send iovar failed\n", __func__) );
4703 return result;
4704 }
4705
4706 /* Parse result */
4707 tko = (wl_tko_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response);
4708 if (tko)
4709 {
4710 len = htod16(tko->len);
4711
4712 if (len >= MAX_TKO_CONN + 1) /* MAX_TKO status's + 1 for the count */
4713 {
4714 memcpy(whd_status, tko->data, MAX_TKO_CONN + 1);
4715 }
4716 }
4717 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_TX) );
4718 return result;
4719 }
4720
4721 /* Query FW for number tko max tcp connections */
4722 whd_result_t
whd_tko_max_assoc(whd_interface_t ifp,uint8_t * max)4723 whd_tko_max_assoc(whd_interface_t ifp, uint8_t *max)
4724 {
4725 uint32_t len = 0;
4726 uint8_t *data = NULL;
4727 uint8_t *pdata = NULL;
4728 wl_tko_t *tko = NULL;
4729 whd_buffer_t buffer;
4730 whd_buffer_t response;
4731 wl_tko_max_tcp_t *tko_max_tcp = NULL;
4732 wl_tko_max_tcp_t tcp_result;
4733 whd_driver_t whd_driver;
4734 whd_result_t result = WHD_SUCCESS;
4735 CHECK_IFP_NULL(ifp);
4736
4737 whd_driver = ifp->whd_driver;
4738
4739 len = (int)(100 - strlen(IOVAR_STR_TKO) - 1);
4740 data = (uint8_t * )whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)len, IOVAR_STR_TKO);
4741 CHECK_IOCTL_BUFFER(data);
4742
4743 tko = (wl_tko_t *)data;
4744
4745 tko->subcmd_id = WL_TKO_SUBCMD_MAX_TCP;
4746 tko->len = TKO_DATA_OFFSET;
4747
4748 tko_max_tcp = (wl_tko_max_tcp_t *)tko->data;
4749 tko->len += sizeof(wl_tko_max_tcp_t);
4750
4751 tko->subcmd_id = htod16(tko->subcmd_id);
4752 tko->len = htod16(tko->len);
4753
4754 result = whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response);
4755 if (result != WHD_SUCCESS)
4756 {
4757 WPRINT_WHD_ERROR( ("%s: send iovar failed\n", __func__) );
4758 return result;
4759 }
4760 tko_max_tcp = &tcp_result;
4761 pdata = whd_buffer_get_current_piece_data_pointer(whd_driver, response);
4762 CHECK_PACKET_NULL(pdata, WHD_NO_REGISTER_FUNCTION_POINTER);
4763 memcpy( (char *)tko_max_tcp,
4764 (char *)pdata + TKO_DATA_OFFSET,
4765 (sizeof(wl_tko_max_tcp_t) ) );
4766 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_TX) );
4767
4768 *max = tko_max_tcp->max;
4769 return WHD_SUCCESS;
4770 }
4771
4772 /* Exercise GET of wl_tko_connect_t IOVAR */
4773 /* Given a index, return info about that index */
4774 whd_result_t
whd_tko_get_FW_connect(whd_interface_t ifp,uint8_t index,whd_tko_connect_t * whd_connect,uint16_t buflen)4775 whd_tko_get_FW_connect(whd_interface_t ifp, uint8_t index, whd_tko_connect_t *whd_connect, uint16_t buflen)
4776 {
4777 uint32_t len = 0;
4778 uint8_t *data = NULL;
4779 wl_tko_t *tko = NULL;
4780 wl_tko_connect_t *connect = NULL;
4781 whd_result_t result = WHD_SUCCESS;
4782 whd_buffer_t response;
4783 whd_buffer_t buffer;
4784 whd_driver_t whd_driver;
4785 CHECK_IFP_NULL(ifp);
4786
4787 whd_driver = ifp->whd_driver;
4788 CHECK_DRIVER_NULL(whd_driver);
4789
4790 len = (int)(WHD_PAYLOAD_MTU - strlen(IOVAR_STR_TKO) - 1);
4791 data = (uint8_t * )whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)len, IOVAR_STR_TKO);
4792 CHECK_IOCTL_BUFFER(data);
4793
4794 tko = (wl_tko_t *)data;
4795
4796 tko->subcmd_id = WL_TKO_SUBCMD_CONNECT;
4797 tko->len = offsetof(wl_tko_t, data);
4798 connect = (wl_tko_connect_t *)tko->data;
4799 connect->index = index;
4800
4801 tko->subcmd_id = htod16(tko->subcmd_id);
4802 tko->len = htod16(tko->len);
4803
4804 result = whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response);
4805 if (result != WHD_SUCCESS)
4806 {
4807 WPRINT_WHD_ERROR( ("%s: send iovar failed\n", __func__) );
4808 return result;
4809 }
4810 tko = (wl_tko_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response);
4811 tko->subcmd_id = dtoh16(tko->subcmd_id);
4812 tko->len = dtoh16(tko->len);
4813
4814 if (tko->subcmd_id != WL_TKO_SUBCMD_CONNECT)
4815 {
4816 WPRINT_WHD_ERROR( ("%s: IOVAR returned garbage!\n", __func__) );
4817 return WHD_BADARG;
4818 }
4819 connect = (wl_tko_connect_t *)tko->data;
4820 if (tko->len >= sizeof(*connect) )
4821 {
4822 connect->local_port = dtoh16(connect->local_port);
4823 connect->remote_port = dtoh16(connect->remote_port);
4824 connect->local_seq = dtoh32(connect->local_seq);
4825 connect->remote_seq = dtoh32(connect->remote_seq);
4826 if (connect->ip_addr_type != 0)
4827 {
4828 WPRINT_WHD_ERROR( ("%s: Address type not IPV4\n", __func__) );
4829 return WHD_BADARG;
4830 }
4831 if (connect->ip_addr_type == 0)
4832 {
4833 /* IPv4 */
4834 uint16_t mylen;
4835 mylen = sizeof(wl_tko_connect_t) + (2 * IPV4_ADDR_LEN) + connect->request_len + connect->response_len;
4836 if (buflen < mylen)
4837 {
4838 WPRINT_WHD_ERROR( ("%s: Buf len (%d) too small , need %d\n", __func__, buflen, mylen) );
4839 return WHD_BADARG;
4840 }
4841
4842 /*
4843 * Assumes whd_tko_connect_t and wl_tko_connect_t are the same.
4844 * If/when they become different (due to different FW versions, etc) than
4845 * this may have to be copied field by field instead.
4846 */
4847 memcpy(whd_connect, connect, MIN_OF(mylen, buflen) );
4848 }
4849 }
4850 return WHD_SUCCESS;
4851 }
4852
4853 whd_result_t
whd_tko_toggle(whd_interface_t ifp,whd_bool_t enable)4854 whd_tko_toggle(whd_interface_t ifp, whd_bool_t enable)
4855 {
4856 uint32_t len = 0;
4857 uint8_t *data = NULL;
4858 wl_tko_t *tko = NULL;
4859 whd_buffer_t buffer;
4860 wl_tko_enable_t *tko_enable = NULL;
4861 whd_driver_t whd_driver;
4862 whd_result_t result;
4863 CHECK_IFP_NULL(ifp);
4864
4865 whd_driver = ifp->whd_driver;
4866
4867
4868
4869 len = (int)(WHD_PAYLOAD_MTU - strlen(IOVAR_STR_TKO) - 1);
4870 data = (uint8_t * )whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)len, IOVAR_STR_TKO);
4871 CHECK_IOCTL_BUFFER(data);
4872
4873 tko = (wl_tko_t *)data;
4874
4875 tko->subcmd_id = WL_TKO_SUBCMD_ENABLE;
4876 tko->len = TKO_DATA_OFFSET;
4877
4878 tko_enable = (wl_tko_enable_t *)tko->data;
4879 tko_enable->enable = enable;
4880
4881 tko->len += sizeof(wl_tko_enable_t);
4882
4883 tko->subcmd_id = htod16(tko->subcmd_id);
4884 tko->len = htod16(tko->len);
4885
4886 /* invoke SET iovar */
4887 result = whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL);
4888 if (result != WHD_SUCCESS)
4889 {
4890 WPRINT_WHD_ERROR( ("%s: tko %s FAILED\n", __func__, (enable == WHD_TRUE ? "enable" : "disable") ) );
4891 return result;
4892 }
4893 else
4894 {
4895 WPRINT_WHD_ERROR( ("%s: Successfully %s\n", __func__, (enable == WHD_TRUE ? "enabled" : "disabled") ) );
4896 }
4897 return result;
4898 }
4899
4900