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