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(&current_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