1 /***************************************************************************/ /**
2 * @file sl_wifi_callback_framework.c
3 *******************************************************************************
4 * # License
5 * <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
6 *******************************************************************************
7 *
8 * SPDX-License-Identifier: Zlib
9 *
10 * The licensor of this software is Silicon Laboratories Inc.
11 *
12 * This software is provided 'as-is', without any express or implied
13 * warranty. In no event will the authors be held liable for any damages
14 * arising from the use of this software.
15 *
16 * Permission is granted to anyone to use this software for any purpose,
17 * including commercial applications, and to alter it and redistribute it
18 * freely, subject to the following restrictions:
19 *
20 * 1. The origin of this software must not be misrepresented; you must not
21 * claim that you wrote the original software. If you use this software
22 * in a product, an acknowledgment in the product documentation would be
23 * appreciated but is not required.
24 * 2. Altered source versions must be plainly marked as such, and must not be
25 * misrepresented as being the original software.
26 * 3. This notice may not be removed or altered from any source distribution.
27 *
28 ******************************************************************************/
29
30 #include "sl_wifi_callback_framework.h"
31 #include "sl_si91x_host_interface.h"
32 #include "sl_constants.h"
33 #include "sl_si91x_core_utilities.h"
34 #include "sl_si91x_driver.h"
35 #include "sl_wifi.h"
36
37 /// Entry in the callback table
38 typedef struct {
39 sl_wifi_callback_function_t function; /// User provided callback function pointer
40 void *arg; /// User provided callback argument
41 } sl_wifi_callback_entry_t;
42
43 //#define EXECUTE_CALLBACK(id, packet) do { if (registered_callbacks[id].function) {return registered_callbacks[id].function(packet->command, packet->data, packet->length, registered_callbacks[id].arg); } } while(0)
44 static sl_wifi_callback_entry_t *get_callback_entry(sl_wifi_event_group_t group);
45 static sl_wifi_event_group_t get_event_group_from_event(sl_wifi_event_t event);
46
47 sl_wifi_callback_entry_t registered_callbacks[SL_WIFI_EVENT_GROUP_COUNT];
48
sl_wifi_set_callback(sl_wifi_event_group_t group,sl_wifi_callback_function_t function,void * optional_arg)49 sl_status_t sl_wifi_set_callback(sl_wifi_event_group_t group, sl_wifi_callback_function_t function, void *optional_arg)
50 {
51 sl_wifi_callback_entry_t *entry = get_callback_entry(group);
52 if (entry != NULL) {
53 entry->function = function;
54 entry->arg = optional_arg;
55 return SL_STATUS_OK;
56 }
57 return SL_STATUS_FAIL;
58 }
59
sl_wifi_default_event_handler(sl_wifi_event_t event,sl_wifi_buffer_t * buffer)60 sl_status_t sl_wifi_default_event_handler(sl_wifi_event_t event, sl_wifi_buffer_t *buffer)
61 {
62 sl_wifi_callback_entry_t *entry = get_callback_entry((sl_wifi_event_group_t)event);
63
64 // Verify there is a callback registered, if not return immediately
65 if (entry == NULL || entry->function == NULL) {
66 return SL_STATUS_OK;
67 }
68
69 // Start processing the event
70 sl_si91x_packet_t *packet = (sl_si91x_packet_t *)sl_si91x_host_get_buffer_data((sl_wifi_buffer_t *)buffer, 0, NULL);
71 if (SL_WIFI_CHECK_IF_EVENT_FAILED(event)) {
72 sl_status_t status = convert_and_save_firmware_status(get_si91x_frame_status(packet));
73 if (packet->command == RSI_WLAN_RSP_JOIN) {
74 sl_status_t temp_status = sl_si91x_driver_send_command(RSI_WLAN_REQ_INIT,
75 SI91X_WLAN_CMD,
76 NULL,
77 0,
78 SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
79 NULL,
80 NULL);
81 VERIFY_STATUS_AND_RETURN(temp_status);
82 }
83
84 return entry->function(event, &status, 0, entry->arg);
85 }
86 if (RSI_WLAN_RSP_CLIENT_CONNECTED == packet->command) {
87 sli_si91x_update_ap_client_info();
88 }
89
90 if (event == SL_WIFI_TRANSCEIVER_TX_DATA_STATUS_CB) {
91 sl_wifi_transceiver_tx_data_confirmation_t tx_cfm_cb_data = { 0 };
92 tx_cfm_cb_data.status = packet->desc[15];
93 tx_cfm_cb_data.rate = packet->data[0]; //Extended descriptor in data[] for rate
94 tx_cfm_cb_data.priority = packet->data[4]; //Extended descriptor in data[] for priority
95 memcpy(&tx_cfm_cb_data.token, &packet->data[8], 4); //Extended descriptor in data[] for token
96
97 return entry->function(event, &tx_cfm_cb_data, 0, entry->arg);
98 } else if (event == SL_WIFI_TRANSCEIVER_RX_DATA_RECEIVE_CB) {
99 sl_wifi_transceiver_rx_data_t rx_cb_data = { 0 };
100 uint16_t payload_offset = packet->desc[4];
101 uint16_t payload_length = packet->length & 0xFFF;
102 uint32_t status = *(uint32_t *)(&packet->data[12]);
103
104 rx_cb_data.length = payload_length - payload_offset;
105 rx_cb_data.buffer = packet->data + payload_offset;
106 rx_cb_data.rssi = *(uint16_t *)(&packet->data[0]); //Extended descriptor in data[] for rssi
107 rx_cb_data.rate = *(uint16_t *)(&packet->data[2]); //Extended descriptor in data[] for rate
108
109 /*
110 * SL_STATUS_UNKNOWN_PEER - If SL_SI91X_FEAT_TRANSCEIVER_MAC_PEER_DS_SUPPORT is enabled but
111 * data packet is received from a peer not present in MAC layer.
112 */
113 if ((status & TRANSCEIVER_RX_PKT_TA_MATCH_BIT) || IS_BCAST_MCAST_MAC(rx_cb_data.buffer[4]))
114 rx_cb_data.status = SL_STATUS_OK;
115 else
116 rx_cb_data.status = SL_STATUS_UNKNOWN_PEER;
117
118 return entry->function(event, &rx_cb_data, 0, entry->arg);
119 }
120
121 if (packet->length) {
122 return entry->function(event, packet->data, packet->length, entry->arg);
123 } else {
124 return entry->function(event, NULL, packet->length, entry->arg);
125 }
126 }
127
get_callback_entry(sl_wifi_event_group_t group)128 static sl_wifi_callback_entry_t *get_callback_entry(sl_wifi_event_group_t group)
129 {
130 if (group > SL_WIFI_EVENT_GROUP_COUNT) {
131 group = get_event_group_from_event((sl_wifi_event_t)group);
132 }
133 return ®istered_callbacks[group];
134 }
135
get_event_group_from_event(sl_wifi_event_t event)136 static sl_wifi_event_group_t get_event_group_from_event(sl_wifi_event_t event)
137 {
138 //For TWT Events
139 if (event == SL_WIFI_TWT_UNSOLICITED_SESSION_SUCCESS_EVENT || event == SL_WIFI_TWT_AP_REJECTED_EVENT
140 || event == SL_WIFI_TWT_OUT_OF_TOLERANCE_EVENT || event == SL_WIFI_TWT_RESPONSE_NOT_MATCHED_EVENT
141 || event == SL_WIFI_TWT_UNSUPPORTED_RESPONSE_EVENT || event == SL_WIFI_TWT_TEARDOWN_SUCCESS_EVENT
142 || event == SL_WIFI_TWT_AP_TEARDOWN_SUCCESS_EVENT || event == SL_WIFI_TWT_FAIL_MAX_RETRIES_REACHED_EVENT
143 || event == SL_WIFI_TWT_INACTIVE_DUE_TO_ROAMING_EVENT || event == SL_WIFI_TWT_INACTIVE_DUE_TO_DISCONNECT_EVENT
144 || event == SL_WIFI_RESCHEDULE_TWT_SUCCESS_EVENT || event == SL_WIFI_TWT_INFO_FRAME_EXCHANGE_FAILED_EVENT
145 || event == SL_WIFI_TWT_INACTIVE_NO_AP_SUPPORT_EVENT) {
146 return SL_WIFI_TWT_RESPONSE_EVENTS;
147 }
148 // for STATS Events
149 else if (event == SL_WIFI_STATS_EVENT || event == SL_WIFI_STATS_ASYNC_EVENT || event == SL_WIFI_STATS_ADVANCE_EVENT
150 || event == SL_WIFI_STATS_TEST_MODE_EVENT || event == SL_WIFI_STATS_MODULE_STATE_EVENT) {
151 return SL_WIFI_STATS_RESPONSE_EVENTS;
152 } else if (event == SL_WIFI_TRANSCEIVER_RX_DATA_RECEIVE_CB || event == SL_WIFI_TRANSCEIVER_TX_DATA_STATUS_CB) {
153 return SL_WIFI_TRANSCEIVER_EVENTS;
154 } else {
155 event = SL_WIFI_INVALID_EVENT;
156 }
157 return (sl_wifi_event_group_t)event;
158 }
159