1 /***************************************************************************/ /**
2 * @file
3 * @brief
4 *******************************************************************************
5 * # License
6 * <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
7 *******************************************************************************
8 *
9 * SPDX-License-Identifier: Zlib
10 *
11 * The licensor of this software is Silicon Laboratories Inc.
12 *
13 * This software is provided 'as-is', without any express or implied
14 * warranty. In no event will the authors be held liable for any damages
15 * arising from the use of this software.
16 *
17 * Permission is granted to anyone to use this software for any purpose,
18 * including commercial applications, and to alter it and redistribute it
19 * freely, subject to the following restrictions:
20 *
21 * 1. The origin of this software must not be misrepresented; you must not
22 * claim that you wrote the original software. If you use this software
23 * in a product, an acknowledgment in the product documentation would be
24 * appreciated but is not required.
25 * 2. Altered source versions must be plainly marked as such, and must not be
26 * misrepresented as being the original software.
27 * 3. This notice may not be removed or altered from any source distribution.
28 *
29 ******************************************************************************/
30 #include "sl_si91x_host_interface.h"
31 #include "sl_si91x_types.h"
32 #include "sl_si91x_protocol_types.h"
33 #include "sl_si91x_driver.h"
34 #include "sl_wifi_constants.h"
35 #include "sl_wifi_types.h"
36 #include "sl_rsi_utility.h"
37 #include "cmsis_os2.h"
38 #include "cmsis_compiler.h"
39 #include "sl_si91x_core_utilities.h"
40 #include <string.h>
41 #ifdef SLI_SI91X_MCU_INTERFACE
42 #include "rsi_m4.h"
43 #endif
44 #ifdef SLI_SI91X_OFFLOAD_NETWORK_STACK
45 #include "sl_si91x_socket_types.h"
46 #include "sl_si91x_socket_utility.h"
47 #include "sl_net_si91x_integration_handler.h"
48 #else
49 // This macro defines a handler for dispatching network events.
50 // It is used to handle events related to the SI91x module
51 #define SL_NET_EVENT_DISPATCH_HANDLER(data, packet) \
52 { \
53 UNUSED_PARAMETER(data); \
54 UNUSED_PARAMETER(packet); \
55 }
56 #endif
57
58 #ifdef SLI_SI91X_ENABLE_BLE
59 #include "rsi_bt_common.h"
60 #endif
61
62 #define BUS_THREAD_EVENTS \
63 (SL_SI91X_ALL_TX_PENDING_COMMAND_EVENTS | SL_SI91X_SOCKET_DATA_TX_PENDING_EVENT | SL_SI91X_NCP_HOST_BUS_RX_EVENT \
64 | SL_SI91X_SOCKET_COMMAND_TX_PENDING_EVENT | SL_SI91X_GENERIC_DATA_TX_PENDING_EVENT \
65 | SL_SI91X_TA_BUFFER_FULL_CLEAR_EVENT | SL_SI91X_TERMINATE_BUS_THREAD_EVENT)
66
67 /**
68 * All flags used with async events
69 */
70 #define SL_SI91X_NOTIFICATION_FLAG(x) (1 << (x))
71
72 // Indicates asynchronous RX response received for WLAN command type
73 #define NCP_HOST_WLAN_NOTIFICATION_EVENT SL_SI91X_NOTIFICATION_FLAG(SI91X_WLAN_CMD)
74
75 // Indicates asynchronous RX response received for NETWORK command type
76 #define NCP_HOST_NETWORK_NOTIFICATION_EVENT SL_SI91X_NOTIFICATION_FLAG(SI91X_NETWORK_CMD)
77
78 // Indicates asynchronous RX response received for SOCKET command type
79 #define NCP_HOST_SOCKET_NOTIFICATION_EVENT SL_SI91X_NOTIFICATION_FLAG(SI91X_SOCKET_CMD)
80
81 // Indicates asynchronous RX response received for SOCKET data type
82 #define NCP_HOST_SOCKET_DATA_NOTIFICATION_EVENT SL_SI91X_NOTIFICATION_FLAG(SI91X_CMD_MAX)
83
84 /******************************************************
85 * Variable Definitions
86 ******************************************************/
87
88 extern osEventFlagsId_t si91x_async_events;
89 extern osEventFlagsId_t si91x_events;
90
91 volatile uint32_t tx_command_queues_status = 0;
92 volatile uint32_t tx_socket_command_queues_status = 0;
93 volatile uint32_t tx_socket_data_queues_status = 0;
94 volatile uint32_t tx_generic_socket_data_queues_status = 0;
95
96 volatile uint32_t tx_command_queues_command_in_flight_status = 0;
97 volatile uint8_t tx_socket_command_command_in_flight_queues_status = 0;
98
99 #if SLI_SI91X_MCU_INTERFACE
100 extern sl_si91x_buffer_queue_t sli_ahb_bus_rx_queue;
101 #endif
102
103 #if SL_NCP_UART_INTERFACE
104 extern sl_si91x_buffer_queue_t sli_uart_bus_rx_queue;
105 #endif
106
107 /******************************************************
108 * Function Declarations
109 ******************************************************/
110
111 void si91x_event_handler_thread(const void *args);
112
113 static void set_async_event(uint32_t event_mask);
114
115 // Declaration of a global flag to indicate if background mode is enabled
116 extern bool bg_enabled;
117
118 // Declaration of the SI91x event handler function
119 extern sl_wifi_event_handler_t si91x_event_handler;
120
121 extern sli_si91x_command_queue_t cmd_queues[SI91X_CMD_MAX];
122 extern sl_si91x_buffer_queue_t sli_tx_data_queue;
123
124 void si91x_event_handler_thread(const void *args);
125
126 extern sl_status_t sl_create_generic_rx_packet_from_params(sli_si91x_queue_packet_t **queue_packet,
127 sl_wifi_buffer_t **packet_buffer,
128 uint16_t packet_id,
129 uint8_t flags,
130 void *sdk_context,
131 uint16_t frame_status);
132
133 void sli_submit_rx_buffer(void);
134 void si91x_bus_thread(const void *args);
135 void sli_handle_dhcp_and_rejoin_failure(void *sdk_context, sl_wifi_buffer_t *temp_buffer, uint16_t frame_status);
136 void si91x_event_handler_thread(const void *args);
137 #ifdef SLI_SI91X_MCU_INTERFACE
138 // External declaration of a function to configure M4 DMA descriptors on reset
139 extern void sli_si91x_config_m4_dma_desc_on_reset(void);
140 void unmask_ta_interrupt(uint32_t interrupt_no);
141 #endif
142
143 static sl_status_t bus_write_data_frame(sl_si91x_buffer_queue_t *queue);
144
145 static sl_status_t bus_write_frame(sli_si91x_command_queue_t *queue,
146 sl_si91x_command_type_t command_type,
147 sl_wifi_buffer_type_t buffer_type,
148 bool *global_queue_block);
149
150 sl_status_t si91x_req_wakeup(void);
151 #ifdef SLI_SI91X_OFFLOAD_NETWORK_STACK
152 static sli_si91x_socket_t *get_socket_from_packet(sl_si91x_packet_t *socket_packet);
153 #endif
154 bool sli_si91x_is_bus_ready(bool global_queue_block);
155
156 /******************************************************
157 * Function Definitions
158 ******************************************************/
159
sl_create_generic_rx_packet_from_params(sli_si91x_queue_packet_t ** queue_packet,sl_wifi_buffer_t ** packet_buffer,uint16_t packet_id,uint8_t flags,void * sdk_context,uint16_t frame_status)160 sl_status_t sl_create_generic_rx_packet_from_params(sli_si91x_queue_packet_t **queue_packet,
161 sl_wifi_buffer_t **packet_buffer,
162 uint16_t packet_id,
163 uint8_t flags,
164 void *sdk_context,
165 uint16_t frame_status)
166 {
167 sli_si91x_queue_packet_t *packet = NULL;
168 sl_wifi_buffer_t *buffer = NULL;
169 sl_status_t status = SL_STATUS_OK;
170 uint16_t temp = 0;
171
172 status = sl_si91x_host_allocate_buffer(&buffer,
173 SL_WIFI_RX_FRAME_BUFFER,
174 sizeof(sli_si91x_queue_packet_t),
175 SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME);
176 if (status != SL_STATUS_OK) {
177 SL_DEBUG_LOG("\r\n HEAP EXHAUSTED DURING ALLOCATION \r\n");
178 BREAKPOINT();
179 }
180
181 *packet_buffer = buffer;
182
183 packet = sl_si91x_host_get_buffer_data(buffer, 0, &temp);
184 if (packet == NULL) {
185 return SL_STATUS_NOT_AVAILABLE;
186 }
187
188 // Fill dummy packet with details passed
189 buffer->id = packet_id;
190 packet->sdk_context = sdk_context;
191 packet->flags = flags;
192 packet->frame_status = frame_status;
193 packet->firmware_queue_id = RSI_WLAN_MGMT_Q;
194
195 *queue_packet = packet;
196 return SL_STATUS_OK;
197 }
198
sli_handle_dhcp_and_rejoin_failure(void * sdk_context,sl_wifi_buffer_t * response_buffer,uint16_t frame_status)199 void sli_handle_dhcp_and_rejoin_failure(void *sdk_context, sl_wifi_buffer_t *response_buffer, uint16_t frame_status)
200 {
201 sl_status_t status;
202 sl_wifi_buffer_t *temp_buffer = NULL;
203 sli_si91x_queue_packet_t *node;
204
205 // Retrieve the packet data from the response buffer
206 sl_si91x_packet_t *packet = sl_si91x_host_get_buffer_data(response_buffer, 0, NULL);
207
208 // Check for remote Wi-Fi client disconnection in concurrent mode
209 if (packet->command == RSI_WLAN_RSP_CLIENT_DISCONNECTED && (get_opermode() == SL_SI91X_CONCURRENT_MODE)) {
210 packet->desc[7] = SL_SI91X_WIFI_AP_VAP_ID; // Set the AP VAP ID
211 }
212
213 // Create a generic RX packet from the parameters
214 status = sl_create_generic_rx_packet_from_params(&node, &temp_buffer, 0, 0, NULL, frame_status);
215 if (status != SL_STATUS_OK) {
216 return; // Exit if packet creation fails
217 }
218
219 sl_wifi_buffer_t *dummy_packet_buffer = NULL;
220
221 // Allocate buffer for the dummy packet
222 status = sl_si91x_host_allocate_buffer(&dummy_packet_buffer,
223 SL_WIFI_RX_FRAME_BUFFER,
224 (sizeof(packet->desc) + packet->length),
225 SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME);
226 if (status != SL_STATUS_OK) {
227 sl_si91x_host_free_buffer(temp_buffer); // Free temp buffer on failure
228 return; // Exit if buffer allocation fails
229 }
230
231 // Get the dummy packet data from the allocated buffer
232 sl_si91x_packet_t *dummy_packet = sl_si91x_host_get_buffer_data(dummy_packet_buffer, 0, NULL);
233 node->host_packet = dummy_packet_buffer; // Link dummy packet to the node
234 node->sdk_context = sdk_context;
235
236 // Copy the original packet data to the dummy packet
237 memcpy(dummy_packet, packet, (sizeof(packet->desc) + packet->length));
238
239 // Enqueue the node packet and trigger the async event
240 sli_si91x_add_to_queue(&cmd_queues[SI91X_NETWORK_CMD].event_queue, temp_buffer);
241 set_async_event(NCP_HOST_NETWORK_NOTIFICATION_EVENT);
242 }
243
244 // Weak implementation of the function to process data frames received from the SI91x module
sl_si91x_host_process_data_frame(sl_wifi_interface_t interface,sl_wifi_buffer_t * buffer)245 __WEAK sl_status_t sl_si91x_host_process_data_frame(sl_wifi_interface_t interface, sl_wifi_buffer_t *buffer)
246 {
247 UNUSED_PARAMETER(interface);
248 UNUSED_PARAMETER(buffer);
249 return SL_STATUS_OK;
250 }
251
252 /// Thread which handles the notification events.
si91x_event_handler_thread(const void * args)253 void si91x_event_handler_thread(const void *args)
254 {
255 UNUSED_PARAMETER(args);
256 sl_wifi_event_t wifi_event = 0;
257 uint32_t event = 0;
258 sl_wifi_buffer_t *buffer = NULL;
259 sl_si91x_packet_t *packet = NULL;
260 sli_si91x_queue_packet_t *data = NULL;
261 uint16_t frame_status = 0;
262 const uint32_t event_mask = (NCP_HOST_WLAN_NOTIFICATION_EVENT | NCP_HOST_NETWORK_NOTIFICATION_EVENT
263 | NCP_HOST_SOCKET_NOTIFICATION_EVENT | NCP_HOST_SOCKET_DATA_NOTIFICATION_EVENT);
264
265 while (1) {
266 event = osEventFlagsWait(si91x_async_events, event_mask, osFlagsWaitAny, osWaitForever);
267 // event = si91x_host_wait_for_async_event(event_mask, osWaitForever);
268
269 if ((event & NCP_HOST_WLAN_NOTIFICATION_EVENT) != 0) {
270 // Process WLAN notification events
271 while (sl_si91x_host_queue_status(&cmd_queues[SI91X_WLAN_CMD].event_queue) != 0) {
272 if (sli_si91x_remove_from_queue(&cmd_queues[SI91X_WLAN_CMD].event_queue, &buffer) == SL_STATUS_OK) {
273 packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
274 frame_status = get_si91x_frame_status(packet);
275
276 // Call event handler
277 if (si91x_event_handler != NULL) {
278 wifi_event = convert_si91x_event_to_sl_wifi_event(packet->command, frame_status);
279
280 if (RSI_WLAN_RSP_SCAN_RESULTS == packet->command) {
281 sli_handle_wifi_beacon(packet);
282 }
283
284 if (wifi_event != SL_WIFI_INVALID_EVENT) {
285 si91x_event_handler(wifi_event, buffer);
286 }
287 } else {
288 // TODO: error handling
289 }
290 sl_si91x_host_free_buffer(buffer);
291 }
292 }
293 }
294
295 // If firmware sends network events even if the sl_net component is not include
296 // (probably firmware issue), Free the resources of the packet to avoid memory leak
297 if ((event & NCP_HOST_NETWORK_NOTIFICATION_EVENT) != 0) {
298 while (sl_si91x_host_queue_status(&cmd_queues[SI91X_NETWORK_CMD].event_queue) != 0) {
299 if (sli_si91x_remove_from_queue(&cmd_queues[SI91X_NETWORK_CMD].event_queue, &buffer) == SL_STATUS_OK) {
300 data = (sli_si91x_queue_packet_t *)sl_si91x_host_get_buffer_data(buffer, 0, NULL);
301 packet = (sl_si91x_packet_t *)sl_si91x_host_get_buffer_data(data->host_packet, 0, NULL);
302
303 SL_NET_EVENT_DISPATCH_HANDLER(data, packet);
304
305 // Free the resources associated with the packet.
306 sl_si91x_host_free_buffer(data->host_packet);
307 sl_si91x_host_free_buffer(buffer);
308 } else {
309 // TODO: error handling
310 }
311 }
312 }
313
314 // Process socket notification events
315 if ((event & NCP_HOST_SOCKET_NOTIFICATION_EVENT) != 0) {
316 while (0 != sl_si91x_host_queue_status(&cmd_queues[SI91X_SOCKET_CMD].event_queue)) {
317 if (sli_si91x_remove_from_queue(&cmd_queues[SI91X_SOCKET_CMD].event_queue, &buffer) == SL_STATUS_OK) {
318 data = (sli_si91x_queue_packet_t *)sl_si91x_host_get_buffer_data(buffer, 0, NULL);
319 packet = (sl_si91x_packet_t *)sl_si91x_host_get_buffer_data(data->host_packet, 0, NULL);
320
321 SL_NET_EVENT_DISPATCH_HANDLER(data, packet);
322
323 // Free the resources associated with the packet
324 sl_si91x_host_free_buffer(data->host_packet);
325 sl_si91x_host_free_buffer(buffer);
326 } else {
327 // TODO: error handling
328 }
329 }
330 }
331
332 #ifdef SLI_SI91X_OFFLOAD_NETWORK_STACK
333 // Process socket data events
334 if (event & NCP_HOST_SOCKET_DATA_NOTIFICATION_EVENT) {
335 for (int i = 0; i < NUMBER_OF_SOCKETS; ++i) {
336 if (sli_si91x_sockets[i] != NULL) {
337 if (sli_si91x_remove_from_queue(&sli_si91x_sockets[i]->rx_data_queue, &buffer) == SL_STATUS_OK) {
338 if (sli_si91x_sockets[i]->recv_data_callback != NULL) {
339 packet = (sl_si91x_packet_t *)sl_si91x_host_get_buffer_data(buffer, 0, NULL);
340 sl_si91x_socket_metadata_t *receive_data = (sl_si91x_socket_metadata_t *)packet->data;
341 sli_si91x_sockets[i]->recv_data_callback(i,
342 &packet->data[receive_data->offset],
343 receive_data->length,
344 receive_data);
345 }
346 sl_si91x_host_free_buffer(buffer);
347 }
348 }
349 }
350 }
351 #endif
352 }
353 }
354
355 // Thread which handles the TX and RX events.
si91x_bus_thread(const void * args)356 void si91x_bus_thread(const void *args)
357 {
358 UNUSED_PARAMETER(args);
359 sl_status_t status;
360 uint16_t temp;
361 sli_si91x_queue_packet_t *node = NULL;
362 sli_si91x_queue_packet_t *error_node = NULL;
363 sl_wifi_buffer_t *packet;
364 sl_wifi_buffer_t *error_packet = NULL;
365 sl_wifi_buffer_t *buffer;
366 uint8_t tx_queues_empty = 0;
367 uint32_t event = 0;
368 uint8_t *data;
369 uint16_t length;
370 uint8_t queue_id = 0;
371 uint16_t frame_type = 0;
372 uint16_t frame_status = 0;
373 bool global_queue_block = false;
374 uint16_t interrupt_status = 0;
375 sl_wifi_performance_profile_t current_power_profile_mode = { 0 };
376 uint32_t bus_wait_time = 0;
377
378 // Array to track the status of commands in flight
379 cmd_queues[SI91X_COMMON_CMD].sequential = true;
380 cmd_queues[SI91X_WLAN_CMD].sequential = true;
381 cmd_queues[SI91X_NETWORK_CMD].sequential = true;
382 cmd_queues[SI91X_BT_CMD].sequential = true;
383 cmd_queues[SI91X_SOCKET_CMD].sequential = true;
384
385 while (1) {
386 // 0 - give up bus thread
387 // 1 - need to process some tx commands/data packets
388 tx_queues_empty = (
389 #ifdef SLI_SI91X_OFFLOAD_NETWORK_STACK
390 (tx_socket_data_queues_status
391 || (tx_socket_command_queues_status & (~(tx_socket_command_command_in_flight_queues_status))))
392 ||
393 #endif
394 (tx_command_queues_status & (~(tx_command_queues_command_in_flight_status)))
395 || tx_generic_socket_data_queues_status);
396 // TODO: Add checking ALL socket command queues
397
398 // Set wait time:
399 // If there might be a buffer to receive, do that immediately,
400 // If the last interrupt_status check indicates buffer full, wait up to 10ms,
401 // If there is queue not empty or some event to be processed do that immediately,
402 // Otherwise there is nothing left to do and thus wait for an event
403 if (event & SL_SI91X_NCP_HOST_BUS_RX_EVENT) {
404 bus_wait_time = 0;
405 } else if (interrupt_status & RSI_BUFFER_FULL) {
406 bus_wait_time = 10;
407 } else if (tx_queues_empty == 0) {
408 bus_wait_time = osWaitForever;
409 } else {
410 bus_wait_time = 0;
411 }
412
413 event |= si91x_host_wait_for_bus_event(BUS_THREAD_EVENTS, bus_wait_time);
414
415 #ifndef SLI_SI91X_MCU_INTERFACE
416 // Wake device, if needed
417 if ((current_performance_profile != HIGH_PERFORMANCE)) {
418 while (si91x_req_wakeup() != SL_STATUS_OK) {
419 osDelay(1);
420 }
421 }
422
423 // Read the interrupt status
424 if (sl_si91x_bus_read_interrupt_status(&interrupt_status) != SL_STATUS_OK) {
425 continue;
426 }
427
428 // Check if there is no RX packet pending or the bus RX event is not set
429 if (!((interrupt_status & RSI_RX_PKT_PENDING) || (event & SL_SI91X_NCP_HOST_BUS_RX_EVENT))) {
430 if (current_performance_profile != HIGH_PERFORMANCE) {
431 // Clear the sleep indicator if the device is not in high-performance mode
432 sl_si91x_host_clear_sleep_indicator();
433 }
434 }
435 #endif
436
437 // Check if there is an RX packet pending or bus RX event is set
438 if ((event & SL_SI91X_NCP_HOST_BUS_RX_EVENT)
439 #ifndef SLI_SI91X_MCU_INTERFACE
440 && (interrupt_status & RSI_RX_PKT_PENDING)
441 #endif
442 && (sl_si91x_bus_read_frame(&buffer) == SL_STATUS_OK)) { // Allocation from RX buffer type!
443
444 if (current_performance_profile != HIGH_PERFORMANCE) {
445 sl_si91x_host_clear_sleep_indicator();
446 }
447
448 // Check if the rx queue is empty
449 #ifdef SLI_SI91X_MCU_INTERFACE
450 if (sli_si91x_buffer_queue_empty(&sli_ahb_bus_rx_queue)) {
451 #else
452 #ifdef SL_NCP_UART_INTERFACE
453 if (sli_si91x_buffer_queue_empty(&sli_uart_bus_rx_queue)) {
454 #else
455 {
456 #endif
457 #endif
458 event &= ~SL_SI91X_NCP_HOST_BUS_RX_EVENT; // Reset the event flag
459 }
460
461 data = (uint8_t *)sl_si91x_host_get_buffer_data(buffer, 0, &length);
462 // Process the frame
463 queue_id = ((data[1] & 0xF0) >> 4); // Extract the queue ID
464 frame_type = (uint16_t)(data[2] + (data[3] << 8)); // Extract the frame type
465 frame_status = (uint16_t)(data[12] + (data[13] << 8)); // Extract the frame status
466 #ifdef SLI_SI91X_MCU_INTERFACE
467 if ((frame_type == RSI_COMMON_RSP_TA_M4_COMMANDS) || (frame_type == RSI_WLAN_REQ_SET_CERTIFICATE)) {
468 // clear flag
469 sli_si91x_update_flash_command_status(false);
470 }
471 #endif
472
473 const sl_si91x_packet_t *response = (const sl_si91x_packet_t *)data;
474 SL_DEBUG_LOG("><<<< Rx -> queueId : %u, frameId : 0x%x, frameStatus: 0x%x, length : %u\n",
475 queue_id,
476 frame_type,
477 frame_status,
478 (response->length & (~(0xF000))));
479
480 switch (queue_id) {
481 case RSI_WLAN_MGMT_Q: {
482 // Erase queue ID as it overlays with the length field which is only 24-bit
483 data[1] &= 0xF;
484 switch (frame_type) {
485 // Handle different frame types within the WLAN management queue
486 case RSI_COMMON_RSP_OPERMODE:
487 case RSI_COMMON_RSP_SOFT_RESET:
488 case RSI_COMMON_RSP_PWRMODE: {
489 if (frame_type == cmd_queues[SI91X_COMMON_CMD].frame_type) {
490 if ((RSI_COMMON_RSP_PWRMODE == frame_type) && (frame_status == SL_STATUS_OK)) {
491 get_wifi_current_performance_profile(¤t_power_profile_mode);
492 current_performance_profile = current_power_profile_mode.profile;
493 }
494 if (current_performance_profile != HIGH_PERFORMANCE) {
495 // Clear the sleep indicator if the device is not in high-performance mode
496 sl_si91x_host_clear_sleep_indicator();
497 }
498 global_queue_block = false;
499 }
500 }
501 // intentional fallthrough
502 __attribute__((fallthrough));
503 case RSI_COMMON_RSP_GET_EFUSE_DATA:
504 case RSI_COMMON_RSP_GET_RAM_DUMP:
505 case RSI_COMMON_RSP_ANTENNA_SELECT:
506 case RSI_COMMON_RSP_ENCRYPT_CRYPTO:
507 #ifdef SLI_PUF_ENABLE
508 case RSI_COMMON_RSP_PUF_ENROLL:
509 case RSI_COMMON_RSP_PUF_DIS_ENROLL:
510 case RSI_COMMON_RSP_PUF_START:
511 case RSI_COMMON_RSP_PUF_SET_KEY:
512 case RSI_COMMON_RSP_PUF_DIS_SET_KEY:
513 case RSI_COMMON_RSP_PUF_GET_KEY:
514 case RSI_COMMON_RSP_PUF_DIS_GET_KEY:
515 case RSI_COMMON_RSP_PUF_LOAD_KEY:
516 case RSI_COMMON_RSP_AES_ENCRYPT:
517 case RSI_COMMON_RSP_AES_DECRYPT:
518 case RSI_COMMON_RSP_AES_MAC:
519 case RSI_COMMON_RSP_PUF_INTR_KEY:
520 #endif
521 case RSI_COMMON_RSP_SET_RTC_TIMER:
522 case RSI_COMMON_RSP_GET_RTC_TIMER:
523 case RSI_COMMON_RSP_TA_M4_COMMANDS:
524 case RSI_COMMON_RSP_SET_CONFIG:
525 case RSI_COMMON_RSP_GET_CONFIG:
526 case RSI_COMMON_RSP_DEBUG_LOG:
527 case RSI_COMMON_RSP_FEATURE_FRAME: {
528 ++cmd_queues[SI91X_COMMON_CMD].rx_counter; // Increment the received counter for common commands
529
530 // Check if this command is expected to have a response status
531 if (((cmd_queues[SI91X_COMMON_CMD].flags & SI91X_PACKET_RESPONSE_STATUS) == SI91X_PACKET_RESPONSE_STATUS)
532 && (cmd_queues[SI91X_COMMON_CMD].frame_type == frame_type)) {
533 // Allocate a packet to store the response
534 status = sl_si91x_host_allocate_buffer(&packet,
535 SL_WIFI_RX_FRAME_BUFFER,
536 sizeof(sli_si91x_queue_packet_t),
537 1000);
538 if (status != SL_STATUS_OK) {
539 SL_DEBUG_LOG("\r\n HEAP EXHAUSTED DURING ALLOCATION \r\n");
540 BREAKPOINT();
541 }
542 node = sl_si91x_host_get_buffer_data(packet, 0, &temp);
543
544 // Depending on the configuration, attach the original buffer or not
545 if (SI91X_PACKET_RESPONSE_PACKET
546 == (cmd_queues[SI91X_COMMON_CMD].flags & SI91X_PACKET_RESPONSE_PACKET)) {
547 node->host_packet = buffer;
548 } else {
549 node->host_packet = NULL;
550 sl_si91x_host_free_buffer(buffer);
551 }
552
553 // Populate packet metadata
554 node->frame_status = frame_status;
555 node->firmware_queue_id = RSI_WLAN_MGMT_Q;
556 node->command_type = SI91X_COMMON_CMD;
557 node->sdk_context = cmd_queues[SI91X_COMMON_CMD].sdk_context;
558 node->flags = cmd_queues[SI91X_COMMON_CMD].flags;
559 // node->packet_id = cmd_queues[SI91X_COMMON_CMD].packet_id;
560 buffer->id = cmd_queues[SI91X_COMMON_CMD].packet_id;
561 packet->id = cmd_queues[SI91X_COMMON_CMD].packet_id;
562
563 if (sl_si91x_host_elapsed_time(cmd_queues[SI91X_COMMON_CMD].command_tickcount)
564 <= (cmd_queues[SI91X_COMMON_CMD].command_timeout)) {
565 // Add the response packet to the common response queue
566 sli_si91x_append_to_buffer_queue(&cmd_queues[SI91X_COMMON_CMD].rx_queue, packet);
567 sli_si91x_set_event(NCP_HOST_COMMON_RESPONSE_EVENT);
568 } else {
569 // no user thread is waiting for the response so flush the packet
570 sl_si91x_host_free_buffer(packet);
571 if ((cmd_queues[SI91X_COMMON_CMD].flags & SI91X_PACKET_RESPONSE_PACKET)
572 == SI91X_PACKET_RESPONSE_PACKET) {
573 sl_si91x_host_free_buffer(buffer);
574 }
575 }
576 cmd_queues[SI91X_COMMON_CMD].command_tickcount = 0;
577 cmd_queues[SI91X_COMMON_CMD].command_timeout = 0;
578 } else {
579 sl_si91x_host_free_buffer(buffer);
580 }
581
582 // Marking a received frame as not in flight when it matches the expected type.
583 if (frame_type == cmd_queues[SI91X_COMMON_CMD].frame_type) {
584 cmd_queues[SI91X_COMMON_CMD].command_in_flight = false;
585 cmd_queues[SI91X_COMMON_CMD].frame_type = 0;
586 }
587 break;
588 }
589 case RSI_WLAN_RSP_BAND:
590 case RSI_WLAN_RSP_INIT:
591 case RSI_WLAN_RSP_RADIO:
592 case RSI_WLAN_RSP_EAP_CONFIG:
593 case RSI_WLAN_RSP_SET_CERTIFICATE:
594 case RSI_WLAN_RSP_HOST_PSK:
595 case RSI_WLAN_RSP_JOIN:
596 case RSI_WLAN_RSP_SCAN:
597 case RSI_WLAN_RSP_SCAN_RESULTS:
598 case RSI_WLAN_RSP_FW_VERSION:
599 case RSI_WLAN_RSP_FULL_FW_VERSION:
600 case RSI_WLAN_RSP_FWUP:
601 case RSI_WLAN_RSP_DISCONNECT:
602 case RSI_WLAN_RSP_AP_STOP:
603 case RSI_WLAN_RSP_RSSI:
604 case RSI_WLAN_RSP_TSF:
605 case RSI_WLAN_RSP_AP_CONFIGURATION:
606 case RSI_WLAN_RSP_WPS_METHOD:
607 case RSI_WLAN_RSP_QUERY_NETWORK_PARAMS:
608 case RSI_WLAN_RSP_SET_MAC_ADDRESS:
609 case RSI_WLAN_RSP_SET_REGION:
610 case RSI_WLAN_RSP_SET_REGION_AP:
611 case RSI_WLAN_RSP_MAC_ADDRESS:
612 case RSI_WLAN_RSP_EXT_STATS:
613 case RSI_WLAN_RSP_GET_STATS:
614 case RSI_WLAN_RSP_RX_STATS:
615 case RSI_WLAN_RSP_MODULE_STATE:
616 case RSI_WLAN_RSP_QUERY_GO_PARAMS:
617 case RSI_WLAN_RSP_ROAM_PARAMS:
618 case RSI_WLAN_RSP_HTTP_OTAF:
619 case RSI_WLAN_RSP_CLIENT_CONNECTED:
620 case RSI_WLAN_RSP_CLIENT_DISCONNECTED:
621 case RSI_WLAN_RSP_CALIB_WRITE:
622 case RSI_WLAN_RSP_GET_DPD_DATA:
623 case RSI_WLAN_RSP_CALIB_READ:
624 case RSI_WLAN_RSP_FREQ_OFFSET:
625 case RSI_WLAN_RSP_EVM_OFFSET:
626 case RSI_WLAN_RSP_EVM_WRITE:
627 case RSI_WLAN_RSP_EFUSE_READ:
628 case RSI_WLAN_RSP_FILTER_BCAST_PACKETS:
629 case RSI_WLAN_RSP_TWT_PARAMS:
630 case RSI_WLAN_RSP_TWT_ASYNC:
631 case RSI_WLAN_RSP_TWT_AUTO_CONFIG:
632 case RSI_WLAN_RSP_11AX_PARAMS:
633 case SL_WIFI_RSP_RESCHEDULE_TWT:
634 case RSI_WLAN_RSP_REJOIN_PARAMS:
635 case RSI_WLAN_RSP_GAIN_TABLE:
636 case RSI_WLAN_RSP_TX_TEST_MODE:
637 case RSI_WLAN_RSP_TIMEOUT:
638 case RSI_WLAN_RSP_BEACON_STOP:
639 case RSI_WLAN_RSP_DYNAMIC_POOL:
640 case RSI_WLAN_RSP_TRANSCEIVER_SET_CHANNEL:
641 case RSI_WLAN_RSP_TRANSCEIVER_CONFIG_PARAMS:
642 case RSI_WLAN_RSP_TRANSCEIVER_PEER_LIST_UPDATE:
643 case RSI_WLAN_RSP_TRANSCEIVER_SET_MCAST_FILTER:
644 case RSI_WLAN_RSP_TRANSCEIVER_FLUSH_DATA_Q:
645 case RSI_WLAN_RSP_TRANSCEIVER_TX_DATA_STATUS:
646 case RSI_WLAN_RSP_HT_CAPABILITIES:
647 case RSI_WLAN_RSP_SET_MULTICAST_FILTER: {
648 ++cmd_queues[SI91X_WLAN_CMD].rx_counter;
649
650 // Marking a received frame as not in flight when it matches the expected type
651 if (frame_type == cmd_queues[SI91X_WLAN_CMD].frame_type) {
652 cmd_queues[SI91X_WLAN_CMD].command_in_flight = false;
653 }
654
655 // Check if the frame type indicates a failed join operation or a disconnect
656 if (((RSI_WLAN_RSP_JOIN == frame_type) && (frame_status != SL_STATUS_OK))
657 || (RSI_WLAN_RSP_DISCONNECT == frame_type) || (RSI_WLAN_RSP_CLIENT_DISCONNECTED == frame_type)
658 || (RSI_WLAN_RSP_AP_STOP == frame_type)) {
659
660 // create dummy packets for respective queues to be cleared
661 sli_handle_dhcp_and_rejoin_failure(cmd_queues[SI91X_WLAN_CMD].sdk_context, buffer, frame_status);
662 }
663 if (((RSI_WLAN_RSP_JOIN == frame_type) && (frame_status != SL_STATUS_OK))
664 || (RSI_WLAN_RSP_DISCONNECT == frame_type)) {
665 // Reset current performance profile and set it to high performance
666 reset_coex_current_performance_profile();
667 current_performance_profile = HIGH_PERFORMANCE;
668 }
669
670 // check if the frame type is valid
671 if (((cmd_queues[SI91X_WLAN_CMD].flags & SI91X_PACKET_RESPONSE_STATUS) == SI91X_PACKET_RESPONSE_STATUS)
672 && (cmd_queues[SI91X_WLAN_CMD].frame_type == frame_type)) {
673
674 // Allocate a buffer for the response packet
675 status = sl_si91x_host_allocate_buffer(&packet,
676 SL_WIFI_RX_FRAME_BUFFER,
677 sizeof(sli_si91x_queue_packet_t),
678 1000);
679 if (status != SL_STATUS_OK) {
680 SL_DEBUG_LOG("\r\n HEAP EXHAUSTED DURING ALLOCATION \r\n");
681 BREAKPOINT();
682 }
683
684 node = sl_si91x_host_get_buffer_data(packet, 0, &temp);
685
686 // Check if the packet response mode is set, and associate the host packet accordingly
687 if (SI91X_PACKET_RESPONSE_PACKET == (cmd_queues[SI91X_WLAN_CMD].flags & SI91X_PACKET_RESPONSE_PACKET)) {
688 node->host_packet = buffer;
689 } else {
690 node->host_packet = NULL;
691 sl_si91x_host_free_buffer(buffer);
692 }
693
694 // Populate the response packet information
695 node->frame_status = frame_status;
696 node->firmware_queue_id = RSI_WLAN_MGMT_Q;
697 node->command_type = SI91X_WLAN_CMD;
698 node->sdk_context = cmd_queues[SI91X_WLAN_CMD].sdk_context;
699 node->flags = cmd_queues[SI91X_WLAN_CMD].flags;
700 // node->packet_id = cmd_queues[SI91X_WLAN_CMD].packet_id;
701 packet->id = cmd_queues[SI91X_WLAN_CMD].packet_id;
702 buffer->id = cmd_queues[SI91X_WLAN_CMD].packet_id;
703
704 if (sl_si91x_host_elapsed_time(cmd_queues[SI91X_WLAN_CMD].command_tickcount)
705 <= (cmd_queues[SI91X_WLAN_CMD].command_timeout)) {
706 // Add the response packet to the WLAN response queue and set the WLAN response event
707 sli_si91x_add_to_queue(&cmd_queues[SI91X_WLAN_CMD].rx_queue, packet);
708 sli_si91x_set_event(NCP_HOST_WLAN_RESPONSE_EVENT);
709 } else {
710 // no user thread is waiting for the response so flush the packet
711 sl_si91x_host_free_buffer(packet);
712 if ((cmd_queues[SI91X_WLAN_CMD].flags & SI91X_PACKET_RESPONSE_PACKET)
713 == SI91X_PACKET_RESPONSE_PACKET) {
714 sl_si91x_host_free_buffer(buffer);
715 }
716 }
717 cmd_queues[SI91X_WLAN_CMD].command_tickcount = 0;
718 cmd_queues[SI91X_WLAN_CMD].command_timeout = 0;
719 } else {
720 // The received frame does not match the expected response status and frame type,
721 // so add it to the WLAN event queue and set the WLAN notification event
722 sli_si91x_add_to_queue(&cmd_queues[SI91X_WLAN_CMD].event_queue, buffer);
723 set_async_event(NCP_HOST_WLAN_NOTIFICATION_EVENT);
724 }
725
726 // Resetting the frame_type in cmd_queues when it matches the expected frame_type
727 if (frame_type == cmd_queues[SI91X_WLAN_CMD].frame_type) {
728 cmd_queues[SI91X_WLAN_CMD].frame_type = 0;
729 }
730
731 break;
732 }
733 // Handle WLAN response frame type for background scan
734 case RSI_WLAN_RSP_BG_SCAN: {
735 ++cmd_queues[SI91X_WLAN_CMD].rx_counter;
736
737 // Check if the received frame matches the expected response status and frame type
738 if (((cmd_queues[SI91X_WLAN_CMD].flags & SI91X_PACKET_RESPONSE_STATUS) == SI91X_PACKET_RESPONSE_STATUS)
739 && (cmd_queues[SI91X_WLAN_CMD].frame_type == frame_type)) {
740 // Allocate a buffer for the response packet
741 status = sl_si91x_host_allocate_buffer(&packet,
742 SL_WIFI_RX_FRAME_BUFFER,
743 sizeof(sli_si91x_queue_packet_t),
744 1000);
745 if (status != SL_STATUS_OK) {
746 SL_DEBUG_LOG("\r\n HEAP EXHAUSTED DURING ALLOCATION \r\n");
747 BREAKPOINT();
748 }
749 node = sl_si91x_host_get_buffer_data(packet, 0, &temp);
750
751 node->frame_status = frame_status;
752 node->firmware_queue_id = RSI_WLAN_MGMT_Q;
753 node->command_type = SI91X_WLAN_CMD;
754 node->sdk_context = cmd_queues[SI91X_WLAN_CMD].sdk_context;
755 node->flags = cmd_queues[SI91X_WLAN_CMD].flags;
756 // node->packet_id = cmd_queues[SI91X_WLAN_CMD].packet_id;
757 buffer->id = cmd_queues[SI91X_WLAN_CMD].packet_id;
758 packet->id = cmd_queues[SI91X_WLAN_CMD].packet_id;
759 node->host_packet = NULL;
760
761 if (sl_si91x_host_elapsed_time(cmd_queues[SI91X_WLAN_CMD].command_tickcount)
762 <= (cmd_queues[SI91X_WLAN_CMD].command_timeout)) {
763 // Add the response packet to the WLAN response queue and set the WLAN response event
764 sli_si91x_add_to_queue(&cmd_queues[SI91X_WLAN_CMD].rx_queue, packet);
765 sli_si91x_set_event(NCP_HOST_WLAN_RESPONSE_EVENT);
766 } else {
767 // no user thread is waiting for the response so flush the packet and buffer
768 sl_si91x_host_free_buffer(packet);
769 }
770 cmd_queues[SI91X_WLAN_CMD].command_tickcount = 0;
771 cmd_queues[SI91X_WLAN_CMD].command_timeout = 0;
772 sl_si91x_host_free_buffer(buffer);
773 } else {
774 // If frame status is OK, set bg_enabled flag
775 if (frame_status == SL_STATUS_OK) {
776 bg_enabled = true;
777 }
778 // Add the received frame to the WLAN event queue and set the WLAN notification event
779 sli_si91x_add_to_queue(&cmd_queues[SI91X_WLAN_CMD].event_queue, buffer);
780 set_async_event(NCP_HOST_WLAN_NOTIFICATION_EVENT);
781 }
782 // Marking a received frame as not in flight when it matches the expected type
783 if (frame_type == cmd_queues[SI91X_WLAN_CMD].frame_type) {
784 cmd_queues[SI91X_WLAN_CMD].command_in_flight = false;
785 cmd_queues[SI91X_WLAN_CMD].frame_type = 0;
786 }
787 break;
788 }
789 case RSI_WLAN_RSP_CONFIG: {
790 ++cmd_queues[SI91X_WLAN_CMD].rx_counter;
791
792 // Check if the received frame matches the expected response status and frame type
793 if (((cmd_queues[SI91X_WLAN_CMD].flags & SI91X_PACKET_RESPONSE_STATUS) == SI91X_PACKET_RESPONSE_STATUS)
794 && (cmd_queues[SI91X_WLAN_CMD].frame_type == frame_type)) {
795 // Allocate a buffer for the response packet
796 status = sl_si91x_host_allocate_buffer(&packet,
797 SL_WIFI_RX_FRAME_BUFFER,
798 sizeof(sli_si91x_queue_packet_t),
799 1000);
800 if (status != SL_STATUS_OK) {
801 SL_DEBUG_LOG("\r\n HEAP EXHAUSTED DURING ALLOCATION \r\n");
802 BREAKPOINT();
803 }
804 node = sl_si91x_host_get_buffer_data(packet, 0, &temp);
805
806 // Check if the frame status indicates an invalid configuration type
807 if ((SL_STATUS_SI91X_INVALID_CONFIG_TYPE & 0xFF) == frame_status) {
808 node->frame_status = 0;
809 } else {
810 node->frame_status = frame_status;
811 }
812 node->firmware_queue_id = RSI_WLAN_MGMT_Q;
813 node->command_type = SI91X_WLAN_CMD;
814 node->sdk_context = cmd_queues[SI91X_WLAN_CMD].sdk_context;
815 node->flags = cmd_queues[SI91X_WLAN_CMD].flags;
816 // node->packet_id = cmd_queues[SI91X_WLAN_CMD].packet_id;
817 buffer->id = cmd_queues[SI91X_WLAN_CMD].packet_id;
818 packet->id = cmd_queues[SI91X_WLAN_CMD].packet_id;
819 node->host_packet = NULL;
820
821 if (sl_si91x_host_elapsed_time(cmd_queues[SI91X_WLAN_CMD].command_tickcount)
822 <= (cmd_queues[SI91X_WLAN_CMD].command_timeout)) {
823 // Add the response packet to response queue and set the WLAN response event
824 sli_si91x_add_to_queue(&cmd_queues[SI91X_WLAN_CMD].rx_queue, packet);
825 sli_si91x_set_event(NCP_HOST_WLAN_RESPONSE_EVENT);
826 } else {
827 // no user thread is waiting for the response so flush the packet
828 sl_si91x_host_free_buffer(packet);
829 }
830 cmd_queues[SI91X_WLAN_CMD].command_tickcount = 0;
831 cmd_queues[SI91X_WLAN_CMD].command_timeout = 0;
832 }
833
834 // check if the frame type is valid.
835 if (frame_type == cmd_queues[SI91X_WLAN_CMD].frame_type) {
836 cmd_queues[SI91X_WLAN_CMD].command_in_flight = false;
837 cmd_queues[SI91X_WLAN_CMD].frame_type = 0;
838 }
839
840 sl_si91x_host_free_buffer(buffer);
841 break;
842 }
843 case RSI_COMMON_RSP_ULP_NO_RAM_RETENTION: {
844 //This frame will come, when the M4 is waken in without ram retention. This frame is equivalent to RSI_COMMON_RSP_CARDREADY
845 sl_si91x_host_clear_sleep_indicator();
846 }
847 // intentional fallthrough
848 __attribute__((fallthrough));
849 case RSI_COMMON_RSP_CARDREADY: {
850 ++cmd_queues[SI91X_COMMON_CMD].rx_counter;
851
852 // Check if the frame type is valid
853 if (frame_type == cmd_queues[SI91X_COMMON_CMD].frame_type) {
854 // Mark the common command as not in flight
855 cmd_queues[SI91X_COMMON_CMD].command_in_flight = false;
856 cmd_queues[SI91X_COMMON_CMD].frame_type = 0;
857 cmd_queues[SI91X_COMMON_CMD].command_tickcount = 0;
858 cmd_queues[SI91X_COMMON_CMD].command_timeout = 0;
859 }
860
861 sl_si91x_host_free_buffer(buffer);
862 sli_si91x_set_event(NCP_HOST_COMMON_RESPONSE_EVENT);
863 break;
864 }
865 case RSI_WLAN_RSP_IPCONFV4:
866 case RSI_WLAN_RSP_IPCONFV6:
867 case RSI_WLAN_RSP_IPV4_CHANGE:
868 case RSI_WLAN_RSP_OTA_FWUP:
869 case RSI_WLAN_RSP_DNS_QUERY:
870 case RSI_WLAN_RSP_DNS_SERVER_ADD:
871 case RSI_WLAN_RSP_SET_SNI_EMBEDDED:
872 case RSI_WLAN_RSP_MULTICAST:
873 case RSI_WLAN_RSP_PING_PACKET:
874 case RSI_WLAN_RSP_SNTP_CLIENT:
875 case RSI_WLAN_RSP_EMB_MQTT_CLIENT:
876 case RSI_WLAN_RSP_EMB_MQTT_PUBLISH_PKT:
877 case RSI_WLAN_RSP_MQTT_REMOTE_TERMINATE:
878 case RSI_WLAN_RSP_MDNSD: {
879 // Increment the received frame counter for network commands
880 ++cmd_queues[SI91X_NETWORK_CMD].rx_counter;
881
882 // Allocate a buffer for the response packet
883 status =
884 sl_si91x_host_allocate_buffer(&packet, SL_WIFI_RX_FRAME_BUFFER, sizeof(sli_si91x_queue_packet_t), 1000);
885 if (status != SL_STATUS_OK) {
886 SL_DEBUG_LOG("\r\n HEAP EXHAUSTED DURING ALLOCATION \r\n");
887 BREAKPOINT();
888 }
889 node = sl_si91x_host_get_buffer_data(packet, 0, &temp);
890
891 // Set frame status, queue ID, and command type for the network response
892 node->frame_status = frame_status;
893 node->firmware_queue_id = RSI_WLAN_MGMT_Q;
894 node->command_type = SI91X_NETWORK_CMD;
895
896 // Check if the frame type is valid
897 if ((frame_type == cmd_queues[SI91X_NETWORK_CMD].frame_type)
898 || (frame_type == RSI_WLAN_RSP_IPCONFV6
899 && cmd_queues[SI91X_NETWORK_CMD].frame_type == RSI_WLAN_REQ_IPCONFV6)) {
900 node->sdk_context = cmd_queues[SI91X_NETWORK_CMD].sdk_context;
901 node->flags = cmd_queues[SI91X_NETWORK_CMD].flags;
902 // node->packet_id = cmd_queues[SI91X_NETWORK_CMD].packet_id;
903 packet->id = cmd_queues[SI91X_NETWORK_CMD].packet_id;
904 buffer->id = cmd_queues[SI91X_NETWORK_CMD].packet_id;
905 } else {
906 node->sdk_context = NULL;
907 node->flags = 0;
908 // node->packet_id = 0;
909 packet->id = 0;
910 buffer->id = 0;
911 }
912 // Set the host packet to the received buffer
913 node->host_packet = buffer;
914
915 if (((frame_type == RSI_WLAN_RSP_MQTT_REMOTE_TERMINATE)
916 || (frame_type == RSI_WLAN_RSP_EMB_MQTT_CLIENT
917 && frame_status == (SL_STATUS_SI91X_MQTT_KEEP_ALIVE_TERMINATE_ERROR & ~BIT(16))))
918 && (cmd_queues[SI91X_NETWORK_CMD].frame_type == RSI_WLAN_RSP_EMB_MQTT_CLIENT)) {
919 cmd_queues[SI91X_NETWORK_CMD].command_in_flight = false;
920 cmd_queues[SI91X_NETWORK_CMD].frame_type = 0;
921
922 if (cmd_queues[SI91X_NETWORK_CMD].flags == 0) {
923 sli_si91x_add_to_queue(&cmd_queues[SI91X_NETWORK_CMD].event_queue, packet);
924 set_async_event(NCP_HOST_NETWORK_NOTIFICATION_EVENT);
925 break;
926 }
927
928 // if command present in cmd_queues, an error RX packet is enqueued to network queue and command in flight is set to false.
929
930 // Allocate a buffer for the error packet
931 status = sl_si91x_host_allocate_buffer(&error_packet,
932 SL_WIFI_RX_FRAME_BUFFER,
933 sizeof(sli_si91x_queue_packet_t),
934 1000);
935 if (status != SL_STATUS_OK) {
936 SL_DEBUG_LOG("\r\n HEAP EXHAUSTED DURING ALLOCATION \r\n");
937 BREAKPOINT();
938 }
939 error_node = sl_si91x_host_get_buffer_data(error_packet, 0, NULL);
940 error_node->frame_status = (SL_STATUS_SI91X_MQTT_REMOTE_TERMINATE_ERROR
941 & 0xFFFF); // error given by firmware for remote terminate
942 error_node->host_packet = NULL;
943 error_node->flags = cmd_queues[SI91X_NETWORK_CMD].flags;
944 // error_node->packet_id = cmd_queues[SI91X_NETWORK_CMD].packet_id;
945 error_packet->id = cmd_queues[SI91X_NETWORK_CMD].packet_id;
946
947 sli_si91x_add_to_queue(&cmd_queues[SI91X_NETWORK_CMD].rx_queue, error_packet);
948 sli_si91x_set_event(NCP_HOST_NETWORK_RESPONSE_EVENT);
949 cmd_queues[SI91X_NETWORK_CMD].command_tickcount = 0;
950 cmd_queues[SI91X_NETWORK_CMD].command_timeout = 0;
951 break;
952 }
953
954 // Check if it's a response packet, and handle accordingly
955 if (((cmd_queues[SI91X_NETWORK_CMD].flags & SI91X_PACKET_RESPONSE_STATUS) == SI91X_PACKET_RESPONSE_STATUS)
956 && ((cmd_queues[SI91X_NETWORK_CMD].frame_type == frame_type)
957 || (cmd_queues[SI91X_NETWORK_CMD].frame_type == RSI_WLAN_REQ_IPCONFV6
958 && frame_type == RSI_WLAN_RSP_IPCONFV6))) {
959
960 // Check if the response packet should be free or not
961 if (SI91X_PACKET_RESPONSE_PACKET
962 != (cmd_queues[SI91X_NETWORK_CMD].flags & SI91X_PACKET_RESPONSE_PACKET)) {
963 node->host_packet = NULL;
964 sl_si91x_host_free_buffer(buffer);
965 }
966 if (sl_si91x_host_elapsed_time(cmd_queues[SI91X_NETWORK_CMD].command_tickcount)
967 <= (cmd_queues[SI91X_NETWORK_CMD].command_timeout)) {
968 // Add the response packet to response queue and set the network response event
969 sli_si91x_add_to_queue(&cmd_queues[SI91X_NETWORK_CMD].rx_queue, packet);
970 sli_si91x_set_event(NCP_HOST_NETWORK_RESPONSE_EVENT);
971 } else {
972 // no user thread is waiting for the response so flush the packet
973 sl_si91x_host_free_buffer(packet);
974 if ((cmd_queues[SI91X_NETWORK_CMD].flags & SI91X_PACKET_RESPONSE_PACKET)
975 == SI91X_PACKET_RESPONSE_PACKET) {
976 sl_si91x_host_free_buffer(buffer);
977 }
978 }
979 cmd_queues[SI91X_NETWORK_CMD].command_tickcount = 0;
980 cmd_queues[SI91X_NETWORK_CMD].command_timeout = 0;
981 } else {
982 // Add the packet to event queue and set the async network event
983 sli_si91x_add_to_queue(&cmd_queues[SI91X_NETWORK_CMD].event_queue, packet);
984 set_async_event(NCP_HOST_NETWORK_NOTIFICATION_EVENT);
985 }
986
987 // Check If the frame type is valid.
988 if ((frame_type == cmd_queues[SI91X_NETWORK_CMD].frame_type)
989 || (frame_type == RSI_WLAN_RSP_IPCONFV6
990 && cmd_queues[SI91X_NETWORK_CMD].frame_type == RSI_WLAN_REQ_IPCONFV6)) {
991 cmd_queues[SI91X_NETWORK_CMD].command_in_flight = false;
992 cmd_queues[SI91X_NETWORK_CMD].frame_type = 0;
993 }
994
995 // Check if the frame type indicates a failed join operation or a disconnect
996 if (((RSI_WLAN_RSP_IPCONFV4 == frame_type) && (frame_status != SL_STATUS_OK))
997 || (RSI_WLAN_RSP_IPV4_CHANGE == frame_type)) {
998 // Reset current performance profile and set it to high performance
999 reset_coex_current_performance_profile();
1000 current_performance_profile = HIGH_PERFORMANCE;
1001 // check for command in flight and create dummy packets for respective queues to be cleared
1002 sli_handle_dhcp_and_rejoin_failure(cmd_queues[SI91X_NETWORK_CMD].sdk_context, buffer, frame_status);
1003 sli_si91x_add_to_queue(&cmd_queues[SI91X_NETWORK_CMD].event_queue, packet);
1004 set_async_event(NCP_HOST_NETWORK_NOTIFICATION_EVENT);
1005 }
1006 break;
1007 }
1008 #ifdef SLI_SI91X_OFFLOAD_NETWORK_STACK
1009 case RSI_WLAN_RSP_CONN_ESTABLISH:
1010 frame_type = RSI_WLAN_RSP_SOCKET_ACCEPT;
1011 // fall-through
1012 case RSI_WLAN_RSP_SOCKET_CONFIG:
1013 case RSI_WLAN_RSP_SOCKET_CREATE:
1014 case RSI_WLAN_RSP_SOCKET_CLOSE:
1015 case RSI_WLAN_RSP_SELECT_REQUEST:
1016 case RSI_WLAN_RSP_SOCKET_READ_DATA: // Socket read data response only is expected incase of failure
1017 case RSI_WLAN_RSP_SOCKET_ACCEPT:
1018 case RSI_WLAN_RSP_REMOTE_TERMINATE: {
1019 // Find relevant socket
1020 sl_si91x_packet_t *socket_packet = (sl_si91x_packet_t *)data;
1021 sli_si91x_socket_t *socket = get_socket_from_packet(socket_packet);
1022 sli_si91x_command_queue_t *socket_command_queue;
1023
1024 if ((socket == NULL) || (frame_type == RSI_WLAN_RSP_SELECT_REQUEST)
1025 || (frame_type == RSI_WLAN_RSP_SOCKET_CREATE) || (frame_type == RSI_WLAN_RSP_SOCKET_CONFIG)) {
1026 socket_command_queue = &cmd_queues[SI91X_SOCKET_CMD];
1027 } else {
1028 socket_command_queue = &socket->command_queue;
1029 }
1030
1031 if (frame_type == RSI_WLAN_RSP_SELECT_REQUEST) {
1032 // Allocate a buffer for the response packet
1033 status = sl_si91x_host_allocate_buffer(&packet,
1034 SL_WIFI_RX_FRAME_BUFFER,
1035 sizeof(sli_si91x_queue_packet_t),
1036 1000);
1037 if (status != SL_STATUS_OK) {
1038 SL_DEBUG_LOG("\r\n HEAP EXHAUSTED DURING ALLOCATION \r\n");
1039 BREAKPOINT();
1040 }
1041 node = sl_si91x_host_get_buffer_data(packet, 0, &temp);
1042
1043 // Set frame status, queue ID, and command type for the network response
1044 node->frame_status = frame_status;
1045 node->firmware_queue_id = RSI_WLAN_MGMT_Q;
1046 node->command_type = SI91X_SOCKET_CMD;
1047 node->host_packet = buffer;
1048 node->sdk_context = NULL;
1049 // and set asynchronous socket notification event
1050 sli_si91x_add_to_queue(&cmd_queues[SI91X_SOCKET_CMD].event_queue, packet);
1051 set_async_event(NCP_HOST_SOCKET_NOTIFICATION_EVENT);
1052 break;
1053 }
1054 ++socket_command_queue->rx_counter;
1055
1056 if ((socket_command_queue->command_timeout != 0)
1057 && (sl_si91x_host_elapsed_time(socket_command_queue->command_tickcount)
1058 > (socket_command_queue->command_timeout))) {
1059 sl_si91x_host_free_buffer(buffer);
1060 socket_command_queue->command_tickcount = 0;
1061 socket_command_queue->command_timeout = 0;
1062 break;
1063 }
1064
1065 if (frame_type == RSI_WLAN_RSP_SOCKET_READ_DATA && socket_command_queue->frame_type == frame_type) {
1066 buffer->id = (uint8_t)(socket->command_queue.packet_id);
1067 socket_command_queue->command_in_flight = false;
1068 socket_command_queue->frame_type = 0;
1069 sli_si91x_add_to_queue(&socket->rx_data_queue, buffer);
1070 sli_si91x_set_socket_event(1 << socket->index);
1071 break;
1072 }
1073
1074 // Allocate a buffer for the response packet
1075 status =
1076 sl_si91x_host_allocate_buffer(&packet, SL_WIFI_RX_FRAME_BUFFER, sizeof(sli_si91x_queue_packet_t), 1000);
1077 if (status != SL_STATUS_OK) {
1078 SL_DEBUG_LOG("\r\n HEAP EXHAUSTED DURING ALLOCATION \r\n");
1079 BREAKPOINT();
1080 }
1081 node = sl_si91x_host_get_buffer_data(packet, 0, &temp);
1082
1083 // Set frame status, queue ID, and command type for the socket response
1084 node->frame_status = frame_status;
1085 node->firmware_queue_id = RSI_WLAN_MGMT_Q;
1086 node->command_type = SI91X_SOCKET_CMD;
1087 node->host_packet = buffer;
1088
1089 // Check if the frame type is valid
1090 if (socket_command_queue->frame_type == frame_type) {
1091 node->sdk_context = socket_command_queue->sdk_context;
1092 node->flags = socket_command_queue->flags;
1093 // node->packet_id = socket_command_queue->packet_id;
1094 buffer->id = socket_command_queue->packet_id;
1095 packet->id = socket_command_queue->packet_id;
1096 } else {
1097 node->sdk_context = NULL;
1098 node->flags = 0;
1099 // node->packet_id = 0;
1100 buffer->id = 0;
1101 packet->id = 0;
1102 }
1103
1104 // Check if it's a response packet, and handle accordingly
1105 if ((socket_command_queue->flags & SI91X_PACKET_RESPONSE_STATUS)
1106 && (socket_command_queue->frame_type == frame_type)) {
1107
1108 // Check if the response packet should be free or not
1109 if ((socket_command_queue->flags & SI91X_PACKET_RESPONSE_PACKET) == 0) {
1110 node->host_packet = NULL;
1111 sl_si91x_host_free_buffer(buffer);
1112 }
1113
1114 // Add the response packet to the socket response queue and set the socket response event
1115 sli_si91x_add_to_queue(&socket_command_queue->rx_queue, packet);
1116
1117 if (socket_command_queue == &cmd_queues[SI91X_SOCKET_CMD]) {
1118 sli_si91x_set_event(NCP_HOST_SOCKET_RESPONSE_EVENT);
1119 } else {
1120 sli_si91x_set_socket_event(1 << socket->index);
1121 }
1122 socket_command_queue->command_tickcount = 0;
1123 socket_command_queue->command_timeout = 0;
1124
1125 } else {
1126 // and set asynchronous socket notification event
1127 sli_si91x_add_to_queue(&cmd_queues[SI91X_SOCKET_CMD].event_queue, packet);
1128 set_async_event(NCP_HOST_SOCKET_NOTIFICATION_EVENT);
1129 }
1130
1131 // If the frame_type matches the expected frame_type for the socket command
1132 // mark the command as not in flight and clear the frame_type
1133 if (frame_type == socket_command_queue->frame_type) {
1134 socket_command_queue->command_in_flight = false;
1135 socket_command_queue->frame_type = 0;
1136 }
1137
1138 break;
1139 }
1140 #endif
1141
1142 // Handle TCP ACK Indication response
1143 case RSI_WLAN_RSP_TCP_ACK_INDICATION: {
1144 // Allocate memory for a new packet
1145 status =
1146 sl_si91x_host_allocate_buffer(&packet, SL_WIFI_RX_FRAME_BUFFER, sizeof(sli_si91x_queue_packet_t), 1000);
1147 if (status != SL_STATUS_OK) {
1148 SL_DEBUG_LOG("\r\n HEAP EXHAUSTED DURING ALLOCATION \r\n");
1149 BREAKPOINT();
1150 }
1151 node = sl_si91x_host_get_buffer_data(packet, 0, &temp);
1152
1153 // Populate the packet's information
1154 node->frame_status = frame_status;
1155 node->firmware_queue_id = RSI_WLAN_MGMT_Q;
1156 node->command_type = SI91X_SOCKET_CMD;
1157 node->host_packet = buffer;
1158
1159 node->sdk_context = NULL;
1160 node->flags = 0;
1161 // node->packet_id = 0;
1162 buffer->id = 0;
1163 packet->id = 0;
1164
1165 // Add the packet to the socket event queue and set the asynchronous socket notification event
1166 sli_si91x_add_to_queue(&cmd_queues[SI91X_SOCKET_CMD].event_queue, packet);
1167 set_async_event(NCP_HOST_SOCKET_NOTIFICATION_EVENT);
1168 break;
1169 }
1170 #ifdef SLI_SI91X_INTERNAL_HTTP_CLIENT
1171 case RSI_WLAN_RSP_HTTP_CLIENT_GET:
1172 case RSI_WLAN_RSP_HTTP_CLIENT_POST:
1173 case RSI_WLAN_RSP_HTTP_CLIENT_POST_DATA: {
1174 ++cmd_queues[SI91X_NETWORK_CMD].rx_counter;
1175
1176 if (cmd_queues[SI91X_NETWORK_CMD].frame_type == RSI_WLAN_RSP_HTTP_CLIENT_GET) {
1177 // If it's an HTTP GET response, check if the frame_status is not OK or if end_of_data is set to 1.
1178 sl_si91x_packet_t *get_response_packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
1179 const uint16_t *end_of_data = (uint16_t *)&get_response_packet->data;
1180
1181 if (frame_status != SL_STATUS_OK || *end_of_data == 1) {
1182 // Mark the command as not in flight and clear the frame_type
1183 cmd_queues[SI91X_NETWORK_CMD].command_in_flight = false;
1184 cmd_queues[SI91X_NETWORK_CMD].frame_type = 0;
1185 }
1186 } else {
1187 // For other HTTP responses, mark the command as not in flight and clear the frame_type
1188 cmd_queues[SI91X_NETWORK_CMD].command_in_flight = false;
1189 cmd_queues[SI91X_NETWORK_CMD].frame_type = 0;
1190 }
1191
1192 // Allocate memory for a new packet
1193 status =
1194 sl_si91x_host_allocate_buffer(&packet, SL_WIFI_RX_FRAME_BUFFER, sizeof(sli_si91x_queue_packet_t), 1000);
1195 if (status != SL_STATUS_OK) {
1196 SL_DEBUG_LOG("\r\n HEAP EXHAUSTED DURING ALLOCATION \r\n");
1197 BREAKPOINT();
1198 }
1199 node = sl_si91x_host_get_buffer_data(packet, 0, &temp);
1200
1201 // Populate the packet's information
1202 node->host_packet = buffer;
1203 node->frame_status = frame_status;
1204 node->firmware_queue_id = RSI_WLAN_MGMT_Q;
1205 node->command_type = SI91X_NETWORK_CMD;
1206 node->sdk_context = cmd_queues[SI91X_NETWORK_CMD].sdk_context;
1207 node->flags = cmd_queues[SI91X_NETWORK_CMD].flags;
1208 // node->packet_id = cmd_queues[SI91X_NETWORK_CMD].packet_id;
1209 buffer->id = cmd_queues[SI91X_NETWORK_CMD].packet_id;
1210 packet->id = cmd_queues[SI91X_NETWORK_CMD].packet_id;
1211
1212 // Add the packet to the network event queue and set the asynchronous network notification event
1213 sli_si91x_add_to_queue(&cmd_queues[SI91X_NETWORK_CMD].event_queue, packet);
1214 set_async_event(NCP_HOST_NETWORK_NOTIFICATION_EVENT);
1215 break;
1216 }
1217 case RSI_WLAN_RSP_HTTP_ABORT:
1218 case RSI_WLAN_RSP_HTTP_CLIENT_PUT: {
1219 ++cmd_queues[SI91X_NETWORK_CMD].rx_counter;
1220
1221 status =
1222 sl_si91x_host_allocate_buffer(&packet, SL_WIFI_RX_FRAME_BUFFER, sizeof(sli_si91x_queue_packet_t), 1000);
1223 if (status != SL_STATUS_OK) {
1224 SL_DEBUG_LOG("\r\n HEAP EXHAUSTED DURING ALLOCATION \r\n");
1225 BREAKPOINT();
1226 }
1227 node = sl_si91x_host_get_buffer_data(packet, 0, &temp);
1228
1229 // Populate the packet's information
1230 node->frame_status = frame_status;
1231 node->firmware_queue_id = RSI_WLAN_MGMT_Q;
1232 node->command_type = SI91X_NETWORK_CMD;
1233 node->sdk_context = cmd_queues[SI91X_NETWORK_CMD].sdk_context;
1234 node->flags = cmd_queues[SI91X_NETWORK_CMD].flags;
1235 // node->packet_id = command_trace[SI91X_NETWORK_CMD].packet_id;
1236 buffer->id = cmd_queues[SI91X_NETWORK_CMD].packet_id;
1237 packet->id = cmd_queues[SI91X_NETWORK_CMD].packet_id;
1238
1239 if (((cmd_queues[SI91X_NETWORK_CMD].flags & SI91X_PACKET_RESPONSE_STATUS) == SI91X_PACKET_RESPONSE_STATUS)
1240 && (cmd_queues[SI91X_NETWORK_CMD].frame_type == frame_type)) {
1241 // If it's a response status and the frame_type matches, set host_packet to NULL and free the buffer
1242 node->host_packet = NULL;
1243 sl_si91x_host_free_buffer(buffer);
1244
1245 if (sl_si91x_host_elapsed_time(cmd_queues[SI91X_NETWORK_CMD].command_tickcount)
1246 <= (cmd_queues[SI91X_NETWORK_CMD].command_timeout)) {
1247 // Add the packet to the network response queue and set the network response event
1248 sli_si91x_add_to_queue(&cmd_queues[SI91X_NETWORK_CMD].rx_queue, packet);
1249 sli_si91x_set_event(NCP_HOST_NETWORK_RESPONSE_EVENT);
1250 } else {
1251 // no user thread is waiting for the response so flush the packet and buffer
1252 sl_si91x_host_free_buffer(packet);
1253 if ((cmd_queues[SI91X_NETWORK_CMD].flags & SI91X_PACKET_RESPONSE_STATUS)
1254 != SI91X_PACKET_RESPONSE_STATUS) {
1255 sl_si91x_host_free_buffer(buffer);
1256 }
1257 }
1258 } else {
1259 // For other cases, set host_packet to buffer and add it to the network event queue
1260 node->host_packet = buffer;
1261
1262 sli_si91x_add_to_queue(&cmd_queues[SI91X_NETWORK_CMD].event_queue, packet);
1263 set_async_event(NCP_HOST_NETWORK_NOTIFICATION_EVENT);
1264 }
1265
1266 if (frame_type == cmd_queues[SI91X_NETWORK_CMD].frame_type) {
1267 // mark the command as not in flight and clear the frame_type
1268 cmd_queues[SI91X_NETWORK_CMD].command_in_flight = false;
1269 cmd_queues[SI91X_NETWORK_CMD].frame_type = 0;
1270 cmd_queues[SI91X_NETWORK_CMD].command_tickcount = 0;
1271 cmd_queues[SI91X_NETWORK_CMD].command_timeout = 0;
1272 }
1273 break;
1274 }
1275 #endif
1276 default: {
1277 // frame_type doesn't match any known cases
1278 if (PRINT_ERROR_LOGS) {
1279 PRINT_ERROR_STATUS(INFO_TAG, frame_type);
1280 }
1281 // Free the buffer
1282 sl_si91x_host_free_buffer(buffer);
1283 break;
1284 }
1285 }
1286 break;
1287 }
1288
1289 case RSI_WLAN_DATA_Q: {
1290 // Erase queue ID as it overlays with the length field which is only 24-bit
1291 data[1] &= 0xF;
1292 if (frame_type == RSI_RECEIVE_RAW_DATA) {
1293 // If the frame type is raw data reception
1294
1295 #ifdef SLI_SI91X_OFFLOAD_NETWORK_STACK
1296 SL_DEBUG_LOG("Raw Data\n");
1297 sl_si91x_packet_t *socket_packet = (sl_si91x_packet_t *)data;
1298 sli_si91x_socket_t *socket = NULL;
1299 int socket_id = sli_si91x_get_socket_id(socket_packet);
1300 socket = sli_si91x_get_socket_from_id(socket_id, LISTEN, -1);
1301
1302 // Check if we found a matching socket
1303 if (socket != NULL) {
1304 buffer->id = (uint8_t)(socket->command_queue.packet_id);
1305 // Check if command has timed out
1306 if (socket->command_queue.command_tickcount == 0
1307 || (sl_si91x_host_elapsed_time(socket->command_queue.command_tickcount)
1308 <= (socket->command_queue.command_timeout))) {
1309 if (((socket->command_queue.frame_type == RSI_WLAN_RSP_SOCKET_READ_DATA)
1310 || (socket->command_queue.frame_type == socket_packet->command))
1311 && socket->command_queue.command_in_flight
1312 && socket->command_queue.flags & SI91X_PACKET_RESPONSE_PACKET) {
1313 socket->command_queue.command_in_flight = false;
1314 sli_si91x_add_to_queue(&socket->rx_data_queue, buffer);
1315 sli_si91x_set_socket_event(1 << socket->index);
1316 } else {
1317 sli_si91x_add_to_queue(&socket->rx_data_queue, buffer);
1318 set_async_event(NCP_HOST_SOCKET_DATA_NOTIFICATION_EVENT);
1319 }
1320 } else {
1321 sli_si91x_add_to_queue(&socket->rx_data_queue, buffer);
1322 set_async_event(NCP_HOST_SOCKET_DATA_NOTIFICATION_EVENT);
1323 // sl_si91x_host_free_buffer(buffer);
1324 }
1325 socket->command_queue.command_tickcount = 0;
1326 socket->command_queue.command_timeout = 0;
1327 }
1328 #else
1329 // If SLI_SI91X_OFFLOAD_NETWORK_STACK is not defined, process the data frame and free the buffer.
1330 sl_si91x_host_process_data_frame(SL_WIFI_CLIENT_INTERFACE, buffer);
1331 sl_si91x_host_free_buffer(buffer);
1332 #endif
1333 } else if (frame_type == SL_SI91X_WIFI_RX_DOT11_DATA) {
1334 ++cmd_queues[SI91X_WLAN_CMD].rx_counter;
1335
1336 // Marking a received frame as not in flight when it matches the expected type
1337 if (frame_type == cmd_queues[SI91X_WLAN_CMD].frame_type) {
1338 cmd_queues[SI91X_WLAN_CMD].command_in_flight = false;
1339 cmd_queues[SI91X_WLAN_CMD].command_tickcount = 0;
1340 cmd_queues[SI91X_WLAN_CMD].command_timeout = 0;
1341 }
1342
1343 // Add it to the WLAN event queue and set the WLAN notification event
1344 sli_si91x_add_to_queue(&cmd_queues[SI91X_WLAN_CMD].event_queue, buffer);
1345 set_async_event(NCP_HOST_WLAN_NOTIFICATION_EVENT);
1346 }
1347 break;
1348 }
1349
1350 #ifdef SLI_SI91X_ENABLE_BLE
1351 case RSI_BT_Q: {
1352 SL_DEBUG_LOG("Received BLE packet\n");
1353 // Increment the receive counter for the Bluetooth command
1354 ++cmd_queues[SI91X_BT_CMD].rx_counter;
1355
1356 if (frame_type == cmd_queues[SI91X_BT_CMD].frame_type) {
1357 // Mark the command as not in flight and clear the frame_type
1358 cmd_queues[SI91X_BT_CMD].command_in_flight = false;
1359 cmd_queues[SI91X_BT_CMD].frame_type = 0;
1360 }
1361
1362 // Process the Bluetooth response data and free the buffer
1363 rsi_driver_process_bt_resp_handler(data);
1364 sl_si91x_host_free_buffer(buffer);
1365 break;
1366 }
1367 #endif
1368 default: {
1369 // If the frame_type doesn't match any known cases
1370 // Free the buffer
1371 sl_si91x_host_free_buffer(buffer);
1372 break;
1373 }
1374 }
1375 sli_submit_rx_buffer();
1376 } else {
1377 event &= ~SL_SI91X_NCP_HOST_BUS_RX_EVENT; // Reset the event flag
1378 }
1379
1380 if (event & SL_SI91X_ALL_TX_PENDING_COMMAND_EVENTS) {
1381 // This condition is checked before writing frames to the bus
1382 for (int i = 0; i < SI91X_CMD_MAX; i++) {
1383 if (!(event & (SL_SI91X_TX_PENDING_FLAG(i)))) {
1384 continue;
1385 }
1386 if (cmd_queues[i].command_in_flight == true) {
1387 tx_command_queues_command_in_flight_status |= SL_SI91X_TX_PENDING_FLAG(i);
1388 continue;
1389 } else {
1390 tx_command_queues_command_in_flight_status &= ~SL_SI91X_TX_PENDING_FLAG(i);
1391 }
1392 // Check if the bus is ready for a packet
1393 if (!sli_si91x_is_bus_ready(global_queue_block)) {
1394 break;
1395 }
1396
1397 bus_write_frame(&cmd_queues[i], i, SL_WIFI_CONTROL_BUFFER, &global_queue_block);
1398 if (sli_si91x_buffer_queue_empty(&cmd_queues[i].tx_queue)) {
1399 event &= ~SL_SI91X_TX_PENDING_FLAG(i);
1400 tx_command_queues_status &= ~SL_SI91X_TX_PENDING_FLAG(i);
1401 }
1402 }
1403 }
1404
1405 #ifdef SLI_SI91X_OFFLOAD_NETWORK_STACK
1406 if (tx_socket_command_queues_status & (~(tx_command_queues_command_in_flight_status))) {
1407 for (int i = 0; i < NUMBER_OF_SOCKETS; i++) {
1408 if (sli_si91x_sockets[i] != NULL
1409 && !sli_si91x_buffer_queue_empty(&sli_si91x_sockets[i]->command_queue.tx_queue)) {
1410 if (sli_si91x_sockets[i]->command_queue.command_in_flight == true) {
1411 tx_socket_command_command_in_flight_queues_status |= (1 << i);
1412 continue;
1413 } else {
1414 tx_socket_command_command_in_flight_queues_status &= ~(1 << i);
1415 }
1416 // Check if the bus is ready for a packet
1417 if (!sli_si91x_is_bus_ready(global_queue_block)) {
1418 break;
1419 }
1420
1421 // Send the socket specific command
1422 bus_write_frame(&sli_si91x_sockets[i]->command_queue,
1423 SI91X_SOCKET_CMD,
1424 SL_WIFI_CONTROL_BUFFER,
1425 &global_queue_block);
1426 if (sli_si91x_buffer_queue_empty(&sli_si91x_sockets[i]->command_queue.tx_queue)) {
1427 tx_socket_command_queues_status &= ~(1 << i);
1428 }
1429 }
1430 }
1431 // Clear the event flag for socket queues if there are no commands left
1432 if (tx_socket_command_queues_status == 0) {
1433 event &= ~SL_SI91X_SOCKET_COMMAND_TX_PENDING_EVENT;
1434 }
1435 }
1436
1437 if (event & SL_SI91X_SOCKET_DATA_TX_PENDING_EVENT) {
1438 bool all_socket_data_sent = true;
1439 // Check each socket if it has something to send
1440 for (int i = 0; i < NUMBER_OF_SOCKETS; ++i) {
1441 if (sli_si91x_sockets[i] != NULL && !sli_si91x_buffer_queue_empty(&sli_si91x_sockets[i]->tx_data_queue)) {
1442 all_socket_data_sent = false;
1443
1444 // Check if the bus is ready for a packet
1445 if (!sli_si91x_is_bus_ready(global_queue_block)) {
1446 break;
1447 }
1448
1449 sl_status_t status = bus_write_data_frame(&sli_si91x_sockets[i]->tx_data_queue);
1450 if (status == SL_STATUS_OK) {
1451 --sli_si91x_sockets[i]->data_buffer_count;
1452 }
1453 if (sli_si91x_buffer_queue_empty(&sli_si91x_sockets[i]->tx_data_queue)) {
1454 tx_socket_data_queues_status &= ~(1 << i);
1455 }
1456 }
1457 }
1458
1459 // Clear event bit if we confirmed no more packets to send
1460 if (all_socket_data_sent) {
1461 event &= ~SL_SI91X_SOCKET_DATA_TX_PENDING_EVENT;
1462 }
1463 }
1464 #endif
1465 if (event & SL_SI91X_GENERIC_DATA_TX_PENDING_EVENT) {
1466 // Check if the bus is ready for a packet
1467 sl_si91x_bus_read_interrupt_status(&interrupt_status);
1468 if (!(interrupt_status & RSI_BUFFER_FULL)) {
1469 bus_write_data_frame(&sli_tx_data_queue);
1470 if (sli_si91x_buffer_queue_empty(&sli_tx_data_queue)) {
1471 event &= ~SL_SI91X_GENERIC_DATA_TX_PENDING_EVENT;
1472 tx_generic_socket_data_queues_status &= ~(SL_SI91X_GENERIC_DATA_TX_PENDING_EVENT);
1473 }
1474 }
1475 #ifdef SLI_SI91X_MCU_INTERFACE
1476 else {
1477 unmask_ta_interrupt(TA_RSI_BUFFER_FULL_CLEAR_EVENT);
1478 }
1479 #endif
1480 }
1481 if (event & SL_SI91X_TERMINATE_BUS_THREAD_EVENT) {
1482 // Clear the termination event flag
1483 event &= ~SL_SI91X_TERMINATE_BUS_THREAD_EVENT;
1484
1485 // Acknowledge the termination request
1486 osEventFlagsSet(si91x_events, SL_SI91X_TERMINATE_BUS_THREAD_EVENT_ACK);
1487
1488 // Terminate the current thread
1489 osThreadTerminate(osThreadGetId());
1490 }
1491 }
1492 //To suppress warning unused parameter, no code effect
1493 UNUSED_PARAMETER(event);
1494 }
1495
1496 static sl_status_t bus_write_frame(sli_si91x_command_queue_t *queue,
1497 sl_si91x_command_type_t command_type,
1498 sl_wifi_buffer_type_t buffer_type,
1499 bool *global_queue_block)
1500 {
1501 UNUSED_PARAMETER(buffer_type);
1502 UNUSED_PARAMETER(command_type);
1503 sl_status_t status;
1504 sl_wifi_buffer_t *buffer;
1505 sl_si91x_packet_t *packet;
1506 sli_si91x_queue_packet_t *node = NULL;
1507
1508 if ((current_performance_profile != HIGH_PERFORMANCE) && (si91x_req_wakeup() != SL_STATUS_OK)) {
1509 return SL_STATUS_TIMEOUT;
1510 }
1511
1512 status = sli_si91x_remove_from_queue(&queue->tx_queue, &buffer);
1513 if (status != SL_STATUS_OK) {
1514 if (current_performance_profile != HIGH_PERFORMANCE) {
1515 sl_si91x_host_clear_sleep_indicator();
1516 }
1517 VERIFY_STATUS_AND_RETURN(status);
1518 }
1519
1520 node = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
1521 packet = sl_si91x_host_get_buffer_data(node->host_packet, 0, NULL);
1522 uint16_t length = packet->length;
1523
1524 // Modify the packet's descriptor to include the firmware queue ID in the length field
1525 packet->desc[1] |= (node->firmware_queue_id << 4);
1526
1527 if (packet->command) {
1528 // Set the global_queue_block flag if it is present in the packet's flags
1529 if (SI91X_PACKET_GLOBAL_QUEUE_BLOCK & node->flags) {
1530 *global_queue_block = true;
1531 }
1532
1533 if (SI91X_PACKET_WITH_ASYNC_RESPONSE != (node->flags & SI91X_PACKET_WITH_ASYNC_RESPONSE)) {
1534 // Update trace information with packet details
1535 // If the packet doesn't have an async response, mark the command as in flight
1536 queue->command_in_flight = true;
1537 queue->packet_id = node->host_packet->id;
1538 queue->firmware_queue_id = node->firmware_queue_id;
1539 queue->frame_type = packet->command;
1540 queue->flags = node->flags;
1541 queue->command_timeout = node->command_timeout;
1542 queue->command_tickcount = node->command_tickcount;
1543 queue->sdk_context = node->sdk_context;
1544 }
1545 }
1546 #ifdef SLI_SI91X_MCU_INTERFACE
1547 if ((packet->command == RSI_COMMON_RSP_TA_M4_COMMANDS) || (packet->command == RSI_WLAN_REQ_SET_CERTIFICATE)) {
1548 // set flag
1549 sli_si91x_update_flash_command_status(true);
1550 }
1551 #endif
1552 // Write the frame to the bus using packet data and length
1553 status = sl_si91x_bus_write_frame(packet, packet->data, length);
1554
1555 #ifdef SLI_SI91X_MCU_INTERFACE
1556 if (packet->desc[2] == RSI_COMMON_REQ_SOFT_RESET) {
1557 sli_si91x_config_m4_dma_desc_on_reset();
1558 }
1559 #endif
1560
1561 // Handle errors during frame writing
1562 if (status != SL_STATUS_OK) {
1563 SL_DEBUG_LOG("\r\n BUS_WRITE_ERROR \r\n");
1564 BREAKPOINT();
1565 }
1566
1567 SL_DEBUG_LOG("<>>>> Tx -> queueId : %u, frameId : 0x%x, length : %u\n",
1568 node->firmware_queue_id,
1569 packet->command,
1570 length);
1571
1572 if (current_performance_profile != HIGH_PERFORMANCE) {
1573 sl_si91x_host_clear_sleep_indicator();
1574 }
1575
1576 #ifdef SLI_SI91X_ENABLE_BLE
1577 if (command_type == SI91X_BT_CMD) {
1578 rsi_bt_common_tx_done(packet);
1579 }
1580 #endif
1581
1582 sl_si91x_host_free_buffer(node->host_packet);
1583 sl_si91x_host_free_buffer(buffer);
1584
1585 queue->tx_counter++;
1586 return SL_STATUS_OK;
1587 }
1588
1589 // This function is called for writing data
1590 static sl_status_t bus_write_data_frame(sl_si91x_buffer_queue_t *queue)
1591 {
1592 sl_status_t status;
1593 sl_wifi_buffer_t *buffer;
1594 sl_si91x_packet_t *packet;
1595
1596 if ((current_performance_profile != HIGH_PERFORMANCE) && (si91x_req_wakeup() != SL_STATUS_OK)) {
1597 return SL_STATUS_TIMEOUT;
1598 }
1599
1600 status = sli_si91x_remove_from_queue(queue, &buffer);
1601 if (status != SL_STATUS_OK) {
1602 if (current_performance_profile != HIGH_PERFORMANCE) {
1603 sl_si91x_host_clear_sleep_indicator();
1604 }
1605 VERIFY_STATUS_AND_RETURN(status);
1606 }
1607
1608 packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
1609 uint16_t length = packet->length;
1610
1611 // Modify the packet's descriptor to include the firmware queue ID in the length field
1612 packet->desc[1] |= (5 << 4);
1613
1614 // Write the frame to the bus using packet data and length
1615 status = sl_si91x_bus_write_frame(packet, packet->data, length);
1616
1617 // Handle errors during frame writing
1618 if (status != SL_STATUS_OK) {
1619 SL_DEBUG_LOG("\r\n BUS_WRITE_ERROR \r\n");
1620 BREAKPOINT();
1621 }
1622
1623 SL_DEBUG_LOG("<>>>> Tx -> queueId : %u, frameId : 0x%x, length : %u\n", 5, 0, length);
1624
1625 if (current_performance_profile != HIGH_PERFORMANCE) {
1626 sl_si91x_host_clear_sleep_indicator();
1627 }
1628
1629 sl_si91x_host_free_buffer(buffer);
1630 return SL_STATUS_OK;
1631 }
1632
1633 static void set_async_event(uint32_t event_mask)
1634 {
1635 osEventFlagsSet(si91x_async_events, event_mask);
1636 }
1637
1638 // Function to check if the bus is ready for writing
1639 bool sli_si91x_is_bus_ready(bool global_queue_block)
1640 {
1641 if (global_queue_block) {
1642 return false;
1643 }
1644 uint16_t interrupt_status = 0;
1645 sl_si91x_bus_read_interrupt_status(&interrupt_status);
1646 if (interrupt_status & RSI_BUFFER_FULL) {
1647 #ifdef SLI_SI91X_MCU_INTERFACE
1648 unmask_ta_interrupt(TA_RSI_BUFFER_FULL_CLEAR_EVENT);
1649 #endif
1650 return false;
1651 }
1652 return true;
1653 }
1654
1655 #ifdef SLI_SI91X_OFFLOAD_NETWORK_STACK
1656 static sli_si91x_socket_t *get_socket_from_packet(sl_si91x_packet_t *socket_packet)
1657 {
1658 int socket_id = sli_si91x_get_socket_id(socket_packet);
1659
1660 if (socket_packet->command == RSI_WLAN_RSP_CONN_ESTABLISH) {
1661 socket_packet->command = RSI_WLAN_RSP_SOCKET_ACCEPT;
1662 }
1663
1664 if (socket_packet->command == RSI_WLAN_RSP_SOCKET_CREATE) {
1665 sl_si91x_socket_create_response_t *socket_create_response =
1666 ((sl_si91x_socket_create_response_t *)socket_packet->data);
1667 return sli_si91x_get_socket_from_id(
1668 -1,
1669 RESET,
1670 (int16_t)(socket_create_response->socket_type[0] | (socket_create_response->socket_type[1] << 8)));
1671 } else if (socket_packet->command == RSI_WLAN_RSP_SOCKET_ACCEPT) {
1672 const sli_si91x_socket_t *si91x_socket = sli_si91x_get_socket_from_id(socket_id, RESET, -1);
1673 return get_si91x_socket(si91x_socket->client_id);
1674 } else if (socket_packet->command == RSI_WLAN_RSP_SOCKET_CLOSE) {
1675 return sli_si91x_get_socket_from_id(socket_id, RESET, -1);
1676 } else {
1677 return sli_si91x_get_socket_from_id(socket_id, LISTEN, -1);
1678 }
1679 }
1680 #endif
1681