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_wifi.h"
31 #include "sl_si91x_host_interface.h"
32 #include "sl_wifi_types.h"
33 #include "sl_si91x_status.h"
34 #include "sl_si91x_types.h"
35 #include "sl_si91x_protocol_types.h"
36 #include "sl_wifi_device.h"
37 #include "sl_rsi_utility.h"
38 #include "sl_si91x_driver.h"
39 #include "cmsis_os2.h"
40 #include <stdint.h>
41 #include <string.h>
42 #include <assert.h>
43 #include "sl_si91x_core_utilities.h"
44 #include "em_core.h"
45 #ifdef SLI_SI91X_MCU_INTERFACE
46 #include "sli_siwx917_soc.h"
47 #include "rsi_rom_clks.h"
48 #include "rsi_m4.h"
49 #include "rsi_wisemcu_hardware_setup.h"
50 #endif
51 #ifdef SLI_SI91X_ENABLE_BLE
52 #include "rsi_common_apis.h"
53 #endif
54 
55 #include "sl_wifi_region_db_config.h"
56 
57 #ifdef SLI_SI91X_SOCKETS
58 #include "sl_si91x_socket_utility.h"
59 #include "sl_si91x_socket_callback_framework.h"
60 #endif
61 
62 #ifdef SL_SI91X_SIDE_BAND_CRYPTO
63 #include "rsi_m4.h"
64 #define SIDE_BAND_DONE (1 << 2) //! had to be redefined as this macro is not in .h
65 rsi_m4ta_desc_t crypto_desc[2];
66 extern osEventFlagsId_t ta_events;
67 extern osMutexId_t side_band_crypto_mutex;
68 #endif
69 
70 #ifndef NULL
71 #define NULL (void *)0
72 #endif
73 
74 #define htole16(x) (x)
75 #define htole32(x) (x)
76 
77 #ifndef SL_WIFI_SET_MAC_COMMAND_TIME_OUT
78 #define SL_WIFI_SET_MAC_COMMAND_TIME_OUT 30100 // Retrieved from SAPI 1.0
79 #endif
80 
81 #define SLI_SI91X_GET_TCP_IP_TOTAL_SELECTS_BITS(x) ((x & 0x0000F000) >> 12)
82 
83 #define SL_SI91X_INVALID_MODE 0xFFFF
84 
85 #ifdef SL_SI91X_SIDE_BAND_CRYPTO
86 #define SL_HOST_DESC_LEN  16
87 #define SL_CRYPTO_PKT_LEN 128
88 #endif
89 
90 // Enterprise configuration command parameters
91 /*=======================================================================*/
92 
93 // Enterprise method ,should be one of among TLS, TTLS, FAST or PEAP
94 
95 #define SL_EAP_TLS_METHOD  "TLS"
96 #define SL_EAP_TTLS_METHOD "TTLS"
97 
98 // This parameter is used to configure the module in Enterprise security mode
99 #define SL_EAP_INNER_METHOD "\"auth=MSCHAPV2\""
100 
101 // Private Key Password is required for encrypted private key, format is like "\"12345678\""
102 #define SL_DEFAULT_PRIVATE_KEY_PASSWORD ""
103 
104 /*========================================================================*/
105 // 11ax params
106 /*========================================================================*/
107 #define GUARD_INTERVAL 3
108 
109 #ifdef SLI_SI91X_MCU_INTERFACE
110 #define TX_PKT_TRANSFER_DONE_INTERRUPT BIT(2)
111 #define RX_PKT_TRANSFER_DONE_INTERRUPT BIT(1)
112 
113 // Function declarations related to M4 interface
114 sl_status_t sli_si91x_submit_rx_pkt(void);
115 static sl_status_t sl_si91x_soft_reset(void);
116 void sli_siwx917_update_system_core_clock(void);
117 void sli_m4_ta_interrupt_init(void);
118 #endif
119 
120 // Structure to hold packet information and payload
121 typedef struct {
122   uint16_t packet_id;
123   sli_si91x_queue_packet_t *packet;
124   void *payload;
125 } sl_si91x_driver_context_t;
126 
127 static sl_si91x_timeout_t timeout_glbl = { .auth_assoc_timeout_value       = SL_WIFI_DEFAULT_AUTH_ASSOCIATION_TIMEOUT,
128                                            .active_chan_scan_timeout_value = SL_WIFI_DEFAULT_ACTIVE_CHANNEL_SCAN_TIME,
129                                            .keep_alive_timeout_value       = SL_WIFI_DEFAULT_KEEP_ALIVE_TIMEOUT,
130                                            .passive_scan_timeout_value = SL_WIFI_DEFAULT_PASSIVE_CHANNEL_SCAN_TIME };
131 
132 sl_status_t sl_si91x_driver_send_command_packet(uint32_t command,
133                                                 sl_si91x_command_type_t command_type,
134                                                 sl_wifi_buffer_t *buffer,
135                                                 sl_si91x_wait_period_t wait_period,
136                                                 void *sdk_context,
137                                                 sl_wifi_buffer_t **data_buffer);
138 static sl_status_t sl_si91x_driver_send_data_packet(sl_wifi_buffer_t *buffer, uint32_t wait_time);
139 sl_status_t sl_si91x_driver_raw_send_command(uint8_t command,
140                                              const void *data,
141                                              uint32_t data_length,
142                                              uint32_t wait_time);
143 sl_status_t sl_si91x_allocate_data_buffer(sl_wifi_buffer_t **host_buffer,
144                                           void **buffer,
145                                           uint32_t data_size,
146                                           uint32_t wait_duration_ms);
147 sl_status_t sl_si91x_driver_init_wifi_radio(const sl_wifi_device_configuration_t *config);
148 sl_status_t sli_verify_device_boot(uint32_t *rom_version);
149 sl_status_t sl_si91x_enable_radio(void);
150 sl_status_t sli_wifi_select_option(const uint8_t configuration);
151 sl_status_t si91x_bootup_firmware(const uint8_t select_option);
152 sl_status_t sl_si91x_host_power_cycle(void);
153 
154 // This variable stores the frame status of response packet in case of API executed being failed.
155 // Note: This will not store the error values of asynchronous events.
156 sl_wifi_event_handler_t si91x_event_handler = NULL;
157 
158 // Global variables for device and driver management
159 sl_wifi_interface_t default_interface;
160 bool device_initialized                           = false;
161 bool interface_is_up[SL_WIFI_MAX_INTERFACE_INDEX] = { false, false, false, false, false };
162 bool bg_enabled                                   = false;
163 uint32_t frontend_switch_control                  = 0;
164 static uint32_t feature_bit_map                   = 0;
165 //static uint16_t queue_packet_id[SI91X_CMD_MAX]    = { 0 };
166 static uint8_t ap_join_feature_bitmap         = SL_SI91X_JOIN_FEAT_LISTEN_INTERVAL_VALID;
167 static uint8_t client_join_feature_bitmap     = SL_SI91X_JOIN_FEAT_LISTEN_INTERVAL_VALID;
168 static uint32_t client_listen_interval        = 1000;
169 static sl_si91x_efuse_data_t si91x_efuse_data = { 0 };
170 //! Currently, initialized_opermode is used only to handle concurrent mode using sl_net_init()
171 static uint16_t initialized_opermode = SL_SI91X_INVALID_MODE;
172 extern sli_si91x_command_queue_t cmd_queues[SI91X_CMD_MAX];
173 extern sl_si91x_buffer_queue_t sli_tx_data_queue;
174 
175 sli_si91x_performance_profile_t performance_profile;
176 extern osEventFlagsId_t si91x_events;
177 extern volatile uint32_t tx_command_queues_status;
178 extern volatile uint32_t tx_generic_socket_data_queues_status;
179 
180 #ifdef SLI_SI91X_ENABLE_BLE
181 //! Memory length for driver
182 #define GLOBAL_BUFF_LEN 1500
183 
184 //! Memory to initialize driver
185 uint8_t global_buf[GLOBAL_BUFF_LEN] = { 0 };
186 #endif
187 // clang-format off
188 const sl_wifi_scan_configuration_t default_wifi_scan_configuration = { .type  = SL_WIFI_SCAN_TYPE_ACTIVE,
189                                                                        .flags = 0,
190                                                                        .periodic_scan_interval = 0,
191                                                                        .channel_bitmap_2g4     = 0xFFFF,
192                                                                        .channel_bitmap_5g      = { 0xFFFFFFFF,
193                                                                                               0xFFFFFFFF,
194                                                                                               0xFFFFFFFF,
195                                                                                               0xFFFFFFFF,
196                                                                                               0xFFFFFFFF,
197                                                                                               0xFFFFFFFF,
198                                                                                               0xFFFFFFFF,
199                                                                                               0xFFFFFFFF },
200                                                                        .lp_mode = 0};
201 
202 // clang-format on
203 const sl_wifi_buffer_configuration_t default_buffer_configuration = {
204   .control_buffer_quota = 10,
205   .tx_buffer_quota      = 10,
206   .rx_buffer_quota      = 10,
207 #ifdef SPI_EXTENDED_TX_LEN_2K
208   .block_size = 2300,
209 #else
210   .block_size = 1616,
211 #endif
212   .buffer_memory = NULL,
213 };
214 
215 const sl_wifi_ap_configuration_t default_wifi_ap_configuration = {
216   .ssid                = { .value = "SILICON_LABS_AP", .length = sizeof("SILICON_LABS_AP") - 1 },
217   .security            = SL_WIFI_WPA2,
218   .encryption          = SL_WIFI_CCMP_ENCRYPTION,
219   .channel             = { .channel = 11 },
220   .rate_protocol       = SL_WIFI_RATE_PROTOCOL_AUTO,
221   .options             = 0,
222   .credential_id       = 2, //SL_NET_DEFAULT_WIFI_AP_CREDENTIAL_ID,
223   .keepalive_type      = SL_SI91X_AP_NULL_BASED_KEEP_ALIVE,
224   .beacon_interval     = 100,
225   .client_idle_timeout = 120000,
226   .dtim_beacon_count   = 4,
227   .maximum_clients     = 4
228 };
229 
230 // clang-format off
231 static uint8_t firmware_queue_id[SI91X_CMD_MAX]   = { [SI91X_COMMON_CMD]  = RSI_WLAN_MGMT_Q,
232                                                     [SI91X_WLAN_CMD]      = RSI_WLAN_MGMT_Q,
233                                                     [SI91X_NETWORK_CMD]   = RSI_WLAN_MGMT_Q,
234 													[SI91X_SOCKET_CMD]    = RSI_WLAN_MGMT_Q,
235                                                     [SI91X_BT_CMD]        = RSI_BT_Q };
236 //static uint32_t response_event_map[SI91X_CMD_MAX] = { [SI91X_COMMON_CMD]  = NCP_HOST_COMMON_RESPONSE_EVENT,
237 //                                                      [SI91X_WLAN_CMD]    = NCP_HOST_WLAN_RESPONSE_EVENT,
238 //                                                      [SI91X_NETWORK_CMD] = NCP_HOST_NETWORK_RESPONSE_EVENT,
239 //                                                      [SI91X_SOCKET_CMD]  = NCP_HOST_SOCKET_RESPONSE_EVENT,
240 //                                                      [SI91X_BT_CMD]      = NCP_HOST_BT_RESPONSE_EVENT };
241 // clang-format on
242 #ifdef SLI_SI91X_MCU_INTERFACE
243 extern sl_wifi_buffer_t *rx_pkt_buffer;
244 #endif
245 
si91x_packet_identification_function(const sl_wifi_buffer_t * buffer,const void * user_data)246 static bool si91x_packet_identification_function(const sl_wifi_buffer_t *buffer, const void *user_data)
247 {
248   const uint8_t *packet_id = (const uint8_t *)user_data;
249 
250   // Check if the packet's packet ID matches the expected one
251   return (*packet_id == buffer->id);
252 }
253 
sl_si91x_get_efuse_data(sl_si91x_efuse_data_t * efuse_data)254 void sl_si91x_get_efuse_data(sl_si91x_efuse_data_t *efuse_data)
255 {
256   memcpy(efuse_data, &si91x_efuse_data, sizeof(sl_si91x_efuse_data_t));
257 }
258 
sl_si91x_set_efuse_data(const sl_si91x_efuse_data_t * efuse_data)259 void sl_si91x_set_efuse_data(const sl_si91x_efuse_data_t *efuse_data)
260 {
261   memcpy(&si91x_efuse_data, efuse_data, sizeof(sl_si91x_efuse_data_t));
262 }
263 
sl_si91x_driver_init_wifi_radio(const sl_wifi_device_configuration_t * config)264 sl_status_t sl_si91x_driver_init_wifi_radio(const sl_wifi_device_configuration_t *config)
265 {
266   sl_status_t status;
267 
268 // Set 11ax configuration with guard interval if SLI_SI91X_CONFIG_WIFI6_PARAMS is supported
269 #ifdef SLI_SI91X_CONFIG_WIFI6_PARAMS
270   status = sl_wifi_set_11ax_config(GUARD_INTERVAL);
271   VERIFY_STATUS_AND_RETURN(status);
272 #endif
273 
274   // Send WLAN request to set the operating band (2.4GHz or 5GHz)
275   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_BAND,
276                                         SI91X_WLAN_CMD,
277                                         &config->band,
278                                         1,
279                                         SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
280                                         NULL,
281                                         NULL);
282   VERIFY_STATUS_AND_RETURN(status);
283 
284   if (config->boot_config.oper_mode != SL_SI91X_ACCESS_POINT_MODE) {
285     if (timeout_glbl.active_chan_scan_timeout_value != SL_WIFI_DEFAULT_ACTIVE_CHANNEL_SCAN_TIME) {
286       status =
287         sl_si91x_configure_timeout(SL_SI91X_CHANNEL_ACTIVE_SCAN_TIMEOUT, timeout_glbl.active_chan_scan_timeout_value);
288       VERIFY_STATUS_AND_RETURN(status);
289     }
290 
291     if (timeout_glbl.auth_assoc_timeout_value != SL_WIFI_DEFAULT_AUTH_ASSOCIATION_TIMEOUT) {
292       status =
293         sl_si91x_configure_timeout(SL_SI91X_AUTHENTICATION_ASSOCIATION_TIMEOUT, timeout_glbl.auth_assoc_timeout_value);
294       VERIFY_STATUS_AND_RETURN(status);
295     }
296 
297     if (timeout_glbl.keep_alive_timeout_value != SL_WIFI_DEFAULT_KEEP_ALIVE_TIMEOUT) {
298       status = sl_si91x_configure_timeout(SL_SI91X_KEEP_ALIVE_TIMEOUT, timeout_glbl.keep_alive_timeout_value);
299       VERIFY_STATUS_AND_RETURN(status);
300     }
301     if (timeout_glbl.passive_scan_timeout_value != SL_WIFI_DEFAULT_PASSIVE_CHANNEL_SCAN_TIME) {
302       status =
303         sl_si91x_configure_timeout(SL_SI91X_CHANNEL_PASSIVE_SCAN_TIMEOUT, timeout_glbl.passive_scan_timeout_value);
304       VERIFY_STATUS_AND_RETURN(status);
305     }
306   }
307 
308   // Initialize the WLAN subsystem
309   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_INIT,
310                                         SI91X_WLAN_CMD,
311                                         NULL,
312                                         0,
313                                         SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
314                                         NULL,
315                                         NULL);
316   VERIFY_STATUS_AND_RETURN(status);
317 
318 #ifndef SL_SI91X_ACX_MODULE
319   if (IGNORE_REGION != config->region_code) {
320     // Set the device's region based on configuration
321     status = sl_si91x_set_device_region(config->boot_config.oper_mode, config->band, config->region_code);
322     VERIFY_STATUS_AND_RETURN(status);
323   }
324 #endif
325 
326   // Configure the RTS threshold for WLAN
327   sl_si91x_config_request_t config_request = { .config_type = CONFIG_RTSTHRESHOLD, .value = RSI_RTS_THRESHOLD };
328   status                                   = sl_si91x_driver_send_command(RSI_WLAN_REQ_CONFIG,
329                                         SI91X_WLAN_CMD,
330                                         &config_request,
331                                         sizeof(config_request),
332                                         SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
333                                         NULL,
334                                         NULL);
335   VERIFY_STATUS_AND_RETURN(status);
336   return status;
337 }
338 
sl_si91x_driver_init(const sl_wifi_device_configuration_t * config,sl_wifi_event_handler_t event_handler)339 sl_status_t sl_si91x_driver_init(const sl_wifi_device_configuration_t *config, sl_wifi_event_handler_t event_handler)
340 {
341   sl_status_t status;
342   sl_si91x_host_init_configuration init_config = { 0 };
343   const uint8_t select_option                  = config->boot_option;
344   if (config->boot_config.coex_mode == SL_SI91X_WLAN_MODE) { // Check for not support mode
345     return SL_STATUS_NOT_SUPPORTED;
346   }
347 
348   // Determine the default interface based on operating mode (AP or Client)
349   if (config->boot_config.oper_mode == SL_SI91X_ACCESS_POINT_MODE) {
350     default_interface = SL_WIFI_AP_INTERFACE;
351   } else {
352     default_interface = SL_WIFI_CLIENT_INTERFACE;
353   }
354 
355   // Configure the interface for 5GHz band if selected (currently not supported for Si91x)
356   if (config->band == SL_SI91X_WIFI_BAND_5GHZ) {
357     default_interface |= SL_WIFI_5GHZ_INTERFACE;
358   } else {
359     default_interface |= SL_WIFI_2_4GHZ_INTERFACE;
360   }
361 
362   // Set the event handler for the SI91x wireless driver
363   si91x_event_handler = event_handler;
364 
365   // Check if the device is already initialized
366   if (device_initialized) {
367     // If it's already initialized, ensure the requested operating mode is compatible
368     if (initialized_opermode == SL_SI91X_CONCURRENT_MODE) {
369       return (initialized_opermode == config->boot_config.oper_mode) ? SL_STATUS_OK : SL_STATUS_WIFI_INVALID_OPERMODE;
370     }
371     return SL_STATUS_ALREADY_INITIALIZED;
372   }
373   // Initialize BLE if BLE is enabled
374 #ifdef SLI_SI91X_ENABLE_BLE
375   int32_t rsi_status = 0;
376   rsi_status         = rsi_ble_driver_init(global_buf, GLOBAL_BUFF_LEN);
377   if ((rsi_status < 0) || (rsi_status > GLOBAL_BUFF_LEN)) {
378     return SL_STATUS_FAIL;
379   }
380 #endif
381 
382 #ifndef SLI_SI91X_ENABLE_IPV6
383   uint32_t *tcp_ip_feature_bit_map = (uint32_t *)&(config->boot_config.tcp_ip_feature_bit_map);
384 
385   // check if the module network stack is in IPV6 mode.
386   if (*tcp_ip_feature_bit_map & (SI91X_IPV6_MODE)) {
387     return SL_STATUS_NOT_AVAILABLE;
388   }
389 #endif
390 
391   // Initialize the buffer manager
392   status = sl_si91x_host_init_buffer_manager(&default_buffer_configuration);
393   if (status != SL_STATUS_OK) {
394     return status;
395   }
396 
397   init_config.rx_irq      = sl_si91x_bus_rx_irq_handler;
398   init_config.rx_done     = sl_si91x_bus_rx_done_handler;
399   init_config.boot_option = config->boot_option;
400 
401   // Initialize the SI91x host
402   status = sl_si91x_host_init(&init_config);
403   VERIFY_STATUS_AND_RETURN(status);
404 
405   // Initialize the SI91x platform
406   status = sl_si91x_platform_init();
407   VERIFY_STATUS_AND_RETURN(status);
408 
409   // Power cycle the SI91x device
410   status = sl_si91x_host_power_cycle();
411   VERIFY_STATUS_AND_RETURN(status);
412 
413   // sl_si91x_bus_init() will be implemented for all available buses
414   status = sl_si91x_bus_init();
415   VERIFY_STATUS_AND_RETURN(status);
416 
417 #ifdef SLI_SI91X_MCU_INTERFACE
418   // firmware bootup is require only for the first time, no need to do it again if we call init after deinit
419   static bool is_bootup_firmware_required = true;
420   if (is_bootup_firmware_required) {
421     status = si91x_bootup_firmware(select_option);
422     VERIFY_STATUS_AND_RETURN(status);
423     is_bootup_firmware_required = false;
424   } else {
425     // Initialize NWP interrupt and submit RX packets
426     sli_m4_ta_interrupt_init();
427     sli_si91x_submit_rx_pkt();
428   }
429 #else
430   status = si91x_bootup_firmware(select_option);
431   VERIFY_STATUS_AND_RETURN(status);
432 #endif
433 
434   // Initialize task register index to save firmware status
435   status = sli_fw_status_storage_index_init();
436   VERIFY_STATUS_AND_RETURN(status);
437 
438 #ifdef SL_SI91X_SPI_HIGH_SPEED_ENABLE
439   // Enable high speed bus on the device and the host
440   status = sl_si91x_bus_enable_high_speed();
441   VERIFY_STATUS_AND_RETURN(status);
442   sl_si91x_host_enable_high_speed_bus();
443 #endif
444   sl_si91x_host_enable_bus_interrupt();
445 
446 // Wait for card ready command response
447 #ifdef SLI_SI91X_MCU_INTERFACE
448   // NWP would not send card ready command response, if we call init after deinit
449 
450   if (get_card_ready_required()) {
451     uint32_t events = sli_si91x_wait_for_event(NCP_HOST_COMMON_RESPONSE_EVENT, 5000);
452     if (!(events & NCP_HOST_COMMON_RESPONSE_EVENT)) {
453       return SL_STATUS_CARD_READY_TIMEOUT;
454     }
455     set_card_ready_required(false);
456   }
457 #else
458   uint32_t events = sli_si91x_wait_for_event(NCP_HOST_COMMON_RESPONSE_EVENT, 3000);
459   if (!(events & NCP_HOST_COMMON_RESPONSE_EVENT)) {
460     return SL_STATUS_CARD_READY_TIMEOUT;
461   }
462 #endif
463   // Send WLAN request to set the operating mode and configuration
464   status = sl_si91x_driver_send_command(RSI_COMMON_REQ_OPERMODE,
465                                         SI91X_COMMON_CMD,
466                                         &config->boot_config,
467                                         sizeof(sl_si91x_boot_configuration_t),
468                                         SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
469                                         NULL,
470                                         NULL);
471   VERIFY_STATUS_AND_RETURN(status);
472 #ifdef SL_WDT_MANAGER_PRESENT
473   sl_si91x_nwp_configuration_t nwp_config;
474 
475   // NWP WDT configuration
476   memset(&nwp_config, 0, sizeof(sl_si91x_nwp_configuration_t));
477   nwp_config.code                    = SL_SI91X_ENABLE_NWP_WDT_FROM_HOST;
478   nwp_config.values.wdt_timer_val    = 0x20;
479   nwp_config.values.wdt_enable_in_ps = 0;
480   status                             = sl_si91x_set_nwp_config_request(nwp_config);
481   VERIFY_STATUS_AND_RETURN(status);
482 #endif
483 
484   feature_bit_map = config->boot_config.feature_bit_map;
485 
486 #ifdef SLI_SI91X_ENABLE_BLE
487   if (config->boot_config.coex_mode == SL_SI91X_BLE_MODE || config->boot_config.coex_mode == SL_SI91X_WLAN_BLE_MODE) {
488     // Wait for BT card ready
489     rsi_bt_common_init();
490   }
491 #endif
492 
493   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_DYNAMIC_POOL,
494                                         SI91X_WLAN_CMD,
495                                         &config->ta_pool,
496                                         sizeof(sl_si91x_dynamic_pool),
497                                         SL_SI91X_WAIT_FOR(30100),
498                                         NULL,
499                                         NULL);
500   VERIFY_STATUS_AND_RETURN(status);
501 
502   // Configure various wireless features
503   sl_si91x_feature_frame_request feature_frame_request = { .pll_mode        = PLL_MODE,
504                                                            .rf_type         = RF_TYPE,
505                                                            .wireless_mode   = WIRELESS_MODE,
506                                                            .enable_ppp      = ENABLE_PPP,
507                                                            .afe_type        = AFE_TYPE,
508                                                            .feature_enables = FEATURE_ENABLES };
509 
510   // Setting PLL mode to 1 in case of high clock frequency
511   //pll_mode 1 is not supported in coex mode
512   if ((!config->boot_config.coex_mode)
513       && (config->boot_config.custom_feature_bit_map
514           & (SL_SI91X_CUSTOM_FEAT_SOC_CLK_CONFIG_160MHZ | SL_SI91X_CUSTOM_FEAT_SOC_CLK_CONFIG_120MHZ))) {
515     feature_frame_request.pll_mode = 1;
516   } else {
517     feature_frame_request.pll_mode = 0;
518   }
519 
520   // For the transmit test mode we need to disable BIT 0, 4, 5. These bitmaps are only required in powersave.
521   // To receive broadcast data packets in transceiver opermode, we need to enable BIT 1.
522   if (config->boot_config.oper_mode == SL_SI91X_TRANSMIT_TEST_MODE) {
523     feature_frame_request.feature_enables &= ~(FEATURE_ENABLES);
524   } else if (config->boot_config.oper_mode == SL_SI91X_TRANSCEIVER_MODE) {
525     feature_frame_request.feature_enables |= SI91X_FEAT_FRAME_PERMIT_UNDESTINED_PACKETS;
526   } else {
527     feature_frame_request.feature_enables = feature_frame_request.feature_enables;
528   }
529 
530   // Dispatch a feature request frame to the SI91x driver
531   status = sl_si91x_driver_send_command(RSI_COMMON_REQ_FEATURE_FRAME,
532                                         SI91X_COMMON_CMD,
533                                         &feature_frame_request,
534                                         sizeof(feature_frame_request),
535                                         SL_SI91X_WAIT_FOR(10000),
536                                         NULL,
537                                         NULL);
538   VERIFY_STATUS_AND_RETURN(status);
539 
540   // if 16th bit of ext_tcp_ip_feature_bit_map is not set, then firmware auto closes the TCP socket on remote termination.
541   save_tcp_auto_close_choice(
542     (config->boot_config.ext_tcp_ip_feature_bit_map & SL_SI91X_EXT_TCP_IP_WAIT_FOR_SOCKET_CLOSE) == 0);
543 
544 #ifdef SLI_SI91X_OFFLOAD_NETWORK_STACK
545   sli_si91x_socket_init(SLI_SI91X_GET_TCP_IP_TOTAL_SELECTS_BITS(config->boot_config.ext_tcp_ip_feature_bit_map));
546   VERIFY_STATUS_AND_RETURN(status);
547 #endif
548 
549   // Set the MAC address if provided in the configuration
550   if (config->mac_address != NULL) {
551     status = sl_wifi_set_mac_address(default_interface, config->mac_address);
552     VERIFY_STATUS_AND_RETURN(status);
553   }
554 
555   // Initialize the WiFi radio if the coexistence mode is not BLE
556   if (config->boot_config.coex_mode != SL_SI91X_BLE_MODE) {
557     status = sl_si91x_driver_init_wifi_radio(config);
558     VERIFY_STATUS_AND_RETURN(status);
559   }
560 
561   // Check and update the frontend switch control based on custom feature bit map
562   if (config->boot_config.custom_feature_bit_map & SL_SI91X_CUSTOM_FEAT_EXTENSION_VALID) {
563     frontend_switch_control = (config->boot_config.ext_custom_feature_bit_map & (BIT(29) | (BIT(30))));
564   }
565 
566 #ifdef SLI_SI91X_MCU_INTERFACE
567   // Program wireless GPIO front-end switch controls
568   if (frontend_switch_control != 0) {
569     sli_si91x_configure_wireless_frontend_controls(frontend_switch_control);
570   }
571 #endif
572   // Mark the device as initialized
573   device_initialized   = true;
574   initialized_opermode = config->boot_config.oper_mode;
575 
576   // Set interface status flags based on operating mode and band
577   if ((config->boot_config.oper_mode == SL_SI91X_CLIENT_MODE)
578       || (config->boot_config.oper_mode == SL_SI91X_ENTERPRISE_CLIENT_MODE)
579       || (config->boot_config.oper_mode == SL_SI91X_CONCURRENT_MODE)
580       || (config->boot_config.oper_mode == SL_SI91X_TRANSMIT_TEST_MODE)) {
581     if (config->band == SL_SI91X_WIFI_BAND_2_4GHZ) {
582       interface_is_up[SL_WIFI_CLIENT_2_4GHZ_INTERFACE_INDEX] = true;
583     } else if (config->band == SL_SI91X_WIFI_BAND_5GHZ) {
584       interface_is_up[SL_WIFI_CLIENT_5GHZ_INTERFACE_INDEX] = true;
585     }
586   }
587   // Save the coexistence mode in the driver
588   save_coex_mode(config->boot_config.coex_mode);
589 #ifdef SL_SI91X_GET_EFUSE_DATA
590   status = sl_si91x_get_flash_efuse_data(&si91x_efuse_data, config->efuse_data_type);
591 #endif
592 #ifdef SLI_SI91X_MCU_INTERFACE
593   if (status == SL_STATUS_OK) {
594     /* send a notification to the NWP indicating whether the M4 core is currently utilizing the XTAL as its clock source*/
595     sli_si91x_send_m4_xtal_usage_notification_to_ta();
596   }
597 #endif
598 
599   return status;
600 }
601 
sl_si91x_driver_deinit(void)602 sl_status_t sl_si91x_driver_deinit(void)
603 {
604   sl_status_t status = SL_STATUS_OK;
605 
606   // Check if the device has been initialized if not, return an error
607   if (!device_initialized) {
608     return SL_STATUS_NOT_INITIALIZED;
609   }
610 
611 #ifdef SLI_SI91X_MCU_INTERFACE
612   // If the SLI_SI91X_MCU_INTERFACE is defined, perform a soft reset
613   status = sl_si91x_soft_reset();
614   VERIFY_STATUS_AND_RETURN(status);
615 
616   // Mask specific interrupts related to packet transfer
617   mask_ta_interrupt(TX_PKT_TRANSFER_DONE_INTERRUPT | RX_PKT_TRANSFER_DONE_INTERRUPT);
618 #endif
619 
620 #ifdef SLI_SI91X_ENABLE_BLE
621   int32_t rsi_status = 0;
622   // If SLI_SI91X_ENABLE_BLE is defined, deinitialize the BLE driver and check for errors
623   rsi_status = rsi_ble_driver_deinit();
624   if (rsi_status != RSI_SUCCESS) {
625     return SL_STATUS_FAIL;
626   }
627 #endif
628 
629   // Flush all TX Wi-Fi queues with the status indicating Wi-Fi connection is lost
630   sli_si91x_flush_all_tx_wifi_queues(SL_STATUS_WIFI_CONNECTION_LOST);
631 
632   // Flush the generic TX data queue
633   sli_si91x_flush_generic_data_queues(&sli_tx_data_queue);
634 
635 #if defined(SLI_SI91X_OFFLOAD_NETWORK_STACK) && defined(SLI_SI91X_SOCKETS)
636 
637   // Flush all pending socket commands in the client VAP queue due to Wi-Fi connection loss
638   sli_si91x_flush_all_socket_command_queues(SL_STATUS_WIFI_CONNECTION_LOST, SL_SI91X_WIFI_CLIENT_VAP_ID);
639 
640   // Flush all pending socket data in the client VAP queue due to Wi-Fi connection loss
641   sli_si91x_flush_all_socket_data_queues(SL_SI91X_WIFI_CLIENT_VAP_ID);
642 
643   // Flush all pending socket commands in the AP VAP queue due to Wi-Fi connection loss
644   sli_si91x_flush_all_socket_command_queues(SL_STATUS_WIFI_CONNECTION_LOST, SL_SI91X_WIFI_AP_VAP_ID);
645 
646   // Flush all pending socket data in the AP VAP queue due to Wi-Fi connection loss
647   sli_si91x_flush_all_socket_data_queues(SL_SI91X_WIFI_AP_VAP_ID);
648 
649   // Shutdown and change the state of the client VAP sockets
650   status = sli_si91x_vap_shutdown(SL_SI91X_WIFI_CLIENT_VAP_ID);
651   VERIFY_STATUS_AND_RETURN(status);
652 
653   // Shutdown and change the state of the AP VAP sockets
654   status = sli_si91x_vap_shutdown(SL_SI91X_WIFI_AP_VAP_ID);
655   VERIFY_STATUS_AND_RETURN(status);
656 
657   // Deinitialize and free all socket-related resources
658   status = sli_si91x_socket_deinit();
659   VERIFY_STATUS_AND_RETURN(status);
660 
661 #endif // End of check for offloaded network stack and sockets
662 
663   // Deinitialize the SI91x platform
664   status = sl_si91x_platform_deinit();
665   VERIFY_STATUS_AND_RETURN(status);
666 
667   // Deinitialize the SI91x host
668   status = sl_si91x_host_deinit();
669   VERIFY_STATUS_AND_RETURN(status);
670 
671 #ifdef SLI_SI91X_MCU_INTERFACE
672   // Check the RX buffer valid bit is set or not.
673   if (M4SS_P2P_INTR_SET_REG & RX_BUFFER_VALID) {
674 
675     // Clear the RX buffer valid bit.
676     M4SS_P2P_INTR_CLR_REG = (RX_BUFFER_VALID);
677 
678     // Clear the RX buffer.
679     sl_si91x_host_free_buffer(rx_pkt_buffer);
680   }
681 #endif
682 
683   // Deinitialize the buffer manager
684   status = sl_si91x_host_deinit_buffer_manager();
685   VERIFY_STATUS_AND_RETURN(status);
686 
687   sl_si91x_host_disable_bus_interrupt();
688 
689   status = sl_si91x_host_power_cycle();
690   VERIFY_STATUS_AND_RETURN(status);
691 
692   // Clear the event handler and reset initialization status
693   si91x_event_handler  = NULL;
694   device_initialized   = false;
695   initialized_opermode = SL_SI91X_INVALID_MODE;
696 
697   // Reset all the interfaces
698   memset(interface_is_up, 0, sizeof(interface_is_up));
699 
700   return status;
701 }
702 
sl_si91x_get_flash_efuse_data(sl_si91x_efuse_data_t * efuse_data,uint8_t efuse_data_type)703 sl_status_t sl_si91x_get_flash_efuse_data(sl_si91x_efuse_data_t *efuse_data, uint8_t efuse_data_type)
704 {
705   sl_status_t status;
706   sl_wifi_buffer_t *buffer = NULL;
707   SL_WIFI_ARGS_CHECK_NULL_POINTER(efuse_data);
708 
709   if (!device_initialized) {
710     return SL_STATUS_NOT_INITIALIZED;
711   }
712 
713   status = sl_si91x_driver_send_command(RSI_COMMON_REQ_GET_EFUSE_DATA,
714                                         SI91X_COMMON_CMD,
715                                         &efuse_data_type,
716                                         sizeof(efuse_data_type),
717                                         SL_SI91X_WAIT_FOR_RESPONSE(15000),
718                                         NULL,
719                                         &buffer);
720   if ((status != SL_STATUS_OK) && (buffer != NULL)) {
721     sl_si91x_host_free_buffer(buffer);
722   }
723   VERIFY_STATUS_AND_RETURN(status);
724 
725   const sl_si91x_packet_t *packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
726   if (packet->length > 0) {
727     switch (efuse_data_type) {
728       case SL_SI91X_EFUSE_MFG_SW_VERSION:
729         memcpy(&efuse_data->mfg_sw_version, packet->data, packet->length);
730         break;
731       case SL_SI91X_EFUSE_PTE_CRC:
732         memcpy(&efuse_data->pte_crc, packet->data, packet->length);
733         break;
734       default:
735         break;
736     }
737   }
738   sl_si91x_host_free_buffer(buffer);
739   return SL_STATUS_OK;
740 }
741 
sl_si91x_driver_raw_send_command(uint8_t command,const void * data,uint32_t data_length,uint32_t wait_time)742 sl_status_t sl_si91x_driver_raw_send_command(uint8_t command,
743                                              const void *data,
744                                              uint32_t data_length,
745                                              uint32_t wait_time)
746 {
747   UNUSED_PARAMETER(wait_time);
748   sl_wifi_buffer_t *buffer;
749   sl_si91x_packet_t *packet;
750   sl_status_t status = SL_STATUS_OK;
751 
752   // Allocate a data buffer with space for the data and metadata
753   status = sl_si91x_allocate_data_buffer(&buffer,
754                                          (void **)&packet,
755                                          sizeof(sl_si91x_packet_t) + data_length,
756                                          SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME);
757   VERIFY_STATUS_AND_RETURN(status);
758 
759   // If the packet is not allocated successfully, return an allocation failed error
760   if (packet == NULL) {
761     return SL_STATUS_ALLOCATION_FAILED;
762   }
763 
764   // Clear the packet descriptor and copy the command data if available
765   memset(packet->desc, 0, sizeof(packet->desc));
766   if (data != NULL) {
767     memcpy(packet->data, data, data_length);
768   }
769   packet->length  = data_length & 0xFFF;
770   packet->command = command;
771 
772   // Adding the packet to the queue with atomic action
773   return sl_si91x_driver_send_data_packet(buffer, wait_time);
774 }
775 
sl_si91x_driver_send_socket_data(const sli_si91x_socket_send_request_t * request,const void * data,uint32_t wait_time)776 sl_status_t sl_si91x_driver_send_socket_data(const sli_si91x_socket_send_request_t *request,
777                                              const void *data,
778                                              uint32_t wait_time)
779 {
780   UNUSED_PARAMETER(wait_time);
781   sl_wifi_buffer_t *buffer;
782   sl_si91x_packet_t *packet;
783   sli_si91x_socket_send_request_t *send;
784 
785   sl_status_t status     = SL_STATUS_OK;
786   uint16_t header_length = (request->data_offset - sizeof(sli_si91x_socket_send_request_t));
787   uint32_t data_length   = request->length;
788 
789   if (data == NULL) {
790     return SL_STATUS_NULL_POINTER;
791   }
792 
793   // Allocate a buffer for the socket data with appropriate size
794   status = sl_si91x_host_allocate_buffer(
795     &buffer,
796     SL_WIFI_TX_FRAME_BUFFER,
797     sizeof(sl_si91x_packet_t) + sizeof(sli_si91x_socket_send_request_t) + header_length + data_length,
798     SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME);
799 
800   VERIFY_STATUS_AND_RETURN(status);
801   packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
802 
803   // If the packet is not allocated successfully, return an allocation failed error
804   if (packet == NULL) {
805     return SL_STATUS_WIFI_BUFFER_ALLOC_FAIL;
806   }
807 
808   memset(packet->desc, 0, sizeof(packet->desc));
809 
810   send = (sli_si91x_socket_send_request_t *)packet->data;
811   memcpy(send, request, sizeof(sli_si91x_socket_send_request_t));
812   memcpy((send->send_buffer + header_length), data, data_length);
813 
814   // Fill frame type
815   packet->length = (sizeof(sli_si91x_socket_send_request_t) + header_length + data_length) & 0xFFF;
816 
817   return sl_si91x_driver_send_data_packet(buffer, wait_time);
818 }
819 
sl_si91x_custom_driver_send_command(uint32_t command,sl_si91x_command_type_t command_type,const void * data,uint32_t data_length,sl_si91x_wait_period_t wait_period,void * sdk_context,sl_wifi_buffer_t ** data_buffer,uint8_t custom_host_desc)820 sl_status_t sl_si91x_custom_driver_send_command(uint32_t command,
821                                                 sl_si91x_command_type_t command_type,
822                                                 const void *data,
823                                                 uint32_t data_length,
824                                                 sl_si91x_wait_period_t wait_period,
825                                                 void *sdk_context,
826                                                 sl_wifi_buffer_t **data_buffer,
827                                                 uint8_t custom_host_desc)
828 {
829   sl_wifi_buffer_t *buffer;
830   sl_si91x_packet_t *packet;
831   sl_status_t status;
832 
833   // Check if the queue type is within valid range
834   if (command_type >= SI91X_CMD_MAX) {
835     return SL_STATUS_INVALID_INDEX;
836   }
837 
838   // Allocate a buffer for the command with appropriate size
839   status = sli_si91x_allocate_command_buffer(&buffer,
840                                              (void **)&packet,
841                                              sizeof(sl_si91x_packet_t) + data_length,
842                                              SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME);
843   VERIFY_STATUS_AND_RETURN(status);
844 
845   // Clear the packet descriptor and copy the command data if available
846   memset(packet->desc, 0, sizeof(packet->desc));
847   if (data != NULL) {
848     memcpy(packet->data, data, data_length);
849   }
850 
851   // Fill frame type
852   packet->length  = data_length & 0xFFF;
853   packet->command = (uint16_t)command;
854   // Fill the packet identifier
855   packet->unused[1] = custom_host_desc;
856   return sl_si91x_driver_send_command_packet(command, command_type, buffer, wait_period, sdk_context, data_buffer);
857 }
858 
sl_si91x_driver_send_command(uint32_t command,sl_si91x_command_type_t command_type,const void * data,uint32_t data_length,sl_si91x_wait_period_t wait_period,void * sdk_context,sl_wifi_buffer_t ** data_buffer)859 sl_status_t sl_si91x_driver_send_command(uint32_t command,
860                                          sl_si91x_command_type_t command_type,
861                                          const void *data,
862                                          uint32_t data_length,
863                                          sl_si91x_wait_period_t wait_period,
864                                          void *sdk_context,
865                                          sl_wifi_buffer_t **data_buffer)
866 {
867   sl_wifi_buffer_t *buffer;
868   sl_si91x_packet_t *packet;
869   sl_status_t status;
870 
871   // Check if the queue type is within valid range
872   if (command_type >= SI91X_CMD_MAX) {
873     return SL_STATUS_INVALID_INDEX;
874   }
875 
876   // Allocate a buffer for the command with appropriate size
877   status = sli_si91x_allocate_command_buffer(&buffer,
878                                              (void **)&packet,
879                                              sizeof(sl_si91x_packet_t) + data_length,
880                                              SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME);
881   VERIFY_STATUS_AND_RETURN(status);
882 
883   // Clear the packet descriptor and copy the command data if available
884   memset(packet->desc, 0, sizeof(packet->desc));
885   if (data != NULL) {
886     memcpy(packet->data, data, data_length);
887   }
888 
889   // Set SLI_SI91X_FEAT_FW_UPDATE_NEW_CODE in the feature bit map to retrieve the latest firmware result codes
890   if (command == RSI_COMMON_REQ_OPERMODE) {
891     sl_si91x_boot_configuration_t *boot_configuration = (sl_si91x_boot_configuration_t *)packet->data;
892     boot_configuration->feature_bit_map |= SLI_SI91X_FEAT_FW_UPDATE_NEW_CODE;
893   }
894 
895   // Fill frame type
896   packet->length  = data_length & 0xFFF;
897   packet->command = (uint16_t)command;
898   return sl_si91x_driver_send_command_packet(command, command_type, buffer, wait_period, sdk_context, data_buffer);
899 }
900 
901 #ifdef SL_SI91X_SIDE_BAND_CRYPTO
sl_si91x_driver_send_side_band_crypto(uint32_t command,const void * data,uint32_t data_length,sl_si91x_wait_period_t wait_period)902 sl_status_t sl_si91x_driver_send_side_band_crypto(uint32_t command,
903                                                   const void *data,
904                                                   uint32_t data_length,
905                                                   sl_si91x_wait_period_t wait_period)
906 {
907   sl_wifi_buffer_t *buffer;
908   sl_si91x_packet_t *packet;
909   uint32_t result;
910   sl_status_t status = SL_STATUS_OK;
911 
912   // Allocate a buffer for the command with appropriate size
913   status = sli_si91x_allocate_command_buffer(&buffer, (void **)&packet, sizeof(sl_si91x_packet_t) + data_length, 1000);
914   VERIFY_STATUS_AND_RETURN(status);
915 
916   // Clear the packet descriptor and copy the command data if available
917   memset(packet->desc, 0, sizeof(packet->desc));
918   if (data != NULL) {
919     memcpy(packet->data, data, data_length);
920   }
921 
922   // Fill frame type
923   packet->length  = data_length & 0xFFF;
924   packet->command = command;
925 
926   // Acquire Mutex
927   osMutexAcquire(side_band_crypto_mutex, 0xFFFFFFFFUL);
928 
929   // fill crypto desc
930   crypto_desc[0].addr   = (uint32_t)packet->desc;
931   crypto_desc[0].length = SL_HOST_DESC_LEN;
932   crypto_desc[1].addr   = (uint32_t)packet->data;
933   crypto_desc[1].length = SL_CRYPTO_PKT_LEN;
934 
935   //! Enter Critical Section
936   __disable_irq();
937 
938   sli_si91x_raise_side_band_interrupt_to_ta();
939 
940   //! Exit Critical Section
941   __enable_irq();
942 
943   result =
944     osEventFlagsWait(ta_events, SIDE_BAND_DONE, (osFlagsWaitAny), (wait_period & ~SL_SI91X_WAIT_FOR_RESPONSE_BIT));
945   if (result == (uint32_t)osErrorTimeout || result == (uint32_t)osErrorResource) {
946     osMutexRelease(side_band_crypto_mutex);
947     sl_si91x_host_free_buffer(buffer);
948     return SL_STATUS_TIMEOUT;
949   }
950 
951   status =
952     (((uint8_t *)crypto_desc[0].addr)[12] + (((uint8_t *)crypto_desc[0].addr)[13] << 8)); // Extract the frame status
953 
954   // Release Mutex
955   osMutexRelease(side_band_crypto_mutex);
956 
957   sl_si91x_host_free_buffer(buffer);
958   return status;
959 }
960 #endif
961 
sl_si91x_driver_send_bt_command(rsi_wlan_cmd_request_t command,sl_si91x_command_type_t command_type,sl_wifi_buffer_t * data,uint8_t sync_command)962 sl_status_t sl_si91x_driver_send_bt_command(rsi_wlan_cmd_request_t command,
963                                             sl_si91x_command_type_t command_type,
964                                             sl_wifi_buffer_t *data,
965                                             uint8_t sync_command)
966 {
967   sl_si91x_wait_period_t wait_period = SL_SI91X_RETURN_IMMEDIATELY;
968 
969   // Check if the queue type is within valid range
970   if (command_type >= SI91X_CMD_MAX) {
971 
972     return SL_STATUS_INVALID_INDEX;
973   }
974 
975   if (sync_command) {
976     return sl_si91x_driver_send_command_packet(command, command_type, data, wait_period, NULL, NULL);
977   } else {
978     return sl_si91x_driver_send_async_command(command, command_type, data, 0);
979   }
980 }
981 
sl_si91x_driver_wait_for_response(rsi_wlan_cmd_request_t command,sl_si91x_wait_period_t wait_period)982 sl_status_t sl_si91x_driver_wait_for_response(rsi_wlan_cmd_request_t command, sl_si91x_wait_period_t wait_period)
983 {
984   UNUSED_PARAMETER(command);
985   UNUSED_PARAMETER(wait_period);
986 #ifdef SI91x_ENABLE_WAIT_ON_RESULTS
987   // Wait for WLAN response events with a specified timeout
988   uint32_t events =
989     sli_si91x_wait_for_event(NCP_HOST_WLAN_RESPONSE_EVENT, (wait_period & ~SL_SI91X_WAIT_FOR_RESPONSE_BIT));
990 
991   sli_si91x_clear_event(NCP_HOST_WLAN_RESPONSE_EVENT);
992 
993   //TODO: Change error handling from event based to response
994   if (events & NCP_HOST_WLAN_RESPONSE_EVENT) {
995     return convert_and_save_firmware_status(si91x_frame_error_status);
996   } else if (events == 0) {
997     return SL_STATUS_TIMEOUT;
998   }
999 #endif
1000   return SL_STATUS_NOT_SUPPORTED;
1001 }
1002 
sli_si91x_driver_wait_for_response_packet(sl_si91x_buffer_queue_t * queue,osEventFlagsId_t event_flag,uint32_t event_mask,uint16_t packet_id,sl_si91x_wait_period_t wait_period,sl_wifi_buffer_t ** packet_buffer)1003 sl_status_t sli_si91x_driver_wait_for_response_packet(sl_si91x_buffer_queue_t *queue,
1004                                                       osEventFlagsId_t event_flag,
1005                                                       uint32_t event_mask,
1006                                                       uint16_t packet_id,
1007                                                       sl_si91x_wait_period_t wait_period,
1008                                                       sl_wifi_buffer_t **packet_buffer)
1009 {
1010   // Verify that packet_buffer is a valid pointer, return error if invalid
1011   SL_VERIFY_POINTER_OR_RETURN(packet_buffer, SL_STATUS_INVALID_PARAMETER);
1012 
1013   // Variables to store event flags, start time, and elapsed time
1014   uint32_t events       = 0;
1015   uint32_t start_time   = osKernelGetTickCount(); // Capture the start time of the wait period
1016   uint32_t elapsed_time = 0;                      // Elapsed time tracker
1017   sl_wifi_buffer_t *buffer;
1018 
1019   do {
1020     // Wait for event flag(s) to be set within the specified wait period.
1021     // This blocks the thread until any event in the mask is set or a timeout occurs.
1022     events = osEventFlagsWait(event_flag, event_mask, (osFlagsWaitAny | osFlagsNoClear), (wait_period - elapsed_time));
1023 
1024     // If the event wait times out or resources are unavailable, return timeout status
1025     if (events == (uint32_t)osErrorTimeout || events == (uint32_t)osErrorResource) {
1026       return SL_STATUS_TIMEOUT;
1027     }
1028 
1029     // Log the event and queue details (for debugging purposes)
1030     SL_DEBUG_LOG("Event: %u, queue %u\n", events, queue);
1031 
1032     // Traverse the queue to check if the packet with the desired packet_id is at the head.
1033     // Introduce a delay if the head of the queue packet doesn't belong to the current thread.
1034     // This allows other threads to process the packet at the head.
1035     do {
1036       buffer = queue->head; // Peek at the head of the queue
1037     } while ((buffer != NULL) && (buffer->id != packet_id)
1038              && osDelay(1) == 0); // Delay to yield if packet_id does not match
1039 
1040     // Update the elapsed time since the start of the wait
1041     elapsed_time = sl_si91x_host_elapsed_time(start_time);
1042 
1043   } while (buffer == NULL || (buffer->id != packet_id)); // Loop until the correct packet is found or timeout occurs
1044 
1045   // Remove the identified packet from the queue
1046   sli_si91x_pop_from_buffer_queue(queue, &buffer);
1047 
1048   // Assign the identified packet to packet_buffer
1049   *packet_buffer = buffer;
1050 
1051   // Enter atomic section to ensure thread safety while clearing the event flag
1052   CORE_irqState_t state = CORE_EnterAtomic();
1053   // If the queue is empty after popping the packet, clear the event flag to avoid unnecessary waits
1054   if (queue->head == NULL) {
1055     osEventFlagsClear(event_flag, event_mask);
1056   }
1057   CORE_ExitAtomic(state); // Exit atomic section
1058 
1059   return SL_STATUS_OK; // Return success status
1060 }
1061 
sl_si91x_driver_send_command_packet(uint32_t command,sl_si91x_command_type_t command_type,sl_wifi_buffer_t * buffer,sl_si91x_wait_period_t wait_period,void * sdk_context,sl_wifi_buffer_t ** data_buffer)1062 sl_status_t sl_si91x_driver_send_command_packet(uint32_t command,
1063                                                 sl_si91x_command_type_t command_type,
1064                                                 sl_wifi_buffer_t *buffer,
1065                                                 sl_si91x_wait_period_t wait_period,
1066                                                 void *sdk_context,
1067                                                 sl_wifi_buffer_t **data_buffer)
1068 {
1069   uint16_t firmware_status;
1070   sli_si91x_queue_packet_t *node = NULL;
1071   sl_status_t status;
1072   sl_wifi_buffer_t *packet;
1073   sl_wifi_buffer_t *response;
1074   uint8_t flags        = 0;
1075   uint16_t data_length = 0;
1076   //  sl_si91x_driver_context_t context = { 0 };
1077   sl_si91x_wait_period_t wait_time = 0;
1078   static uint8_t command_packet_id = 0;
1079 
1080   // Allocate a command packet and set flags based on the command type
1081   status = sli_si91x_allocate_command_buffer(&packet,
1082                                              (void **)&node,
1083                                              sizeof(sli_si91x_queue_packet_t),
1084                                              SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME);
1085   if (status != SL_STATUS_OK) {
1086     sl_si91x_host_free_buffer(buffer);
1087     return status;
1088   }
1089 
1090 #ifdef RSI_CHIP_MFG_EN
1091   // WLAN soc frequency
1092   if (command == RSI_BOOTUP_PARAMS) {
1093     host_desc[14] = RSI_SOC_FREQ;
1094   }
1095 #endif
1096 
1097   // Check the wait_period to determine the flags for packet handling
1098   if (wait_period == SL_SI91X_RETURN_IMMEDIATELY) {
1099     // If wait_period indicates an immediate return, set flags to 0
1100     flags = 0;
1101   } else {
1102     // If not an immediate return, set the SI91X_PACKET_RESPONSE_STATUS flag
1103     flags |= SI91X_PACKET_RESPONSE_STATUS;
1104     // Additionally, set the SI91X_PACKET_RESPONSE_PACKET flag if the SL_SI91X_WAIT_FOR_RESPONSE_BIT is set in wait_period
1105     if (data_buffer != NULL) {
1106       flags |= ((wait_period & SL_SI91X_WAIT_FOR_RESPONSE_BIT) ? SI91X_PACKET_RESPONSE_PACKET : 0);
1107     }
1108   }
1109 
1110   // Check the command type and set the flags accordingly
1111   switch (command) {
1112     case RSI_COMMON_REQ_PWRMODE:
1113     case RSI_COMMON_REQ_OPERMODE:
1114     case RSI_COMMON_REQ_SOFT_RESET:
1115       flags |= SI91X_PACKET_GLOBAL_QUEUE_BLOCK;
1116       break;
1117     default:
1118       break;
1119   }
1120 
1121   // Set various properties of the node representing the command packet
1122   node->host_packet       = buffer;
1123   node->firmware_queue_id = firmware_queue_id[command_type];
1124   node->command_type      = command_type;
1125   node->flags             = flags;
1126   node->sdk_context       = sdk_context;
1127 
1128   // Configure the context for packet handling
1129   //  context.packet = node;
1130   //  context.payload = &(queue_packet_id[command_type]);
1131 
1132   if (flags != SI91X_PACKET_WITH_ASYNC_RESPONSE) {
1133     node->command_tickcount = osKernelGetTickCount();
1134     // Calculate the wait time based on wait_period
1135     if ((wait_period & SL_SI91X_WAIT_FOR_EVER) == SL_SI91X_WAIT_FOR_EVER) {
1136       node->command_timeout = osWaitForever;
1137     } else {
1138       node->command_timeout = (wait_period & ~SL_SI91X_WAIT_FOR_RESPONSE_BIT);
1139     }
1140   }
1141 
1142   //! Enter Critical Section
1143   CORE_irqState_t state = CORE_EnterAtomic();
1144 
1145   const uint8_t this_packet_id = command_packet_id;
1146   command_packet_id++;
1147   buffer->id        = this_packet_id;
1148   packet->id        = this_packet_id;
1149   packet->node.node = NULL;
1150   sli_si91x_append_to_buffer_queue(&cmd_queues[command_type].tx_queue, packet);
1151   tx_command_queues_status |= SL_SI91X_TX_PENDING_FLAG(command_type);
1152   sl_si91x_host_set_bus_event(SL_SI91X_TX_PENDING_FLAG(command_type));
1153   CORE_ExitAtomic(state);
1154 
1155   // Check if the command should return immediately or wait for a response
1156   if (wait_period == SL_SI91X_RETURN_IMMEDIATELY) {
1157     return SL_STATUS_IN_PROGRESS;
1158   }
1159 
1160   // Calculate the wait time based on wait_period
1161   if ((wait_period & SL_SI91X_WAIT_FOR_EVER) == SL_SI91X_WAIT_FOR_EVER) {
1162     wait_time = osWaitForever;
1163   } else {
1164     wait_time = (wait_period & ~SL_SI91X_WAIT_FOR_RESPONSE_BIT);
1165   }
1166 
1167   // Wait for a response packet and handle it
1168   status = sli_si91x_driver_wait_for_response_packet(&cmd_queues[command_type].rx_queue,
1169                                                      si91x_events,
1170                                                      SL_SI91X_RESPONSE_FLAG(command_type),
1171                                                      this_packet_id,
1172                                                      wait_time,
1173                                                      &response);
1174   // Check if the status is SL_STATUS_TIMEOUT, indicating a timeout has occurred
1175   if (status == SL_STATUS_TIMEOUT) {
1176     // Declare a temporary packet pointer to hold the packet to be removed
1177     sl_wifi_buffer_t *temp_packet;
1178     sl_status_t temp_status = sli_si91x_remove_buffer_from_queue_by_comparator(&cmd_queues[command_type].tx_queue,
1179                                                                                &this_packet_id,
1180                                                                                si91x_packet_identification_function,
1181                                                                                &temp_packet);
1182 
1183     // Check if the packet removal was successful
1184     if (temp_status == SL_STATUS_OK) {
1185 
1186       // Retrieve the actual packet node data from the removed buffer
1187       sli_si91x_queue_packet_t *temp_node = sl_si91x_host_get_buffer_data(temp_packet, 0, NULL);
1188 
1189       // Free the host packet memory associated with the node (TX packet memory)
1190       sl_si91x_host_free_buffer(temp_node->host_packet);
1191 
1192       // Free the temporary buffer memory that held the packet
1193       sl_si91x_host_free_buffer(temp_packet);
1194     }
1195   }
1196   VERIFY_STATUS_AND_RETURN(status);
1197 
1198   // Process the response packet and return the firmware status
1199   node            = (sli_si91x_queue_packet_t *)sl_si91x_host_get_buffer_data(response, 0, &data_length);
1200   firmware_status = node->frame_status;
1201 
1202   // If a data_buffer is provided, set it to the host_packet
1203   if (NULL != data_buffer) {
1204     *data_buffer = node->host_packet;
1205   }
1206   // If the response packet flag is set, free the host_packet buffer
1207   else if (SI91X_PACKET_RESPONSE_PACKET == (node->flags & SI91X_PACKET_RESPONSE_PACKET)) {
1208     sl_si91x_host_free_buffer(node->host_packet);
1209   }
1210 
1211   // Free the response buffer and return the firmware status
1212   sl_si91x_host_free_buffer(response);
1213   return convert_and_save_firmware_status(firmware_status);
1214 }
1215 
sl_si91x_driver_send_data_packet(sl_wifi_buffer_t * buffer,uint32_t wait_time)1216 static sl_status_t sl_si91x_driver_send_data_packet(sl_wifi_buffer_t *buffer, uint32_t wait_time)
1217 {
1218   UNUSED_PARAMETER(wait_time);
1219   sli_si91x_append_to_buffer_queue(&sli_tx_data_queue, buffer);
1220   CORE_irqState_t state = CORE_EnterAtomic();
1221   tx_generic_socket_data_queues_status |= SL_SI91X_GENERIC_DATA_TX_PENDING_EVENT;
1222   sl_si91x_host_set_bus_event(SL_SI91X_GENERIC_DATA_TX_PENDING_EVENT);
1223   CORE_ExitAtomic(state);
1224 
1225   return SL_STATUS_OK;
1226 }
1227 
sl_si91x_driver_send_async_command(uint32_t command,sl_si91x_command_type_t command_type,void * data,uint32_t data_length)1228 sl_status_t sl_si91x_driver_send_async_command(uint32_t command,
1229                                                sl_si91x_command_type_t command_type,
1230                                                void *data,
1231                                                uint32_t data_length)
1232 {
1233 
1234   sli_si91x_queue_packet_t *node = NULL;
1235   sl_status_t return_status;
1236   //  sl_si91x_driver_context_t context = { 0 };
1237   sl_wifi_buffer_t *raw_rx_buffer;
1238   sl_wifi_buffer_t *buffer;
1239   sl_si91x_packet_t *raw_rx_packet;
1240   sl_status_t status;
1241 
1242   if (command_type == SI91X_BT_CMD) {
1243     // BLE packet is created in upper layer, no allocations required here.
1244     raw_rx_buffer = (sl_wifi_buffer_t *)data;
1245   } else {
1246     status = sli_si91x_allocate_command_buffer(&raw_rx_buffer,
1247                                                (void **)&raw_rx_packet,
1248                                                sizeof(sl_si91x_packet_t) + data_length,
1249                                                SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME);
1250     VERIFY_STATUS_AND_RETURN(status);
1251 
1252     memset(raw_rx_packet->desc, 0, sizeof(raw_rx_packet->desc));
1253     if (data != NULL) {
1254       memcpy(raw_rx_packet->data, data, data_length);
1255     }
1256 
1257     // Fill frame type
1258     raw_rx_packet->length  = data_length & 0xFFF;
1259     raw_rx_packet->command = (uint16_t)command;
1260   }
1261 
1262   return_status = sli_si91x_allocate_command_buffer(&buffer,
1263                                                     (void **)&node,
1264                                                     sizeof(sli_si91x_queue_packet_t),
1265                                                     SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME);
1266 
1267   if (return_status != SL_STATUS_OK) {
1268     sl_si91x_host_free_buffer(raw_rx_buffer);
1269     return return_status;
1270   }
1271 
1272 #ifdef RSI_CHIP_MFG_EN
1273   // WLAN soc frequency
1274   if (command == RSI_BOOTUP_PARAMS) {
1275     host_desc[14] = RSI_SOC_FREQ;
1276   }
1277 #endif
1278 
1279   // Configure the node representing the command packet
1280   node->host_packet       = raw_rx_buffer;
1281   node->firmware_queue_id = firmware_queue_id[command_type];
1282   node->command_type      = command_type;
1283   node->sdk_context       = NULL;
1284   node->flags             = SI91X_PACKET_WITH_ASYNC_RESPONSE;
1285 
1286   CORE_irqState_t irqState = CORE_EnterAtomic();
1287   buffer->id               = 0; // Does not use packet ID as async packets do not have a matching response
1288   sli_si91x_append_to_buffer_queue(&cmd_queues[command_type].tx_queue, buffer);
1289   tx_command_queues_status |= SL_SI91X_TX_PENDING_FLAG(command_type);
1290   sl_si91x_host_set_bus_event(SL_SI91X_TX_PENDING_FLAG(command_type));
1291   CORE_ExitAtomic(irqState);
1292 
1293   return SL_STATUS_OK;
1294 }
1295 
1296 /*
1297  * Verifies that the device has booted successfully.
1298  * @return SL_STATUS_OK if verification successful
1299  *         otherwise RSI_ERROR_WAITING_FOR_BOARD_READY, RSI_ERROR_BOOTUP_OPTIONS_NOT_SAVED, RSI_ERROR_BOOTUP_OPTIONS_CHECKSUM_FAIL
1300  */
sli_verify_device_boot(uint32_t * rom_version)1301 sl_status_t sli_verify_device_boot(uint32_t *rom_version)
1302 {
1303   sl_status_t status;
1304   uint8_t value[2] = { 0, 0 };
1305 
1306   // Read a memory register to check if it's valid
1307   status = sl_si91x_bus_read_memory(RSI_HOST_INTF_REG_OUT, 2, &value[0]);
1308   VERIFY_STATUS(status);
1309 
1310   // Verify register read was valid
1311   if (value[1] != SLI_WIFI_REGISTER_VALID) {
1312     return SL_STATUS_WAITING_FOR_BOARD_READY;
1313   }
1314 
1315   // Verify register value
1316   if (value[0] == RSI_BOOTUP_OPTIONS_LAST_CONFIG_NOT_SAVED) {
1317     return SL_STATUS_BOOTUP_OPTIONS_NOT_SAVED;
1318   } else if (value[0] == RSI_BOOTUP_OPTIONS_CHECKSUM_FAIL) {
1319     return SL_STATUS_BOOTUP_OPTIONS_CHECKSUM_FAILURE;
1320   }
1321 #if RSI_BOOTLOADER_VERSION_CHECK
1322   else if (value[0] == RSI_BOOTLOADER_VERSION) {
1323   } else {
1324     return SL_STATUS_BOOTLOADER_VERSION_MISMATCH;
1325   }
1326 #endif
1327 
1328   // Extract ROM version info
1329   if (value[0] == RSI_BOOTLOADER_VERSION_1P0) {
1330     *rom_version = RSI_ROM_VERSION_1P0;
1331   } else if (value[0] == RSI_BOOTLOADER_VERSION_1P1) {
1332     *rom_version = RSI_ROM_VERSION_1P1;
1333   }
1334 
1335   return SL_STATUS_OK;
1336 }
1337 
1338 /**************************************************************************/ /**
1339  * @brief Allocate a buffer for the Wi-Fi driver
1340  *
1341  * @param buffer
1342  * @param buffer_size is the size of the buffer to allocate
1343  * @param wait_duration_ms is the duration before returning SL_TIMEOUT
1344  * @return SL_STATUS_OK if the values are retrieved correctly,
1345  * SL_TIMEOUT if the buffer is not allocated in time, SL_ERROR otherwise
1346  *****************************************************************************/
sli_si91x_allocate_command_buffer(sl_wifi_buffer_t ** host_buffer,void ** buffer,uint32_t requested_buffer_size,uint32_t wait_duration_ms)1347 sl_status_t sli_si91x_allocate_command_buffer(sl_wifi_buffer_t **host_buffer,
1348                                               void **buffer,
1349                                               uint32_t requested_buffer_size,
1350                                               uint32_t wait_duration_ms)
1351 {
1352   // Allocate a buffer from the SI91x host for WLAN control messages
1353   sl_status_t status =
1354     sl_si91x_host_allocate_buffer(host_buffer, SL_WIFI_CONTROL_BUFFER, requested_buffer_size, wait_duration_ms);
1355   VERIFY_STATUS_AND_RETURN(status);
1356 
1357   uint16_t temp;
1358   // Get a pointer to the allocated buffer's data area
1359   *buffer = sl_si91x_host_get_buffer_data(*host_buffer, 0, &temp);
1360   return SL_STATUS_OK;
1361 }
1362 
sl_si91x_allocate_data_buffer(sl_wifi_buffer_t ** host_buffer,void ** buffer,uint32_t data_size,uint32_t wait_duration_ms)1363 sl_status_t sl_si91x_allocate_data_buffer(sl_wifi_buffer_t **host_buffer,
1364                                           void **buffer,
1365                                           uint32_t data_size,
1366                                           uint32_t wait_duration_ms)
1367 {
1368   // Allocate a buffer from the SI91x host for WLAN data transmission
1369   sl_status_t status =
1370     sl_si91x_host_allocate_buffer(host_buffer,
1371                                   SL_WIFI_TX_FRAME_BUFFER,
1372                                   sizeof(sl_si91x_packet_t) + sizeof(sli_si91x_socket_send_request_t) + data_size,
1373                                   wait_duration_ms);
1374   VERIFY_STATUS_AND_RETURN(status);
1375 
1376   uint16_t temp;
1377   // Get a pointer to the allocated buffer's data area
1378   *buffer = sl_si91x_host_get_buffer_data(*host_buffer, 0, &temp);
1379   return SL_STATUS_OK;
1380 }
1381 
sli_wifi_select_option(const uint8_t configuration)1382 sl_status_t sli_wifi_select_option(const uint8_t configuration)
1383 {
1384   uint16_t boot_command = 0;
1385   sl_status_t status    = 0;
1386   uint16_t read_value   = 0;
1387 
1388   // Write a boot command to initiate the option selection
1389   status = sl_si91x_bus_write_memory(RSI_HOST_INTF_REG_OUT, 2, (uint8_t *)&boot_command);
1390   VERIFY_STATUS_AND_RETURN(status);
1391 
1392   if ((configuration == BURN_NWP_FW) || (configuration == BURN_M4_FW)) {
1393     boot_command = RSI_HOST_INTERACT_REG_VALID_FW | configuration;
1394   } else {
1395     boot_command = RSI_HOST_INTERACT_REG_VALID | configuration;
1396   }
1397 
1398   if (configuration == BURN_M4_FW) {
1399     boot_command |= M4_FW_IMAGE_NUMBER;
1400   }
1401 
1402   // Write the configuration to the SI91x host for option selection
1403   status = sl_si91x_bus_write_memory(RSI_HOST_INTF_REG_IN, 2, (uint8_t *)&boot_command);
1404   VERIFY_STATUS_AND_RETURN(status);
1405 
1406   // Check for a specific response to ensure successful option selection
1407   if ((configuration != LOAD_NWP_FW) && (configuration != LOAD_DEFAULT_NWP_FW_ACTIVE_LOW)) {
1408     uint32_t timestamp = sl_si91x_host_get_timestamp();
1409     while (sl_si91x_host_elapsed_time(timestamp) < 300) {
1410       status = sl_si91x_bus_read_memory(RSI_HOST_INTF_REG_OUT, 2, (uint8_t *)&read_value);
1411       VERIFY_STATUS_AND_RETURN(status);
1412 
1413       if ((configuration == BURN_NWP_FW) || (configuration == BURN_M4_FW)) {
1414         if (read_value == (RSI_HOST_INTERACT_REG_VALID | RSI_SEND_RPS_FILE)) {
1415           return SL_STATUS_OK;
1416         }
1417       } else if (read_value == (RSI_HOST_INTERACT_REG_VALID | configuration)) {
1418         return SL_STATUS_OK;
1419       }
1420     }
1421   } else {
1422     // Check up to 3 seconds for firmware load or upgrade status
1423     uint32_t timestamp               = sl_si91x_host_get_timestamp();
1424     uint16_t default_nwp_fw_selected = 0;
1425     while (sl_si91x_host_elapsed_time(timestamp) < 3000) {
1426       status = sl_si91x_bus_read_memory(RSI_HOST_INTF_REG_OUT, 2, (uint8_t *)&read_value);
1427       if (status != SL_STATUS_OK)
1428         continue;
1429 
1430       if ((read_value & 0xF000) == (RSI_HOST_INTERACT_REG_VALID_FW & 0xF000)) {
1431         if ((read_value & 0xFF) == VALID_FIRMWARE_NOT_PRESENT) {
1432           if (default_nwp_fw_selected == 0) {
1433             boot_command = RSI_HOST_INTERACT_REG_VALID_FW | SELECT_DEFAULT_NWP_FW_IMAGE_NUMBER;
1434             status       = sl_si91x_bus_write_memory(RSI_HOST_INTF_REG_IN, 2, (uint8_t *)&boot_command);
1435             if (status != SL_STATUS_OK) {
1436               return status;
1437             }
1438 
1439             while (sl_si91x_host_elapsed_time(timestamp) < 2000) {
1440               status = sl_si91x_bus_read_memory(RSI_HOST_INTF_REG_OUT, 2, (uint8_t *)&read_value);
1441               if (status != SL_STATUS_OK)
1442                 continue;
1443               if (read_value == (RSI_HOST_INTERACT_REG_VALID | SELECT_DEFAULT_NWP_FW_IMAGE_NUMBER)) {
1444                 break;
1445               }
1446             }
1447 
1448             boot_command = RSI_HOST_INTERACT_REG_VALID_FW | configuration;
1449             status       = sl_si91x_bus_write_memory(RSI_HOST_INTF_REG_IN, 2, (uint8_t *)&boot_command);
1450             if (status != SL_STATUS_OK) {
1451               return status;
1452             }
1453             default_nwp_fw_selected = 1;
1454             continue;
1455           } else {
1456             return SL_STATUS_VALID_FIRMWARE_NOT_PRESENT;
1457           }
1458         }
1459         if ((read_value & 0xFF) == RSI_INVALID_OPTION) {
1460           return SL_STATUS_INVALID_OPTION;
1461         }
1462         if ((read_value & 0xFF) == RSI_CHECKSUM_SUCCESS) {
1463           return status;
1464         }
1465       }
1466     }
1467   }
1468   return SL_STATUS_FW_LOAD_OR_UPGRADE_TIMEOUT;
1469 }
1470 
sl_si91x_enable_radio(void)1471 sl_status_t sl_si91x_enable_radio(void)
1472 {
1473   uint8_t data       = 1;
1474   sl_status_t status = sl_si91x_driver_send_command(RSI_WLAN_REQ_RADIO,
1475                                                     SI91X_WLAN_CMD,
1476                                                     &data,
1477                                                     1,
1478                                                     SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
1479                                                     NULL,
1480                                                     NULL);
1481   VERIFY_STATUS_AND_RETURN(status);
1482   return status;
1483 }
1484 
sl_si91x_disable_radio(void)1485 sl_status_t sl_si91x_disable_radio(void)
1486 {
1487   uint8_t data       = 0;
1488   sl_status_t status = sl_si91x_driver_send_command(RSI_WLAN_REQ_RADIO,
1489                                                     SI91X_WLAN_CMD,
1490                                                     &data,
1491                                                     1,
1492                                                     SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
1493                                                     NULL,
1494                                                     NULL);
1495   VERIFY_STATUS_AND_RETURN(status);
1496   return status;
1497 }
1498 
sl_si91x_write_calibration_data(const si91x_calibration_data_t * data)1499 sl_status_t sl_si91x_write_calibration_data(const si91x_calibration_data_t *data)
1500 {
1501   sl_status_t status = sl_si91x_driver_send_command(RSI_WLAN_REQ_CALIB_WRITE,
1502                                                     SI91X_WLAN_CMD,
1503                                                     data,
1504                                                     sizeof(si91x_calibration_data_t),
1505                                                     SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
1506                                                     NULL,
1507                                                     NULL);
1508   VERIFY_STATUS_AND_RETURN(status);
1509   return status;
1510 }
1511 
sl_si91x_wifi_set_certificate_index(uint8_t certificate_type,uint8_t certificate_index,const uint8_t * buffer,uint32_t certificate_length)1512 sl_status_t sl_si91x_wifi_set_certificate_index(uint8_t certificate_type,
1513                                                 uint8_t certificate_index,
1514                                                 const uint8_t *buffer,
1515                                                 uint32_t certificate_length)
1516 {
1517   uint32_t rem_len                         = 0;
1518   uint16_t chunk_size                      = 0;
1519   uint16_t data_size                       = 0;
1520   uint8_t chunks_remaining                 = 0;
1521   uint32_t offset                          = 0;
1522   sl_status_t status                       = SL_STATUS_OK;
1523   sl_si91x_req_set_certificate_t chunk_ptr = { 0 };
1524 
1525   if (!device_initialized) {
1526     return SL_STATUS_NOT_INITIALIZED;
1527   }
1528 
1529   // Get the certificate chunk size
1530   chunk_size = (SI91X_MAX_CERT_SEND_SIZE - sizeof(sl_si91x_cert_info_t));
1531 
1532   // Get certificate length
1533   rem_len = certificate_length;
1534 
1535   do {
1536     // Memset the PKT
1537     memset(&chunk_ptr, 0, sizeof(sl_si91x_req_set_certificate_t));
1538 
1539     // If certificate length is 0, erase certificate
1540     if (rem_len == 0) {
1541       // Mark Data Size
1542       data_size = 0;
1543 
1544       // More chunks to send
1545       chunks_remaining = 0;
1546     } else if (rem_len >= chunk_size) {
1547       // Mark Data Size
1548       data_size = chunk_size;
1549 
1550       // More chunks to send
1551       chunks_remaining = 1;
1552     } else {
1553       // Mark Data Size
1554       data_size = (uint16_t)rem_len;
1555 
1556       // More chunks to send
1557       chunks_remaining = 0;
1558     }
1559 
1560     if ((data_size > 0) && (NULL != buffer)) {
1561       // Copy the certificate chunk
1562       memcpy(chunk_ptr.certificate, buffer + offset, data_size);
1563     }
1564 
1565     // Move the offset by chunk size
1566     offset += data_size;
1567 
1568     // Subtract the rem_len by the chunk size
1569     rem_len -= data_size;
1570 
1571     //Set the total length of certificate
1572     memcpy(&chunk_ptr.cert_info.total_len, &certificate_length, sizeof(chunk_ptr.cert_info.total_len));
1573 
1574     // Set the certificate type
1575     chunk_ptr.cert_info.certificate_type = certificate_type;
1576 
1577     // Set the certificate index
1578     chunk_ptr.cert_info.certificate_inx = certificate_index;
1579 
1580     // More chunks to send
1581     chunk_ptr.cert_info.more_chunks = chunks_remaining;
1582 
1583     // Set the length of the certificate chunk
1584     chunk_ptr.cert_info.certificate_length = data_size;
1585 
1586     // Send the driver command
1587     status = sl_si91x_driver_send_command(RSI_WLAN_REQ_SET_CERTIFICATE,
1588                                           SI91X_WLAN_CMD,
1589                                           &chunk_ptr,
1590                                           (sizeof(sl_si91x_cert_info_t) + data_size),
1591                                           SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
1592                                           NULL,
1593                                           NULL);
1594     VERIFY_STATUS_AND_RETURN(status);
1595   } while (rem_len > 0);
1596 
1597   // Return status
1598   return status;
1599 }
1600 
sl_si91x_set_rtc_timer(const sl_si91x_module_rtc_time_t * timer)1601 sl_status_t sl_si91x_set_rtc_timer(const sl_si91x_module_rtc_time_t *timer)
1602 {
1603   sl_status_t status = SL_STATUS_OK;
1604 
1605   if (!device_initialized) {
1606     return SL_STATUS_NOT_INITIALIZED;
1607   }
1608 
1609   if ((timer->tm_sec > 59) || (timer->tm_min > 59) || (timer->tm_hour > 23)
1610       || ((timer->tm_mday < 1) || (timer->tm_mday > 31)) || (timer->tm_mon > 11)
1611       || ((timer->tm_wday < 1) || (timer->tm_wday > 7))) {
1612 
1613     // Checking Invalid Parameters
1614     return SL_STATUS_INVALID_PARAMETER;
1615   }
1616 
1617   // Send set RTC timer request
1618   status = sl_si91x_driver_send_command(RSI_COMMON_REQ_SET_RTC_TIMER,
1619                                         SI91X_COMMON_CMD,
1620                                         timer,
1621                                         sizeof(sl_si91x_module_rtc_time_t),
1622                                         SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
1623                                         NULL,
1624                                         NULL);
1625   VERIFY_STATUS_AND_RETURN(status);
1626   return status;
1627 }
1628 
sl_si91x_get_rtc_timer(sl_si91x_module_rtc_time_t * response)1629 sl_status_t sl_si91x_get_rtc_timer(sl_si91x_module_rtc_time_t *response)
1630 {
1631   sl_status_t status       = SL_STATUS_OK;
1632   sl_wifi_buffer_t *buffer = NULL;
1633 
1634   if (!device_initialized) {
1635     return SL_STATUS_NOT_INITIALIZED;
1636   }
1637 
1638   SL_WIFI_ARGS_CHECK_NULL_POINTER(response);
1639 
1640   // Send get RTC timer request
1641   status = sl_si91x_driver_send_command(RSI_COMMON_REQ_GET_RTC_TIMER,
1642                                         SI91X_COMMON_CMD,
1643                                         NULL,
1644                                         0,
1645                                         SL_SI91X_WAIT_FOR_RESPONSE(30000),
1646                                         NULL,
1647                                         &buffer);
1648 
1649   if ((status != SL_STATUS_OK) && (buffer != NULL)) {
1650     sl_si91x_host_free_buffer(buffer);
1651   }
1652   VERIFY_STATUS_AND_RETURN(status);
1653 
1654   // Extract the RTC timer data from the response
1655   const sl_si91x_packet_t *packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
1656   memcpy(response, packet->data, sizeof(sl_si91x_module_rtc_time_t));
1657   sl_si91x_host_free_buffer(buffer);
1658   return SL_STATUS_OK;
1659 }
1660 
sl_si91x_set_device_region(sl_si91x_operation_mode_t operation_mode,sl_si91x_band_mode_t band,sl_si91x_region_code_t region_code)1661 sl_status_t sl_si91x_set_device_region(sl_si91x_operation_mode_t operation_mode,
1662                                        sl_si91x_band_mode_t band,
1663                                        sl_si91x_region_code_t region_code)
1664 {
1665   sl_status_t status = SL_STATUS_OK;
1666 
1667   switch (operation_mode) {
1668     case SL_SI91X_CLIENT_MODE:
1669     case SL_SI91X_ENTERPRISE_CLIENT_MODE:
1670     case SL_SI91X_TRANSMIT_TEST_MODE:
1671     case SL_SI91X_TRANSCEIVER_MODE: {
1672       // For client and transmit test modes, send a command to set the region code
1673       sl_si91x_set_region_request_t request = { 0 };
1674 
1675       request.set_region_code_from_user_cmd = SET_REGION_CODE_FROM_USER;
1676       request.region_code                   = (uint8_t)region_code;
1677 
1678       status = sl_si91x_driver_send_command(RSI_WLAN_REQ_SET_REGION,
1679                                             SI91X_WLAN_CMD,
1680                                             &request,
1681                                             sizeof(sl_si91x_set_region_request_t),
1682                                             SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
1683                                             NULL,
1684                                             NULL);
1685       VERIFY_STATUS_AND_RETURN(status);
1686       break;
1687     }
1688 
1689     case SL_SI91X_CONCURRENT_MODE:
1690     case SL_SI91X_ACCESS_POINT_MODE: {
1691       if (operation_mode == SL_SI91X_CONCURRENT_MODE) {
1692         // For concurrent mode, send a command to set the region code
1693         sl_si91x_set_region_request_t request = { 0 };
1694 
1695         request.set_region_code_from_user_cmd = SET_REGION_CODE_FROM_USER;
1696         request.region_code                   = (uint8_t)region_code;
1697 
1698         status = sl_si91x_driver_send_command(RSI_WLAN_REQ_SET_REGION,
1699                                               SI91X_WLAN_CMD,
1700                                               &request,
1701                                               sizeof(sl_si91x_set_region_request_t),
1702                                               SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
1703                                               NULL,
1704                                               NULL);
1705         VERIFY_STATUS_AND_RETURN(status);
1706       }
1707 
1708       // For AP and concurrent modes, configure region-specific settings
1709       sl_si91x_set_region_ap_request_t request = { 0 };
1710       request.set_region_code_from_user_cmd    = SET_REGION_CODE_FROM_USER;
1711 
1712       // Configure region-specific settings based on the region code and band
1713       switch (region_code) {
1714         // Configure settings for different regions and bands
1715         case DEFAULT_REGION:
1716         case US: {
1717           if (band == SL_SI91X_WIFI_BAND_2_4GHZ) {
1718             request = default_US_region_2_4GHZ_configurations;
1719           } else {
1720             request = default_US_region_5GHZ_configurations;
1721           }
1722           break;
1723         }
1724         case EU: {
1725           if (band == SL_SI91X_WIFI_BAND_2_4GHZ) {
1726             request = default_EU_region_2_4GHZ_configurations;
1727           } else {
1728             request = default_EU_region_5GHZ_configurations;
1729           }
1730           break;
1731         }
1732         case JP: {
1733           if (band == SL_SI91X_WIFI_BAND_2_4GHZ) {
1734             request = default_JP_region_2_4GHZ_configurations;
1735           } else {
1736             request = default_JP_region_5GHZ_configurations;
1737           }
1738           break;
1739         }
1740         case KR: {
1741           if (band == SL_SI91X_WIFI_BAND_2_4GHZ) {
1742             request = default_KR_region_2_4GHZ_configurations;
1743           } else {
1744             request = default_KR_region_5GHZ_configurations;
1745           }
1746           break;
1747         }
1748         case SG: {
1749           if (band == SL_SI91X_WIFI_BAND_2_4GHZ) {
1750             request = default_SG_region_2_4GHZ_configurations;
1751           } else {
1752             request = default_SG_region_5GHZ_configurations;
1753           }
1754           break;
1755         }
1756         case CN: {
1757           if (band == SL_SI91X_WIFI_BAND_2_4GHZ) {
1758             request = default_CN_region_2_4GHZ_configurations;
1759           } else {
1760             request = default_CN_region_5GHZ_configurations;
1761           }
1762           break;
1763         }
1764         default:
1765           return SL_STATUS_NOT_SUPPORTED;
1766       }
1767       status = sl_si91x_driver_send_command(RSI_WLAN_REQ_SET_REGION_AP,
1768                                             SI91X_WLAN_CMD,
1769                                             &request,
1770                                             sizeof(sl_si91x_set_region_ap_request_t),
1771                                             SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
1772                                             NULL,
1773                                             NULL);
1774       VERIFY_STATUS_AND_RETURN(status);
1775       break;
1776     }
1777 
1778     default:
1779       break;
1780   }
1781 
1782   return status;
1783 }
1784 
1785 #ifdef SLI_SI91X_MCU_INTERFACE
1786 
sl_si91x_command_to_write_common_flash(uint32_t write_address,const uint8_t * write_data,uint16_t write_data_length,uint8_t flash_sector_erase_enable)1787 sl_status_t sl_si91x_command_to_write_common_flash(uint32_t write_address,
1788                                                    const uint8_t *write_data,
1789                                                    uint16_t write_data_length,
1790                                                    uint8_t flash_sector_erase_enable)
1791 {
1792   // Check if write_data_length is non-zero
1793   if (write_data_length == 0) {
1794     return SL_STATUS_INVALID_PARAMETER;
1795   }
1796 
1797   sl_status_t status                        = SL_STATUS_OK;
1798   sl_si91x_request_ta2m4_t ta_to_m4_request = { 0 };
1799   uint32_t send_size                        = 0;
1800   uint16_t remaining_length                 = write_data_length;
1801 
1802   // If flash_sector_erase_enable is 1, Send request to NWP in chunks of 4k
1803   if (flash_sector_erase_enable == 1) {
1804     while (remaining_length > 0) {
1805       // Calculate the chunk size, capped at 4k
1806       size_t chunkSize = (remaining_length < FLASH_SECTOR_SIZE) ? remaining_length : FLASH_SECTOR_SIZE;
1807 
1808       // Fill the request structure
1809       memset(&ta_to_m4_request, 0, sizeof(sl_si91x_request_ta2m4_t));
1810       ta_to_m4_request.sub_cmd                   = SL_SI91X_WRITE_TO_COMMON_FLASH;
1811       ta_to_m4_request.addr                      = write_address;
1812       ta_to_m4_request.input_buffer_length       = (uint16_t)chunkSize;
1813       ta_to_m4_request.flash_sector_erase_enable = flash_sector_erase_enable;
1814 
1815       send_size = sizeof(sl_si91x_request_ta2m4_t);
1816 
1817       status = sl_si91x_driver_send_command(RSI_COMMON_REQ_TA_M4_COMMANDS,
1818                                             SI91X_COMMON_CMD,
1819                                             &ta_to_m4_request,
1820                                             send_size,
1821                                             SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
1822                                             NULL,
1823                                             NULL);
1824       VERIFY_STATUS_AND_RETURN(status);
1825 
1826       // Adjust write_address for the next chunk
1827       write_address += chunkSize;
1828 
1829       // Adjust remaining_length for the next chunk
1830       remaining_length -= chunkSize;
1831     }
1832   }
1833 
1834   else {
1835     // Check if write_data pointer is valid
1836     SL_VERIFY_POINTER_OR_RETURN(write_data, SL_STATUS_INVALID_PARAMETER);
1837 
1838     // Write in chunks of MAX_CHUNK_SIZE for flash_sector_erase_enable != 1
1839     while (write_data_length > 0) {
1840       size_t chunkSize = (write_data_length < MAX_CHUNK_SIZE) ? write_data_length : MAX_CHUNK_SIZE;
1841 
1842       // Fill the request structure
1843       memset(&ta_to_m4_request, 0, sizeof(sl_si91x_request_ta2m4_t));
1844       ta_to_m4_request.sub_cmd                   = SL_SI91X_WRITE_TO_COMMON_FLASH;
1845       ta_to_m4_request.addr                      = write_address;
1846       ta_to_m4_request.input_buffer_length       = (uint16_t)chunkSize;
1847       ta_to_m4_request.flash_sector_erase_enable = flash_sector_erase_enable;
1848 
1849       // Copy write_data into the request structure
1850       memcpy(&ta_to_m4_request.input_data, write_data, chunkSize);
1851 
1852       // Calculate the send size and send the command to write to common flash
1853       send_size = sizeof(sl_si91x_request_ta2m4_t) - MAX_CHUNK_SIZE + chunkSize;
1854       status    = sl_si91x_driver_send_command(RSI_COMMON_REQ_TA_M4_COMMANDS,
1855                                             SI91X_COMMON_CMD,
1856                                             &ta_to_m4_request,
1857                                             send_size,
1858                                             SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
1859                                             NULL,
1860                                             NULL);
1861       VERIFY_STATUS_AND_RETURN(status);
1862 
1863       // Adjust pointers and counters
1864       write_address += chunkSize;
1865       write_data += chunkSize;
1866       write_data_length -= chunkSize;
1867     }
1868   }
1869   return status;
1870 }
1871 
sl_si91x_command_to_read_common_flash(uint32_t read_address,size_t length,uint8_t * output_buffer)1872 sl_status_t sl_si91x_command_to_read_common_flash(uint32_t read_address, size_t length, uint8_t *output_buffer)
1873 {
1874   // Check if output_buffer pointer is valid
1875   SL_VERIFY_POINTER_OR_RETURN(output_buffer, SL_STATUS_INVALID_PARAMETER);
1876 
1877   // Check if length is non-zero
1878   if (length == 0) {
1879     return SL_STATUS_INVALID_PARAMETER;
1880   }
1881 
1882   sl_status_t status              = SL_STATUS_OK;
1883   sl_wifi_buffer_t *buffer        = NULL;
1884   const sl_si91x_packet_t *packet = NULL;
1885 
1886   while (length > 0) {
1887     size_t chunkSize = (length < MAX_CHUNK_SIZE) ? length : MAX_CHUNK_SIZE;
1888 
1889     sl_si91x_read_flash_request_t m4_to_ta_read_request = { 0 };
1890     memset(&m4_to_ta_read_request, 0, sizeof(sl_si91x_read_flash_request_t));
1891     m4_to_ta_read_request.sub_cmd              = SL_SI91X_READ_FROM_COMMON_FLASH;
1892     m4_to_ta_read_request.nwp_address          = read_address;
1893     m4_to_ta_read_request.output_buffer_length = (uint16_t)chunkSize;
1894 
1895     uint32_t send_size = sizeof(sl_si91x_read_flash_request_t);
1896 
1897     status = sl_si91x_driver_send_command(RSI_COMMON_REQ_TA_M4_COMMANDS,
1898                                           SI91X_COMMON_CMD,
1899                                           &m4_to_ta_read_request,
1900                                           send_size,
1901                                           SL_SI91X_WAIT_FOR_RESPONSE(32000),
1902                                           NULL,
1903                                           &buffer);
1904     if (status != SL_STATUS_OK) {
1905       if (buffer != NULL)
1906         sl_si91x_host_free_buffer(buffer);
1907       return status;
1908     }
1909     VERIFY_STATUS_AND_RETURN(status);
1910 
1911     packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
1912     memcpy(output_buffer, packet->data, packet->length);
1913     sl_si91x_host_free_buffer(buffer);
1914 
1915     // Adjust pointers and counters
1916     read_address += chunkSize;
1917     output_buffer += chunkSize;
1918     length -= chunkSize;
1919   }
1920 
1921   return status;
1922 }
1923 
sl_si91x_m4_ta_secure_handshake(uint8_t sub_cmd_type,uint8_t input_len,const uint8_t * input_data,uint8_t output_len,const uint8_t * output_data)1924 sl_status_t sl_si91x_m4_ta_secure_handshake(uint8_t sub_cmd_type,
1925                                             uint8_t input_len,
1926                                             const uint8_t *input_data,
1927                                             uint8_t output_len,
1928                                             const uint8_t *output_data)
1929 {
1930   UNUSED_PARAMETER(output_len);
1931   UNUSED_PARAMETER(output_data);
1932   sl_si91x_ta_m4_handshake_parameters_t *handshake_request = NULL;
1933   sl_status_t status                                       = SL_STATUS_OK;
1934 
1935   SL_VERIFY_POINTER_OR_RETURN(input_data, SL_STATUS_INVALID_PARAMETER);
1936 
1937   handshake_request = malloc(sizeof(sl_si91x_ta_m4_handshake_parameters_t) + input_len);
1938   SL_VERIFY_POINTER_OR_RETURN(handshake_request, SL_STATUS_ALLOCATION_FAILED);
1939   memset(handshake_request, 0, sizeof(sl_si91x_ta_m4_handshake_parameters_t) + input_len);
1940   handshake_request->sub_cmd         = sub_cmd_type;
1941   handshake_request->input_data_size = input_len;
1942   memcpy(handshake_request->input_data, input_data, input_len);
1943 
1944   // Send the secure handshake command to the M4 core
1945   status = sl_si91x_driver_send_command(RSI_COMMON_REQ_TA_M4_COMMANDS,
1946                                         SI91X_COMMON_CMD,
1947                                         handshake_request,
1948                                         sizeof(sl_si91x_ta_m4_handshake_parameters_t) + input_len,
1949                                         SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
1950                                         NULL,
1951                                         NULL);
1952   free(handshake_request);
1953   VERIFY_STATUS_AND_RETURN(status);
1954   return status;
1955 }
1956 
1957 // Perform a soft reset
sl_si91x_soft_reset(void)1958 static sl_status_t sl_si91x_soft_reset(void)
1959 {
1960   sl_status_t status;
1961   if (!device_initialized) {
1962     return SL_STATUS_NOT_INITIALIZED;
1963   }
1964   status = sl_si91x_driver_send_command(RSI_COMMON_REQ_SOFT_RESET,
1965                                         SI91X_COMMON_CMD,
1966                                         NULL,
1967                                         0,
1968                                         SL_SI91X_WAIT_FOR_RESPONSE(30000),
1969                                         NULL,
1970                                         NULL);
1971   VERIFY_STATUS_AND_RETURN(status);
1972   return status;
1973 }
1974 #endif
1975 
sl_si91x_assert()1976 sl_status_t sl_si91x_assert()
1977 {
1978   sl_status_t status = SL_STATUS_OK;
1979 
1980   if (!device_initialized) {
1981     return SL_STATUS_NOT_INITIALIZED;
1982   }
1983   status =
1984     sl_si91x_driver_send_command(RSI_COMMON_REQ_ASSERT, SI91X_WLAN_CMD, NULL, 0, SL_SI91X_WAIT_FOR(30000), NULL, NULL);
1985   VERIFY_STATUS_AND_RETURN(status);
1986   return status;
1987 }
1988 
sl_si91x_get_ram_log(uint32_t address,uint32_t length)1989 sl_status_t sl_si91x_get_ram_log(uint32_t address, uint32_t length)
1990 {
1991   if (!device_initialized) {
1992     return SL_STATUS_NOT_INITIALIZED;
1993   }
1994   sl_status_t status      = SL_STATUS_OK;
1995   sl_si91x_ram_dump_t ram = { .address = address, .length = length };
1996 
1997   // Check for invalid length parameter
1998   if (length == 0) {
1999     return SL_STATUS_INVALID_PARAMETER;
2000   }
2001   // Send RAM log request
2002   status = sl_si91x_driver_send_command(RSI_COMMON_REQ_GET_RAM_DUMP,
2003                                         SI91X_COMMON_CMD,
2004                                         &ram,
2005                                         sizeof(sl_si91x_ram_dump_t),
2006                                         SL_SI91X_WAIT_FOR(31000),
2007                                         NULL,
2008                                         NULL);
2009   VERIFY_STATUS_AND_RETURN(status);
2010   return status;
2011 }
2012 
sl_si91x_transmit_test_start(const sl_si91x_request_tx_test_info_t * tx_test_info)2013 sl_status_t sl_si91x_transmit_test_start(const sl_si91x_request_tx_test_info_t *tx_test_info)
2014 {
2015   sl_status_t status = SL_STATUS_OK;
2016 
2017   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_TX_TEST_MODE,
2018                                         SI91X_WLAN_CMD,
2019                                         tx_test_info,
2020                                         sizeof(sl_si91x_request_tx_test_info_t),
2021                                         SL_SI91X_WAIT_FOR(30100),
2022                                         NULL,
2023                                         NULL);
2024   VERIFY_STATUS_AND_RETURN(status);
2025   return status;
2026 }
2027 
sl_si91x_transmit_test_stop(void)2028 sl_status_t sl_si91x_transmit_test_stop(void)
2029 {
2030   sl_status_t status                           = SL_STATUS_OK;
2031   sl_si91x_request_tx_test_info_t tx_test_info = { 0 };
2032   tx_test_info.enable                          = 0;
2033   // Send the transmit test stop command
2034   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_TX_TEST_MODE,
2035                                         SI91X_WLAN_CMD,
2036                                         &tx_test_info,
2037                                         sizeof(sl_si91x_request_tx_test_info_t),
2038                                         SL_SI91X_WAIT_FOR(30100),
2039                                         NULL,
2040                                         NULL);
2041   VERIFY_STATUS_AND_RETURN(status);
2042   return status;
2043 }
2044 
get_opermode(void)2045 sl_si91x_operation_mode_t get_opermode(void)
2046 {
2047   return initialized_opermode;
2048 }
2049 
sl_si91x_calibration_write(sl_si91x_calibration_write_t calib_write)2050 sl_status_t sl_si91x_calibration_write(sl_si91x_calibration_write_t calib_write)
2051 {
2052   sl_status_t status = SL_STATUS_OK;
2053 
2054   if (!device_initialized) {
2055     return SL_STATUS_NOT_INITIALIZED;
2056   }
2057 
2058   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_CALIB_WRITE,
2059                                         SI91X_WLAN_CMD,
2060                                         &calib_write,
2061                                         sizeof(sl_si91x_calibration_write_t),
2062                                         SL_SI91X_WAIT_FOR(30000),
2063                                         NULL,
2064                                         NULL);
2065   VERIFY_STATUS_AND_RETURN(status);
2066   return status;
2067 }
2068 
sl_si91x_calibration_read(sl_si91x_calibration_read_t target,sl_si91x_calibration_read_t * calibration_read)2069 sl_status_t sl_si91x_calibration_read(sl_si91x_calibration_read_t target, sl_si91x_calibration_read_t *calibration_read)
2070 {
2071   sl_wifi_buffer_t *buffer = NULL;
2072   sl_status_t status       = SL_STATUS_OK;
2073 
2074   if (!device_initialized) {
2075     return SL_STATUS_NOT_INITIALIZED;
2076   }
2077   SL_VERIFY_POINTER_OR_RETURN(calibration_read, SL_STATUS_NULL_POINTER);
2078 
2079   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_CALIB_READ,
2080                                         SI91X_WLAN_CMD,
2081                                         &target,
2082                                         sizeof(sl_si91x_calibration_read_t),
2083                                         SL_SI91X_WAIT_FOR_RESPONSE(30100),
2084                                         NULL,
2085                                         &buffer);
2086 
2087   if ((status != SL_STATUS_OK) && (buffer != NULL)) {
2088     sl_si91x_host_free_buffer(buffer);
2089     return status;
2090   }
2091 
2092   const sl_si91x_packet_t *packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
2093   memcpy(calibration_read, packet->data, sizeof(sl_si91x_calibration_read_t));
2094   sl_si91x_host_free_buffer(buffer);
2095   return status;
2096 }
2097 
sl_si91x_frequency_offset(const sl_si91x_freq_offset_t * frequency_calibration)2098 sl_status_t sl_si91x_frequency_offset(const sl_si91x_freq_offset_t *frequency_calibration)
2099 {
2100   sl_status_t status = SL_STATUS_OK;
2101 
2102   if (!device_initialized) {
2103     return SL_STATUS_NOT_INITIALIZED;
2104   }
2105 
2106   SL_VERIFY_POINTER_OR_RETURN(frequency_calibration, SL_STATUS_NULL_POINTER);
2107 
2108   // Send the frequency offset calibration command to the SI91x WLAN module
2109   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_FREQ_OFFSET,
2110                                         SI91X_WLAN_CMD,
2111                                         frequency_calibration,
2112                                         sizeof(sl_si91x_freq_offset_t),
2113                                         SL_SI91X_WAIT_FOR_RESPONSE(35000),
2114                                         NULL,
2115                                         NULL);
2116   VERIFY_STATUS_AND_RETURN(status);
2117   return status;
2118 }
2119 
sl_si91x_evm_offset(const sl_si91x_evm_offset_t * evm_offset)2120 sl_status_t sl_si91x_evm_offset(const sl_si91x_evm_offset_t *evm_offset)
2121 {
2122   sl_status_t status = SL_STATUS_OK;
2123 
2124   if (!device_initialized) {
2125     return SL_STATUS_NOT_INITIALIZED;
2126   }
2127 
2128   SL_VERIFY_POINTER_OR_RETURN(evm_offset, SL_STATUS_NULL_POINTER);
2129 
2130   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_EVM_OFFSET,
2131                                         SI91X_WLAN_CMD,
2132                                         evm_offset,
2133                                         sizeof(sl_si91x_evm_offset_t),
2134                                         SL_SI91X_WAIT_FOR_RESPONSE(35000),
2135                                         NULL,
2136                                         NULL);
2137   VERIFY_STATUS_AND_RETURN(status);
2138   return SL_STATUS_OK;
2139 }
2140 
sl_si91x_evm_write(const sl_si91x_evm_write_t * evm_write)2141 sl_status_t sl_si91x_evm_write(const sl_si91x_evm_write_t *evm_write)
2142 {
2143   sl_status_t status = SL_STATUS_OK;
2144 
2145   if (!device_initialized) {
2146     return SL_STATUS_NOT_INITIALIZED;
2147   }
2148 
2149   SL_VERIFY_POINTER_OR_RETURN(evm_write, SL_STATUS_NULL_POINTER);
2150 
2151   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_EVM_WRITE,
2152                                         SI91X_WLAN_CMD,
2153                                         evm_write,
2154                                         sizeof(sl_si91x_evm_write_t),
2155                                         SL_SI91X_WAIT_FOR_RESPONSE(35000),
2156                                         NULL,
2157                                         NULL);
2158   VERIFY_STATUS_AND_RETURN(status);
2159   return SL_STATUS_OK;
2160 }
2161 
sl_si91x_dpd_calibration(const sl_si91x_get_dpd_calib_data_t * dpd_calib_data)2162 sl_status_t sl_si91x_dpd_calibration(const sl_si91x_get_dpd_calib_data_t *dpd_calib_data)
2163 {
2164   sl_status_t status = SL_STATUS_OK;
2165 
2166   if (!device_initialized) {
2167     return SL_STATUS_NOT_INITIALIZED;
2168   }
2169 
2170   SL_VERIFY_POINTER_OR_RETURN(dpd_calib_data, SL_STATUS_NULL_POINTER);
2171 
2172   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_GET_DPD_DATA,
2173                                         SI91X_WLAN_CMD,
2174                                         dpd_calib_data,
2175                                         sizeof(sl_si91x_get_dpd_calib_data_t),
2176                                         SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
2177                                         NULL,
2178                                         NULL);
2179   VERIFY_STATUS_AND_RETURN(status);
2180   return status;
2181 }
2182 
sl_si91x_efuse_read(const sl_si91x_efuse_read_t * efuse_read,uint8_t * efuse_read_buf)2183 sl_status_t sl_si91x_efuse_read(const sl_si91x_efuse_read_t *efuse_read, uint8_t *efuse_read_buf)
2184 {
2185   sl_wifi_buffer_t *buffer = NULL;
2186   sl_status_t status       = SL_STATUS_OK;
2187 
2188   if (!device_initialized) {
2189     return SL_STATUS_NOT_INITIALIZED;
2190   }
2191   SL_VERIFY_POINTER_OR_RETURN(efuse_read, SL_STATUS_NULL_POINTER);
2192   SL_VERIFY_POINTER_OR_RETURN(efuse_read_buf, SL_STATUS_NULL_POINTER);
2193 
2194   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_EFUSE_READ,
2195                                         SI91X_WLAN_CMD,
2196                                         efuse_read,
2197                                         sizeof(sl_si91x_efuse_read_t),
2198                                         SL_SI91X_WAIT_FOR_RESPONSE(30100),
2199                                         NULL,
2200                                         &buffer);
2201 
2202   if ((status != SL_STATUS_OK) && (buffer != NULL)) {
2203     sl_si91x_host_free_buffer(buffer);
2204     return status;
2205   }
2206 
2207   const sl_si91x_packet_t *packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
2208   memcpy(efuse_read_buf, packet->data, efuse_read->efuse_read_data_len);
2209   sl_si91x_host_free_buffer(buffer);
2210   return status;
2211 }
2212 
sl_si91x_set_join_configuration(sl_wifi_interface_t interface,uint8_t join_feature_bitmap)2213 sl_status_t sl_si91x_set_join_configuration(sl_wifi_interface_t interface, uint8_t join_feature_bitmap)
2214 {
2215   // Determine whether the configuration is for the client or AP interface
2216   if (interface & SL_WIFI_CLIENT_INTERFACE) {
2217     client_join_feature_bitmap = join_feature_bitmap;
2218   } else if (interface & SL_WIFI_AP_INTERFACE) {
2219     ap_join_feature_bitmap = join_feature_bitmap;
2220   } else {
2221     return SL_STATUS_FAIL;
2222   }
2223   return SL_STATUS_OK;
2224 }
2225 
sl_si91x_get_join_configuration(sl_wifi_interface_t interface,uint8_t * join_feature_bitmap)2226 sl_status_t sl_si91x_get_join_configuration(sl_wifi_interface_t interface, uint8_t *join_feature_bitmap)
2227 {
2228   SL_WIFI_ARGS_CHECK_NULL_POINTER(join_feature_bitmap);
2229 
2230   // Determine whether to retrieve the configuration for the client or AP interface
2231   if (interface & SL_WIFI_CLIENT_INTERFACE) {
2232     *join_feature_bitmap = client_join_feature_bitmap;
2233   } else if (interface & SL_WIFI_AP_INTERFACE) {
2234     *join_feature_bitmap = ap_join_feature_bitmap;
2235   } else {
2236     return SL_STATUS_WIFI_UNKNOWN_INTERFACE;
2237   }
2238 
2239   return SL_STATUS_OK;
2240 }
2241 
sl_si91x_set_listen_interval(uint32_t listen_interval)2242 void sl_si91x_set_listen_interval(uint32_t listen_interval)
2243 {
2244   client_listen_interval = listen_interval;
2245   return;
2246 }
2247 
sl_si91x_get_listen_interval(void)2248 uint32_t sl_si91x_get_listen_interval(void)
2249 {
2250   return client_listen_interval;
2251 }
2252 
sl_si91x_set_timeout(const sl_si91x_timeout_t * timeout_config)2253 void sl_si91x_set_timeout(const sl_si91x_timeout_t *timeout_config)
2254 {
2255   memcpy(&timeout_glbl, timeout_config, sizeof(sl_si91x_timeout_t));
2256   return;
2257 }
2258 
sl_si91x_configure_timeout(sl_si91x_timeout_type_t timeout_type,uint16_t timeout_value)2259 sl_status_t sl_si91x_configure_timeout(sl_si91x_timeout_type_t timeout_type, uint16_t timeout_value)
2260 {
2261   sl_status_t status                         = SL_STATUS_OK;
2262   sl_si91x_request_timeout_t timeout_request = { 0 };
2263 
2264   if (timeout_type > SL_SI91X_CHANNEL_PASSIVE_SCAN_TIMEOUT) {
2265     return SL_STATUS_INVALID_PARAMETER;
2266   }
2267 
2268   timeout_request.timeout_bitmap = BIT(timeout_type);
2269   timeout_request.timeout_value  = timeout_value;
2270   status                         = sl_si91x_driver_send_command(RSI_WLAN_REQ_TIMEOUT,
2271                                         SI91X_WLAN_CMD,
2272                                         &timeout_request,
2273                                         sizeof(sl_si91x_request_timeout_t),
2274                                         SL_SI91X_WAIT_FOR(30100),
2275                                         NULL,
2276                                         NULL);
2277   return status;
2278 }
2279 
get_seq_ctrl(uint8_t is_qos)2280 uint16_t get_seq_ctrl(uint8_t is_qos)
2281 {
2282   static uint16_t qos_pkt_count     = 0;
2283   static uint16_t non_qos_pkt_count = 0;
2284 
2285   if (qos_pkt_count > 4095)
2286     qos_pkt_count = 0;
2287 
2288   if (non_qos_pkt_count > 4095)
2289     non_qos_pkt_count = 0;
2290 
2291   return is_qos ? qos_pkt_count++ : non_qos_pkt_count++;
2292 }
2293 
encapsulate_tx_data_packet(sl_wifi_transceiver_tx_data_control_t * control,uint8_t * pkt_data,uint32_t mac_hdr_len)2294 int32_t encapsulate_tx_data_packet(sl_wifi_transceiver_tx_data_control_t *control,
2295                                    uint8_t *pkt_data,
2296                                    uint32_t mac_hdr_len)
2297 {
2298   uint16_t seq_ctrl = 0;
2299   uint16_t *frame_ctrl;
2300   uint32_t qos_ctrl_off = MAC80211_HDR_MIN_LEN;
2301 
2302   SL_VERIFY_POINTER_OR_RETURN(control, SL_STATUS_NULL_POINTER);
2303 
2304   if (IS_MAC_ZERO(control->addr1)) {
2305     return SL_STATUS_TRANSCEIVER_INVALID_MAC_ADDRESS;
2306   }
2307 
2308   /* Auto-rate is unsupported if Peer DS feature in MAC layer is disabled */
2309   if ((!IS_PEER_DS_SUPPORT_ENABLED(feature_bit_map)) && !IS_FIXED_DATA_RATE(control->ctrl_flags)) {
2310     return SL_STATUS_TRANSCEIVER_INVALID_DATA_RATE;
2311   }
2312 
2313   /* Ignore QoS flag for bcast/mcast frames */
2314   if (IS_BCAST_MCAST_MAC(control->addr1[0])) {
2315     control->ctrl_flags &= ~TX_DATA_CTRL_FLAG_QOS_BIT;
2316   }
2317 
2318   if ((IS_QOS_PKT(control->ctrl_flags) && !IS_BCAST_MCAST_MAC(control->addr1[0])) && (control->priority > 3)) {
2319     return SL_STATUS_TRANSCEIVER_INVALID_QOS_PRIORITY;
2320   }
2321 
2322   if (IS_4ADDR(control->ctrl_flags)) {
2323     qos_ctrl_off += MAC80211_HDR_ADDR4_LEN;
2324   }
2325 
2326   memset(pkt_data, 0, mac_hdr_len);
2327   /* Add frame control (2 bytes) */
2328   frame_ctrl = (uint16_t *)&pkt_data[0];
2329   *frame_ctrl |= FC_TYPE_DATA;
2330 
2331   if (IS_4ADDR(control->ctrl_flags)) {
2332     *frame_ctrl |= FC_TO_DS;
2333     *frame_ctrl |= FC_FROM_DS;
2334   } else {
2335     *frame_ctrl |= IS_TODS(control->ctrl_flags) ? FC_TO_DS : 0;
2336     *frame_ctrl |= IS_FROMDS(control->ctrl_flags) ? FC_FROM_DS : 0;
2337   }
2338 
2339   /* Add Addr1, Addr2, Addr3 (18 bytes) */
2340   memcpy(&pkt_data[4], control->addr1, 6);
2341   memcpy(&pkt_data[10], control->addr2, 6);
2342   memcpy(&pkt_data[16], control->addr3, 6);
2343 
2344   if (!IS_PEER_DS_SUPPORT_ENABLED(feature_bit_map)) {
2345     seq_ctrl = (uint16_t)(get_seq_ctrl(IS_QOS_PKT(control->ctrl_flags)) << 4);
2346     memcpy(&pkt_data[22], &seq_ctrl, 2);
2347   }
2348 
2349   /* Add Addr4 optionally based on ctrl_flag (6 bytes) */
2350   if (IS_4ADDR(control->ctrl_flags)) {
2351     memcpy(&pkt_data[24], control->addr4, 6); /* sa */
2352   }
2353   /* Add QoS control optionally based on ctrl_flag (2 bytes) */
2354   if (IS_QOS_PKT(control->ctrl_flags) && !IS_BCAST_MCAST_MAC(control->addr1[0])) {
2355     *frame_ctrl |= FC_SUBTYPE_QOS_DATA;
2356     pkt_data[qos_ctrl_off] = WME_AC_TO_TID(control->priority);
2357   }
2358 
2359   return SL_STATUS_OK;
2360 }
2361 
sl_si91x_driver_send_transceiver_data(sl_wifi_transceiver_tx_data_control_t * control,const uint8_t * payload,uint16_t payload_len,uint32_t wait_time)2362 sl_status_t sl_si91x_driver_send_transceiver_data(sl_wifi_transceiver_tx_data_control_t *control,
2363                                                   const uint8_t *payload,
2364                                                   uint16_t payload_len,
2365                                                   uint32_t wait_time)
2366 {
2367   sl_wifi_buffer_t *buffer;
2368   sl_si91x_packet_t *packet;
2369   sl_status_t status = SL_STATUS_OK;
2370   uint8_t *pkt_offset;
2371   uint8_t ext_desc_size;
2372   uint8_t *host_desc;
2373   uint32_t mac_hdr_len = MAC80211_HDR_MIN_LEN;
2374 
2375   if (IS_QOS_PKT(control->ctrl_flags) && !IS_BCAST_MCAST_MAC(control->addr1[0])) {
2376     mac_hdr_len += MAC80211_HDR_QOS_CTRL_LEN;
2377   }
2378 
2379   if (IS_4ADDR(control->ctrl_flags)) {
2380     mac_hdr_len += MAC80211_HDR_ADDR4_LEN;
2381   }
2382 
2383   ext_desc_size = TRANSCEIVER_TX_DATA_EXT_DESC_SIZE;
2384 
2385   // Allocate a data buffer with space for the data and metadata
2386   status = sl_si91x_allocate_data_buffer(&buffer,
2387                                          (void **)&packet,
2388                                          sizeof(sl_si91x_packet_t) + ext_desc_size + mac_hdr_len + payload_len,
2389                                          SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME);
2390   VERIFY_STATUS_AND_RETURN(status);
2391 
2392   // If the packet is not allocated successfully, return an allocation failed error
2393   if (packet == NULL) {
2394     return SL_STATUS_ALLOCATION_FAILED;
2395   }
2396 
2397   pkt_offset = packet->data + ext_desc_size;
2398   status     = encapsulate_tx_data_packet(control, pkt_offset, mac_hdr_len);
2399   if (status != SL_STATUS_OK) {
2400     sl_si91x_host_free_buffer(buffer);
2401     return status;
2402   }
2403 
2404   memcpy(pkt_offset + mac_hdr_len, payload, payload_len);
2405 
2406 #ifdef TX_RX_FRAME_DUMP_BYTE_COUNT
2407   print_80211_packet(pkt_offset, mac_hdr_len + payload_len, TX_RX_FRAME_DUMP_BYTE_COUNT);
2408 #endif
2409 
2410   // Clear the packet descriptor and copy the command data if available
2411   memset(packet->desc, 0, sizeof(packet->desc));
2412 
2413   // Fill length in first 2 host_desc bytes
2414   packet->length = (ext_desc_size + mac_hdr_len + payload_len) & 0xFFF;
2415 
2416   // Fill packet type
2417   host_desc = packet->desc;
2418 
2419   host_desc[2] = 0x01; //! Frame Type
2420   if (IS_CFM_TO_HOST_SET(control->ctrl_flags)) {
2421     host_desc[3] |= CONFIRM_REQUIRED_TO_HOST; //! This bit is used to set CONFIRM_REQUIRED_TO_HOST in firmware.
2422   }
2423   host_desc[4] = ext_desc_size;                     //! xtend_desc size
2424   host_desc[5] = (uint8_t)((mac_hdr_len + 3) & ~3); //! Mac_header length
2425 
2426   if (IS_BCAST_MCAST_MAC(control->addr1[0])) {
2427     host_desc[7] |= BCAST_INDICATION; //! Bcast_indication
2428     //! If auto-rate is enabled for bcast/mcast pkts, use 1 Mbps
2429     if (!IS_FIXED_DATA_RATE(control->ctrl_flags)) {
2430       host_desc[6] |= MAC_INFO_ENABLE; //! Fixed Rate
2431       host_desc[8] = SL_WIFI_DATA_RATE_1;
2432     }
2433   }
2434 
2435   if (IS_FIXED_DATA_RATE(control->ctrl_flags)) {
2436     host_desc[6] |= MAC_INFO_ENABLE; //! Fixed Rate
2437     host_desc[8] = (uint8_t)control->rate;
2438   }
2439 
2440   if (IS_QOS_PKT(control->ctrl_flags) && !IS_BCAST_MCAST_MAC(control->addr1[0])) {
2441     host_desc[13] |= QOS_ENABLE; // QOS ENABLE
2442   }
2443 
2444   host_desc[14] =
2445     (uint8_t)(((WME_AC_TO_TID(control->priority) & 0xf) << 4) | (WME_AC_TO_QNUM(control->priority) & 0xf));
2446 
2447   //! Initialize extended desc
2448   memcpy(&host_desc[16], &control->token, TRANSCEIVER_TX_DATA_EXT_DESC_SIZE);
2449 
2450   // Send command packet to the SI91x socket data queue and await a response
2451   return sl_si91x_driver_send_data_packet(buffer, wait_time);
2452 }
2453 
sl_si91x_bl_upgrade_firmware(uint8_t * firmware_image,uint32_t fw_image_size,uint8_t flags)2454 sl_status_t sl_si91x_bl_upgrade_firmware(uint8_t *firmware_image, uint32_t fw_image_size, uint8_t flags)
2455 {
2456   static uint16_t boot_cmd = 0;
2457   uint16_t read_value      = 0;
2458   uint32_t offset          = 0;
2459   uint32_t retval          = 0;
2460   uint32_t boot_insn       = 0;
2461   uint32_t poll_resp       = 0;
2462 
2463   //! If it is a start of file set the boot cmd to pong valid
2464   if (flags & SL_SI91X_FW_START_OF_FILE) {
2465     boot_cmd = RSI_HOST_INTERACT_REG_VALID | RSI_PONG_VALID;
2466   }
2467 
2468   //! check for invalid packet
2469   if ((fw_image_size % SL_SI91X_MIN_CHUNK_SIZE != 0) && (!(flags & SL_SI91X_FW_END_OF_FILE))) {
2470     return SL_STATUS_FAIL;
2471   }
2472 
2473   //! loop to execute multiple of 4K chunks
2474   while (offset < fw_image_size) {
2475     switch (boot_cmd) {
2476       case (RSI_HOST_INTERACT_REG_VALID | RSI_PING_VALID):
2477         boot_insn = RSI_PONG_WRITE;
2478         poll_resp = RSI_PING_AVAIL;
2479         boot_cmd  = RSI_HOST_INTERACT_REG_VALID | RSI_PONG_VALID;
2480         break;
2481 
2482       case (RSI_HOST_INTERACT_REG_VALID | RSI_PONG_VALID):
2483         boot_insn = RSI_PING_WRITE;
2484         poll_resp = RSI_PONG_AVAIL;
2485         boot_cmd  = RSI_HOST_INTERACT_REG_VALID | RSI_PING_VALID;
2486         break;
2487 
2488       default:
2489         return SL_STATUS_FAIL;
2490     }
2491 
2492     retval = sl_si91x_boot_instruction((uint8_t)boot_insn, (uint16_t *)(firmware_image + offset));
2493     VERIFY_STATUS_AND_RETURN(retval);
2494 
2495     while (1) {
2496       retval = sl_si91x_boot_instruction(RSI_REG_READ, &read_value);
2497       VERIFY_STATUS_AND_RETURN(retval);
2498 
2499       if (read_value == (RSI_HOST_INTERACT_REG_VALID | poll_resp)) {
2500         break;
2501       }
2502     }
2503     offset += SL_SI91X_MIN_CHUNK_SIZE;
2504   }
2505 
2506   //! For last chunk set boot cmd as End of file reached
2507   if (flags & SL_SI91X_FW_END_OF_FILE) {
2508     boot_cmd = RSI_HOST_INTERACT_REG_VALID | RSI_EOF_REACHED;
2509 
2510     retval = sl_si91x_boot_instruction(RSI_REG_WRITE, &boot_cmd);
2511     VERIFY_STATUS_AND_RETURN(retval);
2512 
2513     //! check for successful firmware upgrade
2514     do {
2515       retval = sl_si91x_boot_instruction(RSI_REG_READ, &read_value);
2516       VERIFY_STATUS_AND_RETURN(retval);
2517 
2518     } while (read_value != (RSI_HOST_INTERACT_REG_VALID | RSI_FWUP_SUCCESSFUL));
2519   }
2520   return retval;
2521 }
2522 
sl_si91x_set_fast_fw_up(void)2523 sl_status_t sl_si91x_set_fast_fw_up(void)
2524 {
2525   uint32_t read_data = 0;
2526   sl_status_t retval = 0;
2527   retval             = sl_si91x_bus_read_memory(SL_SI91X_SAFE_UPGRADE_ADDR, 4, (uint8_t *)&read_data);
2528   VERIFY_STATUS_AND_RETURN(retval);
2529 
2530   //disabling safe upgradation bit
2531   if (read_data & SL_SI91X_SAFE_UPGRADE) {
2532     read_data &= ~(SL_SI91X_SAFE_UPGRADE);
2533     retval = sl_si91x_bus_write_memory(SL_SI91X_SAFE_UPGRADE_ADDR, 4, (uint8_t *)&read_data);
2534     VERIFY_STATUS_AND_RETURN(retval);
2535   }
2536   return retval;
2537 }
2538 
sli_si91x_append_to_buffer_queue(sl_si91x_buffer_queue_t * queue,sl_wifi_buffer_t * buffer)2539 void sli_si91x_append_to_buffer_queue(sl_si91x_buffer_queue_t *queue, sl_wifi_buffer_t *buffer)
2540 {
2541   CORE_irqState_t state = CORE_EnterAtomic();
2542   if (queue->tail == NULL) {
2543     assert(queue->head == NULL); // Both should be NULL at the same time
2544     queue->head = buffer;
2545     queue->tail = buffer;
2546   } else {
2547     queue->tail->node.node = &buffer->node;
2548     queue->tail            = buffer;
2549   }
2550   CORE_ExitAtomic(state);
2551 }
2552 
sli_si91x_pop_from_buffer_queue(sl_si91x_buffer_queue_t * queue,sl_wifi_buffer_t ** buffer)2553 sl_status_t sli_si91x_pop_from_buffer_queue(sl_si91x_buffer_queue_t *queue, sl_wifi_buffer_t **buffer)
2554 {
2555   sl_status_t status    = SL_STATUS_EMPTY;
2556   CORE_irqState_t state = CORE_EnterAtomic();
2557   if (queue->head == NULL) {
2558     assert(queue->tail == NULL); // Both should be NULL at the same time
2559     *buffer = NULL;
2560     status  = SL_STATUS_EMPTY;
2561   } else {
2562     *buffer = queue->head;
2563     status  = SL_STATUS_OK;
2564     if (queue->head == queue->tail) {
2565       queue->head = NULL;
2566       queue->tail = NULL;
2567     } else {
2568       queue->head = (sl_wifi_buffer_t *)queue->head->node.node;
2569     }
2570   }
2571   CORE_ExitAtomic(state);
2572   return status;
2573 }
2574 
sl_si91x_get_firmware_version(sl_si91x_firmware_version_t * version)2575 sl_status_t sl_si91x_get_firmware_version(sl_si91x_firmware_version_t *version)
2576 {
2577   sl_status_t status       = SL_STATUS_OK;
2578   sl_wifi_buffer_t *buffer = NULL;
2579 
2580   if (!device_initialized) {
2581     return SL_STATUS_NOT_INITIALIZED;
2582   }
2583   SL_WIFI_ARGS_CHECK_NULL_POINTER(version);
2584 
2585   status = sl_si91x_driver_send_command(RSI_WLAN_REQ_FULL_FW_VERSION,
2586                                         SI91X_WLAN_CMD,
2587                                         NULL,
2588                                         0,
2589                                         SL_SI91X_WAIT_FOR_RESPONSE(1000),
2590                                         NULL,
2591                                         &buffer);
2592   if ((status != SL_STATUS_OK) && (buffer != NULL)) {
2593     sl_si91x_host_free_buffer(buffer);
2594   }
2595   VERIFY_STATUS_AND_RETURN(status);
2596 
2597   sl_si91x_packet_t *packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
2598 
2599   if (packet == NULL) {
2600     return SL_STATUS_NULL_POINTER;
2601   }
2602 
2603   if (packet->length > 0) {
2604     const sl_wifi_firmware_version_t *response = (const sl_wifi_firmware_version_t *)packet->data;
2605 
2606     if (response == NULL) {
2607       return SL_STATUS_NULL_POINTER;
2608     }
2609 
2610     version->chip_id          = response->chip_id;
2611     version->rom_id           = response->rom_id;
2612     version->major            = response->major;
2613     version->minor            = response->minor;
2614     version->security_version = response->security_version;
2615     version->patch_num        = response->patch_num;
2616     version->customer_id      = response->customer_id;
2617     version->build_num        = (packet->data[7] | packet->data[8]);
2618   }
2619 
2620   sl_si91x_host_free_buffer(buffer);
2621   return status;
2622 }
2623 
sl_si91x_get_firmware_size(void * buffer,uint32_t * fw_image_size)2624 sl_status_t sl_si91x_get_firmware_size(void *buffer, uint32_t *fw_image_size)
2625 {
2626   SL_WIFI_ARGS_CHECK_NULL_POINTER(buffer);
2627 
2628   const sl_si91x_firmware_header_t *fw = (const sl_si91x_firmware_header_t *)buffer;
2629 
2630   *fw_image_size = (fw->image_size + sizeof(sl_si91x_firmware_header_t));
2631 
2632   return SL_STATUS_OK;
2633 }
2634 
sl_si91x_set_nwp_config_request(sl_si91x_nwp_configuration_t nwp_config)2635 sl_status_t sl_si91x_set_nwp_config_request(sl_si91x_nwp_configuration_t nwp_config)
2636 {
2637   sl_status_t status = SL_STATUS_OK;
2638 
2639   if ((nwp_config.code & SL_SI91X_XO_CTUNE_FROM_HOST) || (nwp_config.code & SL_SI91X_ENABLE_NWP_WDT_FROM_HOST)
2640       || (nwp_config.code & SL_SI91X_DISABLE_NWP_WDT_FROM_HOST)) {
2641     status = sl_si91x_driver_send_command(RSI_COMMON_REQ_SET_CONFIG,
2642                                           SI91X_COMMON_CMD,
2643                                           &nwp_config,
2644                                           sizeof(sl_si91x_nwp_configuration_t),
2645                                           SL_SI91X_WAIT_FOR_RESPONSE(3000),
2646                                           NULL,
2647                                           NULL);
2648     VERIFY_STATUS_AND_RETURN(status);
2649   } else
2650     return SL_STATUS_NOT_SUPPORTED;
2651 
2652   return status;
2653 }
2654 
sl_si91x_get_nwp_config(const sl_si91x_nwp_get_configuration_t * nwp_config,uint8_t * response)2655 sl_status_t sl_si91x_get_nwp_config(const sl_si91x_nwp_get_configuration_t *nwp_config, uint8_t *response)
2656 {
2657   sl_status_t status        = SL_STATUS_OK;
2658   sl_wifi_buffer_t *buffer  = NULL;
2659   sl_si91x_packet_t *packet = NULL;
2660 
2661   if (nwp_config->sub_command_type == GET_OPN_BOARD_CONFIG) {
2662     status = sl_si91x_driver_send_command(RSI_COMMON_REQ_GET_CONFIG,
2663                                           SI91X_COMMON_CMD,
2664                                           nwp_config,
2665                                           sizeof(sl_si91x_nwp_get_configuration_t),
2666                                           SL_SI91X_WAIT_FOR_RESPONSE(3000),
2667                                           NULL,
2668                                           &buffer);
2669     if (status != SL_STATUS_OK) {
2670       if (buffer != NULL)
2671         sl_si91x_host_free_buffer(buffer);
2672     }
2673     VERIFY_STATUS_AND_RETURN(status);
2674 
2675     packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
2676     memcpy(response, packet->data, packet->length);
2677     sl_si91x_host_free_buffer(buffer);
2678   } else {
2679     return SL_STATUS_NOT_SUPPORTED;
2680   }
2681   return status;
2682 }
2683 
sl_si91x_debug_log(sl_si91x_assertion_t * assertion)2684 sl_status_t sl_si91x_debug_log(sl_si91x_assertion_t *assertion)
2685 {
2686   sl_status_t status                = SL_STATUS_OK;
2687   sl_si91x_debug_log_t debug_config = { 0 };
2688 
2689   if (!device_initialized) {
2690     return SL_STATUS_NOT_INITIALIZED;
2691   }
2692 
2693   if ((debug_config.assertion_type > SL_SI91X_ASSERTION_TYPE_ALL)
2694       || (debug_config.assertion_level > SL_SI91X_ASSERTION_LEVEL_MAX)) {
2695     return SL_STATUS_INVALID_PARAMETER;
2696   }
2697 
2698   debug_config.assertion_type  = assertion->assert_type;
2699   debug_config.assertion_level = assertion->assert_level;
2700 
2701   status = sl_si91x_driver_send_command(RSI_COMMON_REQ_DEBUG_LOG,
2702                                         SI91X_COMMON_CMD,
2703                                         &debug_config,
2704                                         sizeof(sl_si91x_debug_log_t),
2705                                         SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
2706                                         NULL,
2707                                         NULL);
2708 
2709   VERIFY_STATUS_AND_RETURN(status);
2710   return status;
2711 }
2712