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 ¤t_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 ¤t_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