1 /***************************************************************************/ /**
2  * @file
3  * @brief
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2024 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_si91x_protocol_types.h"
31 #include "sl_si91x_constants.h"
32 #include "sl_si91x_driver.h"
33 #include "sl_wifi_constants.h"
34 #include "sl_wifi_credentials.h"
35 #include "sl_status.h"
36 #include "sl_constants.h"
37 #include "sl_wifi_types.h"
38 #include "sl_rsi_utility.h"
39 #include "cmsis_os2.h" // CMSIS RTOS2
40 #include "sl_si91x_types.h"
41 #include "sl_si91x_core_utilities.h"
42 #ifdef SLI_SI91X_OFFLOAD_NETWORK_STACK
43 #include "sl_si91x_socket_constants.h"
44 #include "sl_si91x_socket_utility.h"
45 #endif
46 #include "em_core.h"
47 #include <string.h>
48 #include "assert.h"
49 
50 /******************************************************
51  *               Macro Declarations
52  ******************************************************/
53 // Macro to check the status and return it if it's not SL_STATUS_OK
54 #define VERIFY_STATUS(s)   \
55   do {                     \
56     if (s != SL_STATUS_OK) \
57       return s;            \
58   } while (0)
59 
60 // WLAN Management Frame Sub-Type
61 #define SLI_WIFI_FRAME_SUBTYPE_MASK       0xf0 // WLAN Management Frame Sub-Type Mask
62 #define SLI_WIFI_FRAME_SUBTYPE_PROBE_RESP 0x50 // WLAN Management Frame Sub-Type Probe Response Frame
63 #define SLI_WIFI_FRAME_SUBTYPE_BEACON     0x80 // WLAN Management Frame Sub-Type Beacon Frame
64 #define SLI_WIFI_MINIMUM_FRAME_LENGTH     36   // Minimum Frame Length of WLAN Management Frame
65 #define SLI_WIFI_HARDWARE_ADDRESS_LENGTH  6    // Hardware Address Length
66 
67 // WLAN Information Element Type
68 #define SLI_WLAN_TAG_SSID            0   // WLAN Information Element Type SSID
69 #define SLI_WLAN_TAG_RSN             48  // WLAN Robust Security Network Information Element
70 #define SLI_WLAN_TAG_VENDOR_SPECIFIC 221 // WLAN Vendor Specific Information Element
71 
72 // Authentication key Management Type
73 #define SLI_AUTH_KEY_MGMT_UNSPEC_802_1X   0x000FAC01 // Unspecified Authentication key Management Type
74 #define SLI_AUTH_KEY_MGMT_PSK_OVER_802_1X 0x000FAC02 // PSK Authentication key Management Type
75 #define SLI_AUTH_KEY_MGMT_802_1X_SHA256   0x000FAC05 // SHA256 Authentication key Management Type
76 #define SLI_AUTH_KEY_MGMT_PSK_SHA256      0x000FAC06 // PSK SHA256 Authentication key Management Type
77 #define SLI_AUTH_KEY_MGMT_SAE             0x000FAC08 // SAE Authentication key Management Type
78 #define SLI_AUTH_KEY_MGMT_FT_SAE          0x000FAC09 // FT_SAE Authentication key Management Type
79 
80 // Authentication key Management Type Flags
81 #define SLI_WLAN_AUTH_KEY_MGMT_TYPE_WPA           0x00000001 // WPA AKM Type
82 #define SLI_WLAN_AUTH_KEY_MGMT_TYPE_WPA2          0x00000002 // WPA2 AKM Type
83 #define SLI_WLAN_AUTH_KEY_MGMT_TYPE_WPA_PSK       0x00000004 // WPA_PSK AKM Type
84 #define SLI_WLAN_AUTH_KEY_MGMT_TYPE_WPA2_PSK      0x00000008 // WPA2_PSK AKM Type
85 #define SLI_WLAN_AUTH_KEY_MGMT_TYPE_SAE           0x00010000 // SAE AKM Type
86 #define SLI_WLAN_AUTH_KEY_MGMT_TYPE_FT_SAE        0x00100000 // FT_SAE AKM Type
87 #define SLI_WLAN_AUTH_KEY_MGMT_TYPE_802_1X_SHA256 0x00020000 // SHA256 AKM Type
88 #define SLI_WLAN_AUTH_KEY_MGMT_TYPE_PSK_SHA256    0x00040000 // PSK_SHA256 AKM Type
89 
90 /// Task register ID to save firmware status
91 #define SLI_FW_STATUS_STORAGE_INVALID_INDEX 0xFF // Invalid index for firmware status storage
92 
93 /******************************************************
94  *               Local Type Declarations
95  ******************************************************/
96 // WLAN Frame
97 typedef struct {
98   uint8_t fc[2];                                   // Frame Control
99   uint8_t duration[2];                             // Duration
100   uint8_t da[SLI_WIFI_HARDWARE_ADDRESS_LENGTH];    // Destination Address
101   uint8_t sa[SLI_WIFI_HARDWARE_ADDRESS_LENGTH];    // Source Address
102   uint8_t bssid[SLI_WIFI_HARDWARE_ADDRESS_LENGTH]; // BSS Id
103   uint8_t sc[2];                                   // Sequence Control Id
104   uint8_t timestamp[8];                            // Time Stamp
105   uint8_t bi[2];                                   // Beacon Interval
106   uint8_t ci[2];                                   // Capability Information
107   uint8_t tagged_info[];                           // Variable Information Elememt
108 } sli_wifi_data_frame_t;
109 
110 // WLAN Information Element
111 typedef struct {
112   uint8_t tag;         // Information Element Tag Id
113   uint8_t data_length; // Information Element Data Length
114   uint8_t data[];      // Information Element Data
115 } sli_wifi_data_tagged_info_t;
116 
117 // Cipher suite
118 typedef struct {
119   uint8_t cs_oui[3]; // Cipher Suite OUI
120   uint8_t cs_type;   // Cipher Suite Type
121 } sli_wlan_cipher_suite_t;
122 
123 // WLAN Robust Security Network Information Element
124 typedef struct {
125   uint8_t version[2];          // RSN Version
126   sli_wlan_cipher_suite_t gcs; // Group cipher suite
127   uint8_t pcsc[2];             // Pairwise cipher suite count
128   uint8_t pcsl[];              // Pairwise cipher suite list
129 } sli_wlan_rsn_element_t;
130 
131 // WLAN Vendor Specific Information Element
132 typedef struct {
133   uint8_t oui[3];              // Vendor OUI
134   uint8_t vs_oui;              // Vendor specific OUI
135   uint8_t type;                // WPA Information Element
136   uint8_t wpa_version[2];      // WPA Version
137   sli_wlan_cipher_suite_t mcs; // Multicast Cipher Suite
138   uint8_t ucsc;                // Unicast Cipher Suite List Count
139   uint8_t ucsl[];              // Unicast Cipher Suite List
140 } sli_wlan_vendor_specific_element_t;
141 
142 // Scan Information
143 typedef struct sli_scan_info_s {
144   struct sli_scan_info_s *next;
145   uint8_t channel;                                 ///< Channel number of the AP
146   uint8_t security_mode;                           ///< Security mode of the AP
147   uint8_t rssi;                                    ///< RSSI value of the AP
148   uint8_t network_type;                            ///< AP network type
149   uint8_t ssid[34];                                ///< SSID of the AP
150   uint8_t bssid[SLI_WIFI_HARDWARE_ADDRESS_LENGTH]; ///< BSSID of the AP
151 } sli_scan_info_t;
152 
153 /******************************************************
154  *               Variable Declarations
155  ******************************************************/
156 osThreadId_t si91x_thread           = 0;
157 osThreadId_t si91x_event_thread     = 0;
158 osEventFlagsId_t si91x_events       = 0;
159 osEventFlagsId_t si91x_bus_events   = 0;
160 osEventFlagsId_t si91x_async_events = 0;
161 osMutexId_t malloc_free_mutex       = 0;
162 
163 #ifdef SL_SI91X_SIDE_BAND_CRYPTO
164 osMutexId_t side_band_crypto_mutex = 0;
165 #endif
166 
167 sli_si91x_command_queue_t cmd_queues[SI91X_CMD_MAX];
168 sl_si91x_buffer_queue_t sli_tx_data_queue;
169 
170 static bool sli_si91x_packet_status = 0;
171 
172 extern bool device_initialized;
173 
174 // Declaration of external functions
175 extern void si91x_bus_thread(void *args);
176 extern void si91x_event_handler_thread(void *args);
177 sl_status_t sl_si91x_host_power_cycle(void);
178 void convert_performance_profile_to_power_save_command(sl_si91x_performance_profile_t profile,
179                                                        sl_si91x_power_save_request_t *power_save_request);
180 extern sl_status_t sl_create_generic_rx_packet_from_params(sli_si91x_queue_packet_t **queue_packet,
181                                                            sl_wifi_buffer_t **packet_buffer,
182                                                            uint16_t packet_id,
183                                                            uint8_t flags,
184                                                            void *sdk_context,
185                                                            uint16_t frame_status);
186 void sl_debug_log(const char *format, ...);
187 
188 extern sli_si91x_performance_profile_t performance_profile;
189 
190 // NOTE: Boolean value determines whether firmware automatically closes the TCP socket in case of receiving termination from remote node or not.
191 static bool tcp_auto_close_enabled;
192 
193 // This value will be used in connect request/ AP configurations to set the TX power of the module
194 static sl_wifi_max_tx_power_t wifi_max_tx_power = {
195   .scan_tx_power = 0x1f, //Default power value set to max value supported in dBm
196   .join_tx_power = 0x1f, //Default power value set to max value supported in dBm
197 };
198 
199 static sl_wifi_rate_t saved_wifi_data_rate = SL_WIFI_AUTO_RATE;
200 
201 static sl_wifi_ap_configuration_t ap_configuration;
202 
203 static bool is_card_ready_required = true;
204 
205 sl_si91x_performance_profile_t current_performance_profile = HIGH_PERFORMANCE;
206 
207 static sl_si91x_boot_configuration_t saved_boot_configuration = { 0 };
208 
209 static sl_si91x_coex_mode_t coex_mode = 0;
210 
211 static sli_scan_info_t *scan_info_database = NULL;
212 
213 /******************************************************
214  *             Internal Function Declarations
215  ******************************************************/
sli_fw_status_storage_index_init(void)216 sl_status_t sli_fw_status_storage_index_init(void)
217 {
218   sl_status_t status = SL_STATUS_OK;
219 
220   // Declare a variable to store the current interrupt state
221   CORE_DECLARE_IRQ_STATE;
222 
223   // Enter a critical section by disabling interrupts
224   // This ensures that the following operations are executed atomically
225   CORE_ENTER_CRITICAL();
226 #ifdef SL_CATALOG_KERNEL_PRESENT
227   // Check if the code is running in a thread context & task register index is invalid
228   if (osThreadGetId() != NULL && sli_fw_status_storage_index == SLI_FW_STATUS_STORAGE_INVALID_INDEX) {
229     // Create a new task register id
230     status = sli_osTaskRegisterNew(&sli_fw_status_storage_index);
231     VERIFY_STATUS_AND_RETURN(status);
232   }
233 #endif
234   CORE_EXIT_CRITICAL();
235   return status;
236 }
237 
238 // Function to update a existing entry or create new entry for scan results database
sli_update_or_create_scan_info_element(const sli_scan_info_t * info)239 static sli_scan_info_t *sli_update_or_create_scan_info_element(const sli_scan_info_t *info)
240 {
241   sli_scan_info_t *element = NULL;
242 
243   element = scan_info_database;
244   while (NULL != element) {
245     if (0 == memcmp(info->bssid, element->bssid, SLI_WIFI_HARDWARE_ADDRESS_LENGTH)) {
246       element->channel       = element->channel;
247       element->security_mode = element->security_mode;
248       element->rssi          = element->rssi;
249       element->network_type  = element->network_type;
250       memcpy(element->ssid, info->ssid, 34);
251       break;
252     }
253     element = element->next;
254   }
255 
256   if (NULL == element) {
257     element = malloc(sizeof(sli_scan_info_t));
258     memcpy(element, info, sizeof(sli_scan_info_t));
259     element->next = NULL;
260     return element;
261   }
262 
263   return NULL;
264 }
265 
266 // Function to store a given scan info element in scan results database
sli_store_scan_info_element(sli_scan_info_t * info)267 static void sli_store_scan_info_element(sli_scan_info_t *info)
268 {
269   sli_scan_info_t *element = NULL;
270   sli_scan_info_t *head    = NULL;
271   sli_scan_info_t *tail    = NULL;
272 
273   if (NULL == info) {
274     return;
275   }
276 
277   element = sli_update_or_create_scan_info_element(info);
278   if (NULL == element) {
279     return;
280   }
281 
282   if (NULL == scan_info_database) {
283     scan_info_database = element;
284     return;
285   }
286 
287   tail = scan_info_database;
288   while (NULL != tail) {
289     if (element->rssi < tail->rssi) {
290       element->next = tail;
291       if (NULL == head) {
292         scan_info_database = element;
293       } else {
294         head->next = element;
295       }
296       break;
297     }
298 
299     head = tail;
300     tail = tail->next;
301 
302     if (NULL == tail) {
303       head->next = element;
304     }
305   }
306 
307   return;
308 }
309 
310 // Function to identify Authentication Key Management Type
sli_get_key_management_info(const sli_wlan_cipher_suite_t * akms,const uint16_t akmsc)311 static uint32_t sli_get_key_management_info(const sli_wlan_cipher_suite_t *akms, const uint16_t akmsc)
312 {
313   uint32_t key_mgmt = 0;
314   uint32_t oui_type;
315 
316   if (NULL == akms) {
317     return 0;
318   }
319 
320   for (int i = 0; i < akmsc; i++) {
321     oui_type = ((akms[i].cs_oui[0] << 24) | (akms[i].cs_oui[1] << 16) | (akms[i].cs_oui[2] << 8) | akms[0].cs_type);
322 
323     switch (oui_type) {
324       case SLI_AUTH_KEY_MGMT_UNSPEC_802_1X:
325         key_mgmt |= SLI_WLAN_AUTH_KEY_MGMT_TYPE_WPA | SLI_WLAN_AUTH_KEY_MGMT_TYPE_WPA2;
326         break;
327       case SLI_AUTH_KEY_MGMT_PSK_OVER_802_1X:
328         key_mgmt |= SLI_WLAN_AUTH_KEY_MGMT_TYPE_WPA_PSK | SLI_WLAN_AUTH_KEY_MGMT_TYPE_WPA2_PSK;
329         break;
330       case SLI_AUTH_KEY_MGMT_802_1X_SHA256:
331         key_mgmt |= SLI_WLAN_AUTH_KEY_MGMT_TYPE_802_1X_SHA256;
332         break;
333       case SLI_AUTH_KEY_MGMT_PSK_SHA256:
334         key_mgmt |= SLI_WLAN_AUTH_KEY_MGMT_TYPE_PSK_SHA256;
335         break;
336       case SLI_AUTH_KEY_MGMT_SAE:
337         key_mgmt |= SLI_WLAN_AUTH_KEY_MGMT_TYPE_SAE;
338         break;
339       case SLI_AUTH_KEY_MGMT_FT_SAE:
340         key_mgmt |= SLI_WLAN_AUTH_KEY_MGMT_TYPE_FT_SAE;
341         break;
342       default:
343         break;
344     }
345   }
346   return key_mgmt;
347 }
348 
349 // Helper function to process RSN element
process_rsn_element(const sli_wifi_data_tagged_info_t * info,sli_scan_info_t * scan_info)350 static void process_rsn_element(const sli_wifi_data_tagged_info_t *info, sli_scan_info_t *scan_info)
351 {
352   scan_info->security_mode            = SL_WIFI_WPA2_ENTERPRISE;
353   sli_wlan_rsn_element_t *rsn         = (sli_wlan_rsn_element_t *)info->data;
354   uint16_t pcsc                       = (uint16_t)(rsn->pcsc[0] | (rsn->pcsc[1] << 8));
355   uint8_t *akmslc                     = (rsn->pcsl + (pcsc * sizeof(sli_wlan_cipher_suite_t)));
356   uint16_t akmsc                      = (uint16_t)(akmslc[0] | (akmslc[1] << 8));
357   const sli_wlan_cipher_suite_t *akms = (sli_wlan_cipher_suite_t *)(akmslc + 2);
358   uint8_t wlan_gcs_oui[3]             = { 0x00, 0x0F, 0xAC };
359 
360   SL_DEBUG_LOG("RSN OUI %02x:%02x:%02x.\n", rsn->gcs.cs_oui[0], rsn->gcs.cs_oui[1], rsn->gcs.cs_oui[2]);
361   SL_DEBUG_LOG("Pairwise cipher suite count: %u.\n", pcsc);
362 
363   if (!memcmp(rsn->gcs.cs_oui, wlan_gcs_oui, 3)) {
364     scan_info->security_mode = SL_WIFI_WPA2;
365     uint32_t key = sli_get_key_management_info((const sli_wlan_cipher_suite_t *)akms, (const uint16_t)akmsc);
366 
367     if (akms[0].cs_type == 1) {
368       scan_info->security_mode = SL_WIFI_WPA2_ENTERPRISE;
369     }
370 
371     if (key & SLI_WLAN_AUTH_KEY_MGMT_TYPE_802_1X_SHA256) {
372       scan_info->security_mode = SL_WIFI_WPA3_ENTERPRISE;
373       if ((key & SLI_WLAN_AUTH_KEY_MGMT_TYPE_WPA) || (key & SLI_WLAN_AUTH_KEY_MGMT_TYPE_WPA2)) {
374         scan_info->security_mode = SL_WIFI_WPA3_TRANSITION_ENTERPRISE;
375       }
376     }
377 
378     if (key & SLI_WLAN_AUTH_KEY_MGMT_TYPE_SAE) {
379       scan_info->security_mode = SL_WIFI_WPA3;
380       if ((key & SLI_WLAN_AUTH_KEY_MGMT_TYPE_PSK_SHA256) || (key & SLI_WLAN_AUTH_KEY_MGMT_TYPE_WPA2_PSK)) {
381         scan_info->security_mode = SL_WIFI_WPA3_TRANSITION;
382       }
383     }
384   }
385 }
386 
387 // Helper function to process Vendor Specific element
process_vendor_specific_element(const sli_wifi_data_tagged_info_t * info,sli_scan_info_t * scan_info)388 static void process_vendor_specific_element(const sli_wifi_data_tagged_info_t *info, sli_scan_info_t *scan_info)
389 {
390   sli_wlan_vendor_specific_element_t *vendor = (sli_wlan_vendor_specific_element_t *)info->data;
391   uint8_t wlan_oui[3]                        = { 0x00, 0x50, 0xF2 };
392 
393   if ((!memcmp(vendor->oui, wlan_oui, 3)) && (vendor->vs_oui == 0x01)
394       && ((scan_info->security_mode == SL_WIFI_OPEN) || (scan_info->security_mode == SL_WIFI_WEP))) {
395     scan_info->security_mode            = SL_WIFI_WPA;
396     uint8_t *list_count                 = (vendor->ucsl + (sizeof(sli_wlan_cipher_suite_t) * vendor->ucsc));
397     uint16_t akmsc                      = (uint16_t)(list_count[0] | (list_count[1] << 8));
398     const sli_wlan_cipher_suite_t *akms = (sli_wlan_cipher_suite_t *)(list_count + 2);
399 
400     if ((0 != akmsc) && (akms[akmsc - 1].cs_type == 1)) {
401       scan_info->security_mode = SL_WIFI_WPA_ENTERPRISE;
402     }
403   }
404 }
405 
406 // Function to parse Information elements in WiFi Beacon or Probe response frames
sli_process_tag_info(const sli_wifi_data_tagged_info_t * info,sli_scan_info_t * scan_info)407 static void sli_process_tag_info(const sli_wifi_data_tagged_info_t *info, sli_scan_info_t *scan_info)
408 {
409   switch (info->tag) {
410     case SLI_WLAN_TAG_SSID:
411       memcpy(scan_info->ssid, info->data, info->data_length);
412       scan_info->ssid[info->data_length] = 0;
413       break;
414 
415     case SLI_WLAN_TAG_RSN:
416       process_rsn_element(info, scan_info);
417       break;
418 
419     case SLI_WLAN_TAG_VENDOR_SPECIFIC:
420       process_vendor_specific_element(info, scan_info);
421       break;
422 
423     default:
424       break;
425   }
426 
427   return;
428 }
429 
430 // Function to identify expected scan result based on filter
sli_filter_scan_info(const sli_scan_info_t * scan_info,const sl_wifi_extended_scan_result_parameters_t * extended_scan_parameters)431 static bool sli_filter_scan_info(const sli_scan_info_t *scan_info,
432                                  const sl_wifi_extended_scan_result_parameters_t *extended_scan_parameters)
433 {
434   if (NULL == scan_info) {
435     return false;
436   }
437 
438   if ((NULL != extended_scan_parameters->channel_filter)
439       && (*(extended_scan_parameters->channel_filter) != scan_info->channel)) {
440     return false;
441   }
442 
443   if ((NULL != extended_scan_parameters->security_mode_filter)
444       && (*(extended_scan_parameters->security_mode_filter) != scan_info->security_mode)) {
445     return false;
446   }
447 
448   if ((NULL != extended_scan_parameters->rssi_filter)
449       && (*(extended_scan_parameters->rssi_filter) <= scan_info->rssi)) {
450     return false;
451   }
452 
453   if ((NULL != extended_scan_parameters->network_type_filter)
454       && (*(extended_scan_parameters->network_type_filter) != scan_info->network_type)) {
455     return false;
456   }
457 
458   return true;
459 }
460 
461 /******************************************************
462  *            Internal Function Declarations
463  ******************************************************/
464 // Function to Parse the Beacon and Probe response Frames
sli_handle_wifi_beacon(sl_si91x_packet_t * packet)465 void sli_handle_wifi_beacon(sl_si91x_packet_t *packet)
466 {
467   uint8_t subtype                   = 0;
468   uint16_t recv_freq                = 0;
469   sli_wifi_data_frame_t *wifi_frame = (sli_wifi_data_frame_t *)packet->data;
470   sli_scan_info_t scan_info         = { 0 };
471   uint16_t ies_length               = 0;
472 
473   recv_freq         = packet->desc[9];
474   recv_freq         = (recv_freq << 8) | packet->desc[8];
475   scan_info.rssi    = (~packet->desc[10]);
476   scan_info.channel = packet->desc[11];
477 
478   // Check for ESS bit and TBSS status bit in capability info
479   // 1 in ESS bit indicates that the transmitter is an AP
480   if (1 == (wifi_frame->ci[0] & 0x03)) {
481     scan_info.network_type = 1;
482   } else {
483     scan_info.network_type = 0;
484   }
485 
486   if (wifi_frame->ci[0] & 0x08) {
487     scan_info.security_mode = SL_WIFI_WEP;
488   } else {
489     scan_info.security_mode = SL_WIFI_OPEN;
490   }
491 
492   subtype = wifi_frame->fc[0] & SLI_WIFI_FRAME_SUBTYPE_MASK;
493   switch (subtype) {
494     case SLI_WIFI_FRAME_SUBTYPE_PROBE_RESP:
495     case SLI_WIFI_FRAME_SUBTYPE_BEACON: {
496       if (packet->length <= SLI_WIFI_MINIMUM_FRAME_LENGTH) {
497         return;
498       }
499       ies_length = packet->length - SLI_WIFI_MINIMUM_FRAME_LENGTH;
500 
501       memcpy(scan_info.bssid, wifi_frame->bssid, SLI_WIFI_HARDWARE_ADDRESS_LENGTH);
502 
503       sli_wifi_data_tagged_info_t *info = (sli_wifi_data_tagged_info_t *)wifi_frame->tagged_info;
504       while (0 != ies_length) {
505         sli_process_tag_info(info, &scan_info);
506         ies_length -= (sizeof(sli_wifi_data_tagged_info_t) + info->data_length);
507         info = (sli_wifi_data_tagged_info_t *)&(info->data[info->data_length]);
508 
509         if (ies_length <= sizeof(sli_wifi_data_tagged_info_t)) {
510           ies_length = 0;
511         }
512       }
513 
514       sli_store_scan_info_element(&scan_info);
515     } break;
516     default:
517       return;
518   }
519 
520   return;
521 }
522 
523 // Function to get all or filtered scan results from scan result database
sli_wifi_get_stored_scan_results(sl_wifi_interface_t interface,sl_wifi_extended_scan_result_parameters_t * extended_scan_parameters)524 sl_status_t sli_wifi_get_stored_scan_results(sl_wifi_interface_t interface,
525                                              sl_wifi_extended_scan_result_parameters_t *extended_scan_parameters)
526 {
527   UNUSED_PARAMETER(interface);
528   if (NULL == extended_scan_parameters) {
529     return SL_STATUS_INVALID_PARAMETER;
530   }
531 
532   sl_wifi_extended_scan_result_t *scan_results = extended_scan_parameters->scan_results;
533   uint16_t *result_count                       = extended_scan_parameters->result_count;
534   uint16_t length                              = extended_scan_parameters->array_length;
535   sli_scan_info_t *scan_info                   = scan_info_database;
536 
537   if ((NULL == scan_results) || (NULL == result_count) || (0 == length)) {
538     return SL_STATUS_INVALID_PARAMETER;
539   }
540   *result_count = 0;
541 
542   while ((0 != length) && (NULL != scan_info)) {
543     if (true == sli_filter_scan_info(scan_info, extended_scan_parameters)) {
544       scan_results[*result_count].rf_channel    = scan_info->channel;
545       scan_results[*result_count].security_mode = scan_info->security_mode;
546       scan_results[*result_count].rssi          = scan_info->rssi;
547       scan_results[*result_count].network_type  = scan_info->network_type;
548       memcpy(scan_results[*result_count].bssid, scan_info->bssid, SLI_WIFI_HARDWARE_ADDRESS_LENGTH);
549       memcpy(scan_results[*result_count].ssid, scan_info->ssid, 34);
550       (*result_count)++;
551       length--;
552     }
553     scan_info = scan_info->next;
554   }
555 
556   return SL_STATUS_OK;
557 }
558 
559 // Function to Clean up all the scan results in scan result database
sli_wifi_flush_scan_results_database(void)560 void sli_wifi_flush_scan_results_database(void)
561 {
562   sli_scan_info_t *scan_info = scan_info_database;
563   sli_scan_info_t *node      = NULL;
564 
565   while (NULL != scan_info) {
566     node      = scan_info;
567     scan_info = scan_info->next;
568     free(node);
569   }
570   scan_info_database = NULL;
571 
572   return;
573 }
574 
575 /******************************************************
576  *               Function Declarations
577  ******************************************************/
save_wifi_current_performance_profile(const sl_wifi_performance_profile_t * profile)578 void save_wifi_current_performance_profile(const sl_wifi_performance_profile_t *profile)
579 {
580   SL_ASSERT(profile != NULL);
581   memcpy(&performance_profile.wifi_performance_profile, profile, sizeof(sl_wifi_performance_profile_t));
582 
583   performance_profile.coex_mode = get_coex_mode();
584 }
585 
586 // Get the current Wi-Fi performance profile
get_wifi_current_performance_profile(sl_wifi_performance_profile_t * profile)587 void get_wifi_current_performance_profile(sl_wifi_performance_profile_t *profile)
588 {
589   SL_ASSERT(profile != NULL);
590   memcpy(profile, &performance_profile.wifi_performance_profile, sizeof(sl_wifi_performance_profile_t));
591 }
592 
593 // Get the coexistence performance profile based on the current coexistence mode
get_coex_performance_profile(sl_si91x_performance_profile_t * profile)594 void get_coex_performance_profile(sl_si91x_performance_profile_t *profile)
595 {
596   SL_ASSERT(profile != NULL);
597   uint8_t mode_decision          = 0;
598   sl_si91x_coex_mode_t coex_mode = performance_profile.coex_mode;
599   if (coex_mode == SL_SI91X_WLAN_ONLY_MODE) { // Treat SL_SI91X_WLAN_ONLY_MODE as SL_SI91X_WLAN_MODE
600     coex_mode = SL_SI91X_WLAN_MODE;
601   }
602   // Determine the mode decision based on the coexistence mode
603   switch (coex_mode) {
604     case SL_SI91X_WLAN_MODE: {
605       // Wi-Fi only mode
606       mode_decision = (uint8_t)((performance_profile.wifi_performance_profile.profile << 4)
607                                 | (performance_profile.wifi_performance_profile.profile));
608     } break;
609     case SL_SI91X_BLUETOOTH_MODE:
610     case SL_SI91X_BLE_MODE:
611     case SL_SI91X_DUAL_MODE: {
612       // Bluetooth only or dual-mode (BT + Wi-Fi) mode
613       mode_decision = (uint8_t)((performance_profile.bt_performance_profile.profile << 4)
614                                 | (performance_profile.bt_performance_profile.profile));
615     } break;
616     case SL_SI91X_WLAN_BLUETOOTH_MODE:
617     case SL_SI91X_WLAN_DUAL_MODE:
618     case SL_SI91X_WLAN_BLE_MODE: {
619       // Wi-Fi + Bluetooth mode
620       mode_decision = (uint8_t)((performance_profile.wifi_performance_profile.profile << 4)
621                                 | (performance_profile.bt_performance_profile.profile));
622     } break;
623     default:
624       break;
625   }
626 
627   // Determine the performance profile based on the mode decision
628   switch (mode_decision) {
629     case 0x00:
630     case 0x01:
631     case 0x02:
632     case 0x03:
633     case 0x04:
634     case 0x10:
635     case 0x20:
636     case 0x30:
637     case 0x40: {
638       *profile = HIGH_PERFORMANCE; // High performance mode
639     } break;
640     case 0x11:
641     case 0x12:
642     case 0x31:
643     case 0x13:
644     case 0x14:
645     case 0x41: {
646       *profile = ASSOCIATED_POWER_SAVE; // Power save mode
647     } break;
648     case 0x22:
649     case 0x21:
650     case 0x32:
651     case 0x23:
652     case 0x42:
653     case 0x24: {
654       *profile = ASSOCIATED_POWER_SAVE_LOW_LATENCY; // Low latency power save mode
655     } break;
656     case 0x33: {
657       *profile = DEEP_SLEEP_WITHOUT_RAM_RETENTION; // Power save mode
658     } break;
659     case 0x44: {
660       *profile = DEEP_SLEEP_WITH_RAM_RETENTION; // Power save mode with RAM retention
661     } break;
662     default: {
663       // Do nothing
664     } break;
665   }
666   return;
667 }
668 
reset_coex_current_performance_profile(void)669 void reset_coex_current_performance_profile(void)
670 {
671   memset(&performance_profile, 0, sizeof(sli_si91x_performance_profile_t));
672 }
673 
save_boot_configuration(const sl_si91x_boot_configuration_t * boot_configuration)674 void save_boot_configuration(const sl_si91x_boot_configuration_t *boot_configuration)
675 {
676   memcpy(&saved_boot_configuration, boot_configuration, sizeof(sl_si91x_boot_configuration_t));
677 }
678 
get_saved_boot_configuration(sl_si91x_boot_configuration_t * boot_configuration)679 void get_saved_boot_configuration(sl_si91x_boot_configuration_t *boot_configuration)
680 {
681   memcpy(boot_configuration, &saved_boot_configuration, sizeof(sl_si91x_boot_configuration_t));
682 }
683 
save_bt_current_performance_profile(const sl_bt_performance_profile_t * profile)684 void save_bt_current_performance_profile(const sl_bt_performance_profile_t *profile)
685 {
686   SL_ASSERT(profile != NULL);
687   memcpy(&performance_profile.bt_performance_profile, profile, sizeof(sl_bt_performance_profile_t));
688 }
689 
get_bt_current_performance_profile(sl_bt_performance_profile_t * profile)690 void get_bt_current_performance_profile(sl_bt_performance_profile_t *profile)
691 {
692   SL_ASSERT(profile != NULL);
693   memcpy(profile, &performance_profile.bt_performance_profile, sizeof(sl_bt_performance_profile_t));
694 }
695 
save_tcp_auto_close_choice(bool is_tcp_auto_close_enabled)696 void save_tcp_auto_close_choice(bool is_tcp_auto_close_enabled)
697 {
698   tcp_auto_close_enabled = is_tcp_auto_close_enabled;
699 }
700 
is_tcp_auto_close_enabled()701 bool is_tcp_auto_close_enabled()
702 {
703   return tcp_auto_close_enabled;
704 }
705 
save_max_tx_power(uint8_t max_scan_tx_power,uint8_t max_join_tx_power)706 void save_max_tx_power(uint8_t max_scan_tx_power, uint8_t max_join_tx_power)
707 {
708   wifi_max_tx_power.scan_tx_power = max_scan_tx_power;
709   wifi_max_tx_power.join_tx_power = max_join_tx_power;
710 }
711 
get_max_tx_power()712 sl_wifi_max_tx_power_t get_max_tx_power()
713 {
714   return wifi_max_tx_power;
715 }
716 
reset_max_tx_power()717 void reset_max_tx_power()
718 {
719   wifi_max_tx_power.scan_tx_power = 0x1f;
720   wifi_max_tx_power.join_tx_power = 0x1f;
721 }
722 
set_card_ready_required(bool card_ready_required)723 void set_card_ready_required(bool card_ready_required)
724 {
725   is_card_ready_required = card_ready_required;
726 }
727 
get_card_ready_required()728 bool get_card_ready_required()
729 {
730   return is_card_ready_required;
731 }
732 
save_coex_mode(sl_si91x_coex_mode_t mode)733 void save_coex_mode(sl_si91x_coex_mode_t mode)
734 {
735   coex_mode = mode;
736 }
737 
get_coex_mode(void)738 sl_si91x_coex_mode_t get_coex_mode(void)
739 {
740   return coex_mode;
741 }
742 
convert_si91x_wifi_client_info(sl_wifi_client_info_response_t * client_info_response,const sl_si91x_client_info_response * sl_si91x_client_info_response)743 sl_status_t convert_si91x_wifi_client_info(sl_wifi_client_info_response_t *client_info_response,
744                                            const sl_si91x_client_info_response *sl_si91x_client_info_response)
745 {
746 
747   SL_WIFI_ARGS_CHECK_NULL_POINTER(sl_si91x_client_info_response);
748   SL_WIFI_ARGS_CHECK_NULL_POINTER(client_info_response);
749 
750   client_info_response->client_count =
751     (uint8_t)(sl_si91x_client_info_response->sta_count[0] | sl_si91x_client_info_response->sta_count[1] << 8);
752 
753   for (uint8_t station_index = 0; station_index < client_info_response->client_count; station_index++) {
754     const uint8_t *si91x_ip_address;
755     uint8_t *sl_ip_address;
756 
757     sl_wifi_client_info_t *sl_client_info            = &client_info_response->client_info[station_index];
758     const sl_si91x_station_info_t *si91x_client_info = &sl_si91x_client_info_response->sta_info[station_index];
759 
760     uint8_t ip_address_size = (uint8_t)(si91x_client_info->ip_version[0] | si91x_client_info->ip_version[1] << 8);
761 
762     si91x_ip_address = ip_address_size == SL_IPV4_ADDRESS_LENGTH ? si91x_client_info->ip_address.ipv4_address
763                                                                  : si91x_client_info->ip_address.ipv6_address;
764     sl_ip_address    = ip_address_size == SL_IPV4_ADDRESS_LENGTH ? sl_client_info->ip_address.ip.v4.bytes
765                                                                  : sl_client_info->ip_address.ip.v6.bytes;
766 
767     sl_client_info->ip_address.type = ip_address_size == SL_IPV4_ADDRESS_LENGTH ? SL_IPV4 : SL_IPV6;
768 
769     memcpy(&sl_client_info->mac_adddress, si91x_client_info->mac, sizeof(sl_mac_address_t));
770     memcpy(sl_ip_address, si91x_ip_address, ip_address_size);
771   }
772 
773   return SL_STATUS_OK;
774 }
775 
convert_si91x_event_to_sl_wifi_event(rsi_wlan_cmd_response_t command,uint16_t frame_status)776 sl_wifi_event_t convert_si91x_event_to_sl_wifi_event(rsi_wlan_cmd_response_t command, uint16_t frame_status)
777 {
778   // Define a constant indicating a fail indication event
779   const sl_wifi_event_t fail_indication = (frame_status != RSI_SUCCESS) ? SL_WIFI_EVENT_FAIL_INDICATION : 0;
780 
781   // Switch-case to map SI91x events to SL Wi-Fi events
782   switch (command) {
783     case RSI_WLAN_RSP_BG_SCAN:
784     case RSI_WLAN_RSP_SCAN:
785       return SL_WIFI_SCAN_RESULT_EVENT | fail_indication;
786     case RSI_WLAN_RSP_JOIN:
787       return SL_WIFI_JOIN_EVENT | fail_indication;
788     case RSI_WLAN_RSP_GET_STATS:
789       if (frame_status != RSI_SUCCESS) {
790         return SL_WIFI_STATS_RESPONSE_EVENTS | fail_indication;
791       }
792       return SL_WIFI_STATS_EVENT;
793     case RSI_WLAN_RSP_RX_STATS:
794       if (frame_status != RSI_SUCCESS) {
795         return SL_WIFI_STATS_RESPONSE_EVENTS | fail_indication;
796       }
797       return SL_WIFI_STATS_ASYNC_EVENT;
798     case RSI_WLAN_RATE_RSP_STATS:
799       if (frame_status != RSI_SUCCESS) {
800         return SL_WIFI_STATS_RESPONSE_EVENTS | fail_indication;
801       }
802       return SL_WIFI_STATS_TEST_MODE_EVENT;
803     case RSI_WLAN_RSP_EXT_STATS:
804       if (frame_status != RSI_SUCCESS) {
805         return SL_WIFI_STATS_RESPONSE_EVENTS | fail_indication;
806       }
807       return SL_WIFI_STATS_ADVANCE_EVENT;
808     case RSI_WLAN_RSP_MODULE_STATE:
809       if (frame_status != RSI_SUCCESS) {
810         return SL_WIFI_STATS_RESPONSE_EVENTS | fail_indication;
811       }
812       return SL_WIFI_STATS_MODULE_STATE_EVENT;
813     case RSI_WLAN_RSP_HTTP_OTAF:
814       return SL_WIFI_HTTP_OTA_FW_UPDATE_EVENT | fail_indication;
815     case RSI_WLAN_RSP_CLIENT_CONNECTED:
816       return SL_WIFI_CLIENT_CONNECTED_EVENT | fail_indication;
817     case RSI_WLAN_RSP_CLIENT_DISCONNECTED:
818       return SL_WIFI_CLIENT_DISCONNECTED_EVENT | fail_indication;
819     case RSI_WLAN_RSP_TWT_ASYNC:
820       if (frame_status == RSI_SUCCESS) {
821         return SL_WIFI_TWT_RESPONSE_EVENT;
822       } else {
823         return SL_WIFI_TWT_RESPONSE_EVENT | (frame_status << 16);
824       }
825     case RSI_WLAN_RSP_TRANSCEIVER_TX_DATA_STATUS:
826       return SL_WIFI_TRANSCEIVER_TX_DATA_STATUS_CB | fail_indication;
827     case SL_SI91X_WIFI_RX_DOT11_DATA:
828       return SL_WIFI_TRANSCEIVER_RX_DATA_RECEIVE_CB | fail_indication;
829     default:
830       return SL_WIFI_INVALID_EVENT;
831   }
832 }
833 
save_sl_wifi_rate(sl_wifi_rate_t transfer_rate)834 sl_status_t save_sl_wifi_rate(sl_wifi_rate_t transfer_rate)
835 {
836   // Check if the provided transfer rate is valid
837   if (transfer_rate == SL_WIFI_RATE_INVALID) {
838     return SL_STATUS_INVALID_CONFIGURATION;
839   }
840 
841   saved_wifi_data_rate = transfer_rate;
842 
843   return SL_STATUS_OK;
844 }
845 
get_saved_sl_wifi_rate(sl_wifi_rate_t * transfer_rate)846 sl_status_t get_saved_sl_wifi_rate(sl_wifi_rate_t *transfer_rate)
847 {
848   SL_WIFI_ARGS_CHECK_NULL_POINTER(transfer_rate);
849 
850   *transfer_rate = saved_wifi_data_rate;
851   return SL_STATUS_OK;
852 }
853 
reset_sl_wifi_rate()854 void reset_sl_wifi_rate()
855 {
856   saved_wifi_data_rate = 0;
857 }
858 
save_ap_configuration(const sl_wifi_ap_configuration_t * wifi_ap_configuration)859 sl_status_t save_ap_configuration(const sl_wifi_ap_configuration_t *wifi_ap_configuration)
860 {
861   // Check if the input pointer is valid
862   SL_WIFI_ARGS_CHECK_NULL_POINTER(wifi_ap_configuration);
863   ap_configuration = *wifi_ap_configuration;
864 
865   return SL_STATUS_OK;
866 }
867 
get_saved_ap_configuration(sl_wifi_ap_configuration_t * wifi_ap_configuration)868 sl_status_t get_saved_ap_configuration(sl_wifi_ap_configuration_t *wifi_ap_configuration)
869 {
870   SL_WIFI_ARGS_CHECK_NULL_POINTER(wifi_ap_configuration);
871   *wifi_ap_configuration = ap_configuration;
872 
873   return SL_STATUS_OK;
874 }
875 
reset_ap_configuration()876 void reset_ap_configuration()
877 {
878   // Initialize the ap_configuration structure with zeros
879   ap_configuration = (sl_wifi_ap_configuration_t){ 0 };
880 }
881 
get_rate_protocol_and_data_rate(const uint8_t data_rate,sl_wifi_rate_protocol_t * rate_protocol,sl_wifi_rate_t * mask)882 sl_status_t get_rate_protocol_and_data_rate(const uint8_t data_rate,
883                                             sl_wifi_rate_protocol_t *rate_protocol,
884                                             sl_wifi_rate_t *mask)
885 {
886   // Map the provided data_rate to a rate_protocol and set the mask accordingly
887   switch (data_rate) {
888     case SL_WIFI_AUTO_RATE: {
889       *rate_protocol = SL_WIFI_RATE_PROTOCOL_AUTO;
890       break;
891     }
892     case SL_WIFI_RATE_11B_1:
893     case SL_WIFI_RATE_11B_2:
894     case SL_WIFI_RATE_11B_5_5:
895     case SL_WIFI_RATE_11B_11: {
896       *rate_protocol = SL_WIFI_RATE_PROTOCOL_B_ONLY;
897       break;
898     }
899     case SL_WIFI_RATE_11G_6:
900     case SL_WIFI_RATE_11G_9:
901     case SL_WIFI_RATE_11G_12:
902     case SL_WIFI_RATE_11G_18:
903     case SL_WIFI_RATE_11G_24:
904     case SL_WIFI_RATE_11G_36:
905     case SL_WIFI_RATE_11G_48:
906     case SL_WIFI_RATE_11G_54: {
907       *rate_protocol = SL_WIFI_RATE_PROTOCOL_G_ONLY;
908       break;
909     }
910     case SL_WIFI_RATE_11N_MCS0:
911     case SL_WIFI_RATE_11N_MCS1:
912     case SL_WIFI_RATE_11N_MCS2:
913     case SL_WIFI_RATE_11N_MCS3:
914     case SL_WIFI_RATE_11N_MCS4:
915     case SL_WIFI_RATE_11N_MCS5:
916     case SL_WIFI_RATE_11N_MCS6:
917     case SL_WIFI_RATE_11N_MCS7: {
918       *rate_protocol = SL_WIFI_RATE_PROTOCOL_N_ONLY;
919       break;
920     }
921     case SL_WIFI_RATE_11AX_MCS0:
922     case SL_WIFI_RATE_11AX_MCS1:
923     case SL_WIFI_RATE_11AX_MCS2:
924     case SL_WIFI_RATE_11AX_MCS3:
925     case SL_WIFI_RATE_11AX_MCS4:
926     case SL_WIFI_RATE_11AX_MCS5:
927     case SL_WIFI_RATE_11AX_MCS6:
928     case SL_WIFI_RATE_11AX_MCS7: {
929       *rate_protocol = SL_WIFI_RATE_PROTOCOL_AX_ONLY;
930       break;
931     }
932     default: {
933       return SL_STATUS_INVALID_CONFIGURATION;
934     }
935   }
936 
937   *mask = data_rate;
938 
939   return SL_STATUS_OK;
940 }
941 
convert_performance_profile_to_power_save_command(sl_si91x_performance_profile_t profile,sl_si91x_power_save_request_t * power_save_request)942 void convert_performance_profile_to_power_save_command(sl_si91x_performance_profile_t profile,
943                                                        sl_si91x_power_save_request_t *power_save_request)
944 {
945   SL_ASSERT(power_save_request != NULL);
946   if (performance_profile.wifi_performance_profile.monitor_interval) {
947     power_save_request->monitor_interval = performance_profile.wifi_performance_profile.monitor_interval;
948   } else {
949     power_save_request->monitor_interval = DEFAULT_MONITOR_INTERVAL;
950   }
951 
952   power_save_request->ulp_mode_enable   = SL_ULP_WITH_RAM_RETENTION;
953   power_save_request->dtim_aligned_type = performance_profile.wifi_performance_profile.dtim_aligned_type;
954   power_save_request->num_of_dtim_skip  = performance_profile.wifi_performance_profile.num_of_dtim_skip;
955   power_save_request->listen_interval   = performance_profile.wifi_performance_profile.listen_interval;
956   power_save_request->psp_type          = SL_MAX_PSP;
957 
958   // Depending on the specified performance profile, configure the power_save_request structure
959   switch (profile) {
960     case HIGH_PERFORMANCE: {
961       // For HIGH_PERFORMANCE profile, reset all fields in the power_save_request structure to zero
962       memset(power_save_request, 0, sizeof(sl_si91x_power_save_request_t));
963       break;
964     }
965 
966     case ASSOCIATED_POWER_SAVE: {
967 #ifdef SLI_SI91X_MCU_INTERFACE
968       power_save_request->power_mode = SL_CONNECTED_M4_BASED_PS;
969 #else
970       power_save_request->power_mode = SL_CONNECTED_GPIO_BASED_PS;
971 #endif
972       break;
973     }
974 
975     case ASSOCIATED_POWER_SAVE_LOW_LATENCY: {
976 #ifdef SLI_SI91X_MCU_INTERFACE
977       power_save_request->power_mode = SL_CONNECTED_M4_BASED_PS;
978 #else
979       power_save_request->power_mode = SL_CONNECTED_GPIO_BASED_PS;
980 #endif
981       power_save_request->psp_type = SL_FAST_PSP;
982       break;
983     }
984 
985     case DEEP_SLEEP_WITHOUT_RAM_RETENTION: {
986 #ifdef SLI_SI91X_MCU_INTERFACE
987       power_save_request->power_mode = SL_M4_BASED_DEEP_SLEEP;
988 #else
989       power_save_request->power_mode = SL_GPIO_BASED_DEEP_SLEEP;
990 #endif
991       power_save_request->ulp_mode_enable = SL_ULP_WITHOUT_RAM_RET_RETENTION;
992       break;
993     }
994 
995     case DEEP_SLEEP_WITH_RAM_RETENTION: {
996 #ifdef SLI_SI91X_MCU_INTERFACE
997       power_save_request->power_mode = SL_M4_BASED_DEEP_SLEEP;
998 #else
999       power_save_request->power_mode = SL_GPIO_BASED_DEEP_SLEEP;
1000 #endif
1001       break;
1002     }
1003     default: {
1004       // Do nothing
1005     } break;
1006   }
1007 
1008   return;
1009 }
1010 
1011 //In Access point mode NWP only supports No Encryption, TKIP and CCMP encryptions.
convert_sl_wifi_to_sl_si91x_encryption(sl_wifi_encryption_t encryption_mode,uint8_t * encryption_request)1012 sl_status_t convert_sl_wifi_to_sl_si91x_encryption(sl_wifi_encryption_t encryption_mode, uint8_t *encryption_request)
1013 {
1014   switch (encryption_mode) {
1015     case SL_WIFI_NO_ENCRYPTION:
1016       *encryption_request = SL_SI91X_NO_ENCRYPTION;
1017       break;
1018     case SL_WIFI_TKIP_ENCRYPTION:
1019       *encryption_request = SL_SI91X_TKIP_ENCRYPTION;
1020       break;
1021     case SL_WIFI_CCMP_ENCRYPTION:
1022     case SL_WIFI_DEFAULT_ENCRYPTION:
1023       *encryption_request = SL_SI91X_CCMP_ENCRYPTION;
1024       break;
1025     default:
1026       return SL_STATUS_NOT_SUPPORTED;
1027   }
1028 
1029   return SL_STATUS_OK;
1030 }
1031 
sl_si91x_platform_init(void)1032 sl_status_t sl_si91x_platform_init(void)
1033 {
1034   sl_status_t status = SL_STATUS_OK;
1035 
1036   // Initialize the command queues
1037   memset(cmd_queues, 0, sizeof(cmd_queues));
1038 
1039   // Create event flags
1040   if (NULL == si91x_events) {
1041     si91x_events = osEventFlagsNew(NULL);
1042   }
1043 
1044   if (NULL == si91x_bus_events) {
1045     si91x_bus_events = osEventFlagsNew(NULL);
1046   }
1047 
1048   if (NULL == si91x_async_events) {
1049     si91x_async_events = osEventFlagsNew(NULL);
1050   }
1051 
1052   // Create and start SI91X bus thread
1053   if (NULL == si91x_thread) {
1054     const osThreadAttr_t attr = {
1055 
1056       .name       = "si91x_bus",
1057       .priority   = osPriorityRealtime,
1058       .stack_mem  = 0,
1059       .stack_size = 1636,
1060       .cb_mem     = 0,
1061       .cb_size    = 0,
1062       .attr_bits  = 0u,
1063       .tz_module  = 0u,
1064     };
1065     si91x_thread = osThreadNew(si91x_bus_thread, NULL, &attr);
1066   }
1067 
1068   // Create and start SI91X event handler thread
1069   if (NULL == si91x_event_thread) {
1070     const osThreadAttr_t attr = {
1071       .name       = "si91x_event",
1072       .priority   = osPriorityRealtime1,
1073       .stack_mem  = 0,
1074       .stack_size = SL_SI91X_EVENT_HANDLER_STACK_SIZE,
1075       .cb_mem     = 0,
1076       .cb_size    = 0,
1077       .attr_bits  = 0u,
1078       .tz_module  = 0u,
1079     };
1080     si91x_event_thread = osThreadNew(si91x_event_handler_thread, NULL, &attr);
1081   }
1082 
1083   // Initialize command queues and associated mutexes
1084   for (int i = 0; i < SI91X_CMD_MAX; i++) {
1085     cmd_queues[i].tx_queue.head    = NULL;
1086     cmd_queues[i].tx_queue.tail    = NULL;
1087     cmd_queues[i].rx_queue.head    = NULL;
1088     cmd_queues[i].rx_queue.tail    = NULL;
1089     cmd_queues[i].event_queue.head = NULL;
1090     cmd_queues[i].event_queue.tail = NULL;
1091     cmd_queues[i].mutex            = osMutexNew(NULL);
1092     cmd_queues[i].flag             = (1 << i);
1093   }
1094 
1095   // Create malloc/free mutex
1096   if (malloc_free_mutex == NULL) {
1097     malloc_free_mutex = osMutexNew(NULL);
1098   }
1099 
1100 #ifdef SL_SI91X_SIDE_BAND_CRYPTO
1101   // Create side_band_crypto_mutex mutex
1102   side_band_crypto_mutex = osMutexNew(NULL);
1103 #endif
1104 
1105   return status;
1106 }
1107 
sl_si91x_platform_deinit(void)1108 sl_status_t sl_si91x_platform_deinit(void)
1109 {
1110 
1111   // Deallocate all threads, mutexes and event handlers
1112 
1113   // Terminate SI91X bus thread
1114   if (NULL != si91x_thread) {
1115     // Signal the thread to terminate
1116     osEventFlagsSet(si91x_bus_events, SL_SI91X_TERMINATE_BUS_THREAD_EVENT);
1117 
1118     // Wait for thread termination acknowledgment
1119     osStatus_t stat = osEventFlagsWait(si91x_events, SL_SI91X_TERMINATE_BUS_THREAD_EVENT_ACK, osFlagsWaitAny, 5000);
1120     if (stat == osErrorTimeout) {
1121       // Return timeout if acknowledgment is not received
1122       return SL_STATUS_TIMEOUT;
1123     }
1124 
1125     si91x_thread = NULL;
1126   }
1127 
1128   // Terminate SI91X event handler thread
1129   if (NULL != si91x_event_thread) {
1130     osThreadTerminate(si91x_event_thread);
1131     si91x_event_thread = NULL;
1132   }
1133 
1134   // Delete event flags
1135   if (NULL != si91x_events) {
1136     osEventFlagsDelete(si91x_events);
1137     si91x_events = NULL;
1138   }
1139 
1140   if (NULL != si91x_bus_events) {
1141     osEventFlagsDelete(si91x_bus_events);
1142     si91x_bus_events = NULL;
1143   }
1144 
1145   if (NULL != si91x_async_events) {
1146     osEventFlagsDelete(si91x_async_events);
1147     si91x_async_events = NULL;
1148   }
1149 
1150   // Delete command queue mutexes
1151   for (int i = 0; i < SI91X_CMD_MAX; i++) {
1152     osMutexDelete(cmd_queues[i].mutex);
1153     cmd_queues[i].mutex = NULL;
1154   }
1155 
1156   // Delete malloc/free mutex
1157   osMutexDelete(malloc_free_mutex);
1158   malloc_free_mutex = NULL;
1159   return SL_STATUS_OK;
1160 }
1161 
sl_si91x_host_get_timestamp(void)1162 sl_si91x_host_timestamp_t sl_si91x_host_get_timestamp(void)
1163 {
1164   return osKernelGetTickCount();
1165 }
1166 
1167 // Calculate elapsed time from the given starting timestamp
sl_si91x_host_elapsed_time(uint32_t starting_timestamp)1168 sl_si91x_host_timestamp_t sl_si91x_host_elapsed_time(uint32_t starting_timestamp)
1169 {
1170   uint32_t current_tickcount = osKernelGetTickCount();
1171 
1172   // Check if the tick count has overflow or not.
1173   if (current_tickcount >= starting_timestamp) {
1174     return (current_tickcount - starting_timestamp);
1175   } else {
1176     return ((0xFFFFFFFF - starting_timestamp) + current_tickcount);
1177   }
1178 }
1179 
1180 // Delay execution for a specified number of milliseconds using an OS-level delay
sl_si91x_host_delay_ms(uint32_t delay_milliseconds)1181 void sl_si91x_host_delay_ms(uint32_t delay_milliseconds)
1182 {
1183   osDelay(delay_milliseconds);
1184 }
1185 
sli_si91x_set_event(uint32_t event_mask)1186 void sli_si91x_set_event(uint32_t event_mask)
1187 {
1188   osEventFlagsSet(si91x_events, event_mask);
1189 }
1190 
sl_si91x_host_set_bus_event(uint32_t event_mask)1191 void sl_si91x_host_set_bus_event(uint32_t event_mask)
1192 {
1193   osEventFlagsSet(si91x_bus_events, event_mask);
1194 }
1195 
sli_si91x_add_to_queue(sl_si91x_buffer_queue_t * queue,sl_wifi_buffer_t * buffer)1196 sl_status_t sli_si91x_add_to_queue(sl_si91x_buffer_queue_t *queue, sl_wifi_buffer_t *buffer)
1197 {
1198   sli_si91x_append_to_buffer_queue(queue, buffer);
1199   return SL_STATUS_OK;
1200 }
1201 
sli_si91x_remove_from_queue(sl_si91x_buffer_queue_t * queue,sl_wifi_buffer_t ** buffer)1202 sl_status_t sli_si91x_remove_from_queue(sl_si91x_buffer_queue_t *queue, sl_wifi_buffer_t **buffer)
1203 {
1204   return sli_si91x_pop_from_buffer_queue(queue, buffer);
1205 }
1206 
sli_si91x_flush_all_tx_wifi_queues(uint16_t frame_status)1207 sl_status_t sli_si91x_flush_all_tx_wifi_queues(uint16_t frame_status)
1208 {
1209   // free all TX queues except BT
1210   for (int queue_id = 0; queue_id < SI91X_CMD_MAX; queue_id++) {
1211     if (queue_id == SI91X_BT_CMD) {
1212       continue;
1213     }
1214     sli_si91x_flush_queue_based_on_type(&cmd_queues[queue_id],
1215                                         SL_SI91X_RESPONSE_FLAG(queue_id),
1216                                         frame_status,
1217                                         NULL,
1218                                         NULL);
1219   }
1220   return SL_STATUS_OK;
1221 }
1222 
sli_si91x_flush_generic_data_queues(sl_si91x_buffer_queue_t * tx_data_queue)1223 sl_status_t sli_si91x_flush_generic_data_queues(sl_si91x_buffer_queue_t *tx_data_queue)
1224 {
1225   sl_wifi_buffer_t *current_packet = NULL;
1226   sl_wifi_buffer_t *next_packet    = NULL;
1227 
1228   // Validate input
1229   if (tx_data_queue == NULL) {
1230     return SL_STATUS_FAIL;
1231   }
1232 
1233   // Prevent race conditions
1234   CORE_irqState_t state = CORE_EnterAtomic();
1235 
1236   // Free all packets in the queue
1237   current_packet = tx_data_queue->head;
1238   while (current_packet != NULL) {
1239     next_packet = (sl_wifi_buffer_t *)current_packet->node.node;
1240     sl_si91x_host_free_buffer(current_packet);
1241     current_packet = next_packet;
1242   }
1243 
1244   // Reset the queue
1245   tx_data_queue->head = NULL;
1246   tx_data_queue->tail = NULL;
1247 
1248   // Clear pending TX status
1249   tx_generic_socket_data_queues_status &= ~(SL_SI91X_GENERIC_DATA_TX_PENDING_EVENT);
1250 
1251   CORE_ExitAtomic(state);
1252 
1253   return SL_STATUS_OK;
1254 }
1255 
sli_si91x_flush_queue_based_on_type(sli_si91x_command_queue_t * queue,uint32_t event_mask,uint16_t frame_status,sl_si91x_compare_function_t compare_function,void * user_data)1256 sl_status_t sli_si91x_flush_queue_based_on_type(sli_si91x_command_queue_t *queue,
1257                                                 uint32_t event_mask,
1258                                                 uint16_t frame_status,
1259                                                 sl_si91x_compare_function_t compare_function,
1260                                                 void *user_data)
1261 {
1262   sl_wifi_buffer_t *current_packet     = NULL;
1263   sl_wifi_buffer_t *next_packet        = NULL;
1264   sli_si91x_queue_packet_t *queue_node = NULL;
1265   sl_wifi_buffer_t *previous_packet    = NULL;
1266   sl_status_t status                   = SL_STATUS_FAIL;
1267 
1268   // Enter atomic section to prevent race conditions
1269   CORE_irqState_t state = CORE_EnterAtomic();
1270 
1271   // Check if the queue is not the BT command queue and has a command in flight
1272   if ((queue != &cmd_queues[SI91X_BT_CMD]) && (queue->command_in_flight == true)) {
1273     // Create a generic RX packet
1274     status = sl_create_generic_rx_packet_from_params(&queue_node,
1275                                                      &current_packet,
1276                                                      queue->packet_id,
1277                                                      queue->flags,
1278                                                      queue->sdk_context,
1279                                                      frame_status);
1280     if (status != SL_STATUS_OK) {
1281       CORE_ExitAtomic(state);
1282       return status; // Exit if packet creation fails
1283     }
1284     sl_wifi_buffer_t *dummy_packet_buffer = NULL;
1285 
1286     // Allocate buffer for the dummy packet
1287     status = sl_si91x_host_allocate_buffer(&dummy_packet_buffer,
1288                                            SL_WIFI_RX_FRAME_BUFFER,
1289                                            sizeof(sl_si91x_packet_t),
1290                                            SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME);
1291     if (status != SL_STATUS_OK) {
1292       CORE_ExitAtomic(state);
1293       sl_si91x_host_free_buffer(current_packet); // Free current_packet on failure
1294       return status;                             // Exit if buffer allocation fails
1295     }
1296 
1297     // Get the dummy packet data from the allocated buffer
1298     sl_si91x_packet_t *dummy_packet = sl_si91x_host_get_buffer_data(dummy_packet_buffer, 0, NULL);
1299     queue_node->host_packet         = dummy_packet_buffer; // Link dummy packet to the node
1300     dummy_packet->desc[2]           = (uint8_t)queue->frame_type;
1301     dummy_packet->desc[3]           = (uint8_t)((0xFF00 & queue->frame_type) >> 8);
1302 
1303     if (!compare_function || compare_function(queue_node->host_packet, user_data)) {
1304 
1305       if (!(queue->flags & SI91X_PACKET_RESPONSE_PACKET)) {
1306         sl_si91x_host_free_buffer(dummy_packet_buffer);
1307       }
1308       // Check if the packet in the queue is synchronous or asynchronous response
1309       if (sl_si91x_host_elapsed_time(queue->command_tickcount) <= (queue->command_timeout)) {
1310         // Add the packet to the response queue and set the event
1311         sli_si91x_add_to_queue(&queue->rx_queue, current_packet);
1312         sli_si91x_set_event(event_mask);
1313       } else {
1314         // no user thread is waiting for the response so flush the packet
1315         sl_si91x_host_free_buffer(current_packet);
1316         sl_si91x_host_free_buffer(dummy_packet_buffer);
1317       }
1318       tx_command_queues_command_in_flight_status &= ~(event_mask);
1319 
1320       // Reset command trace for the queue
1321       queue->command_in_flight = false;
1322       queue->frame_type        = 0;
1323       queue->flag              = 0;
1324       queue->command_tickcount = 0;
1325       queue->command_timeout   = 0;
1326     }
1327   }
1328 
1329   // Start with the head of the TX queue
1330   current_packet = queue->tx_queue.head;
1331 
1332   // Iterate through all packets in the TX queue
1333   while (current_packet != NULL) {
1334     // Get the associated queue node
1335     queue_node = sl_si91x_host_get_buffer_data(current_packet, 0, NULL);
1336     if (queue_node == NULL) {
1337       CORE_ExitAtomic(state);
1338       return SL_STATUS_NOT_AVAILABLE; // Exit if queue node retrieval fails
1339     }
1340 
1341     if (!compare_function || compare_function(queue_node->host_packet, user_data) == false) {
1342       previous_packet = current_packet;
1343       current_packet  = (sl_wifi_buffer_t *)current_packet->node.node;
1344       continue;
1345     }
1346 
1347     // Save the next packet in the queue
1348     next_packet = (sl_wifi_buffer_t *)current_packet->node.node;
1349 
1350     // Check if the packet in the TX queue is synchronous or asynchronous
1351     if (queue_node->flags & SI91X_PACKET_RESPONSE_STATUS) {
1352       // Update the frame_status and other details
1353       queue_node->frame_status  = frame_status;
1354       current_packet->node.node = NULL;
1355 
1356       // Check if the TX packet is not expecting a response, then free the host packet
1357       if (!(queue_node->flags & SI91X_PACKET_RESPONSE_PACKET)) {
1358         if (queue_node->host_packet != NULL) {
1359           sl_si91x_host_free_buffer(queue_node->host_packet);
1360           queue_node->host_packet = NULL;
1361         }
1362       }
1363 
1364       // Check if the packet in the queue is synchronous or asynchronous response
1365       if (sl_si91x_host_elapsed_time(queue_node->command_tickcount) <= (queue_node->command_timeout)) {
1366         // Add the packet to the response queue and set the event
1367         sli_si91x_add_to_queue(&queue->rx_queue, current_packet);
1368         sli_si91x_set_event(event_mask);
1369       } else {
1370         // no user thread is waiting for the response so flush the packet
1371         if ((queue_node->flags & SI91X_PACKET_RESPONSE_PACKET) == SI91X_PACKET_RESPONSE_PACKET) {
1372           sl_si91x_host_free_buffer(queue_node->host_packet);
1373         }
1374         sl_si91x_host_free_buffer(current_packet);
1375       }
1376     } else {
1377       // Handle asynchronous packets by freeing them
1378       sl_si91x_host_free_buffer(current_packet);
1379     }
1380 
1381     // Update the head of the queue if the current packet is the head
1382     if (current_packet == queue->tx_queue.head) {
1383       queue->tx_queue.head = next_packet;
1384     }
1385 
1386     // Update the tail of the queue if the current packet is the tail
1387     if (current_packet == queue->tx_queue.tail) {
1388       queue->tx_queue.tail = previous_packet;
1389     }
1390 
1391     // Move to the next packet
1392     previous_packet = current_packet;
1393     current_packet  = next_packet;
1394   }
1395 
1396   // Check if the queue is empty and update tx_command_queues_status
1397   if (queue->tx_queue.head == NULL) {
1398     // Clear the tail pointer of the TX queue
1399     queue->tx_queue.tail = NULL;
1400     tx_command_queues_status &= ~(event_mask);
1401   }
1402 
1403   // Exit atomic section
1404   CORE_ExitAtomic(state);
1405 
1406   // Return SL_STATUS_OK indicating the operation was successful
1407   return SL_STATUS_OK;
1408 }
1409 
1410 #ifdef SLI_SI91X_OFFLOAD_NETWORK_STACK
sli_si91x_flush_all_socket_command_queues(uint16_t frame_status,uint8_t vap_id)1411 sl_status_t sli_si91x_flush_all_socket_command_queues(uint16_t frame_status, uint8_t vap_id)
1412 {
1413   sl_status_t status;
1414 
1415   // Loop through all sockets
1416   for (int index = 0; index < NUMBER_OF_SOCKETS; index++) {
1417     // Check if the socket exists and matches the required VAP ID
1418     if ((sli_si91x_sockets[index] != NULL) && (sli_si91x_sockets[index]->vap_id == vap_id)) {
1419       // Flush the command queues for the current socket based on queue type
1420       status = sli_si91x_flush_socket_command_queues_based_on_queue_type(index, frame_status);
1421       // If flushing fails, return the error status immediately
1422       if (status != SL_STATUS_OK) {
1423         return status;
1424       }
1425     }
1426   }
1427   // Return SL_STATUS_OK if all sockets were processed successfully
1428   return SL_STATUS_OK;
1429 }
1430 
sli_si91x_flush_socket_command_queues_based_on_queue_type(uint8_t index,uint16_t frame_status)1431 sl_status_t sli_si91x_flush_socket_command_queues_based_on_queue_type(uint8_t index, uint16_t frame_status)
1432 {
1433   sl_wifi_buffer_t *current_packet     = NULL;
1434   sl_wifi_buffer_t *next_packet        = NULL;
1435   sli_si91x_queue_packet_t *queue_node = NULL;
1436 
1437   // Retrieve the socket using the provided index
1438   sli_si91x_socket_t *socket = get_si91x_socket(index);
1439 
1440   if (socket == NULL) {
1441     return SL_STATUS_FAIL;
1442   }
1443 
1444   // Enter atomic state to prevent race conditions
1445   CORE_irqState_t state = CORE_EnterAtomic();
1446 
1447   // Check if there is a command currently in flight
1448   if ((socket->command_queue.command_in_flight) && ((socket->command_queue.flags) & SI91X_PACKET_RESPONSE_STATUS)) {
1449     // Create a generic RX packet from the current command parameters
1450     sl_status_t status = sl_create_generic_rx_packet_from_params(&queue_node,
1451                                                                  &current_packet,
1452                                                                  socket->command_queue.packet_id,
1453                                                                  socket->command_queue.flags,
1454                                                                  socket->command_queue.sdk_context,
1455                                                                  frame_status);
1456     // If packet creation fails, exit atomic state and return the error status
1457     if (status != SL_STATUS_OK) {
1458       CORE_ExitAtomic(state);
1459       return status;
1460     }
1461 
1462     // Handle packets that expect a response
1463     if (queue_node->flags & SI91X_PACKET_RESPONSE_PACKET) {
1464       sl_wifi_buffer_t *host_packet = NULL;
1465       uint16_t length               = 0;
1466       if (socket->command_queue.frame_type == RSI_WLAN_RSP_SOCKET_CLOSE) {
1467         length = sizeof(sl_si91x_packet_t) + sizeof(sl_si91x_socket_close_response_t);
1468       } else {
1469         length = sizeof(sl_si91x_packet_t);
1470       }
1471       // Allocate a buffer for the host packet
1472       status = sl_si91x_host_allocate_buffer(&host_packet,
1473                                              SL_WIFI_RX_FRAME_BUFFER,
1474                                              length,
1475                                              SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME);
1476       // If buffer allocation fails, log an error, trigger a breakpoint, and return
1477       if (status != SL_STATUS_OK) {
1478         SL_DEBUG_LOG("\r\n HEAP EXHAUSTED DURING ALLOCATION \r\n");
1479         BREAKPOINT();
1480       }
1481 
1482       // Populate the packet descriptor with frame status
1483       sl_si91x_packet_t *si91x_packet = (sl_si91x_packet_t *)sl_si91x_host_get_buffer_data(host_packet, 0, NULL);
1484       si91x_packet->desc[12]          = (uint8_t)(frame_status & 0x00FF);
1485       si91x_packet->desc[13]          = (uint8_t)((frame_status & 0xFF00) >> 8);
1486       queue_node->host_packet         = host_packet;
1487       host_packet->id                 = current_packet->id;
1488       if (socket->command_queue.frame_type == RSI_WLAN_RSP_SOCKET_CLOSE) {
1489         si91x_packet->desc[12]   = 0;
1490         si91x_packet->desc[13]   = 0;
1491         queue_node->frame_status = SL_STATUS_OK;
1492         sl_si91x_socket_close_response_t *socket_close_response =
1493           (sl_si91x_socket_close_response_t *)si91x_packet->data;
1494         socket_close_response->socket_id   = (uint16_t)socket->id;
1495         socket_close_response->port_number = socket->local_address.sin6_port;
1496       }
1497     }
1498 
1499     // Add the packet to the appropriate queue and set the event
1500     if (sl_si91x_host_elapsed_time(socket->command_queue.command_tickcount) <= socket->command_queue.command_timeout) {
1501       if (socket->command_queue.frame_type == RSI_WLAN_RSP_SOCKET_READ_DATA) {
1502         sli_si91x_add_to_queue(&socket->rx_data_queue, queue_node->host_packet);
1503       } else {
1504         sli_si91x_add_to_queue(&socket->command_queue.rx_queue, current_packet);
1505       }
1506       sli_si91x_set_socket_event((1 << socket->index));
1507     } else {
1508       // no user thread is waiting for the response so flush the packet
1509       if (queue_node->flags & SI91X_PACKET_RESPONSE_PACKET) {
1510         sl_si91x_host_free_buffer(queue_node->host_packet);
1511       }
1512       sl_si91x_host_free_buffer(current_packet);
1513     }
1514     tx_socket_command_command_in_flight_queues_status |= (1 << socket->index);
1515     // Reset command trace fields in the queue
1516     socket->command_queue.command_in_flight = false;
1517     socket->command_queue.command_tickcount = 0;
1518     socket->command_queue.command_timeout   = 0;
1519     socket->command_queue.frame_type        = 0;
1520   }
1521 
1522   // Start processing the TX queue
1523   current_packet = socket->command_queue.tx_queue.head;
1524 
1525   // Iterate through all packets in the command queue
1526   while (current_packet != NULL) {
1527     // Retrieve the queue node from the current packet
1528     queue_node = sl_si91x_host_get_buffer_data(current_packet, 0, NULL);
1529     if (queue_node == NULL) {
1530       // If queue node is NULL, exit atomic state and return error status
1531       CORE_ExitAtomic(state);
1532       return SL_STATUS_NOT_AVAILABLE;
1533     }
1534 
1535     // Assign next_packet to the next node in the list
1536     next_packet = (sl_wifi_buffer_t *)current_packet->node.node;
1537 
1538     // Check if the packet in the TX queue is synchronous or asynchronous
1539     if (queue_node->flags & SI91X_PACKET_RESPONSE_STATUS) {
1540       // Update the frame_status and other details for synchronous packets
1541       queue_node->frame_status  = frame_status;
1542       current_packet->node.node = NULL;
1543       int32_t frame_type        = sli_get_socket_command_from_host_packet(queue_node->host_packet);
1544       // Check if the TX packet is not expecting a response, then free the host packet
1545       if (!(queue_node->flags & SI91X_PACKET_RESPONSE_PACKET)) {
1546         if (queue_node->host_packet != NULL) {
1547           sl_si91x_host_free_buffer(queue_node->host_packet);
1548           queue_node->host_packet = NULL;
1549         }
1550       }
1551 
1552       // Add to response queue and raise event based on frame type
1553       if (sl_si91x_host_elapsed_time(queue_node->command_tickcount) <= queue_node->command_timeout) {
1554         if (frame_type == RSI_WLAN_RSP_SOCKET_CLOSE) {
1555           sl_si91x_host_free_buffer(queue_node->host_packet);
1556           sl_wifi_buffer_t *host_packet = NULL;
1557           // Allocate a buffer for the host packet
1558           sl_status_t status =
1559             sl_si91x_host_allocate_buffer(&host_packet,
1560                                           SL_WIFI_RX_FRAME_BUFFER,
1561                                           sizeof(sl_si91x_packet_t) + sizeof(sl_si91x_socket_close_response_t),
1562                                           SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME);
1563           // If buffer allocation fails, log an error, trigger a breakpoint, and return
1564           if (status != SL_STATUS_OK) {
1565             SL_DEBUG_LOG("\r\n HEAP EXHAUSTED DURING ALLOCATION \r\n");
1566             BREAKPOINT();
1567           }
1568           queue_node->host_packet  = host_packet;
1569           queue_node->frame_status = SL_STATUS_OK;
1570           sl_si91x_packet_t *si91x_packet =
1571             (sl_si91x_packet_t *)sl_si91x_host_get_buffer_data(queue_node->host_packet, 0, NULL);
1572           si91x_packet->desc[12] = 0;
1573           si91x_packet->desc[13] = 0;
1574           sl_si91x_socket_close_response_t *socket_close_response =
1575             (sl_si91x_socket_close_response_t *)si91x_packet->data;
1576           socket_close_response->socket_id   = (uint16_t)socket->id;
1577           socket_close_response->port_number = socket->local_address.sin6_port;
1578         }
1579         if (frame_type == RSI_WLAN_RSP_SOCKET_READ_DATA) {
1580           sl_si91x_packet_t *si91x_packet =
1581             (sl_si91x_packet_t *)sl_si91x_host_get_buffer_data(queue_node->host_packet, 0, NULL);
1582           if (si91x_packet != NULL) {
1583             si91x_packet->desc[12] = (uint8_t)(frame_status & 0x00FF);
1584             si91x_packet->desc[13] = (uint8_t)((frame_status & 0xFF00) >> 8);
1585             sli_si91x_add_to_queue(&socket->rx_data_queue, queue_node->host_packet);
1586           }
1587         } else {
1588           sli_si91x_add_to_queue(&socket->command_queue.rx_queue, current_packet);
1589         }
1590 
1591         sli_si91x_set_socket_event((1 << socket->index));
1592       } else {
1593         // no user thread is waiting for the response so flush the packet
1594         if ((queue_node->flags & SI91X_PACKET_RESPONSE_PACKET) == SI91X_PACKET_RESPONSE_PACKET) {
1595           sl_si91x_host_free_buffer(queue_node->host_packet);
1596         }
1597         sl_si91x_host_free_buffer(current_packet);
1598       }
1599     } else {
1600       // Handle asynchronous packets by freeing the buffer
1601       sl_si91x_host_free_buffer(current_packet);
1602     }
1603 
1604     // Move to the next packet in the queue
1605     current_packet = next_packet;
1606   }
1607 
1608   // Clear the head and tail pointers of the TX queue
1609   socket->command_queue.tx_queue.head = NULL;
1610   socket->command_queue.tx_queue.tail = NULL;
1611   // Clear the socket command queue status
1612   tx_socket_command_queues_status &= ~(1 << socket->index);
1613 
1614   // Exit atomic state
1615   CORE_ExitAtomic(state);
1616   // Return successful status
1617   return SL_STATUS_OK;
1618 }
sli_si91x_flush_all_socket_data_queues(uint8_t vap_id)1619 sl_status_t sli_si91x_flush_all_socket_data_queues(uint8_t vap_id)
1620 {
1621   sl_status_t status;
1622 
1623   // Loop through all sockets
1624   for (int index = 0; index < NUMBER_OF_SOCKETS; index++) {
1625     // Retrieve the socket using the provided index
1626     const sli_si91x_socket_t *socket = sli_si91x_sockets[index];
1627 
1628     // Check if the socket exists and matches the required VAP ID
1629     if ((socket != NULL) && (socket->vap_id == vap_id)) {
1630       // Flush the data queues for the current socket based on queue type
1631       status = sli_si91x_flush_socket_data_queues_based_on_queue_type(index);
1632       // If flushing fails, return the error status immediately
1633       if (status != SL_STATUS_OK) {
1634         return status;
1635       }
1636     }
1637   }
1638   // Return SL_STATUS_OK if all sockets were processed successfully
1639   return SL_STATUS_OK;
1640 }
1641 
sli_si91x_flush_socket_data_queues_based_on_queue_type(uint8_t index)1642 sl_status_t sli_si91x_flush_socket_data_queues_based_on_queue_type(uint8_t index)
1643 {
1644   sl_wifi_buffer_t *current_packet = NULL;
1645   sl_wifi_buffer_t *next_packet    = NULL;
1646 
1647   // Retrieve the socket using the provided index
1648   sli_si91x_socket_t *socket = get_si91x_socket(index);
1649 
1650   if (socket == NULL) {
1651     return SL_STATUS_FAIL;
1652   }
1653 
1654   // Enter atomic section to prevent race conditions
1655   CORE_irqState_t state = CORE_EnterAtomic();
1656 
1657   // Start with the head of the TX data queue
1658   current_packet = socket->tx_data_queue.head;
1659 
1660   // Iterate through all packets in the queue
1661   while (current_packet != NULL) {
1662     // Save the next packet in the queue
1663     next_packet = (sl_wifi_buffer_t *)current_packet->node.node;
1664 
1665     // Free the current packet using the provided free function
1666     sl_si91x_host_free_buffer(current_packet);
1667 
1668     // Move to the next packet
1669     current_packet = next_packet;
1670   }
1671 
1672   // Clear the head and tail pointers of the queue to indicate it is empty
1673   socket->tx_data_queue.head = NULL;
1674   socket->tx_data_queue.tail = NULL;
1675 
1676   // Clear the socket data queue status
1677   tx_socket_data_queues_status &= ~(1 << socket->index);
1678 
1679   // Exit atomic section
1680   CORE_ExitAtomic(state);
1681 
1682   // Return SL_STATUS_OK indicating the operation was successful
1683   return SL_STATUS_OK;
1684 }
1685 
1686 #endif
1687 
sl_si91x_host_queue_status(sl_si91x_buffer_queue_t * queue)1688 uint32_t sl_si91x_host_queue_status(sl_si91x_buffer_queue_t *queue)
1689 {
1690   return queue->head != NULL;
1691 }
1692 
sli_si91x_wait_for_event(uint32_t event_mask,uint32_t timeout)1693 uint32_t sli_si91x_wait_for_event(uint32_t event_mask, uint32_t timeout)
1694 {
1695   uint32_t result = osEventFlagsWait(si91x_events, event_mask, osFlagsWaitAny, timeout);
1696 
1697   if (result == (uint32_t)osErrorTimeout || result == (uint32_t)osErrorResource) {
1698     return 0;
1699   }
1700   return result;
1701 }
1702 
si91x_host_wait_for_bus_event(uint32_t event_mask,uint32_t timeout)1703 uint32_t si91x_host_wait_for_bus_event(uint32_t event_mask, uint32_t timeout)
1704 {
1705   uint32_t result = osEventFlagsWait(si91x_bus_events, event_mask, osFlagsWaitAny, timeout);
1706 
1707   if (result == (uint32_t)osErrorTimeout || result == (uint32_t)osErrorResource) {
1708     return 0;
1709   }
1710   return result;
1711 }
1712 
sli_si91x_clear_event(uint32_t event_mask)1713 uint32_t sli_si91x_clear_event(uint32_t event_mask)
1714 {
1715   uint32_t result = osEventFlagsClear(si91x_events, event_mask);
1716   if (result == (uint32_t)osErrorResource) {
1717     return 0;
1718   }
1719   return result;
1720 }
1721 
sli_si91x_send_power_save_request(const sl_wifi_performance_profile_t * wifi_profile,const sl_bt_performance_profile_t * bt_profile)1722 sl_status_t sli_si91x_send_power_save_request(const sl_wifi_performance_profile_t *wifi_profile,
1723                                               const sl_bt_performance_profile_t *bt_profile)
1724 {
1725   sl_status_t status;
1726   sl_si91x_power_save_request_t power_save_request          = { 0 };
1727   sl_si91x_performance_profile_t selected_coex_profile_mode = { 0 };
1728   // Disable power save mode by setting it to HIGH_PERFORMANCE profile
1729   status = sl_si91x_driver_send_command(RSI_COMMON_REQ_PWRMODE,
1730                                         SI91X_COMMON_CMD,
1731                                         &power_save_request,
1732                                         sizeof(sl_si91x_power_save_request_t),
1733                                         SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
1734                                         NULL,
1735                                         NULL);
1736   VERIFY_STATUS_AND_RETURN(status);
1737 
1738   if (NULL != wifi_profile) {
1739     // Save the new Wi-Fi profile
1740     save_wifi_current_performance_profile(wifi_profile);
1741   }
1742 
1743   if (NULL != bt_profile) {
1744     // Save the new BT/BLE profile
1745     save_bt_current_performance_profile(bt_profile);
1746   }
1747 
1748   // get the updated coex profile
1749   get_coex_performance_profile(&selected_coex_profile_mode);
1750 
1751   // If the requested performance profile is HIGH_PERFORMANCE, no need to send the request to firmware
1752   if (selected_coex_profile_mode == HIGH_PERFORMANCE) {
1753     return SL_STATUS_OK;
1754   }
1755 
1756   // Convert the performance profile to a power save request.
1757   convert_performance_profile_to_power_save_command(selected_coex_profile_mode, &power_save_request);
1758 
1759   status = sl_si91x_driver_send_command(RSI_COMMON_REQ_PWRMODE,
1760                                         SI91X_COMMON_CMD,
1761                                         &power_save_request,
1762                                         sizeof(sl_si91x_power_save_request_t),
1763                                         SL_SI91X_WAIT_FOR_RESPONSE(3000),
1764                                         NULL,
1765                                         NULL);
1766   VERIFY_STATUS_AND_RETURN(status);
1767   return status;
1768 }
1769 
sl_si91x_host_power_cycle(void)1770 sl_status_t sl_si91x_host_power_cycle(void)
1771 {
1772   sl_si91x_host_hold_in_reset();
1773   sl_si91x_host_delay_ms(100);
1774 
1775   sl_si91x_host_release_from_reset();
1776   sl_si91x_host_delay_ms(100);
1777 
1778   return SL_STATUS_OK;
1779 }
1780 
print_80211_packet(const uint8_t * packet,uint32_t packet_length,uint16_t max_payload_length)1781 void print_80211_packet(const uint8_t *packet, uint32_t packet_length, uint16_t max_payload_length)
1782 {
1783   uint32_t dump_bytes    = 0;
1784   uint32_t header_length = MAC80211_HDR_MIN_LEN;
1785 
1786   header_length += (packet[0] & BIT(7)) ? 2 : 0;                           /* 2 bytes QoS control */
1787   header_length += ((packet[1] & BIT(0)) && (packet[1] & BIT(1))) ? 6 : 0; /* 6 byte Addr4 */
1788 
1789   sl_debug_log("%02x %02x | ", packet[0], packet[1]); /* FC */
1790   sl_debug_log("%02x %02x | ", packet[2], packet[3]); /* Dur */
1791   sl_debug_log("%02x:%02x:%02x:%02x:%02x:%02x | ",
1792                packet[4],
1793                packet[5],
1794                packet[6],
1795                packet[7],
1796                packet[8],
1797                packet[9]); /* Addr1/RA */
1798   sl_debug_log("%02x:%02x:%02x:%02x:%02x:%02x | ",
1799                packet[10],
1800                packet[11],
1801                packet[12],
1802                packet[13],
1803                packet[14],
1804                packet[15]); /* Addr2/NWP */
1805   sl_debug_log("%02x:%02x:%02x:%02x:%02x:%02x | ",
1806                packet[16],
1807                packet[17],
1808                packet[18],
1809                packet[19],
1810                packet[20],
1811                packet[21]);                             /* Addr3/DA */
1812   sl_debug_log("%02x %02x | ", packet[22], packet[23]); /* Seq control */
1813   if ((packet[1] & BIT(0)) && (packet[1] & BIT(1))) {   /* Addr4 */
1814     sl_debug_log("%02x:%02x:%02x:%02x:%02x:%02x | ",
1815                  packet[24],
1816                  packet[25],
1817                  packet[26],
1818                  packet[27],
1819                  packet[28],
1820                  packet[29]);
1821   }
1822   if (packet[0] & BIT(7)) {
1823     sl_debug_log("%02x %02x | ", packet[30], packet[31]); /* QoS control */
1824   }
1825 
1826   // Determine number of payload bytes to print
1827   dump_bytes = packet_length - header_length;
1828   dump_bytes = max_payload_length > dump_bytes ? dump_bytes : max_payload_length;
1829 
1830   for (uint32_t i = header_length; i < header_length + dump_bytes; i++) {
1831     sl_debug_log("%02x ", packet[i]);
1832   }
1833 
1834   sl_debug_log("|\r\n");
1835 }
1836 
sli_si91x_get_command_queue(sl_si91x_command_type_t type)1837 sli_si91x_command_queue_t *sli_si91x_get_command_queue(sl_si91x_command_type_t type)
1838 {
1839   switch (type) {
1840     case SI91X_WLAN_CMD:
1841       return &cmd_queues[SI91X_WLAN_CMD];
1842     case SI91X_NETWORK_CMD:
1843       return &cmd_queues[SI91X_NETWORK_CMD];
1844     case SI91X_BT_CMD:
1845       return &cmd_queues[SI91X_BT_CMD];
1846     case SI91X_SOCKET_CMD:
1847       return &cmd_queues[SI91X_SOCKET_CMD];
1848 
1849     case SI91X_COMMON_CMD:
1850     default:
1851       return &cmd_queues[SI91X_COMMON_CMD];
1852   }
1853 }
1854 
sli_lmac_crc8_c(uint8_t crc8_din,uint8_t crc8_state,uint8_t end)1855 uint8_t sli_lmac_crc8_c(uint8_t crc8_din, uint8_t crc8_state, uint8_t end)
1856 {
1857   uint8_t din[8];
1858   uint8_t state[8];
1859   uint8_t state_c[8];
1860   uint8_t crc8_out;
1861 
1862   din[0] = ((crc8_din & BIT(7)) >> 7);
1863   din[1] = ((crc8_din & BIT(6)) >> 6);
1864   din[2] = ((crc8_din & BIT(5)) >> 5);
1865   din[3] = ((crc8_din & BIT(4)) >> 4);
1866   din[4] = ((crc8_din & BIT(3)) >> 3);
1867   din[5] = ((crc8_din & BIT(2)) >> 2);
1868   din[6] = ((crc8_din & BIT(1)) >> 1);
1869   din[7] = ((crc8_din & BIT(0)) >> 0);
1870 
1871   state[0] = ((crc8_state & BIT(0)) >> 0);
1872   state[1] = ((crc8_state & BIT(1)) >> 1);
1873   state[2] = ((crc8_state & BIT(2)) >> 2);
1874   state[3] = ((crc8_state & BIT(3)) >> 3);
1875   state[4] = ((crc8_state & BIT(4)) >> 4);
1876   state[5] = ((crc8_state & BIT(5)) >> 5);
1877   state[6] = ((crc8_state & BIT(6)) >> 6);
1878   state[7] = ((crc8_state & BIT(7)) >> 7);
1879 
1880   state_c[7] = (state[7] ^ din[7]) ^ (state[6] ^ din[6]) ^ (state[5] ^ din[5]);
1881 
1882   state_c[6] = (state[6] ^ din[6]) ^ (state[5] ^ din[5]) ^ (state[4] ^ din[4]);
1883 
1884   state_c[5] = (state[5] ^ din[5]) ^ (state[4] ^ din[4]) ^ (state[3] ^ din[3]);
1885 
1886   state_c[4] = (state[4] ^ din[4]) ^ (state[3] ^ din[3]) ^ (state[2] ^ din[2]);
1887 
1888   state_c[3] = (state[1] ^ din[1]) ^ (state[2] ^ din[2]) ^ (state[3] ^ din[3]) ^ (state[7] ^ din[7]);
1889 
1890   state_c[2] = (state[0] ^ din[0]) ^ (state[1] ^ din[1]) ^ (state[2] ^ din[2]) ^ (state[6] ^ din[6]);
1891 
1892   state_c[1] = (state[0] ^ din[0]) ^ (state[1] ^ din[1]) ^ (state[6] ^ din[6]);
1893 
1894   state_c[0] = (state[0] ^ din[0]) ^ (state[7] ^ din[7]) ^ (state[6] ^ din[6]);
1895   if (!end) {
1896     crc8_out = (uint8_t)(((state_c[0] & BIT(0)) << 0) | ((state_c[1] & BIT(0)) << 1) | ((state_c[2] & BIT(0)) << 2)
1897                          | ((state_c[3] & BIT(0)) << 3) | ((state_c[4] & BIT(0)) << 4) | ((state_c[5] & BIT(0)) << 5)
1898                          | ((state_c[6] & BIT(0)) << 6) | ((state_c[7] & BIT(0)) << 7));
1899   } else {
1900     crc8_out = (uint8_t)(((state_c[7] & BIT(0)) << 0) | ((state_c[6] & BIT(0)) << 1) | ((state_c[5] & BIT(0)) << 2)
1901                          | ((state_c[4] & BIT(0)) << 3) | ((state_c[3] & BIT(0)) << 4) | ((state_c[2] & BIT(0)) << 5));
1902 
1903     crc8_out = ~crc8_out;
1904     crc8_out &= 0x3f;
1905   }
1906   return crc8_out;
1907 }
1908 
sli_multicast_mac_hash(const uint8_t * mac)1909 uint8_t sli_multicast_mac_hash(const uint8_t *mac)
1910 {
1911   uint8_t crc = 0xff;
1912   for (uint8_t i = 0; i < 6; i++) {
1913     crc = sli_lmac_crc8_c(mac[i], crc, ((i == 5) ? 1 : 0));
1914   }
1915   return crc;
1916 }
1917 
1918 /* Function to get the current status of the NVM command progress
1919 Returns true if an NVM command is in progress, false otherwise*/
sli_si91x_get_flash_command_status()1920 bool sli_si91x_get_flash_command_status()
1921 {
1922   return sli_si91x_packet_status;
1923 }
1924 
sli_si91x_update_flash_command_status(bool flag)1925 void sli_si91x_update_flash_command_status(bool flag)
1926 {
1927   sli_si91x_packet_status = flag;
1928 }
1929 
1930 /*  This function is used to update the power manager to see whether the device is ready for sleep or not.
1931  True indicates ready for sleep, and false indicates not ready for sleep.*/
sli_si91x_is_sdk_ok_to_sleep()1932 bool sli_si91x_is_sdk_ok_to_sleep()
1933 {
1934   return ((!sli_si91x_get_flash_command_status()) && (sl_si91x_is_device_initialized()));
1935 }
1936 
sl_si91x_is_device_initialized(void)1937 bool sl_si91x_is_device_initialized(void)
1938 {
1939   return device_initialized;
1940 }
1941 
sli_si91x_remove_buffer_from_queue_by_comparator(sl_si91x_buffer_queue_t * queue,const void * user_data,sli_si91x_wifi_buffer_comparator comparator,sl_wifi_buffer_t ** buffer)1942 sl_status_t sli_si91x_remove_buffer_from_queue_by_comparator(sl_si91x_buffer_queue_t *queue,
1943                                                              const void *user_data,
1944                                                              sli_si91x_wifi_buffer_comparator comparator,
1945                                                              sl_wifi_buffer_t **buffer)
1946 {
1947   // Check if the queue is empty
1948   if (queue->head == NULL) {
1949     assert(queue->tail == NULL);
1950     return SL_STATUS_EMPTY;
1951   }
1952 
1953   CORE_irqState_t state            = CORE_EnterAtomic();
1954   sl_wifi_buffer_t *current_buffer = queue->head;
1955   sl_wifi_buffer_t *prev_buffer    = NULL;
1956 
1957   // Iterate through the queue to find a matching buffer based on the comparator function
1958   while (current_buffer != NULL) {
1959     // Skip to the next buffer if this one doesn't match
1960     if (!comparator(current_buffer, user_data)) {
1961       prev_buffer    = current_buffer;
1962       current_buffer = (sl_wifi_buffer_t *)current_buffer->node.node;
1963       continue;
1964     }
1965 
1966     // Buffer matches, proceed to remove it
1967     *buffer = current_buffer;
1968 
1969     if (current_buffer == queue->head) {
1970       // Removing the head of the queue
1971       queue->head = (sl_wifi_buffer_t *)current_buffer->node.node;
1972       if (queue->head == NULL) {
1973         queue->tail = NULL; // Queue is now empty
1974       }
1975     } else if (current_buffer == queue->tail) {
1976       // Removing the tail of the queue
1977       queue->tail            = prev_buffer;
1978       prev_buffer->node.node = NULL;
1979     } else {
1980       // Removing a buffer from the middle
1981       prev_buffer->node.node = current_buffer->node.node;
1982     }
1983 
1984     CORE_ExitAtomic(state);
1985     return SL_STATUS_OK;
1986   }
1987 
1988   // No matching buffer was found
1989   CORE_ExitAtomic(state);
1990   return SL_STATUS_NOT_FOUND;
1991 }
1992 
sl_si91x_host_get_credentials(sl_wifi_credential_id_t id,uint8_t type,sl_wifi_credential_t * cred)1993 sl_status_t sl_si91x_host_get_credentials(sl_wifi_credential_id_t id, uint8_t type, sl_wifi_credential_t *cred)
1994 {
1995   uint32_t credential_length = sizeof(sl_wifi_credential_t) - offsetof(sl_wifi_credential_t, pmk);
1996   sl_status_t status         = sl_wifi_get_credential(id, &cred->type, &cred->pmk, &credential_length);
1997   VERIFY_STATUS_AND_RETURN(status);
1998 
1999   if (type == SL_WIFI_PSK_CREDENTIAL) {
2000     if ((cred->type == SL_WIFI_PSK_CREDENTIAL) || (cred->type == SL_WIFI_PMK_CREDENTIAL)) {
2001       return SL_STATUS_OK;
2002     } else {
2003       return SL_STATUS_FAIL;
2004     }
2005   } else if (type != cred->type) {
2006     return SL_STATUS_FAIL;
2007   }
2008 
2009   return SL_STATUS_OK;
2010 }
2011