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