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 * Provides generic APSTA functionality that chip specific files use
20 */
21 #include "whd_debug.h"
22 #include "whd_ap.h"
23 #include "bus_protocols/whd_chip_reg.h"
24 #include "whd_chip_constants.h"
25 #include "whd_chip.h"
26 #include "whd_sdpcm.h"
27 #include "whd_thread_internal.h"
28 #include "whd_events_int.h"
29 #include "whd_int.h"
30 #include "whd_utils.h"
31 #include "whd_wifi_api.h"
32 #include "whd_buffer_api.h"
33 #include "whd_wlioctl.h"
34
35 /******************************************************
36 ** @cond Constants
37 *******************************************************/
38
39 #define WLC_EVENT_MSG_LINK (0x01)
40 #define RATE_SETTING_11_MBPS (11000000 / 500000)
41 #define AMPDU_AP_DEFAULT_BA_WSIZE 8
42 #define AMPDU_STA_DEFAULT_BA_WSIZE 8
43 #define AMPDU_STA_DEFAULT_MPDU 4 /* STA default num MPDU per AMPDU */
44 #define PWE_LOOP_COUNT 5
45 /******************************************************
46 ** Enumerations
47 *******************************************************/
48 typedef enum
49 {
50 BSS_AP = 3,
51 BSS_STA = 2,
52 BSS_UP = 1,
53 BSS_DOWN = 0
54 } bss_arg_option_t;
55
56 /******************************************************
57 * * Function Declarations
58 * ******************************************************/
59 static void *whd_handle_apsta_event(whd_interface_t ifp, const whd_event_header_t *event_header,
60 const uint8_t *event_data, void *handler_user_data);
61
62 /******************************************************
63 * Variables Definitions
64 *****************************************************/
65 static const whd_event_num_t apsta_events[] = { WLC_E_IF, WLC_E_LINK, WLC_E_NONE };
66 /******************************************************
67 * Function Definitions
68 ******************************************************/
69
whd_ap_info_init(whd_driver_t whd_driver)70 void whd_ap_info_init(whd_driver_t whd_driver)
71 {
72 whd_driver->ap_info.ap_is_up = WHD_FALSE;
73 whd_driver->ap_info.is_waiting_event = WHD_FALSE;
74 }
75
whd_wifi_set_ap_is_up(whd_driver_t whd_driver,whd_bool_t new_state)76 void whd_wifi_set_ap_is_up(whd_driver_t whd_driver, whd_bool_t new_state)
77 {
78 if (whd_driver->ap_info.ap_is_up != new_state)
79 {
80 whd_driver->ap_info.ap_is_up = new_state;
81 }
82 }
83
whd_wifi_get_ap_is_up(whd_driver_t whd_driver)84 whd_bool_t whd_wifi_get_ap_is_up(whd_driver_t whd_driver)
85 {
86 return whd_driver->ap_info.ap_is_up;
87 }
88
whd_wifi_set_block_ack_window_size_common(whd_interface_t ifp,uint16_t ap_win_size,uint16_t sta_win_size)89 whd_result_t whd_wifi_set_block_ack_window_size_common(whd_interface_t ifp, uint16_t ap_win_size, uint16_t sta_win_size)
90 {
91 whd_result_t retval;
92 uint16_t block_ack_window_size = ap_win_size;
93
94 /* If the AP interface is already up then don't change the Block Ack window size */
95 if (ifp->role == WHD_AP_ROLE)
96 {
97 return WHD_SUCCESS;
98 }
99
100 if (ifp->role == WHD_STA_ROLE)
101 {
102 block_ack_window_size = sta_win_size;
103 }
104
105 retval = whd_wifi_set_iovar_value(ifp, IOVAR_STR_AMPDU_BA_WINDOW_SIZE, ( uint32_t )block_ack_window_size);
106
107 whd_assert("set_block_ack_window_size: Failed to set block ack window size\r\n", retval == WHD_SUCCESS);
108
109 return retval;
110 }
111
whd_wifi_set_ampdu_parameters_common(whd_interface_t ifp,uint8_t ba_window_size,int8_t ampdu_mpdu,uint8_t rx_factor)112 whd_result_t whd_wifi_set_ampdu_parameters_common(whd_interface_t ifp, uint8_t ba_window_size, int8_t ampdu_mpdu,
113 uint8_t rx_factor)
114 {
115 CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_AMPDU_BA_WINDOW_SIZE, ba_window_size) );
116
117 /* Set number of MPDUs available for AMPDU */
118 CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_AMPDU_MPDU, ( uint32_t )ampdu_mpdu) );
119
120 if (rx_factor != AMPDU_RX_FACTOR_INVALID)
121 {
122 CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_AMPDU_RX_FACTOR, rx_factor) );
123 }
124 return WHD_SUCCESS;
125 }
126
127 /** Sets the chip specific AMPDU parameters for AP and STA
128 * For SDK 3.0, and beyond, each chip will need it's own function for setting AMPDU parameters.
129 */
whd_wifi_set_ampdu_parameters(whd_interface_t ifp)130 whd_result_t whd_wifi_set_ampdu_parameters(whd_interface_t ifp)
131 {
132 whd_driver_t whd_driver = ifp->whd_driver;
133 /* Get the chip number */
134 uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver);
135
136 if ( (wlan_chip_id == 43012) || (wlan_chip_id == 0x4373) )
137 {
138 return whd_wifi_set_ampdu_parameters_common(ifp, AMPDU_STA_DEFAULT_BA_WSIZE, AMPDU_MPDU_AUTO,
139 AMPDU_RX_FACTOR_64K);
140 }
141 else if ( (wlan_chip_id == 43909) || (wlan_chip_id == 43907) || (wlan_chip_id == 54907) )
142 {
143 return whd_wifi_set_ampdu_parameters_common(ifp, AMPDU_STA_DEFAULT_BA_WSIZE, AMPDU_MPDU_AUTO,
144 AMPDU_RX_FACTOR_INVALID);
145 }
146 else
147 {
148 return whd_wifi_set_ampdu_parameters_common(ifp, AMPDU_STA_DEFAULT_BA_WSIZE, AMPDU_STA_DEFAULT_MPDU,
149 AMPDU_RX_FACTOR_8K);
150 }
151 }
152
153 /* All chips */
whd_handle_apsta_event(whd_interface_t ifp,const whd_event_header_t * event_header,const uint8_t * event_data,void * handler_user_data)154 static void *whd_handle_apsta_event(whd_interface_t ifp, const whd_event_header_t *event_header,
155 const uint8_t *event_data, void *handler_user_data)
156 {
157 whd_driver_t whd_driver = ifp->whd_driver;
158 whd_ap_int_info_t *ap;
159
160 UNUSED_PARAMETER(event_header);
161 UNUSED_PARAMETER(event_data);
162 UNUSED_PARAMETER(handler_user_data);
163
164 ap = &whd_driver->ap_info;
165
166 if (ap->is_waiting_event == WHD_TRUE)
167 {
168 if ( (event_header->event_type == (whd_event_num_t)WLC_E_LINK) ||
169 (event_header->event_type == WLC_E_IF) )
170 {
171 whd_result_t result;
172 result = cy_rtos_set_semaphore(&ap->whd_wifi_sleep_flag, WHD_FALSE);
173 WPRINT_WHD_DEBUG( ("%s failed to post AP link semaphore at %d\n", __func__, __LINE__) );
174 REFERENCE_DEBUG_ONLY_VARIABLE(result);
175 }
176 }
177 return handler_user_data;
178 }
179
180 /* All chips */
whd_wifi_init_ap(whd_interface_t ifp,whd_ssid_t * ssid,whd_security_t auth_type,const uint8_t * security_key,uint8_t key_length,uint8_t channel)181 uint32_t whd_wifi_init_ap(whd_interface_t ifp, whd_ssid_t *ssid, whd_security_t auth_type,
182 const uint8_t *security_key, uint8_t key_length, uint8_t channel)
183 {
184 whd_driver_t whd_driver;
185 whd_bool_t wait_for_interface = WHD_FALSE;
186 whd_result_t result;
187 whd_buffer_t response;
188 whd_buffer_t buffer;
189 whd_interface_t prim_ifp;
190 whd_ap_int_info_t *ap;
191 uint32_t *data;
192 uint32_t bss_index;
193 uint16_t wlan_chip_id;
194 uint32_t auth_mfp = WL_MFP_NONE;
195 uint16_t event_entry = (uint16_t)0xFF;
196
197
198 CHECK_IFP_NULL(ifp);
199
200 whd_driver = ifp->whd_driver;
201
202 CHECK_DRIVER_NULL(whd_driver);
203
204 /* Get the Chip Number */
205 wlan_chip_id = whd_chip_get_chip_id(whd_driver);
206
207 if ( (auth_type & WEP_ENABLED) != 0 )
208 {
209 WPRINT_WHD_ERROR( ("WEP auth type is not allowed , %s failed at line %d \n", __func__, __LINE__) );
210 return WHD_WEP_NOT_ALLOWED;
211 }
212
213 if ( (auth_type & WPA3_SECURITY) &&
214 ( (wlan_chip_id == 43430) || (wlan_chip_id == 43909) || (wlan_chip_id == 43907) || (wlan_chip_id == 54907) ||
215 (wlan_chip_id == 43012) ) )
216 {
217 WPRINT_WHD_ERROR( ("WPA3 is not supported, %s failed at line %d \n", __func__, __LINE__) );
218 return WHD_UNSUPPORTED;
219 }
220
221 ap = &whd_driver->ap_info;
222
223 prim_ifp = whd_get_primary_interface(whd_driver);
224 if (prim_ifp == NULL)
225 {
226 WPRINT_WHD_ERROR( ("%s failed at %d \n", __func__, __LINE__) );
227 return WHD_UNKNOWN_INTERFACE;
228 }
229
230 if (ssid->length > (size_t)SSID_NAME_SIZE)
231 {
232 WPRINT_WHD_ERROR( ("%s: failure: SSID length(%u) error\n", __func__, ssid->length) );
233 return WHD_WLAN_BADSSIDLEN;
234 }
235
236 /* Turn off APSTA when creating AP mode on primary interface */
237 if (ifp == prim_ifp)
238 {
239 CHECK_RETURN(whd_wifi_set_ioctl_buffer(prim_ifp, WLC_DOWN, NULL, 0) );
240 data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)4, IOVAR_STR_APSTA);
241 CHECK_IOCTL_BUFFER(data);
242 *data = 0;
243 result = whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0);
244 if ( (result != WHD_SUCCESS) && (result != WHD_WLAN_UNSUPPORTED) )
245 {
246 WPRINT_WHD_ERROR( ("Could not turn off apsta\n") );
247 return result;
248 }
249 CHECK_RETURN(whd_wifi_set_ioctl_buffer(prim_ifp, WLC_UP, NULL, 0) );
250 }
251
252 bss_index = ifp->bsscfgidx;
253
254 ifp->role = WHD_AP_ROLE;
255
256 if ( ( (auth_type == WHD_SECURITY_WPA_TKIP_PSK) || (auth_type == WHD_SECURITY_WPA2_AES_PSK) ||
257 (auth_type == WHD_SECURITY_WPA2_MIXED_PSK) ) &&
258 ( (key_length < (uint8_t)WSEC_MIN_PSK_LEN) || (key_length > (uint8_t)WSEC_MAX_PSK_LEN) ) )
259 {
260 WPRINT_WHD_ERROR( ("Error: WPA security key length must be between %d and %d\n", WSEC_MIN_PSK_LEN,
261 WSEC_MAX_PSK_LEN) );
262 return WHD_WPA_KEYLEN_BAD;
263 }
264
265 if ( (whd_wifi_get_ap_is_up(whd_driver) == WHD_TRUE) )
266 {
267 WPRINT_WHD_ERROR( ("Error: Soft AP or Wi-Fi Direct group owner already up\n") );
268 return WHD_AP_ALREADY_UP;
269 }
270
271 /* Query bss state (does it exist? if so is it UP?) */
272 data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)4, IOVAR_STR_BSS);
273 CHECK_IOCTL_BUFFER(data);
274
275 if ( (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) )
276 {
277 *data = htod32( (uint32_t)CHIP_AP_INTERFACE );
278 }
279 else
280 {
281 *data = htod32( (uint32_t)bss_index );
282 }
283
284 if ( (wlan_chip_id == 43340) || (wlan_chip_id == 43342) )
285 {
286 if (whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) != WHD_SUCCESS)
287 {
288 /* Note: We don't need to release the response packet since the iovar failed */
289 wait_for_interface = WHD_TRUE;
290 }
291 else
292 {
293 /* Check if the BSS is already UP, if so return */
294 uint32_t *data2 = (uint32_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response);
295 CHECK_PACKET_NULL(data2, WHD_NO_REGISTER_FUNCTION_POINTER);
296 *data2 = dtoh32 (*data2);
297 if (*data2 == (uint32_t)BSS_UP)
298 {
299 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
300 whd_wifi_set_ap_is_up(whd_driver, WHD_TRUE);
301 ap->is_waiting_event = WHD_FALSE;
302 return WHD_SUCCESS;
303 }
304 else
305 {
306 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
307 }
308 }
309 }
310
311 if (whd_cdc_send_iovar(prim_ifp, CDC_GET, buffer, &response) != WHD_SUCCESS)
312 {
313 /* Note: We don't need to release the response packet since the iovar failed */
314 wait_for_interface = WHD_TRUE;
315 }
316 else
317 {
318 /* Check if the BSS is already UP, if so return */
319 uint32_t *data2 = (uint32_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response);
320 CHECK_PACKET_NULL(data2, WHD_NO_REGISTER_FUNCTION_POINTER);
321 *data2 = dtoh32 (*data2);
322 if (*data2 == (uint32_t)BSS_UP)
323 {
324 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
325 whd_wifi_set_ap_is_up(whd_driver, WHD_TRUE);
326 ap->is_waiting_event = WHD_FALSE;
327 return WHD_SUCCESS;
328 }
329 else
330 {
331 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
332 }
333 }
334
335 CHECK_RETURN(cy_rtos_init_semaphore(&ap->whd_wifi_sleep_flag, 1, 0) );
336
337 ap->is_waiting_event = WHD_TRUE;
338 /* Register for interested events */
339 CHECK_RETURN_WITH_SEMAPHORE(whd_management_set_event_handler(ifp, apsta_events, whd_handle_apsta_event,
340 NULL, &event_entry), &ap->whd_wifi_sleep_flag);
341 if (event_entry >= WHD_EVENT_HANDLER_LIST_SIZE)
342 {
343 WPRINT_WHD_DEBUG( ("Event handler registration failed for AP events in function %s and line %d\n",
344 __func__, __LINE__) );
345 return WHD_UNFINISHED;
346 }
347 ifp->event_reg_list[WHD_AP_EVENT_ENTRY] = event_entry;
348
349 if (wait_for_interface == WHD_TRUE)
350 {
351 CHECK_RETURN_WITH_SEMAPHORE(cy_rtos_get_semaphore(&ap->whd_wifi_sleep_flag, (uint32_t)10000,
352 WHD_FALSE), &ap->whd_wifi_sleep_flag);
353 }
354 ap->is_waiting_event = WHD_FALSE;
355
356 if (prim_ifp == ifp)
357 {
358 /* Set AP mode */
359 data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)4);
360 CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(data, &ap->whd_wifi_sleep_flag);
361 *data = 1; /* Turn on AP */
362 CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_AP, buffer, 0),
363 &ap->whd_wifi_sleep_flag);
364 }
365
366 if (NULL_MAC(ifp->mac_addr.octet) )
367 {
368 /* Change the AP MAC address to be different from STA MAC */
369 if ( (result = whd_wifi_get_mac_address(prim_ifp, &ifp->mac_addr) ) != WHD_SUCCESS )
370 {
371 WPRINT_WHD_INFO ( (" Get STA MAC address failed result=%" PRIu32 "\n", result) );
372 return result;
373 }
374 else
375 {
376 WPRINT_WHD_INFO ( (" Get STA MAC address success\n") );
377 }
378 }
379
380 if ( (result = whd_wifi_set_mac_address(ifp, ifp->mac_addr) ) != WHD_SUCCESS )
381 {
382 WPRINT_WHD_INFO ( (" Set AP MAC address failed result=%" PRIu32 "\n", result) );
383 return result;
384 }
385
386 /* Set the SSID */
387 data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)40, "bsscfg:" IOVAR_STR_SSID);
388 CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(data, &ap->whd_wifi_sleep_flag);
389 if (wlan_chip_id == 4334)
390 {
391 data[0] = htod32( (uint32_t)CHIP_AP_INTERFACE ); /* Set the bsscfg index */
392 }
393 else
394 {
395 data[0] = htod32(bss_index); /* Set the bsscfg index */
396 }
397 data[1] = htod32(ssid->length); /* Set the ssid length */
398 memcpy(&data[2], (uint8_t *)ssid->value, ssid->length);
399 if ( (wlan_chip_id == 43340) || (wlan_chip_id == 43342) )
400 {
401 CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0), &ap->whd_wifi_sleep_flag);
402 }
403 else
404 {
405 CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_iovar(prim_ifp, CDC_SET, buffer, 0), &ap->whd_wifi_sleep_flag);
406 }
407
408 /* Set the channel */
409 data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)4);
410 CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(data, &ap->whd_wifi_sleep_flag);
411 *data = htod32(channel);
412 CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_CHANNEL, buffer, 0),
413 &ap->whd_wifi_sleep_flag);
414
415 data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, "bsscfg:" IOVAR_STR_WSEC);
416 CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(data, &ap->whd_wifi_sleep_flag);
417 if ( (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) )
418 {
419 data[0] = htod32( (uint32_t)CHIP_AP_INTERFACE );
420 }
421 else
422 {
423 data[0] = htod32(bss_index);
424 }
425 if ( (auth_type & WPS_ENABLED) != 0 )
426 {
427 data[1] = htod32( (uint32_t)( (auth_type & (~WPS_ENABLED) ) | SES_OW_ENABLED ) );
428 }
429 else
430 {
431 data[1] = htod32( (uint32_t)auth_type & 0xFF );
432 }
433 CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_iovar(prim_ifp, CDC_SET, buffer, 0), &ap->whd_wifi_sleep_flag);
434 if (auth_type == WHD_SECURITY_WPA3_SAE)
435 {
436 auth_mfp = WL_MFP_REQUIRED;
437
438 }
439 else if (auth_type == WHD_SECURITY_WPA3_WPA2_PSK)
440 {
441 auth_mfp = WL_MFP_CAPABLE;
442 }
443 CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_MFP, auth_mfp) );
444
445 if (wlan_chip_id == 4334)
446 {
447 if (auth_type != WHD_SECURITY_OPEN)
448 {
449 wsec_pmk_t *psk;
450
451 /* Set the wpa auth */
452 data =
453 (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, "bsscfg:" IOVAR_STR_WPA_AUTH);
454 CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(data, &ap->whd_wifi_sleep_flag);
455 data[0] = htod32( (uint32_t)CHIP_AP_INTERFACE );
456 data[1] = htod32( (uint32_t)(auth_type == WHD_SECURITY_WPA_TKIP_PSK) ?
457 (WPA_AUTH_PSK) : (WPA2_AUTH_PSK | WPA_AUTH_PSK) );
458 CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_iovar(prim_ifp, CDC_SET, buffer, 0), &ap->whd_wifi_sleep_flag);
459
460 /* Set the passphrase */
461 psk = (wsec_pmk_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, sizeof(wsec_pmk_t) );
462 CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(psk, &ap->whd_wifi_sleep_flag);
463 memcpy(psk->key, security_key, key_length);
464 psk->key_len = htod16(key_length);
465 psk->flags = htod16( (uint16_t)WSEC_PASSPHRASE );
466 CHECK_RETURN(cy_rtos_delay_milliseconds(1) );
467 /* Delay required to allow radio firmware to be ready to receive PMK and avoid intermittent failure */
468 CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_WSEC_PMK, buffer, 0),
469 &ap->whd_wifi_sleep_flag);
470 }
471 }
472 else
473 {
474 if (auth_type != WHD_SECURITY_OPEN)
475 {
476 wsec_pmk_t *psk;
477
478 /* Set the wpa auth */
479 data =
480 (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, "bsscfg:" IOVAR_STR_WPA_AUTH);
481 CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(data, &ap->whd_wifi_sleep_flag);
482 if ( (wlan_chip_id == 43340) || (wlan_chip_id == 43342) )
483 {
484 data[0] = htod32( (uint32_t)CHIP_AP_INTERFACE );
485 }
486 else
487 {
488 data[0] = htod32(bss_index);
489 }
490 if ( (auth_type == WHD_SECURITY_WPA3_SAE) || (auth_type == WHD_SECURITY_WPA3_WPA2_PSK) )
491 {
492 data[1] =
493 htod32( (uint32_t)( (auth_type ==
494 WHD_SECURITY_WPA3_SAE) ? (WPA3_AUTH_SAE_PSK) : (WPA3_AUTH_SAE_PSK |
495 WPA2_AUTH_PSK) ) );
496 }
497 else
498 {
499 data[1] =
500 htod32( (uint32_t)(auth_type ==
501 WHD_SECURITY_WPA_TKIP_PSK) ? (WPA_AUTH_PSK) : (WPA2_AUTH_PSK | WPA_AUTH_PSK) );
502 }
503 if ( (wlan_chip_id == 43340) || (wlan_chip_id == 43342) )
504 {
505 CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0), &ap->whd_wifi_sleep_flag);
506 }
507 else
508 {
509 CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_iovar(prim_ifp, CDC_SET, buffer, 0),
510 &ap->whd_wifi_sleep_flag);
511 }
512 if ( (auth_type == WHD_SECURITY_WPA3_SAE) && (whd_driver->chip_info.fwcap_flags & (1 << WHD_FWCAP_SAE) ) )
513 {
514 whd_wifi_sae_password(ifp, security_key, key_length);
515 }
516 else
517 {
518 if ( (auth_type == WHD_SECURITY_WPA3_WPA2_PSK) &&
519 (whd_driver->chip_info.fwcap_flags & (1 << WHD_FWCAP_SAE) ) )
520 {
521 whd_wifi_sae_password(ifp, security_key, key_length);
522 }
523 /* Set the passphrase */
524 psk = (wsec_pmk_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, sizeof(wsec_pmk_t) );
525 CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(psk, &ap->whd_wifi_sleep_flag);
526 memcpy(psk->key, security_key, key_length);
527 psk->key_len = htod16(key_length);
528 psk->flags = htod16( (uint16_t)WSEC_PASSPHRASE );
529 CHECK_RETURN(cy_rtos_delay_milliseconds(1) );
530 /* Delay required to allow radio firmware to be ready to receive PMK and avoid intermittent failure */
531 CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_WSEC_PMK, buffer,
532 0), &ap->whd_wifi_sleep_flag);
533 }
534 }
535 }
536
537 /* Adjust PWE Loop Count(WPA3-R1 Compatibility Issue) */
538 if (auth_type & WPA3_SECURITY)
539 {
540 data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)4, IOVAR_STR_SAE_PWE_LOOP);
541 CHECK_IOCTL_BUFFER(data);
542 *data = htod32( (uint32_t)PWE_LOOP_COUNT );
543 if (whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) != WHD_SUCCESS)
544 {
545 WPRINT_WHD_DEBUG( ("Some chipsets might not support PWE_LOOP_CNT..Ignore result\n") );
546 }
547 }
548
549 /* Set the multicast transmission rate to 11 Mbps rather than the default 1 Mbps */
550 data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)4, IOVAR_STR_2G_MULTICAST_RATE);
551 CHECK_IOCTL_BUFFER(data);
552 *data = htod32( (uint32_t)RATE_SETTING_11_MBPS );
553 if ( (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) )
554 {
555 result = whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL);
556 whd_assert("start_ap: Failed to set multicast transmission rate\r\n", result == WHD_SUCCESS);
557 }
558 else
559 {
560 CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL), &ap->whd_wifi_sleep_flag);
561 }
562
563 return WHD_SUCCESS;
564 }
565
whd_wifi_start_ap(whd_interface_t ifp)566 uint32_t whd_wifi_start_ap(whd_interface_t ifp)
567 {
568 whd_buffer_t buffer;
569 uint32_t *data;
570 whd_ap_int_info_t *ap;
571 whd_interface_t prim_ifp;
572 whd_driver_t whd_driver;
573
574 CHECK_IFP_NULL(ifp);
575
576 whd_driver = ifp->whd_driver;
577
578 CHECK_DRIVER_NULL(whd_driver);
579
580 prim_ifp = whd_get_primary_interface(whd_driver);
581
582 if (prim_ifp == NULL)
583 {
584 return WHD_UNKNOWN_INTERFACE;
585 }
586
587 ap = &whd_driver->ap_info;
588 ap->is_waiting_event = WHD_TRUE;
589 data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, IOVAR_STR_BSS);
590 CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(data, &ap->whd_wifi_sleep_flag);
591 data[0] = htod32(ifp->bsscfgidx);
592 data[1] = htod32( (uint32_t)BSS_UP );
593 CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_iovar(prim_ifp, CDC_SET, buffer, 0), &ap->whd_wifi_sleep_flag);
594
595 /* Wait until AP is brought up */
596 CHECK_RETURN_WITH_SEMAPHORE(cy_rtos_get_semaphore(&ap->whd_wifi_sleep_flag, (uint32_t)10000,
597 WHD_FALSE), &ap->whd_wifi_sleep_flag);
598 ap->is_waiting_event = WHD_FALSE;
599
600 whd_wifi_set_ap_is_up(whd_driver, WHD_TRUE);
601 return WHD_SUCCESS;
602 }
603
whd_wifi_stop_ap(whd_interface_t ifp)604 uint32_t whd_wifi_stop_ap(whd_interface_t ifp)
605 {
606 uint32_t *data;
607 whd_buffer_t buffer;
608 whd_buffer_t response;
609 whd_result_t result;
610 whd_result_t result2;
611 whd_interface_t prim_ifp;
612 whd_driver_t whd_driver;
613 whd_ap_int_info_t *ap;
614
615 CHECK_IFP_NULL(ifp);
616
617 whd_driver = ifp->whd_driver;
618
619 CHECK_DRIVER_NULL(whd_driver);
620
621 ap = &whd_driver->ap_info;
622
623 prim_ifp = whd_get_primary_interface(whd_driver);
624
625 if (prim_ifp == NULL)
626 {
627 return WHD_UNKNOWN_INTERFACE;
628 }
629
630 /* Get Chip Number */
631 uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver);
632 /* Query bss state (does it exist? if so is it UP?) */
633 data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)4, IOVAR_STR_BSS);
634 CHECK_IOCTL_BUFFER(data);
635 *data = ifp->bsscfgidx;
636
637 result = whd_cdc_send_iovar(prim_ifp, CDC_GET, buffer, &response);
638 if (result == WHD_WLAN_NOTFOUND)
639 {
640 /* AP interface does not exist - i.e. it is down */
641 whd_wifi_set_ap_is_up(whd_driver, WHD_FALSE);
642 return WHD_SUCCESS;
643 }
644
645 CHECK_RETURN(result);
646
647 *data = dtoh32(*(uint32_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response) );
648 CHECK_PACKET_NULL(data, WHD_NO_REGISTER_FUNCTION_POINTER);
649 if (data[0] != (uint32_t)BSS_UP)
650 {
651 /* AP interface indicates it is not up - i.e. it is down */
652 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
653 whd_wifi_set_ap_is_up(whd_driver, WHD_FALSE);
654 return WHD_SUCCESS;
655 }
656
657 CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) );
658
659 ap->is_waiting_event = WHD_TRUE;
660 /* set BSS down */
661 data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, IOVAR_STR_BSS);
662 CHECK_IOCTL_BUFFER(data);
663 data[0] = htod32(ifp->bsscfgidx);
664 data[1] = htod32( (uint32_t)BSS_DOWN );
665 CHECK_RETURN(whd_cdc_send_iovar(prim_ifp, CDC_SET, buffer, 0) );
666
667 /* Wait until AP is brought down */
668 result = cy_rtos_get_semaphore(&ap->whd_wifi_sleep_flag, (uint32_t)10000, WHD_FALSE);
669 if (result != WHD_SUCCESS)
670 {
671 WPRINT_WHD_ERROR( ("Error getting a semaphore, %s failed at %d \n", __func__, __LINE__) );
672 goto sema_fail;
673 }
674
675 /* Disable AP mode only if AP is on primary interface */
676 if (prim_ifp == ifp)
677 {
678 data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)4);
679 CHECK_IOCTL_BUFFER(data);
680 *data = 0;
681 CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_AP, buffer, 0) );
682 if ( (wlan_chip_id != 43430) && (wlan_chip_id != 43439) &&
683 (wlan_chip_id != 43909) && (wlan_chip_id != 43907) &&
684 (wlan_chip_id != 54907) )
685 {
686 result = cy_rtos_get_semaphore(&ap->whd_wifi_sleep_flag, (uint32_t)10000, WHD_FALSE);
687 if (result != WHD_SUCCESS)
688 {
689 WPRINT_WHD_ERROR( ("Error getting a semaphore, %s failed at %d \n", __func__, __LINE__) );
690 goto sema_fail;
691 }
692 }
693 }
694
695 sema_fail:
696 ap->is_waiting_event = WHD_FALSE;
697 result2 = cy_rtos_deinit_semaphore(&ap->whd_wifi_sleep_flag);
698 if (result != WHD_SUCCESS)
699 {
700 WPRINT_WHD_ERROR( ("Error getting a semaphore, %s failed at %d \n", __func__, __LINE__) );
701 return result;
702 }
703 if (result2 != WHD_SUCCESS)
704 {
705 WPRINT_WHD_ERROR( ("Error deleting semaphore, %s failed at %d \n", __func__, __LINE__) );
706 return result2;
707 }
708
709 CHECK_RETURN(whd_wifi_deregister_event_handler(ifp, ifp->event_reg_list[WHD_AP_EVENT_ENTRY]) );
710 ifp->event_reg_list[WHD_AP_EVENT_ENTRY] = WHD_EVENT_NOT_REGISTERED;
711 whd_wifi_set_ap_is_up(whd_driver, WHD_FALSE);
712
713 ifp->role = WHD_INVALID_ROLE;
714 return WHD_SUCCESS;
715 }
716