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