1 /***************************************************************************/ /**
2  * @file
3  * @brief
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
7  *******************************************************************************
8  *
9  * SPDX-License-Identifier: Zlib
10  *
11  * The licensor of this software is Silicon Laboratories Inc.
12  *
13  * This software is provided 'as-is', without any express or implied
14  * warranty. In no event will the authors be held liable for any damages
15  * arising from the use of this software.
16  *
17  * Permission is granted to anyone to use this software for any purpose,
18  * including commercial applications, and to alter it and redistribute it
19  * freely, subject to the following restrictions:
20  *
21  * 1. The origin of this software must not be misrepresented; you must not
22  *    claim that you wrote the original software. If you use this software
23  *    in a product, an acknowledgment in the product documentation would be
24  *    appreciated but is not required.
25  * 2. Altered source versions must be plainly marked as such, and must not be
26  *    misrepresented as being the original software.
27  * 3. This notice may not be removed or altered from any source distribution.
28  *
29  ******************************************************************************/
30 #include "sl_wifi.h"
31 #include "sl_wifi_types.h"
32 #include "sl_wifi_device.h"
33 #include "sl_si91x_host_interface.h"
34 #include "sl_si91x_status.h"
35 #include "sl_si91x_types.h"
36 #include "sl_si91x_protocol_types.h"
37 #include "sl_si91x_driver.h"
38 #include "sl_rsi_utility.h"
39 #if defined(SLI_SI91X_SOCKETS)
40 #include "sl_si91x_socket_utility.h"
41 #endif
42 #include <stdint.h>
43 #include <string.h>
44 
45 #ifndef SL_NCP_DEFAULT_COMMAND_WAIT_TIME
46 #define SL_NCP_DEFAULT_COMMAND_WAIT_TIME 3000
47 #endif
48 
49 #ifdef SL_SI91X_SIDE_BAND_CRYPTO
50 #include "sl_si91x_driver.h"
51 #include "rsi_m4.h"
52 extern rsi_m4ta_desc_t crypto_desc[2];
53 #endif
54 
55 #ifdef SLI_SI91X_MCU_INTERFACE
56 #include "rsi_wisemcu_hardware_setup.h"
57 #endif
58 
59 #ifdef SLI_SI91X_OFFLOAD_NETWORK_STACK
60 #include "sl_net_si91x_integration_handler.h"
61 #else
62 
63 // This macro defines a handler for cleaning up resources.
64 #define SLI_NETWORK_CLEANUP_HANDLER() \
65   {                                   \
66   }
67 #endif
68 // Enterprise configuration command parameters
69 /*=======================================================================*/
70 
71 // Enterprise method ,should be one of among TLS, TTLS, FAST or PEAP
72 
73 #define SL_EAP_TLS_METHOD  "TLS"
74 #define SL_EAP_TTLS_METHOD "TTLS"
75 #define SL_EAP_FAST_METHOD "FAST"
76 #define SL_EAP_PEAP_METHOD "PEAP"
77 #define SL_EAP_LEAP_METHOD "LEAP"
78 
79 // This parameter is used to configure the module in Enterprise security mode
80 #define SL_EAP_INNER_METHOD "\"auth=MSCHAPV2\""
81 
82 // Private Key Password is required for encrypted private key, format is like "\"12345678\""
83 #define SL_DEFAULT_PRIVATE_KEY_PASSWORD ""
84 
85 #define JOIN_TIMEOUT 8000
86 
87 #define ALWAYS_ROAM                          1
88 #define NEVER_ROAM                           0
89 #define MAX_FLOW_ID                          7
90 #define MAX_WAKE_INTERVAL_EXPONENT           31
91 #define MAX_WAKE_INTERVAL_EXPONENT_TOLERANCE 31
92 #define MAX_WAKE_DURATION_UNIT               1
93 #define MAX_TWT_RETRY_LIMIT                  15
94 #define MIN_TWT_RETRY_INTERVAL               5
95 #define MAX_TWT_REQ_TYPE                     2
96 #define REQUEST_TWT                          0
97 #define SUGGEST_TWT                          1
98 #define DEMAND_TWT                           1
99 #define TWT_WAKE_DURATION_UNIT_1024TU        1024
100 #define TWT_WAKE_DURATION_UNIT_256TU         256
101 #define DEVICE_AVERAGE_THROUGHPUT            20000
102 #define MAX_TX_AND_RX_LATENCY_LIMIT          21600000
103 #define MAX_TWT_SUSPEND_DURATION             0x5265c00
104 #define ABSOLUTE_POWER_VALUE_TOGGLE          0x80
105 #define PASSIVE_SCAN_ENABLE                  BIT(7)
106 #define LP_CHAIN_ENABLE                      BIT(6)
107 #define QUICK_SCAN_ENABLE                    1
108 #define SCAN_RESULTS_TO_HOST                 2
109 #define MAX_2_4G_CHANNEL                     14
110 
111 /*========================================================================*/
112 // 11ax params
113 /*========================================================================*/
114 #define NOMINAL_PE                              2
115 #define DCM_ENABLE                              0
116 #define LDPC_ENABLE                             0
117 #define NG_CB_ENABLE                            0
118 #define NG_CB_VALUES                            0
119 #define UORA_ENABLE                             0
120 #define TRIGGER_RESP_IND                        0xF
121 #define IPPS_VALID_VALUE                        0
122 #define TX_ONLY_ON_AP_TRIG                      0
123 #define CONFIG_ER_SU                            0 // 0 - NO ER_SU support, 1 - Use ER_SU rates along with Non_ER_SU rates, 2 - Use ER_SU rates only
124 #define SLI_SI91X_ENABLE_TWT_FEATURE            1
125 #define SLI_SI91X_DISABLE_SU_BEAMFORMEE_SUPPORT 0
126 /*=======================================================================*/
127 extern bool device_initialized;
128 extern bool bg_enabled;
129 extern bool interface_is_up[SL_WIFI_MAX_INTERFACE_INDEX];
130 extern sl_wifi_interface_t default_interface;
131 static sl_wifi_advanced_scan_configuration_t advanced_scan_configuration     = { 0 };
132 static sl_wifi_advanced_client_configuration_t advanced_client_configuration = { 0 };
133 int32_t validate_datarate(sl_wifi_data_rate_t data_rate);
134 sl_status_t sl_wifi_get_associated_client_list(void *client_list_buffer, uint16_t buffer_length, uint32_t timeout);
135 static sl_wifi_client_info_response_t sli_si91x_client_info = { 0 };
136 
fill_join_request_security_using_encryption(sl_wifi_encryption_t encryption_mode,uint8_t * security_type)137 static sl_status_t fill_join_request_security_using_encryption(sl_wifi_encryption_t encryption_mode,
138                                                                uint8_t *security_type)
139 {
140   if (encryption_mode == SL_WIFI_CCMP_ENCRYPTION) {
141     *security_type |= BIT(7);
142   }
143   return SL_STATUS_OK;
144 }
145 
get_configured_join_request(sl_wifi_interface_t module_interface,const void * configuration,sl_si91x_join_request_t * join_request)146 static sl_status_t get_configured_join_request(sl_wifi_interface_t module_interface,
147                                                const void *configuration,
148                                                sl_si91x_join_request_t *join_request)
149 {
150   SL_WIFI_ARGS_CHECK_NULL_POINTER(configuration);
151   SL_WIFI_ARGS_CHECK_NULL_POINTER(join_request);
152   sl_status_t status = SL_STATUS_OK;
153 
154   if (module_interface & SL_WIFI_CLIENT_INTERFACE) {
155     // get join feature bitmap
156     status = sl_si91x_get_join_configuration(SL_WIFI_CLIENT_INTERFACE, &(join_request->join_feature_bitmap));
157     VERIFY_STATUS_AND_RETURN(status);
158 
159     sl_wifi_client_configuration_t *client_configuration = (sl_wifi_client_configuration_t *)configuration;
160 
161     // narrowing conversion from Enum of uint16 to uint8
162     get_saved_sl_wifi_rate(&join_request->data_rate);
163     memcpy(join_request->ssid, client_configuration->ssid.value, client_configuration->ssid.length);
164 
165     join_request->ssid_len      = client_configuration->ssid.length;
166     join_request->security_type = client_configuration->security;
167     if ((join_request->security_type == SL_WIFI_WPA3)
168         || (join_request->security_type == SL_WIFI_WPA3_ENTERPRISE)) { //check for WPA3 security
169       join_request->join_feature_bitmap |= SL_SI91X_JOIN_FEAT_MFP_CAPABLE_REQUIRED;
170     } else if ((join_request->security_type == SL_WIFI_WPA3_TRANSITION)
171                || join_request->security_type == SL_WIFI_WPA3_TRANSITION_ENTERPRISE) {
172       join_request->join_feature_bitmap &= ~(SL_SI91X_JOIN_FEAT_MFP_CAPABLE_REQUIRED);
173       join_request->join_feature_bitmap |= SL_SI91X_JOIN_FEAT_MFP_CAPABLE_ONLY;
174     } else if (join_request->security_type == SL_WIFI_WPA2 || join_request->security_type == SL_WIFI_WPA_WPA2_MIXED) {
175       join_request->join_feature_bitmap |= SL_SI91X_JOIN_FEAT_MFP_CAPABLE_ONLY;
176     }
177 
178     fill_join_request_security_using_encryption(client_configuration->encryption, &(join_request->security_type));
179 
180     join_request->vap_id          = SL_SI91X_WIFI_CLIENT_VAP_ID; // For Station vap_id will be 0
181     join_request->listen_interval = sl_si91x_get_listen_interval();
182     memcpy(join_request->join_bssid, client_configuration->bssid.octet, sizeof(join_request->join_bssid));
183   } else if (module_interface & SL_WIFI_AP_INTERFACE) {
184     // get join feature bitmap
185     status = sl_si91x_get_join_configuration(SL_WIFI_AP_INTERFACE, &(join_request->join_feature_bitmap));
186     VERIFY_STATUS_AND_RETURN(status);
187 
188     sl_wifi_ap_configuration_t *ap_configuration = (sl_wifi_ap_configuration_t *)configuration;
189 
190     get_saved_sl_wifi_rate(&join_request->data_rate);
191     memcpy(join_request->ssid, ap_configuration->ssid.value, ap_configuration->ssid.length);
192 
193     join_request->ssid_len      = ap_configuration->ssid.length;
194     join_request->security_type = ap_configuration->security;
195     join_request->vap_id        = 0;
196     if (join_request->security_type == SL_WIFI_WPA3) { //check for WPA3 security
197       join_request->join_feature_bitmap |= SL_SI91X_JOIN_FEAT_MFP_CAPABLE_REQUIRED;
198     } else if (join_request->security_type == SL_WIFI_WPA3_TRANSITION) { //check for WPA3 Tranisition security
199       join_request->join_feature_bitmap &= ~(SL_SI91X_JOIN_FEAT_MFP_CAPABLE_REQUIRED);
200       join_request->join_feature_bitmap |= SL_SI91X_JOIN_FEAT_MFP_CAPABLE_ONLY;
201     }
202 
203     if (get_opermode() == SL_SI91X_CONCURRENT_MODE) {
204       join_request->vap_id = SL_SI91X_WIFI_AP_VAP_ID; // For Concurrent mode AP vap_id should be 1 else 0.
205     }
206   } else {
207     return SL_STATUS_FAIL;
208   }
209 
210   sl_wifi_max_tx_power_t wifi_max_tx_power = get_max_tx_power();
211 
212   /* Within the 1-byte 'power_level' variable, bit 0 and bit 1 are allocated for encoding power level thresholds(low, mid, high).
213    * The Most Significant Bit serves as an indicator for toggling between absolute power value representation.
214    * When the MSB is set, the 'power_level' variable encodes the absolute power value using bits 2 through 6. */
215   join_request->power_level = (wifi_max_tx_power.join_tx_power << 2) | ABSOLUTE_POWER_VALUE_TOGGLE;
216 
217   return SL_STATUS_OK;
218 }
219 
220 /***************************************************************************/ /**
221  * @brief
222  *   to enable/disable ht capabilities
223  * @pre Pre-conditions:
224  * - @ref sl_wifi_init should be called before this API.
225  * @param[in] interface
226  *   Wi-Fi Access Point interface as identified by @ref sl_wifi_interface_t
227  *  @param[in] HtCaps
228  * HtCaps is identified by @ref sl_si91x_request_ap_high_throughput_capability_t
229  * @return
230  *   sl_status_t. See https://docs.silabs.com/gecko-platform/latest/platform-common/status for details.
231  * @note
232  *   Client interfaces are not supported.
233  ******************************************************************************/
sli_si91x_set_high_throughput_capability(sl_wifi_interface_t interface,sl_si91x_request_ap_high_throughput_capability_t HtCaps)234 static sl_status_t sli_si91x_set_high_throughput_capability(sl_wifi_interface_t interface,
235                                                             sl_si91x_request_ap_high_throughput_capability_t HtCaps)
236 {
237   if (!device_initialized) {
238     return SL_STATUS_NOT_INITIALIZED;
239   }
240 
241   if (interface & SL_WIFI_CLIENT_INTERFACE) {
242     return SL_STATUS_NOT_SUPPORTED;
243   }
244 
245   sl_status_t status = SL_STATUS_OK;
246   status             = sl_si91x_driver_send_command(RSI_WLAN_REQ_HT_CAPABILITIES,
247                                         SI91X_WLAN_CMD,
248                                         &HtCaps,
249                                         sizeof(sl_si91x_request_ap_high_throughput_capability_t),
250                                         SL_SI91X_WAIT_FOR(30100),
251                                         NULL,
252                                         NULL);
253   VERIFY_STATUS_AND_RETURN(status);
254   return status;
255 }
256 
sl_wifi_init(const sl_wifi_device_configuration_t * configuration,sl_wifi_device_context_t * device_context,sl_wifi_event_handler_t event_handler)257 sl_status_t sl_wifi_init(const sl_wifi_device_configuration_t *configuration,
258                          sl_wifi_device_context_t *device_context,
259                          sl_wifi_event_handler_t event_handler)
260 {
261   UNUSED_PARAMETER(device_context);
262 #ifdef SLI_SI91X_MCU_INTERFACE
263 #if defined(SLI_SI917)
264   sl_si91x_efuse_data_t efuse_data;
265 #endif
266 #endif
267   sl_status_t status = SL_STATUS_OK;
268   status             = sl_si91x_driver_init(configuration, event_handler);
269 #ifdef SL_SI91X_SIDE_BAND_CRYPTO
270   if (status == SL_STATUS_OK) {
271     uint32_t crypto_desc_ptr = (uint32_t)crypto_desc;
272     uint32_t *desc_ptr       = &crypto_desc_ptr;
273     status = sl_si91x_m4_ta_secure_handshake(SL_SI91X_ENABLE_SIDE_BAND, sizeof(uint32_t), (uint8_t *)desc_ptr, 0, NULL);
274   }
275 #endif
276 #ifdef SLI_SI91X_MCU_INTERFACE
277 #if defined(SLI_SI917)
278   if (status == SL_STATUS_OK) {
279     /*Getting PTE CRC value to distinguish firmware 17 and 18 boards.*/
280     sl_si91x_get_flash_efuse_data(&efuse_data, SL_SI91X_EFUSE_PTE_CRC);
281 
282     /*PTE FW version check.*/
283     if (efuse_data.pte_crc == FIRMWARE_17_PTE_CRC_VALUE) {
284       /* Enable Higher PWM RO Frequency Mode for PMU for FW17 boards*/
285       RSI_IPMU_Set_Higher_Pwm_Ro_Frequency_Mode_to_PMU();
286       /* Set the RETN_LDO voltage to 0.8V for FW17 boards*/
287       RSI_IPMU_Retn_Voltage_To_Default();
288     }
289   }
290 #endif
291 #endif
292   return status;
293 }
294 
sl_wifi_set_antenna(sl_wifi_interface_t interface,sl_wifi_antenna_t antenna)295 sl_status_t sl_wifi_set_antenna(sl_wifi_interface_t interface, sl_wifi_antenna_t antenna)
296 {
297   UNUSED_PARAMETER(interface);
298   sl_status_t status;
299   sl_si91x_antenna_select_t rsi_antenna = { 0 };
300 
301   if (!device_initialized) {
302     return SL_STATUS_NOT_INITIALIZED;
303   }
304 
305   if (!sl_wifi_is_interface_up(interface)) {
306     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
307   }
308 
309   // Antenna type
310   rsi_antenna.antenna_value = (antenna == SL_WIFI_ANTENNA_EXTERNAL) ? SL_WIFI_SELECT_EXTERNAL_ANTENNA
311                                                                     : SL_WIFI_SELECT_INTERNAL_ANTENNA;
312 
313   status = sl_si91x_driver_send_command(RSI_COMMON_REQ_ANTENNA_SELECT,
314                                         SI91X_COMMON_CMD,
315                                         &rsi_antenna,
316                                         sizeof(rsi_antenna),
317                                         SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
318                                         NULL,
319                                         NULL);
320   VERIFY_STATUS_AND_RETURN(status);
321   return status;
322 }
323 
sl_wifi_wait_for_scan_results(sl_wifi_scan_result_t ** scan_results,uint32_t max_scan_result_count)324 sl_status_t sl_wifi_wait_for_scan_results(sl_wifi_scan_result_t **scan_results, uint32_t max_scan_result_count)
325 {
326   UNUSED_PARAMETER(scan_results);
327   UNUSED_PARAMETER(max_scan_result_count);
328 
329 #ifdef SI91x_ENABLE_WAIT_ON_RESULTS
330   if (!device_initialized) {
331     return SL_STATUS_NOT_INITIALIZED;
332   }
333   sl_status_t status;
334   sl_wifi_buffer_t *buffer;
335   sl_si91x_packet_t *packet;
336 
337   status = sl_si91x_driver_wait_for_response(RSI_WLAN_RSP_SCAN, SL_SI91X_WAIT_FOR(3000));
338   VERIFY_STATUS_AND_RETURN(status);
339 
340   status = sl_si91x_host_remove_from_queue(SI91X_WLAN_RESPONSE_QUEUE, &buffer);
341   VERIFY_STATUS_AND_RETURN(status);
342 
343   packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
344   status = convert_and_save_firmware_status(get_si91x_frame_status(packet));
345   VERIFY_STATUS_AND_RETURN(status);
346 
347   if (packet->command == RSI_WLAN_RSP_SCAN) {
348     *scan_results = (sl_wifi_scan_result_t *)malloc(packet->length);
349     if (scan_results == NULL) {
350       sl_si91x_host_free_buffer(buffer);
351       return SL_STATUS_ALLOCATION_FAILED;
352     }
353     memcpy(*scan_results, packet->data, packet->length);
354   }
355   sl_si91x_host_free_buffer(buffer);
356 #endif
357 
358   return SL_STATUS_NOT_SUPPORTED;
359 }
360 
sl_wifi_start_scan(sl_wifi_interface_t interface,const sl_wifi_ssid_t * optional_ssid,const sl_wifi_scan_configuration_t * configuration)361 sl_status_t sl_wifi_start_scan(sl_wifi_interface_t interface,
362                                const sl_wifi_ssid_t *optional_ssid,
363                                const sl_wifi_scan_configuration_t *configuration)
364 {
365   sl_status_t status = SL_STATUS_FAIL;
366 
367   if (!device_initialized) {
368     return SL_STATUS_NOT_INITIALIZED;
369   }
370 
371   if (!sl_wifi_is_interface_up(interface)) {
372     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
373   }
374 
375   if (SL_WIFI_SCAN_TYPE_ADV_SCAN != configuration->type) {
376     sl_si91x_req_scan_t scan_request = { 0 };
377 
378     //! copying SSID & length
379     if (optional_ssid != NULL) {
380       memcpy(scan_request.ssid, optional_ssid->value, optional_ssid->length);
381     }
382 
383     if ((interface & SL_WIFI_2_4GHZ_INTERFACE) && (configuration->channel_bitmap_2g4 != 0xFFFF)) {
384       memcpy(&scan_request.channel_bit_map_2_4,
385              &configuration->channel_bitmap_2g4,
386              sizeof(scan_request.channel_bit_map_2_4));
387 
388       uint16_t channel_bitmap = configuration->channel_bitmap_2g4;
389       // Set channel, if only one channel is selected in channel_bitmap
390       // if channel is 0, scan on all channels.
391       if ((channel_bitmap > 0) && (0 == (channel_bitmap & (channel_bitmap - 1)))) {
392         for (uint8_t channel = 1; channel <= MAX_2_4G_CHANNEL; channel++) {
393           if (BIT((channel - 1)) == channel_bitmap) {
394             scan_request.channel[0] = channel;
395             break;
396           }
397         }
398       }
399     }
400 
401     if (configuration->type == SL_WIFI_SCAN_TYPE_PASSIVE) {
402       scan_request.pscan_bitmap[3] |= PASSIVE_SCAN_ENABLE;
403     }
404     if (configuration->lp_mode) {
405       scan_request.pscan_bitmap[3] |= LP_CHAIN_ENABLE;
406     }
407     sl_wifi_max_tx_power_t wifi_max_tx_power = get_max_tx_power();
408     // Within the 1-byte scan_feature_bimap variable, last 5 bits(bit 3 through bit 7) are allocated for
409     // encoding the transmit power during scan procedure.
410     scan_request.scan_feature_bitmap = (wifi_max_tx_power.scan_tx_power << 3);
411 
412     // Enable Quick Scan, if SSID and channel are available
413     // Quick Scan is disabled, if channel is 0
414     if ((optional_ssid != NULL) && (scan_request.channel[0] != 0)) {
415       scan_request.scan_feature_bitmap |= QUICK_SCAN_ENABLE;
416     }
417 
418     if (advanced_scan_configuration.active_channel_time != SL_WIFI_DEFAULT_ACTIVE_CHANNEL_SCAN_TIME) {
419       sl_status_t status = sl_si91x_configure_timeout(SL_SI91X_CHANNEL_ACTIVE_SCAN_TIMEOUT,
420                                                       advanced_scan_configuration.active_channel_time);
421       VERIFY_STATUS_AND_RETURN(status);
422     }
423 
424     if (SL_WIFI_SCAN_TYPE_EXTENDED == configuration->type) {
425       scan_request.scan_feature_bitmap |= SCAN_RESULTS_TO_HOST;
426     }
427     sli_wifi_flush_scan_results_database();
428 
429     status = sl_si91x_driver_send_command(RSI_WLAN_REQ_SCAN,
430                                           SI91X_WLAN_CMD,
431                                           &scan_request,
432                                           sizeof(scan_request),
433                                           SL_SI91X_RETURN_IMMEDIATELY,
434                                           NULL,
435                                           NULL);
436   } else {
437     sl_si91x_req_bg_scan_t scan_request = { 0 };
438 
439     scan_request.bgscan_enable            = SI91X_BG_SCAN_ENABLE;
440     scan_request.enable_instant_bgscan    = advanced_scan_configuration.enable_instant_scan;
441     scan_request.passive_scan_duration    = advanced_scan_configuration.passive_channel_time;
442     scan_request.active_scan_duration     = advanced_scan_configuration.active_channel_time;
443     scan_request.bgscan_periodicity       = (uint16_t)configuration->periodic_scan_interval;
444     scan_request.rssi_tolerance_threshold = (uint16_t)advanced_scan_configuration.trigger_level_change;
445     scan_request.bgscan_threshold         = -1 * advanced_scan_configuration.trigger_level;
446     scan_request.multi_probe              = advanced_scan_configuration.enable_multi_probe;
447 
448     status = sl_si91x_driver_send_command(RSI_WLAN_REQ_BG_SCAN,
449                                           SI91X_WLAN_CMD,
450                                           &scan_request,
451                                           sizeof(sl_si91x_req_bg_scan_t),
452                                           SL_SI91X_RETURN_IMMEDIATELY,
453                                           NULL,
454                                           NULL);
455   }
456 
457   VERIFY_STATUS_AND_RETURN(status);
458   return status;
459 }
460 
sl_wifi_get_stored_scan_results(sl_wifi_interface_t interface,sl_wifi_extended_scan_result_parameters_t * extended_scan_parameters)461 sl_status_t sl_wifi_get_stored_scan_results(sl_wifi_interface_t interface,
462                                             sl_wifi_extended_scan_result_parameters_t *extended_scan_parameters)
463 {
464   return sli_wifi_get_stored_scan_results(interface, extended_scan_parameters);
465 }
466 
sl_wifi_connect(sl_wifi_interface_t interface,const sl_wifi_client_configuration_t * ap,uint32_t timeout_ms)467 sl_status_t sl_wifi_connect(sl_wifi_interface_t interface,
468                             const sl_wifi_client_configuration_t *ap,
469                             uint32_t timeout_ms)
470 {
471   sl_status_t status;
472   sl_si91x_req_psk_t psk_request;
473   sl_si91x_req_eap_config_t eap_req = { 0 };
474   sl_si91x_join_request_t join_request;
475   sl_wifi_buffer_t *buffer         = NULL;
476   sl_si91x_packet_t *packet        = NULL;
477   sl_si91x_req_scan_t scan_request = { 0 };
478   uint8_t uid_len                  = 0;
479   uint8_t psk_len                  = 0;
480   uint8_t key_len                  = 0;
481   sl_wifi_credential_t cred        = { 0 };
482 
483   if (!device_initialized) {
484     return SL_STATUS_NOT_INITIALIZED;
485   }
486 
487   if (interface & SL_WIFI_AP_INTERFACE) {
488     return SL_STATUS_NOT_SUPPORTED;
489   }
490 
491   if (!sl_wifi_is_interface_up(interface)) {
492     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
493   }
494 
495   SL_WIFI_ARGS_CHECK_NULL_POINTER(ap);
496   memset(&scan_request, 0, sizeof(scan_request));
497   //! copying SSID & length
498   if (ap->ssid.length > 0) {
499     memcpy(scan_request.ssid, ap->ssid.value, ap->ssid.length);
500   } else {
501     return SL_STATUS_INVALID_PARAMETER;
502   }
503 
504   // Configure channel bitmap for selective channel scan
505 
506   if ((interface & SL_WIFI_CLIENT_2_4GHZ_INTERFACE) && (ap->channel_bitmap.channel_bitmap_2_4 > 0)) {
507     memcpy(&scan_request.channel_bit_map_2_4,
508            &ap->channel_bitmap.channel_bitmap_2_4,
509            sizeof(scan_request.channel_bit_map_2_4));
510   }
511 
512   if ((interface & SL_WIFI_CLIENT_5GHZ_INTERFACE) && (ap->channel_bitmap.channel_bitmap_5 > 0)) {
513     memcpy(&scan_request.channel_bit_map_5,
514            &ap->channel_bitmap.channel_bitmap_5,
515            sizeof(scan_request.channel_bit_map_5));
516   }
517 
518   sl_wifi_max_tx_power_t wifi_max_tx_power = get_max_tx_power();
519   // Within the 1-byte scan_feature_bimap variable, last 5 bits(bit 3 through bit 7) are allocated for
520   // encoding the transmit power during scan procedure.
521   scan_request.scan_feature_bitmap = (wifi_max_tx_power.scan_tx_power << 3);
522 
523   if (advanced_scan_configuration.active_channel_time != SL_WIFI_DEFAULT_ACTIVE_CHANNEL_SCAN_TIME) {
524     sl_status_t status =
525       sl_si91x_configure_timeout(SL_SI91X_CHANNEL_ACTIVE_SCAN_TIMEOUT, advanced_scan_configuration.active_channel_time);
526     VERIFY_STATUS_AND_RETURN(status);
527   }
528   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_SCAN,
529                                         SI91X_WLAN_CMD,
530                                         &scan_request,
531                                         sizeof(scan_request),
532                                         SL_SI91X_WAIT_FOR(60000),
533                                         NULL,
534                                         NULL);
535 
536   VERIFY_STATUS_AND_RETURN(status);
537 
538   if ((SL_WIFI_WPA_ENTERPRISE == ap->security) || (SL_WIFI_WPA2_ENTERPRISE == ap->security)
539       || (SL_WIFI_WPA3_ENTERPRISE == ap->security) || (SL_WIFI_WPA3_TRANSITION_ENTERPRISE == ap->security)) {
540     memset(&eap_req, 0, sizeof(eap_req));
541     eap_req.user_identity[0] = '"';
542     eap_req.password[0]      = '"';
543 
544     status = sl_si91x_host_get_credentials(ap->credential_id, SL_WIFI_EAP_CREDENTIAL, &cred);
545     VERIFY_STATUS_AND_RETURN(status);
546 
547     memcpy(&(eap_req.user_identity[1]), cred.eap.username, 63);
548     memcpy(&(eap_req.password[1]), cred.eap.password, 127);
549     uid_len                            = strlen((char *)eap_req.user_identity);
550     psk_len                            = strlen((char *)eap_req.password);
551     eap_req.user_identity[uid_len]     = '"';
552     eap_req.password[psk_len]          = '"';
553     eap_req.user_identity[uid_len + 1] = 0;
554     eap_req.password[psk_len + 1]      = 0;
555 
556     // copy enterprise configuration data
557     if (SL_WIFI_EAP_TLS_ENCRYPTION == ap->encryption) {
558       strcpy((char *)eap_req.eap_method, SL_EAP_TLS_METHOD);
559     } else if (SL_WIFI_EAP_TTLS_ENCRYPTION == ap->encryption) {
560       strcpy((char *)eap_req.eap_method, SL_EAP_TTLS_METHOD);
561     } else if (SL_WIFI_EAP_FAST_ENCRYPTION == ap->encryption) {
562       strcpy((char *)eap_req.eap_method, SL_EAP_FAST_METHOD);
563     } else if (SL_WIFI_PEAP_MSCHAPV2_ENCRYPTION == ap->encryption) {
564       strcpy((char *)eap_req.eap_method, SL_EAP_PEAP_METHOD);
565     } else if (SL_WIFI_EAP_LEAP_ENCRYPTION == ap->encryption) {
566       strcpy((char *)eap_req.eap_method, SL_EAP_LEAP_METHOD);
567     } else {
568       return SL_STATUS_WIFI_INVALID_ENCRYPTION_METHOD;
569     }
570 
571     strcpy((char *)eap_req.inner_method, SL_EAP_INNER_METHOD);
572     memcpy(eap_req.okc_enable, &cred.eap.eap_flags, sizeof(cred.eap.eap_flags));
573 
574     key_len = strlen((const char *)cred.eap.certificate_key);
575     if ((key_len > 0)) {
576       eap_req.private_key_password[0] = '"';
577       strcpy((char *)eap_req.private_key_password, (const char *)cred.eap.certificate_key);
578       eap_req.private_key_password[key_len + 1] = '"';
579     } else {
580       strcpy((char *)eap_req.private_key_password, SL_DEFAULT_PRIVATE_KEY_PASSWORD);
581     }
582 
583     status = sl_si91x_driver_send_command(RSI_WLAN_REQ_EAP_CONFIG,
584                                           SI91X_WLAN_CMD,
585                                           &eap_req,
586                                           sizeof(eap_req),
587                                           SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
588                                           NULL,
589                                           NULL);
590     VERIFY_STATUS_AND_RETURN(status);
591   } else if ((SL_WIFI_WPA == ap->security) || (SL_WIFI_WPA2 == ap->security) || (SL_WIFI_WPA_WPA2_MIXED == ap->security)
592              || (SL_WIFI_WPA3 == ap->security) || (SL_WIFI_WPA3_TRANSITION == ap->security)) {
593 
594     memset(&psk_request, 0, sizeof(psk_request));
595     status = sl_si91x_host_get_credentials(ap->credential_id, SL_WIFI_PSK_CREDENTIAL, &cred);
596     VERIFY_STATUS_AND_RETURN(status);
597     psk_request.type = cred.type == SL_WIFI_PSK_CREDENTIAL ? 1 : 2;
598     memcpy(psk_request.psk_or_pmk, cred.pmk.value, SL_WIFI_MAX_PMK_LENGTH);
599 
600     status = sl_si91x_driver_send_command(RSI_WLAN_REQ_HOST_PSK,
601                                           SI91X_WLAN_CMD,
602                                           &psk_request,
603                                           sizeof(psk_request),
604                                           SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
605                                           NULL,
606                                           NULL);
607     VERIFY_STATUS_AND_RETURN(status);
608   } else if (SL_WIFI_WEP == ap->security) {
609     return SL_STATUS_NOT_SUPPORTED;
610   } else if (SL_WIFI_OPEN != ap->security) {
611     return SL_STATUS_WIFI_UNKNOWN_SECURITY_TYPE;
612   }
613 
614   memset(&join_request, 0, sizeof(join_request));
615 
616   status = get_configured_join_request(SL_WIFI_CLIENT_INTERFACE, ap, &join_request);
617 
618   VERIFY_STATUS_AND_RETURN(status);
619 
620   status =
621     sl_si91x_driver_send_command(RSI_WLAN_REQ_JOIN,
622                                  SI91X_WLAN_CMD,
623                                  &join_request,
624                                  sizeof(join_request),
625                                  timeout_ms ? SL_SI91X_WAIT_FOR_RESPONSE(timeout_ms) : SL_SI91X_RETURN_IMMEDIATELY,
626                                  NULL,
627                                  &buffer);
628 
629   if (timeout_ms != 0 && status != SL_STATUS_OK) {
630     if (buffer != NULL) {
631       sl_si91x_host_free_buffer(buffer);
632     }
633     sl_status_t temp_status = sl_si91x_driver_send_command(RSI_WLAN_REQ_INIT,
634                                                            SI91X_WLAN_CMD,
635                                                            NULL,
636                                                            0,
637                                                            SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
638                                                            NULL,
639                                                            NULL);
640     VERIFY_STATUS_AND_RETURN(temp_status);
641   }
642 
643   VERIFY_STATUS_AND_RETURN(status);
644 
645   packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
646 
647   if (packet->data[0] != 'C') {
648     sl_si91x_host_free_buffer(buffer);
649     return SL_STATUS_NOT_AVAILABLE;
650   }
651 
652   sl_si91x_host_free_buffer(buffer);
653   return SL_STATUS_OK;
654 }
655 
sl_wifi_set_advanced_client_configuration(sl_wifi_interface_t interface,const sl_wifi_advanced_client_configuration_t * configuration)656 sl_status_t sl_wifi_set_advanced_client_configuration(sl_wifi_interface_t interface,
657                                                       const sl_wifi_advanced_client_configuration_t *configuration)
658 {
659   if (!device_initialized) {
660     return SL_STATUS_NOT_INITIALIZED;
661   }
662 
663   if (interface & SL_WIFI_AP_INTERFACE) {
664     return SL_STATUS_NOT_SUPPORTED;
665   }
666 
667   sl_si91x_rejoin_params_t rejoin_request = { .max_retry_attempts      = configuration->max_retry_attempts,
668                                               .scan_interval           = configuration->scan_interval,
669                                               .beacon_missed_count     = configuration->beacon_missed_count,
670                                               .first_time_retry_enable = configuration->first_time_retry_enable };
671 
672   if (rejoin_request.beacon_missed_count < 40) {
673     SL_DEBUG_LOG("\r\nBeacon Missed Count minimum value should be 40, Updating to the minimum value.\r\n");
674     rejoin_request.beacon_missed_count = 40;
675   }
676 
677   sl_status_t status = sl_si91x_driver_send_command(RSI_WLAN_REQ_REJOIN_PARAMS,
678                                                     SI91X_WLAN_CMD,
679                                                     &rejoin_request,
680                                                     sizeof(rejoin_request),
681                                                     SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
682                                                     NULL,
683                                                     NULL);
684   VERIFY_STATUS_AND_RETURN(status);
685 
686   memcpy(&advanced_client_configuration, configuration, sizeof(sl_wifi_advanced_client_configuration_t));
687 
688   return status;
689 }
690 
sl_wifi_get_signal_strength(sl_wifi_interface_t interface,int32_t * rssi)691 sl_status_t sl_wifi_get_signal_strength(sl_wifi_interface_t interface, int32_t *rssi)
692 {
693   sl_status_t status;
694   sl_wifi_buffer_t *buffer = NULL;
695 
696   if (!device_initialized) {
697     return SL_STATUS_NOT_INITIALIZED;
698   }
699 
700   SL_VERIFY_POINTER_OR_RETURN(rssi, SL_STATUS_WIFI_NULL_PTR_ARG);
701 
702   if (interface & SL_WIFI_AP_INTERFACE) {
703     return SL_STATUS_NOT_SUPPORTED;
704   }
705 
706   if (!sl_wifi_is_interface_up(interface)) {
707     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
708   }
709 
710   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_RSSI,
711                                         SI91X_WLAN_CMD,
712                                         NULL,
713                                         0,
714                                         SL_SI91X_WAIT_FOR_RESPONSE(15000),
715                                         NULL,
716                                         &buffer);
717   if ((status != SL_STATUS_OK) && (buffer != NULL)) {
718     sl_si91x_host_free_buffer(buffer);
719   }
720   VERIFY_STATUS_AND_RETURN(status);
721 
722   sl_si91x_packet_t *packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
723   *rssi                     = -(packet->data[0]);
724   sl_si91x_host_free_buffer(buffer);
725   return SL_STATUS_OK;
726 }
727 
sl_wifi_get_sta_tsf(sl_wifi_interface_t interface,sl_wifi_tsf64_t * tsf)728 sl_status_t sl_wifi_get_sta_tsf(sl_wifi_interface_t interface, sl_wifi_tsf64_t *tsf)
729 {
730   sl_status_t status;
731   sl_wifi_buffer_t *buffer = NULL;
732 
733   if (!device_initialized) {
734     return SL_STATUS_NOT_INITIALIZED;
735   }
736 
737   SL_VERIFY_POINTER_OR_RETURN(tsf, SL_STATUS_WIFI_NULL_PTR_ARG);
738 
739   if (interface & SL_WIFI_AP_INTERFACE) {
740     return SL_STATUS_NOT_SUPPORTED;
741   }
742 
743   if (!sl_wifi_is_interface_up(interface)) {
744     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
745   }
746 
747   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_TSF,
748                                         SI91X_WLAN_CMD,
749                                         NULL,
750                                         0,
751                                         SL_SI91X_WAIT_FOR_RESPONSE(15000),
752                                         NULL,
753                                         &buffer);
754   if ((status != SL_STATUS_OK) && (buffer != NULL)) {
755     sl_si91x_host_free_buffer(buffer);
756   }
757   VERIFY_STATUS_AND_RETURN(status);
758 
759   sl_si91x_packet_t *packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
760   memcpy(tsf, packet->data, packet->length);
761   sl_si91x_host_free_buffer(buffer);
762   return SL_STATUS_OK;
763 }
764 
sl_wifi_set_mac_address(sl_wifi_interface_t interface,const sl_mac_address_t * mac_address)765 sl_status_t sl_wifi_set_mac_address(sl_wifi_interface_t interface, const sl_mac_address_t *mac_address)
766 {
767   UNUSED_PARAMETER(interface);
768 
769   SL_VERIFY_POINTER_OR_RETURN(mac_address, SL_STATUS_NULL_POINTER);
770 
771   sl_status_t status = sl_si91x_driver_send_command(RSI_WLAN_REQ_SET_MAC_ADDRESS,
772                                                     SI91X_WLAN_CMD,
773                                                     mac_address,
774                                                     sizeof(sl_mac_address_t),
775                                                     SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
776                                                     NULL,
777                                                     NULL);
778   VERIFY_STATUS_AND_RETURN(status);
779   return SL_STATUS_OK;
780 }
781 
sl_wifi_get_mac_address(sl_wifi_interface_t interface,sl_mac_address_t * mac)782 sl_status_t sl_wifi_get_mac_address(sl_wifi_interface_t interface, sl_mac_address_t *mac)
783 {
784   sl_status_t status;
785   sl_wifi_buffer_t *buffer = NULL;
786 
787   SL_WIFI_ARGS_CHECK_NULL_POINTER(mac);
788 
789   if (!device_initialized) {
790     return SL_STATUS_NOT_INITIALIZED;
791   }
792 
793   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_MAC_ADDRESS,
794                                         SI91X_WLAN_CMD,
795                                         NULL,
796                                         0,
797                                         SL_SI91X_WAIT_FOR_RESPONSE(15000),
798                                         NULL,
799                                         &buffer);
800   if ((status != SL_STATUS_OK) && (buffer != NULL)) {
801     sl_si91x_host_free_buffer(buffer);
802   }
803   VERIFY_STATUS_AND_RETURN(status);
804 
805   sl_si91x_packet_t *packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
806   if (packet->length > 0) {
807     // In Concurrent mode, for Client Interface, mac address will be at offset 0
808     uint8_t mac_address_offset = 0;
809     if ((SL_SI91X_CONCURRENT_MODE == get_opermode()) && (SL_WIFI_AP_INTERFACE == interface)) {
810       // In Concurrent mode, for AP Interface, mac address will be at offset 6
811       mac_address_offset = sizeof(sl_mac_address_t);
812     }
813     memcpy(mac->octet, packet->data + mac_address_offset, sizeof(*mac));
814   }
815   sl_si91x_host_free_buffer(buffer);
816   return SL_STATUS_OK;
817 }
818 
sl_wifi_set_channel(sl_wifi_interface_t interface,sl_wifi_channel_t channel)819 sl_status_t sl_wifi_set_channel(sl_wifi_interface_t interface, sl_wifi_channel_t channel)
820 {
821   UNUSED_PARAMETER(channel);
822   if (!device_initialized) {
823     return SL_STATUS_NOT_INITIALIZED;
824   }
825 
826   if (!sl_wifi_is_interface_up(interface)) {
827     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
828   }
829 
830   // Firmware doesn't support to change the channel of a running Access Point interface.
831   return SL_STATUS_NOT_SUPPORTED;
832 }
833 
sl_wifi_get_channel(sl_wifi_interface_t interface,sl_wifi_channel_t * channel_info)834 sl_status_t sl_wifi_get_channel(sl_wifi_interface_t interface, sl_wifi_channel_t *channel_info)
835 {
836   sl_status_t status             = SL_STATUS_FAIL;
837   sl_wifi_buffer_t *buffer       = NULL;
838   rsi_wlan_cmd_request_t command = 0;
839 
840   if (!device_initialized) {
841     return SL_STATUS_NOT_INITIALIZED;
842   }
843   if (!sl_wifi_is_interface_up(interface)) {
844     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
845   }
846 
847   if ((interface == SL_WIFI_CLIENT_2_4GHZ_INTERFACE) || (interface == SL_WIFI_CLIENT_5GHZ_INTERFACE))
848     command = RSI_WLAN_REQ_QUERY_NETWORK_PARAMS;
849   else if ((interface == SL_WIFI_AP_2_4GHZ_INTERFACE) || (interface == SL_WIFI_AP_5GHZ_INTERFACE))
850     command = RSI_WLAN_REQ_QUERY_GO_PARAMS;
851 
852   status = sl_si91x_driver_send_command(command,
853                                         SI91X_WLAN_CMD,
854                                         NULL,
855                                         0,
856                                         SL_SI91X_WAIT_FOR_RESPONSE(SL_SI91X_GET_CHANNEL_TIMEOUT),
857                                         NULL,
858                                         &buffer);
859   if ((status != SL_STATUS_OK) && (buffer != NULL)) {
860     sl_si91x_host_free_buffer(buffer);
861   }
862   VERIFY_STATUS_AND_RETURN(status);
863 
864   sl_si91x_packet_t *packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
865 
866   switch (interface) {
867     case SL_WIFI_CLIENT_2_4GHZ_INTERFACE: {
868       channel_info->channel = ((sl_si91x_network_params_response_t *)packet->data)->channel_number;
869       channel_info->band    = SL_WIFI_BAND_2_4GHZ;
870       break;
871     }
872     case SL_WIFI_AP_2_4GHZ_INTERFACE: {
873       memcpy(&channel_info->channel, ((sl_si91x_client_info_response *)packet->data)->channel_number, 2);
874       channel_info->band = SL_WIFI_BAND_2_4GHZ;
875       break;
876     }
877     default:
878       break;
879   }
880 
881   sl_si91x_host_free_buffer(buffer);
882   return status;
883 }
884 
885 /*
886  * This API doesn't have any affect if it is called after connect/start ap.
887  */
sl_wifi_set_max_tx_power(sl_wifi_interface_t interface,sl_wifi_max_tx_power_t max_tx_power)888 sl_status_t sl_wifi_set_max_tx_power(sl_wifi_interface_t interface, sl_wifi_max_tx_power_t max_tx_power)
889 {
890   if (!device_initialized) {
891     return SL_STATUS_NOT_INITIALIZED;
892   }
893 
894   if (
895     (interface & SL_WIFI_CLIENT_INTERFACE) // For the client interface, it’s necessary to check if the interface is up. However, for the AP interface, this check isn’t required since this API will be called before starting the AP.
896     && (!sl_wifi_is_interface_up(interface))) {
897     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
898   }
899 
900   uint8_t max_scan_tx_power = max_tx_power.scan_tx_power;
901   uint8_t max_join_tx_power = max_tx_power.join_tx_power;
902 
903   if ((max_scan_tx_power < 1 || max_scan_tx_power > 31) || (max_join_tx_power < 1 || max_join_tx_power > 31)) {
904     return SL_STATUS_INVALID_PARAMETER;
905   }
906 
907   save_max_tx_power(max_scan_tx_power, max_join_tx_power);
908   return SL_STATUS_OK;
909 }
910 
sl_wifi_get_max_tx_power(sl_wifi_interface_t interface,sl_wifi_max_tx_power_t * max_tx_power)911 sl_status_t sl_wifi_get_max_tx_power(sl_wifi_interface_t interface, sl_wifi_max_tx_power_t *max_tx_power)
912 {
913   if (!device_initialized) {
914     return SL_STATUS_NOT_INITIALIZED;
915   }
916 
917   if (!sl_wifi_is_interface_up(interface)) {
918     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
919   }
920 
921   SL_WIFI_ARGS_CHECK_NULL_POINTER(max_tx_power);
922 
923   *max_tx_power = get_max_tx_power();
924 
925   return SL_STATUS_OK;
926 }
927 
sl_wifi_start_ap(sl_wifi_interface_t interface,const sl_wifi_ap_configuration_t * configuration)928 sl_status_t sl_wifi_start_ap(sl_wifi_interface_t interface, const sl_wifi_ap_configuration_t *configuration)
929 {
930   sl_status_t status                   = SL_STATUS_OK;
931   sl_wifi_buffer_t *rx_buffer          = NULL;
932   sl_si91x_packet_t *join_response     = NULL;
933   sl_si91x_ap_config_request request   = { 0 };
934   sl_si91x_join_request_t join_request = { 0 };
935   sl_wifi_credential_t cred            = { 0 };
936 
937   if (!device_initialized) {
938     return SL_STATUS_NOT_INITIALIZED;
939   }
940 
941   memcpy(request.ssid, configuration->ssid.value, configuration->ssid.length);
942   request.security_type = configuration->security;
943 
944   //This encryption convertions is only required in access point mode
945   status = convert_sl_wifi_to_sl_si91x_encryption(configuration->encryption, &request.encryption_mode);
946   VERIFY_STATUS_AND_RETURN(status);
947 
948   //Configures TDI[7-4] value here
949   if ((configuration->security == SL_WIFI_WPA3) || (configuration->security == SL_WIFI_WPA3_TRANSITION)) {
950     request.encryption_mode |= configuration->tdi_flags & 0xF0;
951   }
952   status = sl_si91x_host_get_credentials(configuration->credential_id, SL_WIFI_PSK_CREDENTIAL, &cred);
953   VERIFY_STATUS_AND_RETURN(status);
954 
955   memcpy(request.psk, cred.psk.value, sizeof(request.psk));
956 
957   request.channel         = configuration->channel.channel;
958   request.beacon_interval = configuration->beacon_interval;
959   request.dtim_period     = configuration->dtim_beacon_count;
960   request.max_sta_support = configuration->maximum_clients;
961   if (configuration->keepalive_type) {
962     request.ap_keepalive_type   = configuration->keepalive_type;
963     request.ap_keepalive_period = configuration->client_idle_timeout;
964   }
965   if (configuration->beacon_stop) {
966     // Using a free bit in ap_keepalive_type since there are no available bits in join feature bitmap.
967     request.ap_keepalive_type |= BIT(2);
968   }
969 
970   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_AP_CONFIGURATION,
971                                         SI91X_WLAN_CMD,
972                                         &request,
973                                         sizeof(request),
974                                         SL_SI91X_WAIT_FOR(15000),
975                                         NULL,
976                                         NULL);
977   VERIFY_STATUS_AND_RETURN(status);
978 
979   if (configuration->is_11n_enabled) {
980     sl_si91x_request_ap_high_throughput_capability_t htcaps = { 0 };
981     htcaps.mode_11n_enable                                  = true;
982     htcaps.ht_caps_bitmap = SL_WIFI_HT_CAPS_NUM_RX_STBC | SL_WIFI_HT_CAPS_SHORT_GI_20MHZ | SL_WIFI_HT_CAPS_GREENFIELD_EN
983                             | SL_WIFI_HT_CAPS_SUPPORT_CH_WIDTH;
984     status = sli_si91x_set_high_throughput_capability(SL_WIFI_AP_INTERFACE, htcaps);
985     VERIFY_STATUS_AND_RETURN(status);
986   }
987 
988   status = get_configured_join_request(SL_WIFI_AP_INTERFACE, configuration, &join_request);
989   VERIFY_STATUS_AND_RETURN(status);
990 
991   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_JOIN,
992                                         SI91X_WLAN_CMD,
993                                         &join_request,
994                                         sizeof(join_request),
995                                         SL_SI91X_WAIT_FOR_RESPONSE(15000),
996                                         NULL,
997                                         &rx_buffer);
998   if ((status != SL_STATUS_OK) && (rx_buffer != NULL)) {
999     sl_si91x_host_free_buffer(rx_buffer);
1000   }
1001   VERIFY_STATUS_AND_RETURN(status);
1002 
1003   join_response = sl_si91x_host_get_buffer_data(rx_buffer, 0, NULL);
1004 
1005   if (join_response->data[0] != 'G') {
1006     sl_si91x_host_free_buffer(rx_buffer);
1007     return SL_STATUS_NOT_AVAILABLE;
1008   }
1009 
1010   save_ap_configuration(configuration);
1011   if (interface == SL_WIFI_AP_2_4GHZ_INTERFACE || interface == SL_WIFI_AP_INTERFACE)
1012     interface_is_up[SL_WIFI_AP_2_4GHZ_INTERFACE_INDEX] = true;
1013   else if (interface == SL_WIFI_AP_5GHZ_INTERFACE)
1014     interface_is_up[SL_WIFI_AP_5GHZ_INTERFACE_INDEX] = true;
1015 
1016   sl_si91x_host_free_buffer(rx_buffer);
1017   return SL_STATUS_OK;
1018 }
1019 
sl_wifi_get_pairwise_master_key(sl_wifi_interface_t interface,const uint8_t type,const sl_wifi_ssid_t * ssid,const char * pre_shared_key,uint8_t * pairwise_master_key)1020 sl_status_t sl_wifi_get_pairwise_master_key(sl_wifi_interface_t interface,
1021                                             const uint8_t type,
1022                                             const sl_wifi_ssid_t *ssid,
1023                                             const char *pre_shared_key,
1024                                             uint8_t *pairwise_master_key)
1025 {
1026   UNUSED_PARAMETER(interface);
1027   sl_status_t status;
1028   sl_wifi_buffer_t *buffer                       = NULL;
1029   sl_si91x_req_psk_t pairwise_master_key_request = { 0 };
1030 
1031   if (pairwise_master_key == NULL) {
1032     return SL_STATUS_WIFI_NULL_PTR_ARG;
1033   }
1034 
1035   pairwise_master_key_request.type = type;
1036   memcpy(pairwise_master_key_request.psk_or_pmk, pre_shared_key, strlen(pre_shared_key));
1037   memcpy(pairwise_master_key_request.ap_ssid, ssid->value, ssid->length);
1038 
1039   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_HOST_PSK,
1040                                         SI91X_WLAN_CMD,
1041                                         &pairwise_master_key_request,
1042                                         sizeof(sl_si91x_req_psk_t),
1043                                         SL_SI91X_WAIT_FOR_RESPONSE(35000),
1044                                         NULL,
1045                                         &buffer);
1046   if ((status != SL_STATUS_OK) && (buffer != NULL)) {
1047     sl_si91x_host_free_buffer(buffer);
1048   }
1049   VERIFY_STATUS_AND_RETURN(status);
1050 
1051   sl_si91x_packet_t *packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
1052   memcpy(pairwise_master_key, packet->data, packet->length);
1053   sl_si91x_host_free_buffer(buffer);
1054   return SL_STATUS_OK;
1055 }
1056 
sl_wifi_get_associated_client_list(void * client_list_buffer,uint16_t buffer_length,uint32_t timeout)1057 sl_status_t sl_wifi_get_associated_client_list(void *client_list_buffer, uint16_t buffer_length, uint32_t timeout)
1058 {
1059   UNUSED_PARAMETER(client_list_buffer);
1060   UNUSED_PARAMETER(buffer_length);
1061   UNUSED_PARAMETER(timeout);
1062   return SL_STATUS_NOT_SUPPORTED;
1063   // sl_status_t status;
1064   // sl_wifi_buffer_t *buffer;
1065 
1066   // status = sl_si91x_driver_send_command(RSI_WLAN_REQ_QUERY_GO_PARAMS,
1067   //                                       SI91X_WLAN_CMD,
1068   //                                       NULL,
1069   //                                       0,
1070   //                                       SL_SI91X_WAIT_FOR_RESPONSE(10000),
1071   //                                       NULL,
1072   //                                       &buffer);
1073   // if (status == SL_STATUS_OK) {
1074   //   sl_si91x_packet_t *packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
1075   //       //  si91x_go_parameters_t* data = &packet->data;
1076   //   // Process data here
1077 
1078   //   sl_si91x_host_free_buffer(buffer);
1079   // }
1080   // return status;
1081 }
1082 
sl_wifi_disconnect_ap_client(sl_wifi_interface_t interface,const sl_mac_address_t * mac,sl_wifi_deauth_reason_t reason)1083 sl_status_t sl_wifi_disconnect_ap_client(sl_wifi_interface_t interface,
1084                                          const sl_mac_address_t *mac,
1085                                          sl_wifi_deauth_reason_t reason)
1086 {
1087   UNUSED_PARAMETER(reason);
1088   SL_WIFI_ARGS_CHECK_NULL_POINTER(mac);
1089 
1090   if (!device_initialized) {
1091     return SL_STATUS_NOT_INITIALIZED;
1092   }
1093 
1094   if (!sl_wifi_is_interface_up(interface)) {
1095     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
1096   }
1097 
1098   sl_si91x_disassociation_request_t disconnect_request = { 0 };
1099 
1100   disconnect_request.mode_flag = SL_SI91X_WIFI_AP_VAP_ID;
1101   memcpy(&disconnect_request.client_mac_address, mac, sizeof(sl_mac_address_t));
1102 
1103   sl_status_t status = sl_si91x_driver_send_command(RSI_WLAN_REQ_DISCONNECT,
1104                                                     SI91X_WLAN_CMD,
1105                                                     &disconnect_request,
1106                                                     sizeof(disconnect_request),
1107                                                     SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
1108                                                     (void *)mac,
1109                                                     NULL);
1110 
1111   VERIFY_STATUS_AND_RETURN(status);
1112   return status;
1113 }
1114 
sl_wifi_get_ap_client_info(sl_wifi_interface_t interface,sl_wifi_client_info_response_t * client_info)1115 sl_status_t sl_wifi_get_ap_client_info(sl_wifi_interface_t interface, sl_wifi_client_info_response_t *client_info)
1116 {
1117   sl_status_t status;
1118   sl_wifi_buffer_t *buffer = NULL;
1119   sl_si91x_packet_t *packet;
1120   sl_si91x_client_info_response sl_si91x_client_info_response = { 0 };
1121 
1122   if (!device_initialized) {
1123     return SL_STATUS_NOT_INITIALIZED;
1124   }
1125 
1126   if (interface & SL_WIFI_CLIENT_INTERFACE) {
1127     return SL_STATUS_NOT_SUPPORTED;
1128   }
1129 
1130   if (!sl_wifi_is_interface_up(SL_WIFI_AP_INTERFACE)) {
1131     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
1132   }
1133 
1134   SL_WIFI_ARGS_CHECK_NULL_POINTER(client_info);
1135 
1136   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_QUERY_GO_PARAMS,
1137                                         SI91X_WLAN_CMD,
1138                                         NULL,
1139                                         0,
1140                                         SL_SI91X_WAIT_FOR_COMMAND_RESPONSE,
1141                                         NULL,
1142                                         &buffer);
1143   if ((status != SL_STATUS_OK) && (buffer != NULL)) {
1144     sl_si91x_host_free_buffer(buffer);
1145   }
1146   VERIFY_STATUS_AND_RETURN(status);
1147 
1148   packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
1149 
1150   memcpy(&sl_si91x_client_info_response, packet->data, sizeof(sl_si91x_client_info_response));
1151   convert_si91x_wifi_client_info(client_info, &sl_si91x_client_info_response);
1152 
1153   sl_si91x_host_free_buffer(buffer);
1154   return status;
1155 }
1156 
sl_wifi_get_firmware_version(sl_wifi_firmware_version_t * version)1157 sl_status_t sl_wifi_get_firmware_version(sl_wifi_firmware_version_t *version)
1158 {
1159   return sl_si91x_get_firmware_version((sl_si91x_firmware_version_t *)version);
1160 }
1161 
sl_wifi_get_wireless_info(sl_si91x_rsp_wireless_info_t * info)1162 sl_status_t sl_wifi_get_wireless_info(sl_si91x_rsp_wireless_info_t *info)
1163 {
1164   sl_status_t status       = 0;
1165   sl_wifi_buffer_t *buffer = NULL;
1166 
1167   if (!device_initialized) {
1168     return SL_STATUS_NOT_INITIALIZED;
1169   }
1170   SL_WIFI_ARGS_CHECK_NULL_POINTER(info);
1171 
1172   if (get_opermode() == SL_SI91X_ACCESS_POINT_MODE) {
1173     // Send cmd for wlan info in AP mode
1174     status = sl_si91x_driver_send_command(RSI_WLAN_REQ_QUERY_GO_PARAMS,
1175                                           SI91X_WLAN_CMD,
1176                                           NULL,
1177                                           0,
1178                                           SL_SI91X_WAIT_FOR_RESPONSE(1000),
1179                                           NULL,
1180                                           &buffer);
1181   } else if ((get_opermode() == SL_SI91X_CLIENT_MODE) || (get_opermode() == SL_SI91X_ENTERPRISE_CLIENT_MODE)) {
1182     //! Send cmd for wlan info in client mode
1183     status = sl_si91x_driver_send_command(RSI_WLAN_REQ_QUERY_NETWORK_PARAMS,
1184                                           SI91X_WLAN_CMD,
1185                                           NULL,
1186                                           0,
1187                                           SL_SI91X_WAIT_FOR_RESPONSE(1000),
1188                                           NULL,
1189                                           &buffer);
1190   } else {
1191     return SL_STATUS_NOT_SUPPORTED;
1192   }
1193 
1194   if ((status != SL_STATUS_OK) && (buffer != NULL)) {
1195     sl_si91x_host_free_buffer(buffer);
1196   }
1197   VERIFY_STATUS_AND_RETURN(status);
1198 
1199   sl_si91x_packet_t *packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
1200 
1201   memset((sl_si91x_rsp_wireless_info_t *)info, 0, sizeof(sl_si91x_rsp_wireless_info_t));
1202 
1203   //In AP mode, receives a buffer equivalent to sl_si91x_client_info_response.
1204   if (packet->length > 0 && get_opermode() == SL_SI91X_ACCESS_POINT_MODE) {
1205     sl_si91x_client_info_response *response = (sl_si91x_client_info_response *)packet->data;
1206     // wlan state: no of stations connected in AP mode
1207     memcpy(&info->wlan_state, (uint16_t *)&response->sta_count, sizeof(uint16_t));
1208     memcpy(&info->channel_number, (uint16_t *)&response->channel_number, sizeof(uint16_t));
1209     memcpy(info->ssid, response->ssid, MIN(sizeof(info->ssid), sizeof(response->ssid)));
1210     memcpy(info->mac_address, response->mac_address, 6);
1211     // PSK for AP mode, PMK for Client mode
1212     memcpy(info->psk_pmk, response->psk, 64);
1213     memcpy(info->ipv4_address, response->ipv4_address, 4);
1214     memcpy(info->ipv6_address, response->ipv6_address, 16);
1215   }
1216   //In Client mode, receives a buffer equivalent to sl_si91x_network_params_response_t.
1217   else if (packet->length > 0
1218            && ((get_opermode() == SL_SI91X_CLIENT_MODE) || (get_opermode() == SL_SI91X_ENTERPRISE_CLIENT_MODE))) {
1219     sl_si91x_network_params_response_t *response = (sl_si91x_network_params_response_t *)packet->data;
1220     memcpy(&info->wlan_state, (uint16_t *)&response->wlan_state, sizeof(uint8_t));
1221     memcpy((uint8_t *)&info->channel_number, &response->channel_number, sizeof(uint8_t));
1222     memcpy(info->ssid, response->ssid, MIN(sizeof(info->ssid), sizeof(response->ssid)));
1223     memcpy(info->mac_address, response->mac_address, 6);
1224     memcpy(&info->sec_type, &response->sec_type, sizeof(uint8_t));
1225     // PSK for AP mode, PMK for Client mode
1226     memcpy(info->psk_pmk, response->psk, 64);
1227     memcpy(info->ipv4_address, response->ipv4_address, 4);
1228     memcpy(info->ipv6_address, response->ipv6_address, 16);
1229   }
1230 
1231   sl_si91x_host_free_buffer(buffer);
1232   return status;
1233 }
1234 
sl_wifi_get_firmware_size(void * buffer,uint32_t * fw_image_size)1235 sl_status_t sl_wifi_get_firmware_size(void *buffer, uint32_t *fw_image_size)
1236 {
1237   return sl_si91x_get_firmware_size(buffer, fw_image_size);
1238 }
1239 
sl_wifi_disconnect(sl_wifi_interface_t interface)1240 sl_status_t sl_wifi_disconnect(sl_wifi_interface_t interface)
1241 {
1242   if (!device_initialized) {
1243     return SL_STATUS_NOT_INITIALIZED;
1244   }
1245 
1246   if (interface & SL_WIFI_AP_INTERFACE) {
1247     return SL_STATUS_NOT_SUPPORTED;
1248   }
1249 
1250   if (!sl_wifi_is_interface_up(interface)) {
1251     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
1252   }
1253 
1254   sl_si91x_disassociation_request_t disconnect_request = { 0 };
1255 
1256   sl_status_t status = sl_si91x_driver_send_command(RSI_WLAN_REQ_DISCONNECT,
1257                                                     SI91X_WLAN_CMD,
1258                                                     &disconnect_request,
1259                                                     sizeof(disconnect_request),
1260                                                     SL_NCP_DEFAULT_COMMAND_WAIT_TIME,
1261                                                     NULL,
1262                                                     NULL);
1263   VERIFY_STATUS_AND_RETURN(status);
1264 
1265   reset_coex_current_performance_profile();
1266 
1267   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_INIT,
1268                                         SI91X_WLAN_CMD,
1269                                         NULL,
1270                                         0,
1271                                         SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
1272                                         NULL,
1273                                         NULL);
1274   VERIFY_STATUS_AND_RETURN(status);
1275 
1276   return status;
1277 }
1278 
sl_wifi_stop_ap(sl_wifi_interface_t interface)1279 sl_status_t sl_wifi_stop_ap(sl_wifi_interface_t interface)
1280 {
1281   sl_status_t status                                   = SL_STATUS_OK;
1282   sl_si91x_disassociation_request_t disconnect_request = { 0 };
1283 
1284   if (!device_initialized) {
1285     return SL_STATUS_NOT_INITIALIZED;
1286   }
1287 
1288   if (interface & SL_WIFI_CLIENT_INTERFACE) {
1289     return SL_STATUS_NOT_SUPPORTED;
1290   }
1291 
1292   if (!sl_wifi_is_interface_up(interface)) {
1293     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
1294   }
1295 
1296   disconnect_request.mode_flag = SL_SI91X_WIFI_AP_VAP_ID;
1297   status                       = sl_si91x_driver_send_command(RSI_WLAN_REQ_AP_STOP,
1298                                         SI91X_WLAN_CMD,
1299                                         &disconnect_request,
1300                                         sizeof(disconnect_request),
1301                                         SL_NCP_DEFAULT_COMMAND_WAIT_TIME,
1302                                         NULL,
1303                                         NULL);
1304   VERIFY_STATUS_AND_RETURN(status);
1305 
1306   reset_ap_configuration();
1307   if (interface == SL_WIFI_AP_2_4GHZ_INTERFACE || interface == SL_WIFI_AP_INTERFACE)
1308     interface_is_up[SL_WIFI_AP_2_4GHZ_INTERFACE_INDEX] = false;
1309   else if (interface == SL_WIFI_AP_5GHZ_INTERFACE)
1310     interface_is_up[SL_WIFI_AP_5GHZ_INTERFACE_INDEX] = false;
1311 
1312   return status;
1313 }
1314 
sl_wifi_get_statistics(sl_wifi_interface_t interface,sl_wifi_statistics_t * statistics)1315 sl_status_t sl_wifi_get_statistics(sl_wifi_interface_t interface, sl_wifi_statistics_t *statistics)
1316 {
1317   sl_status_t status       = SL_STATUS_OK;
1318   sl_wifi_buffer_t *buffer = NULL;
1319   sl_si91x_packet_t *packet;
1320 
1321   if (!device_initialized) {
1322     return SL_STATUS_NOT_INITIALIZED;
1323   }
1324 
1325   if (!sl_wifi_is_interface_up(interface)) {
1326     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
1327   }
1328 
1329   SL_WIFI_ARGS_CHECK_INVALID_INTERFACE(interface);
1330   SL_WIFI_ARGS_CHECK_NULL_POINTER(statistics);
1331 
1332   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_EXT_STATS,
1333                                         SI91X_WLAN_CMD,
1334                                         NULL,
1335                                         0,
1336                                         SL_SI91X_WAIT_FOR_RESPONSE(30500),
1337                                         NULL,
1338                                         &buffer);
1339   if ((status != SL_STATUS_OK) && (buffer != NULL)) {
1340     sl_si91x_host_free_buffer(buffer);
1341   }
1342   VERIFY_STATUS_AND_RETURN(status);
1343 
1344   packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
1345   if (packet->length != sizeof(sl_wifi_statistics_t)) {
1346     sl_si91x_host_free_buffer(buffer);
1347     return SL_STATUS_FAIL;
1348   }
1349 
1350   if (packet->length > 0) {
1351     memcpy(statistics, packet->data, packet->length);
1352   }
1353 
1354   sl_si91x_host_free_buffer(buffer);
1355   return status;
1356 }
1357 
sl_wifi_get_operational_statistics(sl_wifi_interface_t interface,sl_wifi_operational_statistics_t * operational_statistics)1358 sl_status_t sl_wifi_get_operational_statistics(sl_wifi_interface_t interface,
1359                                                sl_wifi_operational_statistics_t *operational_statistics)
1360 {
1361   sl_status_t status       = SL_STATUS_OK;
1362   sl_wifi_buffer_t *buffer = NULL;
1363   sl_si91x_packet_t *packet;
1364 
1365   if (!device_initialized) {
1366     return SL_STATUS_NOT_INITIALIZED;
1367   }
1368 
1369   if (!sl_wifi_is_interface_up(interface)) {
1370     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
1371   }
1372 
1373   SL_WIFI_ARGS_CHECK_INVALID_INTERFACE(interface);
1374   SL_WIFI_ARGS_CHECK_NULL_POINTER(operational_statistics);
1375 
1376   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_GET_STATS,
1377                                         SI91X_WLAN_CMD,
1378                                         NULL,
1379                                         0,
1380                                         SL_SI91X_WAIT_FOR_RESPONSE(30500),
1381                                         NULL,
1382                                         &buffer);
1383   if ((status != SL_STATUS_OK) && (buffer != NULL)) {
1384     sl_si91x_host_free_buffer(buffer);
1385   }
1386   VERIFY_STATUS_AND_RETURN(status);
1387 
1388   packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
1389   if (packet->length != sizeof(sl_wifi_operational_statistics_t)) {
1390     sl_si91x_host_free_buffer(buffer);
1391     return SL_STATUS_FAIL;
1392   }
1393 
1394   if (packet->length > 0) {
1395     memcpy(operational_statistics, packet->data, packet->length);
1396   }
1397 
1398   sl_si91x_host_free_buffer(buffer);
1399   return status;
1400 }
1401 
sl_wifi_start_statistic_report(sl_wifi_interface_t interface,sl_wifi_channel_t channel)1402 sl_status_t sl_wifi_start_statistic_report(sl_wifi_interface_t interface, sl_wifi_channel_t channel)
1403 {
1404   if (!device_initialized) {
1405     return SL_STATUS_NOT_INITIALIZED;
1406   }
1407 
1408   if (!sl_wifi_is_interface_up(interface)) {
1409     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
1410   }
1411 
1412   sl_status_t status               = SL_STATUS_OK;
1413   sl_si91x_req_rx_stats_t rx_stats = { 0 };
1414 
1415   // Configure to start RX stats
1416   rx_stats.start[0] = START_STATISTICS_REPORT;
1417   // Copy the channel number
1418   memcpy(rx_stats.channel, &channel.channel, sizeof(rx_stats.channel));
1419   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_RX_STATS,
1420                                         SI91X_WLAN_CMD,
1421                                         &rx_stats,
1422                                         sizeof(rx_stats),
1423                                         SL_SI91X_RETURN_IMMEDIATELY,
1424                                         NULL,
1425                                         NULL);
1426   VERIFY_STATUS_AND_RETURN(status);
1427   return status;
1428 }
1429 
sl_wifi_stop_statistic_report(sl_wifi_interface_t interface)1430 sl_status_t sl_wifi_stop_statistic_report(sl_wifi_interface_t interface)
1431 {
1432   if (!device_initialized) {
1433     return SL_STATUS_NOT_INITIALIZED;
1434   }
1435 
1436   if (!sl_wifi_is_interface_up(interface)) {
1437     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
1438   }
1439 
1440   sl_si91x_req_rx_stats_t rx_stats = { 0 };
1441 
1442   // Configure to stop RX stats
1443   rx_stats.start[0] = STOP_STATISTICS_REPORT;
1444 
1445   sl_status_t status = sl_si91x_driver_send_command(RSI_WLAN_REQ_RX_STATS,
1446                                                     SI91X_WLAN_CMD,
1447                                                     &rx_stats,
1448                                                     sizeof(rx_stats),
1449                                                     SL_SI91X_WAIT_FOR_COMMAND_RESPONSE,
1450                                                     NULL,
1451                                                     NULL);
1452   VERIFY_STATUS_AND_RETURN(status);
1453   return status;
1454 }
1455 
sl_wifi_set_performance_profile(const sl_wifi_performance_profile_t * profile)1456 sl_status_t sl_wifi_set_performance_profile(const sl_wifi_performance_profile_t *profile)
1457 {
1458   sl_status_t status;
1459   sl_si91x_performance_profile_t selected_coex_profile_mode = { 0 };
1460   sl_wifi_performance_profile_t current_wifi_profile_mode   = { 0 };
1461 
1462   if (!device_initialized) {
1463     return SL_STATUS_NOT_INITIALIZED;
1464   }
1465 
1466   SL_WIFI_ARGS_CHECK_NULL_POINTER(profile);
1467 
1468   if (profile->profile > DEEP_SLEEP_WITH_RAM_RETENTION) {
1469     return SL_STATUS_INVALID_MODE;
1470   }
1471 
1472   // Take backup of current wifi profile
1473   get_wifi_current_performance_profile(&current_wifi_profile_mode);
1474 
1475   // Send the power save command for the requested profile
1476   status = sli_si91x_send_power_save_request(profile, NULL);
1477   if (status != SL_STATUS_OK) {
1478     save_wifi_current_performance_profile(&current_wifi_profile_mode);
1479     return status;
1480   }
1481   get_coex_performance_profile(&selected_coex_profile_mode);
1482 
1483   // Set device_initialized as false since RAM of module will be not retained
1484   // in ULTRA_POWER_SAVE and module needs to be started from init again
1485   if (selected_coex_profile_mode == DEEP_SLEEP_WITHOUT_RAM_RETENTION) {
1486     device_initialized = false;
1487 
1488 #ifdef SLI_SI91X_MCU_INTERFACE
1489     // In soc mode m4 does not get the card ready for next init after deinit, but if device in DEEP_SLEEP_WITHOUT_RAM_RETENTION mode, m4 should wait for card ready for next init
1490     set_card_ready_required(true);
1491 #endif
1492     reset_coex_current_performance_profile();
1493   }
1494 
1495   return SL_STATUS_OK;
1496 }
1497 
sl_wifi_get_performance_profile(sl_wifi_performance_profile_t * profile)1498 sl_status_t sl_wifi_get_performance_profile(sl_wifi_performance_profile_t *profile)
1499 {
1500   if (!device_initialized) {
1501     return SL_STATUS_NOT_INITIALIZED;
1502   }
1503 
1504   get_wifi_current_performance_profile(profile);
1505   return SL_STATUS_OK;
1506 }
1507 
sl_wifi_get_default_interface(void)1508 sl_wifi_interface_t sl_wifi_get_default_interface(void)
1509 {
1510   return default_interface;
1511 }
1512 
sl_wifi_set_default_interface(sl_wifi_interface_t interface)1513 void sl_wifi_set_default_interface(sl_wifi_interface_t interface)
1514 {
1515   default_interface = interface;
1516 }
1517 
sl_wifi_deinit(void)1518 sl_status_t sl_wifi_deinit(void)
1519 {
1520   sl_status_t status;
1521   bg_enabled = false;
1522   reset_coex_current_performance_profile();
1523   reset_max_tx_power();
1524   reset_ap_configuration();
1525   reset_sl_wifi_rate();
1526   memset(&advanced_scan_configuration, 0, sizeof(sl_wifi_advanced_scan_configuration_t));
1527   status = sl_si91x_driver_deinit();
1528   sli_wifi_flush_scan_results_database();
1529 
1530   SLI_NETWORK_CLEANUP_HANDLER();
1531 
1532   return status;
1533 }
1534 
1535 // 5GHz interface is currently not supported for Si91x
sl_wifi_is_interface_up(sl_wifi_interface_t interface)1536 bool sl_wifi_is_interface_up(sl_wifi_interface_t interface)
1537 {
1538   switch (interface) {
1539     case SL_WIFI_CLIENT_INTERFACE:
1540       return interface_is_up[SL_WIFI_CLIENT_2_4GHZ_INTERFACE_INDEX]
1541              | interface_is_up[SL_WIFI_CLIENT_5GHZ_INTERFACE_INDEX];
1542     case SL_WIFI_AP_INTERFACE:
1543       return interface_is_up[SL_WIFI_AP_2_4GHZ_INTERFACE_INDEX] | interface_is_up[SL_WIFI_AP_5GHZ_INTERFACE_INDEX];
1544     case SL_WIFI_CLIENT_2_4GHZ_INTERFACE:
1545       return interface_is_up[SL_WIFI_CLIENT_2_4GHZ_INTERFACE_INDEX];
1546     case SL_WIFI_AP_2_4GHZ_INTERFACE:
1547       return interface_is_up[SL_WIFI_AP_2_4GHZ_INTERFACE_INDEX];
1548     case SL_WIFI_CLIENT_5GHZ_INTERFACE:
1549       return interface_is_up[SL_WIFI_CLIENT_5GHZ_INTERFACE_INDEX];
1550     case SL_WIFI_AP_5GHZ_INTERFACE:
1551       return interface_is_up[SL_WIFI_AP_5GHZ_INTERFACE_INDEX];
1552     case SL_WIFI_2_4GHZ_INTERFACE:
1553       return interface_is_up[SL_WIFI_CLIENT_2_4GHZ_INTERFACE_INDEX]
1554              | interface_is_up[SL_WIFI_AP_2_4GHZ_INTERFACE_INDEX];
1555     case SL_WIFI_5GHZ_INTERFACE:
1556       return interface_is_up[SL_WIFI_CLIENT_5GHZ_INTERFACE_INDEX] | interface_is_up[SL_WIFI_AP_5GHZ_INTERFACE_INDEX];
1557     case SL_WIFI_ALL_INTERFACES:
1558       return interface_is_up[SL_WIFI_CLIENT_5GHZ_INTERFACE_INDEX] | interface_is_up[SL_WIFI_AP_5GHZ_INTERFACE_INDEX]
1559              | interface_is_up[SL_WIFI_CLIENT_2_4GHZ_INTERFACE_INDEX]
1560              | interface_is_up[SL_WIFI_AP_2_4GHZ_INTERFACE_INDEX];
1561     case SL_WIFI_TRANSCEIVER_INTERFACE:
1562       return interface_is_up[SL_WIFI_TRANSCEIVER_INTERFACE_INDEX];
1563     default:
1564       return false;
1565   }
1566 }
1567 
sl_wifi_set_certificate_with_index(uint8_t certificate_type,uint8_t certificate_index,uint8_t * buffer,uint32_t certificate_length)1568 sl_status_t sl_wifi_set_certificate_with_index(uint8_t certificate_type,
1569                                                uint8_t certificate_index,
1570                                                uint8_t *buffer,
1571                                                uint32_t certificate_length)
1572 {
1573   return sl_si91x_wifi_set_certificate_index(certificate_type, certificate_index, buffer, certificate_length);
1574 }
1575 
sl_wifi_set_certificate(uint8_t certificate_type,const uint8_t * buffer,uint32_t certificate_length)1576 sl_status_t sl_wifi_set_certificate(uint8_t certificate_type, const uint8_t *buffer, uint32_t certificate_length)
1577 {
1578   return sl_si91x_wifi_set_certificate_index(certificate_type, 0, buffer, certificate_length);
1579 }
1580 
sl_wifi_set_transmit_rate(sl_wifi_interface_t interface,sl_wifi_rate_protocol_t rate_protocol,sl_wifi_rate_t mask)1581 sl_status_t sl_wifi_set_transmit_rate(sl_wifi_interface_t interface,
1582                                       sl_wifi_rate_protocol_t rate_protocol,
1583                                       sl_wifi_rate_t mask)
1584 {
1585   if (!device_initialized) {
1586     return SL_STATUS_NOT_INITIALIZED;
1587   }
1588 
1589   if (sl_wifi_is_interface_up(interface)) {
1590     if (interface == SL_WIFI_AP_INTERFACE) {
1591       return SL_STATUS_WIFI_UNSUPPORTED;
1592     }
1593   } else {
1594     if (interface == SL_WIFI_CLIENT_INTERFACE) {
1595       return SL_STATUS_WIFI_INTERFACE_NOT_UP;
1596     }
1597   }
1598 
1599   switch (rate_protocol) {
1600     case SL_WIFI_RATE_PROTOCOL_B_ONLY: {
1601       if (mask < SL_WIFI_RATE_11B_MIN || mask > SL_WIFI_RATE_11B_MAX) {
1602         return SL_STATUS_INVALID_CONFIGURATION;
1603       }
1604       break;
1605     }
1606     case SL_WIFI_RATE_PROTOCOL_G_ONLY: {
1607       if (mask < SL_WIFI_RATE_11G_MIN || mask > SL_WIFI_RATE_11G_MAX) {
1608         return SL_STATUS_INVALID_CONFIGURATION;
1609       }
1610       break;
1611     }
1612     case SL_WIFI_RATE_PROTOCOL_N_ONLY: {
1613       if (mask < SL_WIFI_RATE_11N_MIN || mask > SL_WIFI_RATE_11N_MAX) {
1614         return SL_STATUS_INVALID_CONFIGURATION;
1615       }
1616       break;
1617     }
1618     case SL_WIFI_RATE_PROTOCOL_AC_ONLY: {
1619       return SL_STATUS_NOT_SUPPORTED;
1620     }
1621     case SL_WIFI_RATE_PROTOCOL_AX_ONLY: {
1622       if (mask < SL_WIFI_RATE_11AX_MIN || mask > SL_WIFI_RATE_11AX_MAX) {
1623         return SL_STATUS_INVALID_CONFIGURATION;
1624       }
1625       break;
1626     }
1627     case SL_WIFI_RATE_PROTOCOL_AUTO: {
1628       if (mask != SL_WIFI_AUTO_RATE) {
1629         return SL_STATUS_INVALID_CONFIGURATION;
1630       }
1631       break;
1632     }
1633     default: {
1634       return SL_STATUS_INVALID_CONFIGURATION;
1635     }
1636   }
1637 
1638   return save_sl_wifi_rate(mask);
1639 }
1640 
sl_wifi_get_transmit_rate(sl_wifi_interface_t interface,sl_wifi_rate_protocol_t * rate_protocol,sl_wifi_rate_t * mask)1641 sl_status_t sl_wifi_get_transmit_rate(sl_wifi_interface_t interface,
1642                                       sl_wifi_rate_protocol_t *rate_protocol,
1643                                       sl_wifi_rate_t *mask)
1644 {
1645   if (!device_initialized) {
1646     return SL_STATUS_NOT_INITIALIZED;
1647   }
1648 
1649   if (!sl_wifi_is_interface_up(interface)) {
1650     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
1651   }
1652 
1653   SL_WIFI_ARGS_CHECK_NULL_POINTER(rate_protocol);
1654   SL_WIFI_ARGS_CHECK_NULL_POINTER(mask);
1655 
1656   sl_wifi_rate_t transfer_rate;
1657   get_saved_sl_wifi_rate(&transfer_rate);
1658 
1659   return get_rate_protocol_and_data_rate(transfer_rate, rate_protocol, mask);
1660 }
1661 
sl_wifi_get_ap_client_count(sl_wifi_interface_t interface,uint32_t * client_list_count)1662 sl_status_t sl_wifi_get_ap_client_count(sl_wifi_interface_t interface, uint32_t *client_list_count)
1663 {
1664   sl_wifi_client_info_response_t client_info = { 0 };
1665 
1666   SL_WIFI_ARGS_CHECK_NULL_POINTER(client_list_count);
1667 
1668   sl_status_t status = sl_wifi_get_ap_client_info(interface, &client_info);
1669 
1670   if (status == SL_STATUS_OK) {
1671     memcpy(client_list_count, (uint32_t *)&client_info.client_count, sizeof(uint32_t));
1672   }
1673 
1674   return status;
1675 }
1676 
sl_wifi_get_ap_client_list(sl_wifi_interface_t interface,uint16_t client_list_count,sl_mac_address_t * client_list)1677 sl_status_t sl_wifi_get_ap_client_list(sl_wifi_interface_t interface,
1678                                        uint16_t client_list_count,
1679                                        sl_mac_address_t *client_list)
1680 {
1681   sl_wifi_client_info_response_t client_info = { 0 };
1682 
1683   sl_status_t status = sl_wifi_get_ap_client_info(interface, &client_info);
1684 
1685   if (status == SL_STATUS_OK) {
1686     for (uint16_t station_info_index = 0;
1687          station_info_index < client_info.client_count && station_info_index < client_list_count;
1688          station_info_index++) {
1689       memcpy(client_list[station_info_index].octet,
1690              client_info.client_info[station_info_index].mac_adddress.octet,
1691              sizeof(sl_mac_address_t));
1692     }
1693   }
1694 
1695   return status;
1696 }
sl_wifi_generate_wps_pin(sl_wifi_wps_pin_t * wps_pin)1697 sl_status_t sl_wifi_generate_wps_pin(sl_wifi_wps_pin_t *wps_pin)
1698 {
1699   sl_status_t status                               = SL_STATUS_OK;
1700   sl_wifi_buffer_t *buffer                         = NULL;
1701   sl_si91x_packet_t *packet                        = NULL;
1702   sl_si91x_wps_method_request_t wps_method_request = { 0 };
1703 
1704   SL_WIFI_ARGS_CHECK_NULL_POINTER(wps_pin);
1705 
1706   if (!device_initialized) {
1707     return SL_STATUS_NOT_INITIALIZED;
1708   }
1709 
1710   // Set configuration to generate new WPS pin
1711   wps_method_request.wps_method   = SI91X_SET_WPS_METHOD_PIN;
1712   wps_method_request.generate_pin = SI91X_SET_WPS_GENERATE_PIN;
1713 
1714   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_WPS_METHOD,
1715                                         SI91X_WLAN_CMD,
1716                                         &wps_method_request,
1717                                         sizeof(sl_si91x_wps_method_request_t),
1718                                         SL_SI91X_WAIT_FOR_COMMAND_RESPONSE,
1719                                         NULL,
1720                                         &buffer);
1721   if ((status != SL_STATUS_OK) && (buffer != NULL)) {
1722     sl_si91x_host_free_buffer(buffer);
1723   }
1724   VERIFY_STATUS_AND_RETURN(status);
1725 
1726   packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
1727   if (packet->length > 0) {
1728     memcpy(wps_pin->digits, packet->data, sizeof(sl_wifi_wps_pin_t));
1729   }
1730 
1731   sl_si91x_host_free_buffer(buffer);
1732   return status;
1733 }
1734 
sl_wifi_start_wps(sl_wifi_interface_t interface,sl_wifi_wps_mode_t mode,const sl_wifi_wps_pin_t * optional_wps_pin)1735 sl_status_t sl_wifi_start_wps(sl_wifi_interface_t interface,
1736                               sl_wifi_wps_mode_t mode,
1737                               const sl_wifi_wps_pin_t *optional_wps_pin)
1738 {
1739   UNUSED_PARAMETER(optional_wps_pin);
1740 
1741   if (!device_initialized) {
1742     return SL_STATUS_NOT_INITIALIZED;
1743   }
1744 
1745   if (mode != SL_WIFI_WPS_PUSH_BUTTON_MODE || (interface & SL_WIFI_AP_INTERFACE) == 0) {
1746     return SL_STATUS_NOT_SUPPORTED;
1747   }
1748 
1749   if (!sl_wifi_is_interface_up(interface)) {
1750     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
1751   }
1752 
1753   sl_status_t status;
1754   sl_si91x_join_request_t wps_button_press_request = { 0 };
1755   sl_wifi_ap_configuration_t ap_configuration      = { 0 };
1756 
1757   get_saved_ap_configuration(&ap_configuration);
1758   status = get_configured_join_request(SL_WIFI_AP_INTERFACE, &ap_configuration, &wps_button_press_request);
1759 
1760   VERIFY_STATUS_AND_RETURN(status);
1761   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_JOIN,
1762                                         SI91X_WLAN_CMD,
1763                                         &wps_button_press_request,
1764                                         sizeof(wps_button_press_request),
1765                                         SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
1766                                         NULL,
1767                                         NULL);
1768 
1769   VERIFY_STATUS_AND_RETURN(status);
1770   return status;
1771 }
sl_wifi_set_roam_configuration(sl_wifi_interface_t interface,sl_wifi_roam_configuration_t * roam_configuration)1772 sl_status_t sl_wifi_set_roam_configuration(sl_wifi_interface_t interface,
1773                                            sl_wifi_roam_configuration_t *roam_configuration)
1774 {
1775   sl_si91x_req_roam_params_t roam_param_request = { 0 };
1776 
1777   if (!device_initialized) {
1778     return SL_STATUS_NOT_INITIALIZED;
1779   }
1780 
1781   if (interface & SL_WIFI_AP_INTERFACE) {
1782     return SL_STATUS_NOT_SUPPORTED;
1783   }
1784 
1785   if (!sl_wifi_is_interface_up(interface)) {
1786     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
1787   }
1788 
1789   if (roam_configuration->trigger_level != SL_WIFI_NEVER_ROAM) {
1790     roam_param_request.roam_enable = ALWAYS_ROAM;
1791   }
1792 
1793   roam_param_request.roam_threshold  = -1 * roam_configuration->trigger_level;
1794   roam_param_request.roam_hysteresis = roam_configuration->trigger_level_change;
1795 
1796   sl_status_t status = sl_si91x_driver_send_command(RSI_WLAN_REQ_ROAM_PARAMS,
1797                                                     SI91X_WLAN_CMD,
1798                                                     &roam_param_request,
1799                                                     sizeof(sl_si91x_req_roam_params_t),
1800                                                     SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
1801                                                     NULL,
1802                                                     NULL);
1803 
1804   VERIFY_STATUS_AND_RETURN(status);
1805   return status;
1806 }
1807 
sl_wifi_set_advanced_scan_configuration(const sl_wifi_advanced_scan_configuration_t * configuration)1808 sl_status_t sl_wifi_set_advanced_scan_configuration(const sl_wifi_advanced_scan_configuration_t *configuration)
1809 {
1810   SL_WIFI_ARGS_CHECK_NULL_POINTER(configuration);
1811 
1812   if (!device_initialized) {
1813     return SL_STATUS_NOT_INITIALIZED;
1814   }
1815 
1816   memcpy(&advanced_scan_configuration, configuration, sizeof(sl_wifi_advanced_scan_configuration_t));
1817 
1818   return SL_STATUS_OK;
1819 }
1820 
sl_wifi_get_advanced_scan_configuration(sl_wifi_advanced_scan_configuration_t * configuration)1821 sl_status_t sl_wifi_get_advanced_scan_configuration(sl_wifi_advanced_scan_configuration_t *configuration)
1822 {
1823   SL_WIFI_ARGS_CHECK_NULL_POINTER(configuration);
1824 
1825   if (!device_initialized) {
1826     return SL_STATUS_NOT_INITIALIZED;
1827   }
1828 
1829   memcpy(configuration, &advanced_scan_configuration, sizeof(sl_wifi_advanced_scan_configuration_t));
1830 
1831   return SL_STATUS_OK;
1832 }
1833 
sl_wifi_stop_scan(sl_wifi_interface_t interface)1834 sl_status_t sl_wifi_stop_scan(sl_wifi_interface_t interface)
1835 {
1836   sl_status_t status                  = SL_STATUS_OK;
1837   sl_si91x_req_bg_scan_t scan_request = { 0 };
1838 
1839   if (!device_initialized) {
1840     return SL_STATUS_NOT_INITIALIZED;
1841   }
1842 
1843   if (interface & SL_WIFI_AP_INTERFACE) {
1844     return SL_STATUS_NOT_SUPPORTED;
1845   }
1846 
1847   if (!sl_wifi_is_interface_up(interface)) {
1848     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
1849   }
1850 
1851   // Once stop_scan() support for foreground scan is available, "bg_enabled" should be removed.
1852   if (bg_enabled == true) {
1853     scan_request.bgscan_enable = SI91X_BG_SCAN_DISABLE;
1854     status                     = sl_si91x_driver_send_command(RSI_WLAN_REQ_BG_SCAN,
1855                                           SI91X_WLAN_CMD,
1856                                           &scan_request,
1857                                           sizeof(sl_si91x_req_bg_scan_t),
1858                                           SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
1859                                           NULL,
1860                                           NULL);
1861     VERIFY_STATUS_AND_RETURN(status);
1862     bg_enabled = false;
1863   } else {
1864     return SL_STATUS_NOT_SUPPORTED;
1865   }
1866 
1867   return status;
1868 }
1869 
sl_wifi_set_ap_configuration(sl_wifi_interface_t interface,const sl_wifi_ap_configuration_t * configuration)1870 sl_status_t sl_wifi_set_ap_configuration(sl_wifi_interface_t interface, const sl_wifi_ap_configuration_t *configuration)
1871 {
1872   UNUSED_PARAMETER(interface);
1873   UNUSED_PARAMETER(configuration);
1874   if (!device_initialized) {
1875     return SL_STATUS_NOT_INITIALIZED;
1876   }
1877   //Firmware unable to configure the ap configuration of a running AP interface
1878   return SL_STATUS_NOT_SUPPORTED;
1879 }
1880 
sl_wifi_get_ap_configuration(sl_wifi_interface_t interface,sl_wifi_ap_configuration_t * configuration)1881 sl_status_t sl_wifi_get_ap_configuration(sl_wifi_interface_t interface, sl_wifi_ap_configuration_t *configuration)
1882 {
1883   if (!device_initialized) {
1884     return SL_STATUS_NOT_INITIALIZED;
1885   }
1886 
1887   SL_VERIFY_POINTER_OR_RETURN(configuration, SL_STATUS_NULL_POINTER);
1888 
1889   if (!sl_wifi_is_interface_up(interface)) {
1890     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
1891   }
1892 
1893   sl_wifi_ap_configuration_t saved_ap_configuration = { 0 };
1894   get_saved_ap_configuration(&saved_ap_configuration);
1895 
1896   memcpy(configuration, &saved_ap_configuration, sizeof(sl_wifi_ap_configuration_t));
1897 
1898   return SL_STATUS_OK;
1899 }
1900 
sl_wifi_reconfigure_ap(sl_wifi_interface_t interface,sl_si91x_ap_reconfiguration_t config)1901 sl_status_t sl_wifi_reconfigure_ap(sl_wifi_interface_t interface, sl_si91x_ap_reconfiguration_t config)
1902 {
1903   sl_status_t status = SL_STATUS_OK;
1904 
1905   if (!device_initialized) {
1906     return SL_STATUS_NOT_INITIALIZED;
1907   }
1908 
1909   if (interface & SL_WIFI_CLIENT_INTERFACE) {
1910     return SL_STATUS_NOT_SUPPORTED;
1911   }
1912 
1913   if (!sl_wifi_is_interface_up(interface)) {
1914     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
1915   }
1916 
1917   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_BEACON_STOP,
1918                                         SI91X_WLAN_CMD,
1919                                         &config,
1920                                         sizeof(sl_si91x_ap_reconfiguration_t),
1921                                         SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
1922                                         NULL,
1923                                         NULL);
1924   VERIFY_STATUS_AND_RETURN(status);
1925 
1926   return status;
1927 }
1928 
sl_wifi_test_client_configuration(sl_wifi_interface_t interface,const sl_wifi_client_configuration_t * ap,uint32_t timeout_ms)1929 sl_status_t sl_wifi_test_client_configuration(sl_wifi_interface_t interface,
1930                                               const sl_wifi_client_configuration_t *ap,
1931                                               uint32_t timeout_ms)
1932 {
1933   sl_status_t status = sl_wifi_connect(interface, ap, timeout_ms);
1934   VERIFY_STATUS_AND_RETURN(status);
1935 
1936   status = sl_wifi_disconnect(SL_WIFI_CLIENT_INTERFACE);
1937   VERIFY_STATUS_AND_RETURN(status);
1938 
1939   return SL_STATUS_OK;
1940 }
1941 
sl_wifi_send_raw_data_frame(sl_wifi_interface_t interface,const void * data,uint16_t data_length)1942 sl_status_t sl_wifi_send_raw_data_frame(sl_wifi_interface_t interface, const void *data, uint16_t data_length)
1943 {
1944   if (!device_initialized) {
1945     return SL_STATUS_NOT_INITIALIZED;
1946   }
1947 
1948   if (!sl_wifi_is_interface_up(interface)) {
1949     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
1950   }
1951 
1952   SL_VERIFY_POINTER_OR_RETURN(data, SL_STATUS_NULL_POINTER);
1953 
1954   if (data_length == 0) {
1955     return SL_STATUS_INVALID_PARAMETER;
1956   }
1957   return sl_si91x_driver_raw_send_command(RSI_SEND_RAW_DATA, data, data_length, RSI_SEND_RAW_DATA_RESPONSE_WAIT_TIME);
1958 }
1959 
sl_wifi_enable_target_wake_time(sl_wifi_twt_request_t * twt_req)1960 sl_status_t sl_wifi_enable_target_wake_time(sl_wifi_twt_request_t *twt_req)
1961 {
1962   if (!twt_req->twt_enable) {
1963     return SL_STATUS_INVALID_PARAMETER;
1964   }
1965   if (twt_req->twt_flow_id > MAX_FLOW_ID) {
1966     return SL_STATUS_INVALID_PARAMETER;
1967   }
1968   if (twt_req->wake_int_exp > MAX_WAKE_INTERVAL_EXPONENT) {
1969     return SL_STATUS_INVALID_PARAMETER;
1970   }
1971   if (twt_req->wake_int_exp_tol > MAX_WAKE_INTERVAL_EXPONENT_TOLERANCE) {
1972     return SL_STATUS_INVALID_PARAMETER;
1973   }
1974   if (twt_req->wake_duration_unit > MAX_WAKE_DURATION_UNIT) {
1975     return SL_STATUS_INVALID_PARAMETER;
1976   }
1977   if (twt_req->un_announced_twt > 1 || twt_req->triggered_twt > 1 || twt_req->restrict_tx_outside_tsp > 1) {
1978     return SL_STATUS_INVALID_PARAMETER;
1979   }
1980   if (twt_req->twt_retry_limit > MAX_TWT_RETRY_LIMIT) {
1981     return SL_STATUS_INVALID_PARAMETER;
1982   }
1983   if (twt_req->twt_retry_interval < MIN_TWT_RETRY_INTERVAL) {
1984     return SL_STATUS_INVALID_PARAMETER;
1985   }
1986   if (twt_req->req_type > MAX_TWT_REQ_TYPE) {
1987     return SL_STATUS_INVALID_PARAMETER;
1988   }
1989   if ((twt_req->req_type != REQUEST_TWT)
1990       && (twt_req->wake_duration == 0 || twt_req->wake_int_mantissa == 0
1991           || ((uint32_t)twt_req->wake_duration
1992               * (uint32_t)(twt_req->wake_duration_unit ? TWT_WAKE_DURATION_UNIT_1024TU : TWT_WAKE_DURATION_UNIT_256TU))
1993                > ((uint64_t)((twt_req->wake_int_mantissa) * ((uint64_t)1 << twt_req->wake_int_exp))))) {
1994     return SL_STATUS_INVALID_PARAMETER;
1995   }
1996   if ((twt_req->twt_channel != 0) || (twt_req->twt_protection != 0) || (twt_req->implicit_twt != 1)) {
1997     return SL_STATUS_INVALID_PARAMETER;
1998   }
1999   sl_status_t status = sl_si91x_driver_send_command(RSI_WLAN_REQ_TWT_PARAMS,
2000                                                     SI91X_WLAN_CMD,
2001                                                     twt_req,
2002                                                     sizeof(sl_wifi_twt_request_t),
2003                                                     SL_SI91X_WAIT_FOR(35000),
2004                                                     NULL,
2005                                                     NULL);
2006   VERIFY_STATUS_AND_RETURN(status);
2007   return status;
2008 }
2009 
sl_wifi_target_wake_time_auto_selection(sl_wifi_twt_selection_t * twt_auto_request)2010 sl_status_t sl_wifi_target_wake_time_auto_selection(sl_wifi_twt_selection_t *twt_auto_request)
2011 {
2012   if ((twt_auto_request->twt_enable != 0) && (twt_auto_request->twt_enable != 1)) {
2013     return SL_STATUS_INVALID_PARAMETER;
2014   }
2015   if ((twt_auto_request->twt_enable == 1)
2016       && ((twt_auto_request->rx_latency > MAX_TX_AND_RX_LATENCY_LIMIT)
2017           || (twt_auto_request->tx_latency > MAX_TX_AND_RX_LATENCY_LIMIT))) {
2018     return SL_STATUS_INVALID_PARAMETER;
2019   }
2020   twt_auto_request->rx_latency = (twt_auto_request->rx_latency == 0) ? 2000 : twt_auto_request->rx_latency;
2021   if ((twt_auto_request->rx_latency < 2000)
2022       || (twt_auto_request->average_tx_throughput > (DEVICE_AVERAGE_THROUGHPUT / 2))) {
2023     return SL_STATUS_INVALID_PARAMETER;
2024   }
2025   if ((twt_auto_request->tx_latency < 200) && (twt_auto_request->tx_latency != 0)) {
2026     return SL_STATUS_INVALID_PARAMETER;
2027   }
2028   sl_status_t status = sl_si91x_driver_send_command(RSI_WLAN_REQ_TWT_AUTO_CONFIG,
2029                                                     SI91X_WLAN_CMD,
2030                                                     twt_auto_request,
2031                                                     sizeof(sl_wifi_twt_selection_t),
2032                                                     SL_SI91X_WAIT_FOR(35000),
2033                                                     NULL,
2034                                                     NULL);
2035   VERIFY_STATUS_AND_RETURN(status);
2036   return status;
2037 }
2038 
sl_wifi_disable_target_wake_time(sl_wifi_twt_request_t * twt_req)2039 sl_status_t sl_wifi_disable_target_wake_time(sl_wifi_twt_request_t *twt_req)
2040 {
2041   if ((!twt_req->twt_enable) && ((twt_req->twt_flow_id == 0xFF) || (twt_req->twt_flow_id <= 7))) {
2042     sl_status_t status = sl_si91x_driver_send_command(RSI_WLAN_REQ_TWT_PARAMS,
2043                                                       SI91X_WLAN_CMD,
2044                                                       twt_req,
2045                                                       sizeof(sl_wifi_twt_request_t),
2046                                                       SL_SI91X_WAIT_FOR(35000),
2047                                                       NULL,
2048                                                       NULL);
2049     VERIFY_STATUS_AND_RETURN(status);
2050     return status;
2051   }
2052 
2053   return SL_STATUS_INVALID_PARAMETER;
2054 }
2055 
sl_wifi_reschedule_twt(uint8_t flow_id,sl_wifi_reschedule_twt_action_t twt_action,uint64_t suspend_duration)2056 sl_status_t sl_wifi_reschedule_twt(uint8_t flow_id,
2057                                    sl_wifi_reschedule_twt_action_t twt_action,
2058                                    uint64_t suspend_duration)
2059 {
2060   if (!device_initialized) {
2061     return SL_STATUS_NOT_INITIALIZED;
2062   }
2063   if (flow_id > MAX_FLOW_ID) {
2064     return SL_STATUS_INVALID_PARAMETER;
2065   }
2066   if ((twt_action == SL_WIFI_SUSPEND_INDEFINITELY || twt_action == SL_WIFI_RESUME_IMMEDIATELY)
2067       && suspend_duration > 0) {
2068     return SL_STATUS_INVALID_PARAMETER;
2069   }
2070   if (twt_action == SL_WIFI_SUSPEND_FOR_DURATION
2071       && (suspend_duration < 1 || suspend_duration > MAX_TWT_SUSPEND_DURATION)) {
2072     return SL_STATUS_INVALID_PARAMETER;
2073   }
2074   if (twt_action != SL_WIFI_SUSPEND_INDEFINITELY && twt_action != SL_WIFI_SUSPEND_FOR_DURATION
2075       && twt_action != SL_WIFI_RESUME_IMMEDIATELY) {
2076     return SL_STATUS_INVALID_PARAMETER;
2077   }
2078 
2079   sl_wifi_reschedule_twt_config_t reschedule_twt_config = { 0 };
2080   reschedule_twt_config.flow_id                         = flow_id;
2081   reschedule_twt_config.twt_action                      = twt_action;
2082   reschedule_twt_config.suspend_duration                = suspend_duration;
2083   sl_status_t status                                    = sl_si91x_driver_send_command(SL_WIFI_REQ_RESCHEDULE_TWT,
2084                                                     SI91X_WLAN_CMD,
2085                                                     &reschedule_twt_config,
2086                                                     sizeof(sl_wifi_reschedule_twt_config_t),
2087                                                     SL_SI91X_WAIT_FOR(35000),
2088                                                     NULL,
2089                                                     NULL);
2090   VERIFY_STATUS_AND_RETURN(status);
2091   return status;
2092 }
2093 
sl_wifi_filter_broadcast(uint16_t beacon_drop_threshold,uint8_t filter_bcast_in_tim,uint8_t filter_bcast_tim_till_next_cmd)2094 sl_status_t sl_wifi_filter_broadcast(uint16_t beacon_drop_threshold,
2095                                      uint8_t filter_bcast_in_tim,
2096                                      uint8_t filter_bcast_tim_till_next_cmd)
2097 {
2098   sl_status_t status                                       = SL_STATUS_OK;
2099   sl_si91x_request_wlan_filter_broadcast_t sl_filter_bcast = { 0 };
2100   sl_filter_bcast.beacon_drop_threshold[0]                 = beacon_drop_threshold & 0x00FF;
2101   sl_filter_bcast.beacon_drop_threshold[1]                 = (beacon_drop_threshold >> 8) & 0x00FF;
2102   sl_filter_bcast.filter_bcast_in_tim                      = filter_bcast_in_tim;
2103   sl_filter_bcast.filter_bcast_tim_till_next_cmd           = filter_bcast_tim_till_next_cmd;
2104 
2105   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_FILTER_BCAST_PACKETS,
2106                                         SI91X_WLAN_CMD,
2107                                         &sl_filter_bcast,
2108                                         sizeof(sl_si91x_request_wlan_filter_broadcast_t),
2109                                         SL_SI91X_WAIT_FOR(30100),
2110                                         NULL,
2111                                         NULL);
2112   VERIFY_STATUS_AND_RETURN(status);
2113   return status;
2114 }
2115 
sl_wifi_update_gain_table(uint8_t band,uint8_t bandwidth,uint8_t * payload,uint16_t payload_length)2116 sl_status_t sl_wifi_update_gain_table(uint8_t band, uint8_t bandwidth, uint8_t *payload, uint16_t payload_length)
2117 {
2118   sl_status_t status                             = SL_STATUS_OK;
2119   sl_si91x_gain_table_info_t *sl_gain_table_info = malloc(sizeof(sl_si91x_gain_table_info_t) + payload_length);
2120   if (sl_gain_table_info == NULL) {
2121     return SL_STATUS_ALLOCATION_FAILED;
2122   }
2123   sl_gain_table_info->band      = band;
2124   sl_gain_table_info->bandwidth = bandwidth;
2125   sl_gain_table_info->size      = payload_length;
2126   sl_gain_table_info->reserved  = 0;
2127 
2128   memcpy(sl_gain_table_info->gain_table, payload, payload_length);
2129   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_GAIN_TABLE,
2130                                         SI91X_WLAN_CMD,
2131                                         sl_gain_table_info,
2132                                         sizeof(sl_si91x_gain_table_info_t) + (sl_gain_table_info->size),
2133                                         SL_SI91X_WAIT_FOR(30100),
2134                                         NULL,
2135                                         NULL);
2136   free(sl_gain_table_info);
2137   VERIFY_STATUS_AND_RETURN(status);
2138   return status;
2139 }
2140 
sl_wifi_set_11ax_config(uint8_t guard_interval)2141 sl_status_t sl_wifi_set_11ax_config(uint8_t guard_interval)
2142 {
2143   sl_status_t status = SL_STATUS_OK;
2144 #if !(SLI_SI91X_CONFIG_WIFI6_PARAMS)
2145   return SL_STATUS_NOT_SUPPORTED;
2146 #endif
2147   sl_si91x_11ax_config_params_t config_11ax_params = { 0 };
2148   config_11ax_params.guard_interval                = guard_interval;
2149   config_11ax_params.nominal_pe                    = NOMINAL_PE;
2150   config_11ax_params.dcm_enable                    = DCM_ENABLE;
2151   config_11ax_params.ldpc_enable                   = LDPC_ENABLE;
2152   config_11ax_params.ng_cb_enable                  = NG_CB_ENABLE;
2153   config_11ax_params.ng_cb_values                  = NG_CB_VALUES;
2154   config_11ax_params.uora_enable                   = UORA_ENABLE;
2155   config_11ax_params.trigger_rsp_ind               = TRIGGER_RESP_IND;
2156   config_11ax_params.ipps_valid_value              = IPPS_VALID_VALUE;
2157   config_11ax_params.tx_only_on_ap_trig            = TX_ONLY_ON_AP_TRIG;
2158   config_11ax_params.twt_support                   = SLI_SI91X_ENABLE_TWT_FEATURE;
2159   config_11ax_params.config_er_su                  = CONFIG_ER_SU;
2160   config_11ax_params.disable_su_beamformee_support = SLI_SI91X_DISABLE_SU_BEAMFORMEE_SUPPORT;
2161 
2162   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_11AX_PARAMS,
2163                                         SI91X_WLAN_CMD,
2164                                         &config_11ax_params,
2165                                         sizeof(config_11ax_params),
2166                                         SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
2167                                         NULL,
2168                                         NULL);
2169   VERIFY_STATUS_AND_RETURN(status);
2170   return status;
2171 }
2172 
sl_wifi_set_listen_interval(sl_wifi_interface_t interface,sl_wifi_listen_interval_t listen_interval)2173 sl_status_t sl_wifi_set_listen_interval(sl_wifi_interface_t interface, sl_wifi_listen_interval_t listen_interval)
2174 {
2175   UNUSED_PARAMETER(interface);
2176 
2177   if (!device_initialized) {
2178     return SL_STATUS_NOT_INITIALIZED;
2179   }
2180 
2181   sl_si91x_set_listen_interval(listen_interval.listen_interval);
2182 
2183   return SL_STATUS_OK;
2184 }
2185 
sl_wifi_get_listen_interval(sl_wifi_interface_t interface,sl_wifi_listen_interval_t * listen_interval)2186 sl_status_t sl_wifi_get_listen_interval(sl_wifi_interface_t interface, sl_wifi_listen_interval_t *listen_interval)
2187 {
2188   if (!device_initialized) {
2189     return SL_STATUS_NOT_INITIALIZED;
2190   }
2191 
2192   if (!sl_wifi_is_interface_up(interface)) {
2193     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
2194   }
2195 
2196   SL_WIFI_ARGS_CHECK_NULL_POINTER(listen_interval);
2197 
2198   listen_interval->listen_interval = sl_si91x_get_listen_interval();
2199 
2200   return SL_STATUS_OK;
2201 }
2202 
sl_wifi_enable_monitor_mode(sl_wifi_interface_t interface)2203 sl_status_t sl_wifi_enable_monitor_mode(sl_wifi_interface_t interface)
2204 {
2205   UNUSED_PARAMETER(interface);
2206   return SL_STATUS_NOT_SUPPORTED;
2207 }
2208 
sl_wifi_disable_monitor_mode(sl_wifi_interface_t interface)2209 sl_status_t sl_wifi_disable_monitor_mode(sl_wifi_interface_t interface)
2210 {
2211   UNUSED_PARAMETER(interface);
2212   return SL_STATUS_NOT_SUPPORTED;
2213 }
2214 
sl_wifi_start_p2p_discovery(sl_wifi_interface_t interface,const sl_wifi_p2p_configuration_t * configuration,sl_wifi_credential_id_t credential_id)2215 sl_status_t sl_wifi_start_p2p_discovery(sl_wifi_interface_t interface,
2216                                         const sl_wifi_p2p_configuration_t *configuration,
2217                                         sl_wifi_credential_id_t credential_id)
2218 {
2219   UNUSED_PARAMETER(interface);
2220   UNUSED_PARAMETER(configuration);
2221   UNUSED_PARAMETER(credential_id);
2222   return SL_STATUS_NOT_SUPPORTED;
2223 }
2224 
sl_wifi_p2p_connect(sl_wifi_interface_t interface,const sl_wifi_p2p_configuration_t * configuration)2225 sl_status_t sl_wifi_p2p_connect(sl_wifi_interface_t interface, const sl_wifi_p2p_configuration_t *configuration)
2226 {
2227   UNUSED_PARAMETER(interface);
2228   UNUSED_PARAMETER(configuration);
2229   return SL_STATUS_NOT_SUPPORTED;
2230 }
2231 
sl_wifi_transceiver_set_channel(sl_wifi_interface_t interface,sl_wifi_transceiver_set_channel_t channel)2232 sl_status_t sl_wifi_transceiver_set_channel(sl_wifi_interface_t interface, sl_wifi_transceiver_set_channel_t channel)
2233 {
2234   sl_status_t status = SL_STATUS_OK;
2235   sl_si91x_operation_mode_t opermode;
2236 
2237   if (!device_initialized) {
2238     return SL_STATUS_NOT_INITIALIZED;
2239   }
2240 
2241   opermode = get_opermode();
2242   if (opermode != SL_SI91X_TRANSCEIVER_MODE) {
2243     SL_DEBUG_LOG("Invalid mode: %d. Command only supported in Wi-Fi transceiver opermode(7)\r\n", opermode);
2244     return SL_STATUS_SI91X_COMMAND_GIVEN_IN_INVALID_STATE;
2245   }
2246 
2247   if ((channel.chan_info.channel < 1) || (channel.chan_info.channel > 14)) {
2248     return SL_STATUS_TRANSCEIVER_INVALID_CHANNEL;
2249   }
2250 
2251   // User configuration for band and bandwidth are unsupported
2252   channel.chan_info.band      = SL_WIFI_BAND_2_4GHZ;
2253   channel.chan_info.bandwidth = SL_WIFI_BANDWIDTH_20MHz;
2254 
2255   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_SET_TRANSCEIVER_CHANNEL,
2256                                         SI91X_WLAN_CMD,
2257                                         &channel,
2258                                         sizeof(channel),
2259                                         SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
2260                                         NULL,
2261                                         NULL);
2262 
2263   VERIFY_STATUS_AND_RETURN(status);
2264 
2265   if (interface == SL_WIFI_TRANSCEIVER_INTERFACE) {
2266     interface_is_up[SL_WIFI_TRANSCEIVER_INTERFACE_INDEX] = true;
2267   }
2268 
2269   return status;
2270 }
2271 
sl_wifi_set_transceiver_parameters(sl_wifi_interface_t interface,sl_wifi_transceiver_parameters_t * params)2272 sl_status_t sl_wifi_set_transceiver_parameters(sl_wifi_interface_t interface, sl_wifi_transceiver_parameters_t *params)
2273 {
2274   sl_status_t status                 = SL_STATUS_OK;
2275   sl_si91x_operation_mode_t opermode = 0;
2276   sl_wifi_buffer_t *buffer           = NULL;
2277   sl_si91x_packet_t *packet          = NULL;
2278 
2279   if (!device_initialized) {
2280     return SL_STATUS_NOT_INITIALIZED;
2281   }
2282 
2283   opermode = get_opermode();
2284   if (opermode != SL_SI91X_TRANSCEIVER_MODE) {
2285     SL_DEBUG_LOG("Invalid mode: %d. Command only supported in Wi-Fi transceiver opermode(7)\r\n", opermode);
2286     return SL_STATUS_SI91X_COMMAND_GIVEN_IN_INVALID_STATE;
2287   }
2288 
2289   SL_VERIFY_POINTER_OR_RETURN(params, SL_STATUS_NULL_POINTER);
2290 
2291   if (params->set) {
2292     //! Transceiver configurations shall not be changed dynamically
2293     if (sl_wifi_is_interface_up(interface)) {
2294       return SL_STATUS_SI91X_COMMAND_GIVEN_IN_INVALID_STATE;
2295     }
2296 
2297     if ((!params->retransmit_count) || (params->retransmit_count > MAX_RETRANSMIT_COUNT)) {
2298       return SL_STATUS_TRANSCEIVER_INVALID_CONFIG;
2299     }
2300     for (uint8_t i = 0; i < 4; i++) {
2301       if ((params->cw_params[i].cwmin > MAX_CW_EXPN_COUNT) || (params->cw_params[i].cwmax > MAX_CW_EXPN_COUNT)
2302           || (params->cw_params[i].aifsn > MAX_AIFSN)) {
2303         return SL_STATUS_TRANSCEIVER_INVALID_CONFIG;
2304       }
2305     }
2306   }
2307 
2308   status =
2309     sl_si91x_driver_send_command(RSI_WLAN_REQ_TRANSCEIVER_CONFIG_PARAMS,
2310                                  SI91X_WLAN_CMD,
2311                                  params,
2312                                  sizeof(sl_wifi_transceiver_parameters_t),
2313                                  params->set ? SL_SI91X_WAIT_FOR_COMMAND_SUCCESS : SL_SI91X_WAIT_FOR_COMMAND_RESPONSE,
2314                                  NULL,
2315                                  &buffer);
2316 
2317   //! Return if API called to set params. Otherwise, if API called to get params, continue further to copy params received from firmware.
2318   if (params->set) {
2319     return status;
2320   }
2321 
2322   if ((status != SL_STATUS_OK) && (buffer != NULL)) {
2323     sl_si91x_host_free_buffer(buffer);
2324   }
2325 
2326   VERIFY_STATUS_AND_RETURN(status);
2327 
2328   packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
2329   if (packet->length > 0) {
2330     memcpy(params, packet->data, sizeof(sl_wifi_transceiver_parameters_t));
2331   }
2332 
2333   sl_si91x_host_free_buffer(buffer);
2334   return status;
2335 }
2336 
sl_wifi_transceiver_up(sl_wifi_interface_t interface,sl_wifi_transceiver_configuration_t * config)2337 sl_status_t sl_wifi_transceiver_up(sl_wifi_interface_t interface, sl_wifi_transceiver_configuration_t *config)
2338 {
2339   sl_status_t status = SL_STATUS_OK;
2340 
2341   if (!device_initialized) {
2342     return SL_STATUS_NOT_INITIALIZED;
2343   }
2344 
2345   SL_VERIFY_POINTER_OR_RETURN(config, SL_STATUS_NULL_POINTER);
2346 
2347   status = sl_wifi_set_transceiver_parameters(interface, &config->parameters);
2348   if (status != RSI_SUCCESS) {
2349     SL_DEBUG_LOG("\r\nSet transceiver config params failed, error code : 0x%lX\r\n", status);
2350     return status;
2351   } else {
2352     SL_DEBUG_LOG("\r\nSet transceiver config params successful");
2353   }
2354 
2355   // Update params.set = 0 to fetch transceiver config params
2356   memset(&config->parameters, 0, sizeof(sl_wifi_transceiver_parameters_t));
2357   status = sl_wifi_set_transceiver_parameters(interface, &config->parameters);
2358   if (status != RSI_SUCCESS) {
2359     SL_DEBUG_LOG("\r\nGet transceiver config params failed, error code : 0x%lX\r\n", status);
2360   } else {
2361     SL_DEBUG_LOG("\r\nTransceiver config params:");
2362     SL_DEBUG_LOG("\r\nRetransmit count: %d", config->parameters.retransmit_count);
2363     for (uint8_t i = 0; i < 4; i++) {
2364       SL_DEBUG_LOG("\r\nAC index[%d] - cwmin: %d, cwmax: %d, aifsn: %d",
2365                    i,
2366                    config->parameters.cw_params[i].cwmin,
2367                    config->parameters.cw_params[i].cwmax,
2368                    config->parameters.cw_params[i].aifsn);
2369     }
2370   }
2371 
2372   // Set transceiver mode channel
2373   status = sl_wifi_transceiver_set_channel(interface, config->channel);
2374   if (status != SL_STATUS_OK) {
2375     SL_DEBUG_LOG("\r\nSet Channel Failed, Error Code : 0x%lX\r\n", status);
2376     return status;
2377   } else {
2378     SL_DEBUG_LOG("\r\nSet Channel(%d) Initialization success\r\n", config->channel.chan_info.channel);
2379   }
2380 
2381   // Get DUT MAC address to use as Addr2/Transmitter Addresss
2382   status = sl_wifi_get_mac_address(interface, &config->dut_mac);
2383   if (status == SL_STATUS_OK) {
2384     SL_DEBUG_LOG("\r\nDevice MAC address: %x:%x:%x:%x:%x:%x\r\n",
2385                  config->dut_mac.octet[0],
2386                  config->dut_mac.octet[1],
2387                  config->dut_mac.octet[2],
2388                  config->dut_mac.octet[3],
2389                  config->dut_mac.octet[4],
2390                  config->dut_mac.octet[5]);
2391   } else {
2392     SL_DEBUG_LOG("\r\nFailed to get mac address: 0x%lX\r\n", status);
2393     return SL_STATUS_FAIL;
2394   }
2395 
2396   return SL_STATUS_OK;
2397 }
2398 
validate_datarate(sl_wifi_data_rate_t data_rate)2399 int32_t validate_datarate(sl_wifi_data_rate_t data_rate)
2400 {
2401   switch (data_rate) {
2402     case SL_WIFI_DATA_RATE_1:
2403     case SL_WIFI_DATA_RATE_2:
2404     case SL_WIFI_DATA_RATE_5_5:
2405     case SL_WIFI_DATA_RATE_11:
2406     case SL_WIFI_DATA_RATE_6:
2407     case SL_WIFI_DATA_RATE_9:
2408     case SL_WIFI_DATA_RATE_12:
2409     case SL_WIFI_DATA_RATE_18:
2410     case SL_WIFI_DATA_RATE_24:
2411     case SL_WIFI_DATA_RATE_36:
2412     case SL_WIFI_DATA_RATE_48:
2413     case SL_WIFI_DATA_RATE_54:
2414       return SL_STATUS_OK;
2415     default:
2416       return SL_STATUS_TRANSCEIVER_INVALID_DATA_RATE;
2417   }
2418 }
2419 
sl_wifi_send_transceiver_data(sl_wifi_interface_t interface,sl_wifi_transceiver_tx_data_control_t * control,uint8_t * payload,uint16_t payload_len)2420 sl_status_t sl_wifi_send_transceiver_data(sl_wifi_interface_t interface,
2421                                           sl_wifi_transceiver_tx_data_control_t *control,
2422                                           uint8_t *payload,
2423                                           uint16_t payload_len)
2424 {
2425   sl_status_t status = SL_STATUS_OK;
2426 
2427   if (!device_initialized) {
2428     return SL_STATUS_NOT_INITIALIZED;
2429   }
2430 
2431   if (!sl_wifi_is_interface_up(interface)) {
2432     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
2433   }
2434 
2435   if ((!payload_len) || (payload_len > MAX_PAYLOAD_LEN)) {
2436     return SL_STATUS_INVALID_PARAMETER;
2437   }
2438 
2439   SL_VERIFY_POINTER_OR_RETURN(control, SL_STATUS_NULL_POINTER);
2440   SL_VERIFY_POINTER_OR_RETURN(payload, SL_STATUS_NULL_POINTER);
2441 
2442   if (IS_FIXED_DATA_RATE(control->ctrl_flags)) {
2443     if (validate_datarate(control->rate)) {
2444       return SL_STATUS_TRANSCEIVER_INVALID_DATA_RATE;
2445     }
2446   }
2447 
2448   status = sl_si91x_driver_send_transceiver_data(control, payload, payload_len, SL_SI91X_WAIT_FOR(1000));
2449 
2450   return status;
2451 }
2452 
sl_wifi_update_transceiver_peer_list(sl_wifi_interface_t interface,sl_wifi_transceiver_peer_update_t peer)2453 sl_status_t sl_wifi_update_transceiver_peer_list(sl_wifi_interface_t interface, sl_wifi_transceiver_peer_update_t peer)
2454 {
2455   sl_status_t status = SL_STATUS_OK;
2456 
2457   if (!device_initialized) {
2458     return SL_STATUS_NOT_INITIALIZED;
2459   }
2460 
2461   if (!sl_wifi_is_interface_up(interface)) {
2462     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
2463   }
2464 
2465   if ((peer.flags & TRANSCEIVER_PEER_ADD_FLAG) && (peer.flags & TRANSCEIVER_PEER_AUTO_RATE_FLAG)
2466       && (!peer.peer_supported_rate_bitmap)) {
2467     return SL_STATUS_TRANSCEIVER_INVALID_DATA_RATE;
2468   }
2469 
2470   if (IS_MAC_ZERO(peer.peer_mac_address)) {
2471     return SL_STATUS_TRANSCEIVER_INVALID_MAC_ADDRESS;
2472   }
2473   if (IS_BCAST_MCAST_MAC(peer.peer_mac_address[0])) {
2474     return SL_STATUS_TRANSCEIVER_INVALID_MAC_ADDRESS;
2475   }
2476 
2477   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_TRANSCEIVER_PEER_LIST_UPDATE,
2478                                         SI91X_WLAN_CMD,
2479                                         &peer,
2480                                         sizeof(sl_wifi_transceiver_peer_update_t),
2481                                         SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
2482                                         NULL,
2483                                         NULL);
2484   return status;
2485 }
2486 
sl_wifi_set_transceiver_multicast_filter(sl_wifi_interface_t interface,sl_wifi_transceiver_mcast_filter_t mcast)2487 sl_status_t sl_wifi_set_transceiver_multicast_filter(sl_wifi_interface_t interface,
2488                                                      sl_wifi_transceiver_mcast_filter_t mcast)
2489 {
2490   sl_status_t status = SL_STATUS_OK;
2491 
2492   if (!device_initialized) {
2493     return SL_STATUS_NOT_INITIALIZED;
2494   }
2495 
2496   if (!sl_wifi_is_interface_up(interface)) {
2497     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
2498   }
2499   if (mcast.flags & TRANSCEIVER_MCAST_FILTER_EN) {
2500     if ((!mcast.num_of_mcast_addr) || mcast.num_of_mcast_addr > TRANSCEIVER_MCAST_FILTER_ADDR_LIMIT) {
2501       return SL_STATUS_INVALID_PARAMETER;
2502     }
2503     for (uint8_t i = 0; i < mcast.num_of_mcast_addr; i++) {
2504       if (IS_MAC_ZERO(mcast.mac[i])) {
2505         return SL_STATUS_TRANSCEIVER_INVALID_MAC_ADDRESS;
2506       }
2507     }
2508   }
2509 
2510   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_SET_TRANSCEIVER_MCAST_FILTER,
2511                                         SI91X_WLAN_CMD,
2512                                         &mcast,
2513                                         sizeof(sl_wifi_transceiver_mcast_filter_t),
2514                                         SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
2515                                         NULL,
2516                                         NULL);
2517   return status;
2518 }
2519 
sl_wifi_flush_transceiver_data(sl_wifi_interface_t interface)2520 sl_status_t sl_wifi_flush_transceiver_data(sl_wifi_interface_t interface)
2521 {
2522   sl_status_t status = SL_STATUS_OK;
2523 
2524   if (!device_initialized) {
2525     return SL_STATUS_NOT_INITIALIZED;
2526   }
2527 
2528   if (!sl_wifi_is_interface_up(interface)) {
2529     return SL_STATUS_WIFI_INTERFACE_NOT_UP;
2530   }
2531 
2532   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_TRANSCEIVER_FLUSH_DATA_Q,
2533                                         SI91X_WLAN_CMD,
2534                                         NULL,
2535                                         0,
2536                                         SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
2537                                         NULL,
2538                                         NULL);
2539 
2540   return status;
2541 }
2542 
sl_wifi_configure_multicast_filter(sl_wifi_multicast_filter_info_t * multicast_filter_info)2543 sl_status_t sl_wifi_configure_multicast_filter(sl_wifi_multicast_filter_info_t *multicast_filter_info)
2544 {
2545   uint16_t multicast_bitmap = 0;
2546 
2547   if (!device_initialized) {
2548     return SL_STATUS_NOT_INITIALIZED;
2549   }
2550   multicast_bitmap = (uint16_t)multicast_filter_info->command_type;
2551 
2552   if ((multicast_filter_info->command_type == SL_WIFI_MULTICAST_MAC_ADD_BIT)
2553       || (multicast_filter_info->command_type == SL_WIFI_MULTICAST_MAC_CLEAR_BIT)) {
2554     multicast_bitmap |= (sli_multicast_mac_hash((uint8_t *)&(multicast_filter_info->mac_address)) << 8);
2555   }
2556 
2557   sl_status_t status = SL_STATUS_OK;
2558 
2559   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_SET_MULTICAST_FILTER,
2560                                         SI91X_WLAN_CMD,
2561                                         &multicast_bitmap,
2562                                         sizeof(multicast_bitmap),
2563                                         SL_SI91X_WAIT_FOR(30100),
2564                                         NULL,
2565                                         NULL);
2566 
2567   VERIFY_STATUS_AND_RETURN(status);
2568   return status;
2569 }
2570 
sli_si91x_update_ap_client_info()2571 sl_status_t sli_si91x_update_ap_client_info()
2572 {
2573   return sl_wifi_get_ap_client_info(SL_WIFI_AP_INTERFACE, &sli_si91x_client_info);
2574 }
2575 
sli_si91x_get_ap_client_ip_address_from_mac_address(const sl_mac_address_t mac_add)2576 sl_ip_address_t *sli_si91x_get_ap_client_ip_address_from_mac_address(const sl_mac_address_t mac_add)
2577 {
2578 
2579   for (uint16_t station_info_index = 0; station_info_index < sli_si91x_client_info.client_count; station_info_index++) {
2580     sl_wifi_client_info_t *station_info = &sli_si91x_client_info.client_info[station_info_index];
2581     if (!memcmp((const uint8_t *)&mac_add, (uint8_t *)&station_info->mac_adddress, sizeof(sl_mac_address_t))) {
2582       return &station_info->ip_address;
2583     }
2584   }
2585   return NULL;
2586 }
2587