1 /***************************************************************************/ /**
2 * @file sl_si91x_socket_utility.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_si91x_socket_utility.h"
31 #include "sl_si91x_socket_types.h"
32 #include "sl_si91x_socket_callback_framework.h"
33 #include "sl_status.h"
34 #include "sl_constants.h"
35 #include "sl_si91x_driver.h"
36 #include "sl_si91x_protocol_types.h"
37 #include "sl_si91x_socket_constants.h"
38 #include "sl_si91x_host_interface.h"
39 #include "sl_si91x_core_utilities.h"
40 #include "sl_rsi_utility.h"
41 #include "em_core.h"
42 #include <string.h>
43 #include <stdbool.h>
44
45 /******************************************************
46 * Macro Definitions
47 ******************************************************/
48 #define SLI_SI91X_SOCKET_ACCEPT_SUCCESS_EVENT (1 << 0)
49 #define SLI_SI91X_SOCKET_ACCEPT_FAILURE_EVENT (1 << 1)
50
51 #ifndef SL_SOCKET_DEFAULT_BUFFER_LIMIT
52 #define SL_SOCKET_DEFAULT_BUFFER_LIMIT 3
53 #endif
54
55 /******************************************************
56 * Structures
57 ******************************************************/
58
59 typedef struct {
60 uint8_t in_use;
61 uint8_t select_id;
62 uint16_t frame_status;
63 union {
64 sl_si91x_socket_select_callback_t select_callback;
65 sl_si91x_socket_select_rsp_t *response_data;
66 };
67 } sli_si91x_select_request_t;
68
69 /******************************************************
70 * Static Function Declarations
71 ******************************************************/
72
73 static void sli_si91x_clear_select_id(uint8_t flag);
74 static sli_si91x_select_request_t *sli_si91x_get_available_select_id(void);
75
76 /**
77 * A internal function to check whether a particular port is available or not.
78 * @param port_number port_number which needs to be verified for availability.
79 * @return True if available else false.
80 */
81 static bool is_port_available(uint16_t port_number);
82
83 /******************************************************
84 * Variable Definitions
85 ******************************************************/
86 sli_si91x_socket_t *sli_si91x_sockets[NUMBER_OF_SOCKETS] = { 0 };
87 static sl_si91x_socket_remote_termination_callback_t user_remote_socket_termination_callback = NULL;
88 static osMutexId_t sli_si91x_socket_mutex = NULL;
89 static uint8_t sli_si91x_max_select_count = 0;
90
91 static sli_si91x_select_request_t *select_request_table = NULL;
92 //sl_si91x_buffer_queue_t sli_si91x_select_request_queue;
93 //sli_si91x_select_request_t *select_request_head = NULL;
94 sl_si91x_buffer_queue_t sli_si91x_select_response_queue;
95
96 extern sli_si91x_command_queue_t cmd_queues[SI91X_CMD_MAX];
97
98 osEventFlagsId_t si91x_socket_events = 0;
99 osEventFlagsId_t si91x_socket_select_events = 0;
100
101 extern volatile uint32_t tx_socket_command_queues_status;
102
103 extern volatile uint32_t tx_socket_data_queues_status;
104
105 /******************************************************
106 * Function Definitions
107 ******************************************************/
108
handle_accept_response(sli_si91x_socket_t * si91x_client_socket,const sl_si91x_rsp_ltcp_est_t * accept_response)109 void handle_accept_response(sli_si91x_socket_t *si91x_client_socket, const sl_si91x_rsp_ltcp_est_t *accept_response)
110 {
111 //Verifying socket existence
112 if (si91x_client_socket == NULL)
113 return;
114 // Update socket parameters based on the accept response
115 si91x_client_socket->id = accept_response->socket_id;
116 si91x_client_socket->local_address.sin6_port = accept_response->src_port_num;
117 si91x_client_socket->remote_address.sin6_port = accept_response->dest_port;
118 si91x_client_socket->mss = accept_response->mss;
119 si91x_client_socket->state = CONNECTED;
120 si91x_client_socket->remote_address.sin6_family = accept_response->ip_version == SL_IPV6_ADDRESS_LENGTH ? AF_INET6
121 : AF_INET;
122
123 if (si91x_client_socket->remote_address.sin6_family == AF_INET6) {
124 memcpy(si91x_client_socket->remote_address.sin6_addr.s6_addr,
125 accept_response->dest_ip_addr.ipv6_address,
126 SL_IPV6_ADDRESS_LENGTH);
127
128 } else {
129 memcpy(&((struct sockaddr_in *)&si91x_client_socket->remote_address)->sin_addr,
130 accept_response->dest_ip_addr.ipv4_address,
131 SL_IPV4_ADDRESS_LENGTH);
132 }
133 }
134
handle_select_response(const sl_si91x_socket_select_rsp_t * response,sl_si91x_fd_set * readfds,sl_si91x_fd_set * writefds,sl_si91x_fd_set * exception_fd)135 int handle_select_response(const sl_si91x_socket_select_rsp_t *response,
136 sl_si91x_fd_set *readfds,
137 sl_si91x_fd_set *writefds,
138 sl_si91x_fd_set *exception_fd)
139 {
140 // To track of the total number of file descriptors set
141 int total_fd_set_count = 0;
142
143 // Clear file descriptor sets
144 SLI_SI91X_NULL_SAFE_FD_ZERO(readfds);
145 SLI_SI91X_NULL_SAFE_FD_ZERO(writefds);
146 SLI_SI91X_NULL_SAFE_FD_ZERO(exception_fd);
147
148 // Iterate through all host sockets
149 for (int host_socket_index = 0; host_socket_index < NUMBER_OF_SOCKETS; host_socket_index++) {
150 const sli_si91x_socket_t *socket = get_si91x_socket(host_socket_index);
151 //Verifying socket existence
152 if (socket == NULL) {
153 continue;
154 }
155
156 // Check if the read file descriptor set is provided and if the corresponding bit is set in the response
157 if (readfds != NULL && (response->read_fds.fd_array[0] & (1 << socket->id))) {
158 SL_SI91X_FD_SET(host_socket_index, readfds);
159 total_fd_set_count++;
160 }
161
162 // Check if the write file descriptor set is provided and if the corresponding bit is set in the response.
163 if (writefds != NULL && (response->write_fds.fd_array[0] & (1 << socket->id))) {
164 SL_SI91X_FD_SET(host_socket_index, writefds);
165 total_fd_set_count++;
166 }
167 }
168
169 return total_fd_set_count;
170 }
171
sli_si91x_set_accept_callback(sli_si91x_socket_t * server_socket,sl_si91x_socket_accept_callback_t callback,int32_t client_socket_id)172 void sli_si91x_set_accept_callback(sli_si91x_socket_t *server_socket,
173 sl_si91x_socket_accept_callback_t callback,
174 int32_t client_socket_id)
175 {
176 // Set the user-defined accept callback function and the client socket ID
177 server_socket->user_accept_callback = callback;
178 server_socket->client_id = client_socket_id;
179 }
180
sli_si91x_set_remote_socket_termination_callback(sl_si91x_socket_remote_termination_callback_t callback)181 void sli_si91x_set_remote_socket_termination_callback(sl_si91x_socket_remote_termination_callback_t callback)
182 {
183 user_remote_socket_termination_callback = callback;
184 }
185
sli_si91x_socket_init(uint8_t max_select_count)186 sl_status_t sli_si91x_socket_init(uint8_t max_select_count)
187 {
188 // Check if the mutex for socket operations is already initialized.
189 // If not, create a new mutex to ensure thread-safe access.
190 if (sli_si91x_socket_mutex == NULL) {
191 sli_si91x_socket_mutex = osMutexNew(NULL); // Create a new mutex.
192 if (sli_si91x_socket_mutex == NULL) {
193 return SL_STATUS_FAIL; // Return failure if mutex creation fails.
194 }
195 }
196
197 // Check if the event flags object for socket events is already initialized.
198 // If not, create a new event flag set to manage socket events.
199 if (si91x_socket_events == NULL) {
200 si91x_socket_events = osEventFlagsNew(NULL); // Create new event flags.
201 if (si91x_socket_events == NULL) {
202 return SL_STATUS_FAIL; // Return failure if event flag creation fails.
203 }
204 }
205
206 // Check if the event flags object for socket select events is already initialized.
207 // If not, create a new event flag set to manage socket select events.
208 if (si91x_socket_select_events == NULL) {
209 si91x_socket_select_events = osEventFlagsNew(NULL); // Create new event flags.
210 if (si91x_socket_select_events == NULL) {
211 return SL_STATUS_FAIL; // Return failure if event flag creation fails.
212 }
213 }
214
215 /*
216 Allocate memory for the select request table based on the number of select instances.
217 Heap memory is allocated for the number of instances of this structure based on
218 the number of selects configured by the user during device initialization in opermode.
219 Each time a sync or async select command is sent to the firmware, the corresponding
220 structure is updated, and the instance is cleared when the response is received.
221 */
222
223 // Check if the select_request_table is uninitialized and max_select_count is valid.
224 if (select_request_table == NULL && max_select_count != 0 && max_select_count <= 10) {
225 sli_si91x_max_select_count = max_select_count; // Store the max number of selects.
226
227 // Allocate memory for the select request table based on the max_select_count.
228 select_request_table = calloc(max_select_count, sizeof(sli_si91x_select_request_t));
229
230 // If memory allocation fails, return failure.
231 if (select_request_table == NULL) {
232 return SL_STATUS_FAIL; // Return failure if memory allocation fails.
233 }
234 }
235
236 return SL_STATUS_OK; // Return success if initialization is successful.
237 }
238
sli_si91x_socket_deinit(void)239 sl_status_t sli_si91x_socket_deinit(void)
240 {
241 // free the sli_si91x_socket_mutex
242 if (sli_si91x_socket_mutex != NULL) {
243 osMutexDelete(sli_si91x_socket_mutex);
244 sli_si91x_socket_mutex = NULL;
245 }
246 if (si91x_socket_events != NULL) {
247 osEventFlagsDelete(si91x_socket_events);
248 si91x_socket_events = NULL;
249 }
250 if (si91x_socket_select_events != NULL) {
251 osEventFlagsDelete(si91x_socket_select_events);
252 si91x_socket_select_events = NULL;
253 }
254 if (select_request_table != NULL) {
255 free(select_request_table);
256 select_request_table = NULL;
257 }
258 return SL_STATUS_OK;
259 }
260
sli_si91x_vap_shutdown(uint8_t vap_id)261 sl_status_t sli_si91x_vap_shutdown(uint8_t vap_id)
262 {
263 // Iterate through all BSD sockets and modify the state to DISCONNECTED those associated with the given VAP ID
264 for (uint8_t socket_index = 0; socket_index < NUMBER_OF_SOCKETS; socket_index++) {
265 if ((sli_si91x_sockets[socket_index] != NULL) && (sli_si91x_sockets[socket_index]->vap_id == vap_id)) {
266 sli_si91x_sockets[socket_index]->state = DISCONNECTED;
267 }
268 }
269
270 return SL_STATUS_OK;
271 }
272
sli_si91x_handle_websocket(sl_si91x_socket_create_request_t * socket_create_request,const sli_si91x_socket_t * si91x_bsd_socket)273 void sli_si91x_handle_websocket(sl_si91x_socket_create_request_t *socket_create_request,
274 const sli_si91x_socket_t *si91x_bsd_socket)
275 {
276 socket_create_request->ssl_bitmap |= SI91X_WEBSOCKET_FEAT;
277
278 // Copy host name
279 if (si91x_bsd_socket->websocket_info && si91x_bsd_socket->websocket_info->host_length > 0) {
280 memcpy(socket_create_request->webs_host_name,
281 si91x_bsd_socket->websocket_info->websocket_data,
282 si91x_bsd_socket->websocket_info->host_length);
283 socket_create_request->webs_host_name[si91x_bsd_socket->websocket_info->host_length] = '\0'; // Null-terminate
284 }
285
286 // Copy resource name
287 if (si91x_bsd_socket->websocket_info && si91x_bsd_socket->websocket_info->resource_length > 0) {
288 memcpy(socket_create_request->webs_resource_name,
289 si91x_bsd_socket->websocket_info->websocket_data + si91x_bsd_socket->websocket_info->host_length,
290 si91x_bsd_socket->websocket_info->resource_length);
291 socket_create_request->webs_resource_name[si91x_bsd_socket->websocket_info->resource_length] =
292 '\0'; // Null-terminate
293 }
294 }
295
sl_si91x_config_socket(sl_si91x_socket_config_t socket_config)296 sl_status_t sl_si91x_config_socket(sl_si91x_socket_config_t socket_config)
297 {
298 sl_status_t status = SL_STATUS_OK;
299
300 // Send the socket configuration command to the SI91X driver
301 status = sl_si91x_driver_send_command(RSI_WLAN_REQ_SOCKET_CONFIG,
302 SI91X_SOCKET_CMD,
303 &socket_config,
304 sizeof(socket_config),
305 SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
306 NULL,
307 NULL);
308
309 VERIFY_STATUS_AND_RETURN(status);
310 return status;
311 }
312
reset_socket_state(int socket)313 void reset_socket_state(int socket)
314 {
315 if (sli_si91x_sockets[socket] == NULL) {
316 return;
317 }
318
319 if (sli_si91x_sockets[socket]->socket_events != NULL) {
320 osEventFlagsDelete(sli_si91x_sockets[socket]->socket_events);
321 sli_si91x_sockets[socket]->socket_events = NULL;
322 }
323
324 free(sli_si91x_sockets[socket]);
325 sli_si91x_sockets[socket] = NULL;
326 }
327
328 // Get the SI91X socket with the specified index, if it is valid and not in RESET state
get_si91x_socket(int32_t socket)329 sli_si91x_socket_t *get_si91x_socket(int32_t socket)
330 {
331 if (socket < 0 || socket >= NUMBER_OF_SOCKETS) {
332 return NULL;
333 }
334 return sli_si91x_sockets[socket];
335 }
336
sli_si91x_get_socket_from_id(int socket_id,sli_si91x_bsd_socket_state_t excluded_state,int16_t role)337 sli_si91x_socket_t *sli_si91x_get_socket_from_id(int socket_id,
338 sli_si91x_bsd_socket_state_t excluded_state,
339 int16_t role)
340 {
341 sli_si91x_socket_t *possible_socket = NULL;
342 for (uint8_t index = 0; index < NUMBER_OF_SOCKETS; ++index) {
343 sli_si91x_socket_t *socket = sli_si91x_sockets[index];
344 if (socket != NULL && socket->id == socket_id && socket->state != excluded_state
345 && (role == -1 || socket->role == role)) {
346 if (socket->command_queue.command_in_flight == false) {
347 possible_socket = socket;
348 } else {
349 return socket;
350 }
351 }
352 }
353 return possible_socket;
354 }
355
sli_si91x_get_socket_from_port(uint16_t src_port)356 static sli_si91x_socket_t *sli_si91x_get_socket_from_port(uint16_t src_port)
357 {
358 for (int i = 0; i < NUMBER_OF_SOCKETS; i++) {
359 if (sli_si91x_sockets[i] == NULL) {
360 continue;
361 }
362 if ((sli_si91x_sockets[i]->role == SI91X_SOCKET_TCP_SERVER)
363 && (src_port == sli_si91x_sockets[i]->local_address.sin6_port)) {
364 return sli_si91x_sockets[i];
365 }
366 }
367
368 return NULL;
369 }
370
371 // Find and return an available socket and its index
get_free_socket(sli_si91x_socket_t ** socket,int * socket_fd)372 void get_free_socket(sli_si91x_socket_t **socket, int *socket_fd)
373 {
374 *socket = NULL;
375 *socket_fd = -1;
376
377 osMutexAcquire(sli_si91x_socket_mutex, 0xFFFFFFFFUL);
378 // Iterate through all available sockets to find a free one
379 for (uint8_t socket_index = 0; socket_index < NUMBER_OF_SOCKETS; socket_index++) {
380
381 // If the socket is in use skip it
382 if (sli_si91x_sockets[socket_index] != NULL) {
383 continue;
384 }
385
386 // Allocate new socket
387 sli_si91x_sockets[socket_index] = malloc(sizeof(sli_si91x_socket_t));
388 if (sli_si91x_sockets[socket_index] == NULL) {
389 break;
390 }
391 memset(sli_si91x_sockets[socket_index], 0, sizeof(sli_si91x_socket_t));
392 sli_si91x_sockets[socket_index]->id = -1;
393 sli_si91x_sockets[socket_index]->index = socket_index;
394 sli_si91x_sockets[socket_index]->data_buffer_limit = SL_SOCKET_DEFAULT_BUFFER_LIMIT;
395
396 // If a free socket is found, set the socket pointer to point to it
397 *socket = sli_si91x_sockets[socket_index];
398 // Set the socket_fd to the index of the free socket, which can be used as a file descriptor
399 *socket_fd = socket_index;
400 // Exit the loop because a free socket has been found.
401 break;
402 }
403 osMutexRelease(sli_si91x_socket_mutex);
404 }
405
is_port_available(uint16_t port_number)406 static bool is_port_available(uint16_t port_number)
407 {
408 // Check whether local port is already used or not
409 for (uint8_t socket_index = 0; socket_index < NUMBER_OF_SOCKETS; socket_index++) {
410 if (sli_si91x_sockets[socket_index] != NULL
411 && sli_si91x_sockets[socket_index]->local_address.sin6_port == port_number) {
412 return false;
413 }
414 }
415
416 return true;
417 }
418
419 /**
420 * @brief This function is responsible to copy the TLS extension information provided by application into socket structure.
421 *
422 * @param socket_tls_extensions pointer to TLS extension in socket structure
423 * @param tls_extension pointer to the TLS information provided by application
424 * @return sl_status_t possible return values are SL_STATUS_OK and SL_STATUS_SI91X_MEMORY_ERROR
425 */
sli_si91x_add_tls_extension(sli_si91x_tls_extensions_t * socket_tls_extensions,const sl_si91x_socket_type_length_value_t * tls_extension)426 sl_status_t sli_si91x_add_tls_extension(sli_si91x_tls_extensions_t *socket_tls_extensions,
427 const sl_si91x_socket_type_length_value_t *tls_extension)
428 {
429 // To check if memory available for new extension in buffer of socket, max 256 Bytes only
430 if (SI91X_MAX_SIZE_OF_EXTENSION_DATA - socket_tls_extensions->current_size_of_extensions
431 < (int)(sizeof(sl_si91x_socket_type_length_value_t) + tls_extension->length)) {
432 return SL_STATUS_SI91X_MEMORY_ERROR;
433 }
434
435 uint8_t extension_size = (uint8_t)(sizeof(sl_si91x_socket_type_length_value_t) + tls_extension->length);
436
437 // copies TLS extension provided by app into SDK socket struct
438 memcpy(&socket_tls_extensions->buffer[socket_tls_extensions->current_size_of_extensions],
439 tls_extension,
440 extension_size);
441 socket_tls_extensions->current_size_of_extensions += extension_size;
442 socket_tls_extensions->total_extensions++;
443
444 return SL_STATUS_OK;
445 }
446
sli_get_socket_command_from_host_packet(sl_wifi_buffer_t * buffer)447 int32_t sli_get_socket_command_from_host_packet(sl_wifi_buffer_t *buffer)
448 {
449 sl_si91x_packet_t *packet = (sl_si91x_packet_t *)buffer->data;
450 return (packet == NULL ? -1 : packet->command);
451 }
452
453 // Prepare socket request based on socket type and send the request down to the driver.
454 // socket type : [SL_SOCKET_TCP_SERVER, SL_SOCKET_TCP_CLIENT, SL_SOCKET_LUDP, SL_SOCKET_UDP_CLIENT]
create_and_send_socket_request(int socketIdIndex,int type,const int * backlog)455 sl_status_t create_and_send_socket_request(int socketIdIndex, int type, const int *backlog)
456 {
457 sl_status_t status = SL_STATUS_OK;
458 sl_si91x_socket_create_request_t socket_create_request = { 0 };
459 const sl_si91x_socket_create_response_t *socket_create_response = NULL;
460 sli_si91x_socket_t *si91x_bsd_socket = get_si91x_socket(socketIdIndex);
461 sl_si91x_wait_period_t wait_period = SL_SI91X_WAIT_FOR_RESPONSE(5000);
462 //Verifying socket existence
463 if (si91x_bsd_socket == NULL) {
464 return -1;
465 }
466 if (type == SI91X_SOCKET_TCP_CLIENT) {
467 wait_period = SL_SI91X_WAIT_FOR_RESPONSE(100000); // timeout is 10 sec
468 }
469
470 sl_wifi_buffer_t *buffer = NULL;
471 sl_si91x_packet_t *packet = NULL;
472
473 if (si91x_bsd_socket->local_address.sin6_family == AF_INET6) {
474 socket_create_request.ip_version = SL_IPV6_VERSION;
475
476 memcpy(socket_create_request.dest_ip_addr.ipv6_address,
477 si91x_bsd_socket->remote_address.sin6_addr.s6_addr,
478 SL_IPV6_ADDRESS_LENGTH);
479 } else {
480 socket_create_request.ip_version = SL_IPV4_ADDRESS_LENGTH;
481 memcpy(socket_create_request.dest_ip_addr.ipv4_address,
482 &((struct sockaddr_in *)&si91x_bsd_socket->remote_address)->sin_addr,
483 SL_IPV4_ADDRESS_LENGTH);
484 }
485
486 socket_create_request.local_port = si91x_bsd_socket->local_address.sin6_port;
487 socket_create_request.remote_port = si91x_bsd_socket->remote_address.sin6_port;
488
489 // Fill socket type
490 socket_create_request.socket_type = (uint16_t)type;
491
492 if (type == SI91X_SOCKET_TCP_SERVER) {
493 socket_create_request.max_count = (backlog == NULL) ? 0 : (uint16_t)*backlog;
494 socket_create_request.socket_bitmap |= SI91X_SOCKET_FEAT_LTCP_ACCEPT;
495 si91x_bsd_socket->socket_events = osEventFlagsNew(NULL);
496 } else {
497 socket_create_request.max_count = 0;
498 }
499
500 if (si91x_bsd_socket->recv_data_callback == NULL) {
501 socket_create_request.socket_bitmap |= SI91X_SOCKET_FEAT_SYNCHRONOUS;
502 }
503
504 socket_create_request.socket_bitmap |= SI91X_SOCKET_FEAT_TCP_RX_WINDOW;
505
506 // Set the RX window size
507 socket_create_request.rx_window_size = TCP_RX_WINDOW_SIZE;
508
509 // Fill VAP_ID
510 socket_create_request.vap_id = si91x_bsd_socket->vap_id;
511 socket_create_request.tos = 0;
512 socket_create_request.max_tcp_retries_count = si91x_bsd_socket->max_tcp_retries ? si91x_bsd_socket->max_tcp_retries
513 : MAX_TCP_RETRY_COUNT;
514 socket_create_request.tcp_keepalive_initial_time = si91x_bsd_socket->tcp_keepalive_initial_time
515 ? si91x_bsd_socket->tcp_keepalive_initial_time
516 : DEFAULT_TCP_KEEP_ALIVE_TIME;
517 socket_create_request.tcp_mss = si91x_bsd_socket->mss;
518
519 // Check for SSL feature and fill it in SSL bitmap
520 if (si91x_bsd_socket->ssl_bitmap & SL_SI91X_ENABLE_TLS) {
521 socket_create_request.ssl_bitmap = si91x_bsd_socket->ssl_bitmap;
522 socket_create_request.ssl_ciphers_bitmap = SSL_ALL_CIPHERS;
523 #if defined(SLI_SI917) || defined(SLI_SI915)
524 socket_create_request.ssl_ext_ciphers_bitmap = SSL_EXT_CIPHERS;
525 #endif
526 // Check if cert index is not default index
527 if (si91x_bsd_socket->certificate_index > SI91X_CERT_INDEX_0) {
528 socket_create_request.socket_bitmap |= SI91X_SOCKET_FEAT_CERT_INDEX;
529 }
530
531 socket_create_request.socket_cert_inx = si91x_bsd_socket->certificate_index;
532
533 // Check if extension is provided my application and memcopy until the provided size of extensions
534 if (si91x_bsd_socket->tls_extensions.total_extensions > 0) {
535 memcpy(socket_create_request.tls_extension_data,
536 si91x_bsd_socket->tls_extensions.buffer,
537 si91x_bsd_socket->tls_extensions.current_size_of_extensions);
538
539 socket_create_request.total_extension_length = si91x_bsd_socket->tls_extensions.current_size_of_extensions;
540 socket_create_request.no_of_tls_extensions = si91x_bsd_socket->tls_extensions.total_extensions;
541 }
542 wait_period = SL_SI91X_WAIT_FOR_RESPONSE(150000); // timeout is 15 sec
543 }
544
545 // Check for HIGH_PERFORMANCE feature bit
546 if (si91x_bsd_socket->ssl_bitmap & SI91X_HIGH_PERFORMANCE_SOCKET) {
547 socket_create_request.ssl_bitmap |= SI91X_HIGH_PERFORMANCE_SOCKET;
548 }
549
550 // Check for Websocket feature bit
551 if (si91x_bsd_socket->ssl_bitmap & SI91X_WEBSOCKET_FEAT) {
552 sli_si91x_handle_websocket(&socket_create_request, si91x_bsd_socket);
553 }
554
555 // Check for TCP ACK INDICATION feature bit
556 if (si91x_bsd_socket->socket_bitmap & SI91X_SOCKET_FEAT_TCP_ACK_INDICATION) {
557 socket_create_request.socket_bitmap |= SI91X_SOCKET_FEAT_TCP_ACK_INDICATION;
558 }
559 #if defined(SLI_SI917) || defined(SLI_SI915)
560 // Set socket's max retransmission timeout value and TOS (Type of Service) if applicable
561 socket_create_request.max_retransmission_timeout_value = (uint8_t)si91x_bsd_socket->max_retransmission_timeout_value;
562 socket_create_request.tos = (uint16_t)si91x_bsd_socket->tos;
563 #endif
564
565 // Store socket role for future references.
566 si91x_bsd_socket->role = type;
567 status = sl_si91x_driver_send_command(RSI_WLAN_REQ_SOCKET_CREATE,
568 SI91X_SOCKET_CMD,
569 &socket_create_request,
570 sizeof(socket_create_request),
571 wait_period,
572 NULL,
573 &buffer);
574
575 // If the status is not OK and there's a buffer, free the buffer
576 if ((status != SL_STATUS_OK) && (buffer != NULL)) {
577 sl_si91x_host_free_buffer(buffer);
578 }
579 VERIFY_STATUS_AND_RETURN(status);
580
581 // Extract socket creation response information
582 packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
583 socket_create_response = (sl_si91x_socket_create_response_t *)packet->data;
584
585 si91x_bsd_socket->id = (int32_t)(socket_create_response->socket_id[0] | (socket_create_response->socket_id[1] << 8));
586 si91x_bsd_socket->local_address.sin6_port =
587 (uint16_t)(socket_create_response->module_port[0] | (socket_create_response->module_port[1] << 8));
588
589 if (type != SI91X_SOCKET_TCP_SERVER) {
590 si91x_bsd_socket->remote_address.sin6_port =
591 (uint16_t)(socket_create_response->dst_port[0] | socket_create_response->dst_port[1] << 8);
592 }
593
594 si91x_bsd_socket->mss = (uint16_t)((socket_create_response->mss[0]) | (socket_create_response->mss[1] << 8));
595
596 // If socket is already bound to an local address and port, there is no need to copy it again.
597 if (si91x_bsd_socket->state == BOUND) {
598 sl_si91x_host_free_buffer(buffer);
599 return SL_STATUS_OK;
600 }
601
602 // Copy the local address (IPv4 or IPv6) based on family type
603 if (si91x_bsd_socket->local_address.sin6_family == AF_INET) {
604 memcpy(&((struct sockaddr_in *)&si91x_bsd_socket->local_address)->sin_addr.s_addr,
605 socket_create_response->module_ip_addr.ipv4_addr,
606 SL_IPV4_ADDRESS_LENGTH);
607 } else {
608 memcpy(si91x_bsd_socket->local_address.sin6_addr.s6_addr,
609 socket_create_response->module_ip_addr.ipv6_addr,
610 SL_IPV6_ADDRESS_LENGTH);
611 }
612
613 // Free the buffer
614 sl_si91x_host_free_buffer(buffer);
615
616 return SL_STATUS_OK;
617 }
618
sli_si91x_socket(int family,int type,int protocol,sl_si91x_socket_receive_data_callback_t callback)619 int sli_si91x_socket(int family, int type, int protocol, sl_si91x_socket_receive_data_callback_t callback)
620 {
621 // Validate the socket parameters
622 SET_ERRNO_AND_RETURN_IF_TRUE(family != AF_INET && family != AF_INET6, EAFNOSUPPORT);
623 SET_ERRNO_AND_RETURN_IF_TRUE(type != SOCK_STREAM && type != SOCK_DGRAM, EINVAL);
624 SET_ERRNO_AND_RETURN_IF_TRUE(protocol != IPPROTO_TCP && protocol != IPPROTO_UDP && protocol != 0, EINVAL);
625 SET_ERRNO_AND_RETURN_IF_TRUE((type == SOCK_STREAM && (protocol != IPPROTO_TCP && protocol != 0)), EPROTOTYPE);
626 SET_ERRNO_AND_RETURN_IF_TRUE((type == SOCK_DGRAM && (protocol != IPPROTO_UDP && protocol != 0)), EPROTOTYPE);
627
628 // Initialize a new socket structure
629 sli_si91x_socket_t *si91x_socket;
630 int socket_index = -1;
631
632 get_free_socket(&si91x_socket, &socket_index);
633
634 // Check if there is enough memory to create the socket
635 if (socket_index < 0) {
636 SET_ERROR_AND_RETURN(ENOMEM);
637 }
638
639 // Populate the socket structure with provided parameters and callbacks
640 si91x_socket->type = type;
641 si91x_socket->local_address.sin6_family = (uint8_t)family;
642 si91x_socket->protocol = protocol;
643 si91x_socket->state = INITIALIZED;
644 si91x_socket->recv_data_callback = callback;
645
646 // Return the socket index
647 return socket_index;
648 }
649
sli_si91x_accept(int socket,struct sockaddr * addr,socklen_t * addr_len,sl_si91x_socket_accept_callback_t callback)650 int sli_si91x_accept(int socket, struct sockaddr *addr, socklen_t *addr_len, sl_si91x_socket_accept_callback_t callback)
651 {
652 sl_status_t status = SL_STATUS_OK;
653 sli_si91x_socket_t *si91x_client_socket = NULL;
654 sli_si91x_socket_t *si91x_server_socket = get_si91x_socket(socket);
655 sl_si91x_socket_accept_request_t accept_request = { 0 };
656 int32_t client_socket_id = -1;
657 sl_wifi_buffer_t *buffer = NULL;
658
659 // Check if the server socket is valid
660 SET_ERRNO_AND_RETURN_IF_TRUE(si91x_server_socket == NULL, EBADF);
661 SET_ERRNO_AND_RETURN_IF_TRUE(si91x_server_socket->type != SOCK_STREAM, EOPNOTSUPP);
662 SET_ERRNO_AND_RETURN_IF_TRUE(si91x_server_socket->state != LISTEN, EINVAL);
663
664 // Create a new instance for socket
665 client_socket_id = sli_si91x_socket(si91x_server_socket->local_address.sin6_family,
666 si91x_server_socket->type,
667 si91x_server_socket->protocol,
668 si91x_server_socket->recv_data_callback);
669
670 si91x_client_socket = get_si91x_socket(client_socket_id);
671 //Verifying socket existence
672 if (si91x_client_socket == NULL)
673 return -1;
674 memcpy(&si91x_client_socket->local_address, &si91x_server_socket->local_address, sizeof(struct sockaddr_in6));
675
676 // Create accept request
677 accept_request.socket_id = (uint8_t)si91x_server_socket->id;
678 accept_request.source_port = si91x_server_socket->local_address.sin6_port;
679
680 // Set the callback and client socket ID.
681 sli_si91x_set_accept_callback(si91x_server_socket, callback, client_socket_id);
682 if (callback != NULL) {
683 status = sli_si91x_send_socket_command(si91x_client_socket,
684 RSI_WLAN_REQ_SOCKET_ACCEPT,
685 &accept_request,
686 sizeof(accept_request),
687 SL_SI91X_RETURN_IMMEDIATELY,
688 NULL);
689 SOCKET_VERIFY_STATUS_AND_RETURN(status, SL_STATUS_OK, SI91X_UNDEFINED_ERROR);
690 return SL_STATUS_OK;
691 } else {
692 status = sli_si91x_send_socket_command(si91x_client_socket,
693 RSI_WLAN_REQ_SOCKET_ACCEPT,
694 &accept_request,
695 sizeof(accept_request),
696 SL_SI91X_WAIT_FOR_EVER | SL_SI91X_WAIT_FOR_RESPONSE_BIT,
697 &buffer);
698 SOCKET_VERIFY_STATUS_AND_RETURN(status, SL_STATUS_OK, SI91X_UNDEFINED_ERROR);
699 }
700
701 // If the accept request fails, clean up allocated memory and return an error
702 if (status != SL_STATUS_OK) {
703 sli_si91x_shutdown(client_socket_id, SHUTDOWN_BY_ID);
704 if (buffer != NULL) {
705 sl_si91x_host_free_buffer(buffer);
706 }
707 SET_ERROR_AND_RETURN(SI91X_UNDEFINED_ERROR);
708 }
709
710 sli_si91x_queue_packet_t *node = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
711 sl_wifi_buffer_t *response = node->host_packet;
712 sl_si91x_host_free_buffer(buffer);
713
714 if (response == NULL) {
715 SET_ERROR_AND_RETURN(SI91X_UNDEFINED_ERROR);
716 }
717
718 sl_si91x_packet_t *packet = sl_si91x_host_get_buffer_data(response, 0, NULL);
719 sl_si91x_rsp_ltcp_est_t *ltcp = (sl_si91x_rsp_ltcp_est_t *)packet->data;
720
721 handle_accept_response(si91x_client_socket, ltcp);
722
723 // If addr_len is NULL or invalid value, just return the client socket ID
724 if (addr != NULL && *addr_len > 0) {
725 // Copy the remote address to the provided sockaddr structure
726 memcpy(addr,
727 &si91x_client_socket->remote_address,
728 (*addr_len > sizeof(struct sockaddr_in6)) ? sizeof(struct sockaddr_in6) : *addr_len);
729
730 // Update addr_len based on the family of the local address
731 *addr_len = si91x_client_socket->local_address.sin6_family == AF_INET ? sizeof(struct sockaddr_in)
732 : sizeof(struct sockaddr_in6);
733 }
734 // Free resources and return the client socket ID
735 sl_si91x_host_free_buffer(response);
736
737 return client_socket_id;
738 }
739
740 // Shutdown a socket
sli_si91x_shutdown(int socket,int how)741 int sli_si91x_shutdown(int socket, int how)
742 {
743 sl_status_t status = SL_STATUS_OK;
744 sl_si91x_socket_close_request_t socket_close_request = { 0 };
745 sl_si91x_socket_close_response_t *socket_close_response = NULL;
746 sl_si91x_wait_period_t wait_period = SL_SI91X_WAIT_FOR_RESPONSE(SL_SI91X_WAIT_FOR_EVER);
747 sl_wifi_buffer_t *buffer = NULL;
748
749 sli_si91x_socket_t *si91x_socket = get_si91x_socket(socket);
750
751 // Verify the socket's existence
752 SET_ERRNO_AND_RETURN_IF_TRUE(si91x_socket == NULL, EBADF);
753
754 // The firmware maps server socket and first client socket connected to the server would be assigned same firmware socket ID.
755 // Therefore, if Dev attempts to close either first client or server, close request type needs to be set to SHUTDOWN_BY_PORT.
756 int close_request_type = (si91x_socket->state == LISTEN) ? SHUTDOWN_BY_PORT : how;
757
758 // If the socket is in an initial state or marked for auto-close, reset it and return
759 if (si91x_socket->state == BOUND || si91x_socket->state == INITIALIZED
760 || (si91x_socket->state == DISCONNECTED && is_tcp_auto_close_enabled())) {
761 reset_socket_state(socket);
762
763 return SI91X_NO_ERROR;
764 }
765
766 /*If socket is server socket, SHUTDOWN_BY_PORT is to be used irrespective of 'how' parameter.*/
767 socket_close_request.socket_id = (uint16_t)((close_request_type == SHUTDOWN_BY_ID) ? si91x_socket->id : 0);
768 socket_close_request.port_number = (close_request_type == SHUTDOWN_BY_ID) ? 0 : si91x_socket->local_address.sin6_port;
769
770 status = sli_si91x_send_socket_command(si91x_socket,
771 RSI_WLAN_REQ_SOCKET_CLOSE,
772 &socket_close_request,
773 sizeof(socket_close_request),
774 wait_period,
775 &buffer);
776
777 // If the status is not OK and there's a buffer, free the buffer
778 if ((status != SL_STATUS_OK) && (buffer != NULL)) {
779 sl_si91x_host_free_buffer(buffer);
780 }
781 SOCKET_VERIFY_STATUS_AND_RETURN(status, SL_STATUS_OK, SI91X_UNDEFINED_ERROR);
782
783 sli_si91x_queue_packet_t *node = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
784 if (node->host_packet == NULL) {
785 sl_si91x_host_free_buffer(buffer);
786 return SL_STATUS_FAIL;
787 }
788
789 sl_wifi_buffer_t *response_buffer = node->host_packet;
790 sl_si91x_host_free_buffer(buffer);
791
792 sl_si91x_packet_t *packet = sl_si91x_host_get_buffer_data(response_buffer, 0, NULL);
793 socket_close_response = (sl_si91x_socket_close_response_t *)packet->data;
794
795 if (close_request_type == SHUTDOWN_BY_ID && si91x_socket->id == socket_close_response->socket_id) {
796 reset_socket_state(socket);
797 sl_si91x_host_free_buffer(response_buffer);
798 return SI91X_NO_ERROR;
799 }
800 // Reset sockets that match the close request
801 for (uint8_t index = 0; index < NUMBER_OF_SOCKETS; index++) {
802 const sli_si91x_socket_t *socket_id = get_si91x_socket(index);
803 //Verifying socket existence
804 if (socket_id == NULL)
805 continue;
806 else if (close_request_type == SHUTDOWN_BY_PORT
807 && socket_id->local_address.sin6_port == socket_close_response->port_number) {
808 reset_socket_state(index);
809 }
810 }
811
812 sl_si91x_host_free_buffer(response_buffer);
813
814 return SI91X_NO_ERROR;
815 }
816
si91x_socket_event_handler(sl_status_t status,sl_si91x_socket_context_t * sdk_context,sl_si91x_packet_t * rx_packet)817 sl_status_t si91x_socket_event_handler(sl_status_t status,
818 sl_si91x_socket_context_t *sdk_context,
819 sl_si91x_packet_t *rx_packet)
820 {
821 UNUSED_PARAMETER(status);
822
823 // Handle connection establishment response
824 if (rx_packet->command == RSI_WLAN_REQ_SOCKET_ACCEPT) {
825 const sl_si91x_rsp_ltcp_est_t *accept_response = (sl_si91x_rsp_ltcp_est_t *)rx_packet->data;
826 sli_si91x_socket_t *server_socket = sli_si91x_get_socket_from_port(accept_response->src_port_num);
827 int32_t client_socket_id = -1;
828 if (server_socket == NULL) {
829 return -1;
830 }
831 client_socket_id = server_socket->client_id;
832 server_socket->client_id = -1;
833 sli_si91x_socket_t *client_socket = get_si91x_socket(client_socket_id);
834
835 handle_accept_response(client_socket, accept_response);
836
837 if (server_socket->user_accept_callback != NULL) {
838 // Call the accept callback function with relevant socket information
839 server_socket->user_accept_callback(client_socket_id,
840 (struct sockaddr *)&server_socket->remote_address,
841 (uint8_t)server_socket->type);
842 }
843 }
844 // Handle remote socket termination response
845 else if (rx_packet->command == RSI_WLAN_RSP_REMOTE_TERMINATE) {
846
847 sl_si91x_socket_close_response_t *remote_socket_closure = (sl_si91x_socket_close_response_t *)rx_packet->data;
848 // Reset sockets that match the close request
849 for (uint8_t index = 0; index < NUMBER_OF_SOCKETS; index++) {
850 sli_si91x_socket_t *socket = get_si91x_socket(index);
851 //Verifying socket existence
852 if (socket == NULL || remote_socket_closure->socket_id != socket->id || socket->state == LISTEN)
853 continue;
854
855 socket->state = DISCONNECTED;
856 uint16_t frame_status = get_si91x_frame_status(rx_packet);
857 sli_si91x_flush_socket_command_queues_based_on_queue_type(index, frame_status);
858 sli_si91x_flush_socket_data_queues_based_on_queue_type(index);
859
860 if (user_remote_socket_termination_callback != NULL) {
861 user_remote_socket_termination_callback(socket->id,
862 socket->local_address.sin6_port,
863 remote_socket_closure->sent_bytes_count);
864 }
865 break;
866 }
867 } else if (rx_packet->command == RSI_RECEIVE_RAW_DATA) {
868 // Handle the case when raw data is received
869 const sl_si91x_socket_metadata_t *firmware_socket_response = (sl_si91x_socket_metadata_t *)rx_packet->data;
870 uint8_t *data = (rx_packet->data + firmware_socket_response->offset);
871
872 int8_t host_socket = -1;
873
874 // Find the host socket corresponding to the received data
875 for (uint8_t host_socket_index = 0; host_socket_index < NUMBER_OF_SOCKETS; host_socket_index++) {
876 if ((sli_si91x_sockets[host_socket_index] != NULL)
877 && (firmware_socket_response->socket_id == sli_si91x_sockets[host_socket_index]->id)) {
878 host_socket = host_socket_index;
879 }
880 }
881
882 // Retrieve the client socket
883 const sli_si91x_socket_t *client_socket = get_si91x_socket(host_socket);
884 //Verifying socket existence
885 if (client_socket == NULL) {
886 SL_CLEANUP_MALLOC(sdk_context);
887 return -1;
888 }
889
890 // Call the user-defined receive data callback
891 client_socket->recv_data_callback(host_socket, data, firmware_socket_response->length, firmware_socket_response);
892 } else if (rx_packet->command == RSI_WLAN_RSP_SELECT_REQUEST) {
893 sl_si91x_socket_select_rsp_t *socket_select_rsp = (sl_si91x_socket_select_rsp_t *)rx_packet->data;
894
895 if (socket_select_rsp->select_id < sli_si91x_max_select_count
896 && select_request_table[socket_select_rsp->select_id].in_use) {
897 sli_si91x_select_request_t *select_request = &select_request_table[socket_select_rsp->select_id];
898 select_request->frame_status = (uint16_t)(rx_packet->desc[12] + (rx_packet->desc[13] << 8));
899 if (select_request->select_callback != NULL) {
900 sl_si91x_fd_set read_fd;
901 sl_si91x_fd_set write_fd;
902 sl_si91x_fd_set exception_fd;
903
904 // This function handles responses received from the SI91X socket driver
905 handle_select_response((sl_si91x_socket_select_rsp_t *)rx_packet->data, &read_fd, &write_fd, &exception_fd);
906
907 // Call the user-defined select callback function with the updated file descriptor sets and status
908 select_request->select_callback(&read_fd, &write_fd, &exception_fd, status);
909
910 sli_si91x_clear_select_id(select_request->select_id);
911 } else {
912 select_request->response_data = malloc(sizeof(sl_si91x_socket_select_rsp_t));
913 if (select_request->response_data == NULL) {
914 SL_DEBUG_LOG("\r\n HEAP EXHAUSTED DURING ALLOCATION \r\n");
915 } else {
916 memcpy(select_request->response_data, rx_packet->data, sizeof(sl_si91x_socket_select_rsp_t));
917 osEventFlagsSet(si91x_socket_select_events, BIT(socket_select_rsp->select_id));
918 }
919 }
920 } else {
921 SL_DEBUG_LOG("\r\n INVALID SELECT ID\r\n");
922 }
923 }
924 // This block of code is executed when a TCP acknowledgment indication is received.
925 else if (rx_packet->command == RSI_WLAN_RSP_TCP_ACK_INDICATION) {
926 const sl_si91x_rsp_tcp_ack_t *tcp_ack = (sl_si91x_rsp_tcp_ack_t *)rx_packet->data;
927
928 // Initialize a variable to store the host socket ID
929 int8_t host_socket = -1;
930
931 // Iterate through all host sockets to find a matching socket ID
932 for (uint8_t host_socket_index = 0; host_socket_index < NUMBER_OF_SOCKETS; host_socket_index++) {
933 if ((sli_si91x_sockets[host_socket_index] != NULL)
934 && (tcp_ack->socket_id == sli_si91x_sockets[host_socket_index]->id)) {
935 host_socket = host_socket_index;
936 break;
937 }
938 }
939 // Retrieve the SI91X socket associated with the host socket
940 sli_si91x_socket_t *si91x_socket = get_si91x_socket(host_socket);
941 //Verifying socket existence
942 if (si91x_socket == NULL) {
943 SL_CLEANUP_MALLOC(sdk_context);
944 return -1;
945 }
946 // Check if the SI91X_SOCKET_FEAT_TCP_ACK_INDICATION bit is set move the socket to CONNECTED state.
947 if (si91x_socket->socket_bitmap & SI91X_SOCKET_FEAT_TCP_ACK_INDICATION) {
948 si91x_socket->is_waiting_on_ack = false;
949 }
950 // Check if the SI91X socket and its data transfer callback function exist
951 if (si91x_socket != NULL && si91x_socket->data_transfer_callback != NULL) {
952 si91x_socket->data_transfer_callback(host_socket, (uint8_t)(tcp_ack->length[0] | tcp_ack->length[1] << 8));
953 }
954 }
955
956 // Cleanup any dynamically allocated memory in the SDK context
957 SL_CLEANUP_MALLOC(sdk_context);
958
959 return SL_STATUS_OK;
960 }
961
sli_si91x_send_socket_command(sli_si91x_socket_t * socket,uint32_t command,const void * data,uint32_t data_length,uint32_t wait_period,sl_wifi_buffer_t ** response_buffer)962 sl_status_t sli_si91x_send_socket_command(sli_si91x_socket_t *socket,
963 uint32_t command,
964 const void *data,
965 uint32_t data_length,
966 uint32_t wait_period,
967 sl_wifi_buffer_t **response_buffer)
968
969 {
970 sl_wifi_buffer_t *buffer;
971 sl_si91x_packet_t *packet;
972 sl_wifi_buffer_t *node_buffer;
973 sli_si91x_queue_packet_t *node;
974 sl_status_t status;
975 static uint8_t command_packet_id = 0;
976
977 // Allocate a buffer for the command with appropriate size
978 status = sli_si91x_allocate_command_buffer(&buffer,
979 (void **)&packet,
980 sizeof(sl_si91x_packet_t) + data_length,
981 SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME);
982 VERIFY_STATUS_AND_RETURN(status);
983
984 // Allocate a queue node
985 status = sli_si91x_allocate_command_buffer(&node_buffer,
986 (void **)&node,
987 sizeof(sli_si91x_queue_packet_t),
988 SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME);
989 if (status != SL_STATUS_OK) {
990 sl_si91x_host_free_buffer(buffer);
991 return status;
992 }
993
994 // Clear the packet descriptor and copy the command data if available
995 memset(packet->desc, 0, sizeof(packet->desc));
996 if (data != NULL) {
997 memcpy(packet->data, data, data_length);
998 }
999
1000 // Fill frame type
1001 packet->length = data_length & 0xFFF;
1002 packet->command = command;
1003
1004 // Set flags
1005 #ifdef TEST_USE_UNUSED_FLAGS
1006 packet->unused[SLI_SI91X_COMMAND_FLAGS_INDEX] = (wait_period & SL_SI91X_WAIT_FOR_RESPONSE_BIT) ? (1 << 0) : 0;
1007 packet->unused[SLI_SI91X_COMMAND_FLAGS_INDEX] |= (response_buffer == NULL) ? (1 << 1) : 0;
1008 if (command == RSI_WLAN_REQ_SOCKET_ACCEPT) {
1009 packet->unused[SLI_SI91X_COMMAND_RESPONSE_INDEX] = RSI_WLAN_RSP_CONN_ESTABLISH;
1010 } else {
1011 packet->unused[SLI_SI91X_COMMAND_RESPONSE_INDEX] = command;
1012 }
1013 #else
1014 node->flags = (wait_period & SL_SI91X_WAIT_FOR_RESPONSE_BIT) ? SI91X_PACKET_RESPONSE_PACKET : 0;
1015 #endif
1016
1017 wait_period &= ~SL_SI91X_WAIT_FOR_RESPONSE_BIT;
1018
1019 if (wait_period != 0) {
1020 node->flags |= SI91X_PACKET_RESPONSE_STATUS;
1021 }
1022
1023 // Set various properties of the node representing the command packet
1024 node->host_packet = buffer;
1025 node->firmware_queue_id = RSI_WLAN_MGMT_Q;
1026 node->command_type = SI91X_SOCKET_CMD;
1027
1028 if ((node->flags != SI91X_PACKET_WITH_ASYNC_RESPONSE)) {
1029 node->command_tickcount = osKernelGetTickCount();
1030 // Calculate the wait time based on wait_period
1031 if ((wait_period & SL_SI91X_WAIT_FOR_EVER) == SL_SI91X_WAIT_FOR_EVER) {
1032 node->command_timeout = osWaitForever;
1033 } else {
1034 node->command_timeout = (wait_period & ~SL_SI91X_WAIT_FOR_RESPONSE_BIT);
1035 }
1036 }
1037 node->sdk_context = NULL;
1038
1039 CORE_irqState_t state = CORE_EnterAtomic();
1040 uint8_t this_packet_id = command_packet_id++;
1041 buffer->id = this_packet_id;
1042 node_buffer->id = this_packet_id;
1043 sli_si91x_append_to_buffer_queue(&socket->command_queue.tx_queue, node_buffer);
1044 tx_socket_command_queues_status |= (1 << socket->index);
1045 sli_si91x_set_event(SL_SI91X_SOCKET_COMMAND_TX_PENDING_EVENT);
1046 CORE_ExitAtomic(state);
1047
1048 if (wait_period != 0) {
1049
1050 uint16_t firmware_status = 0;
1051 sl_si91x_buffer_queue_t *rx_queue;
1052 if (command == RSI_WLAN_REQ_SOCKET_READ_DATA) {
1053 rx_queue = &socket->rx_data_queue;
1054 } else {
1055 rx_queue = &socket->command_queue.rx_queue;
1056 }
1057
1058 status = sli_si91x_driver_wait_for_response_packet(rx_queue,
1059 si91x_socket_events,
1060 (1 << socket->index),
1061 this_packet_id,
1062 wait_period,
1063 response_buffer);
1064 VERIFY_STATUS_AND_RETURN(status);
1065
1066 if (command == RSI_WLAN_REQ_SOCKET_READ_DATA) {
1067 sl_si91x_packet_t *packet = (sl_si91x_packet_t *)sl_si91x_host_get_buffer_data(*response_buffer, 0, NULL);
1068 firmware_status = (uint16_t)(packet->desc[12] + (packet->desc[13] << 8)); // Extract the frame status
1069
1070 } else {
1071 // Process the response packet and return the firmware status
1072 sli_si91x_queue_packet_t *node =
1073 (sli_si91x_queue_packet_t *)sl_si91x_host_get_buffer_data(*response_buffer, 0, NULL);
1074 firmware_status = node->frame_status;
1075 }
1076 return convert_and_save_firmware_status(firmware_status);
1077 } else {
1078 return SL_STATUS_OK;
1079 }
1080 }
1081
sli_si91x_send_socket_data(sli_si91x_socket_t * si91x_socket,const sli_si91x_socket_send_request_t * request,const void * data)1082 sl_status_t sli_si91x_send_socket_data(sli_si91x_socket_t *si91x_socket,
1083 const sli_si91x_socket_send_request_t *request,
1084 const void *data)
1085 {
1086 sl_wifi_buffer_t *buffer;
1087 sl_si91x_packet_t *packet;
1088 sli_si91x_socket_send_request_t *send;
1089
1090 sl_status_t status = SL_STATUS_OK;
1091 uint16_t header_length = (request->data_offset - sizeof(sli_si91x_socket_send_request_t));
1092 uint32_t data_length = request->length;
1093
1094 if (data == NULL) {
1095 return SL_STATUS_NULL_POINTER;
1096 }
1097
1098 uint32_t start = osKernelGetTickCount();
1099 while (si91x_socket->data_buffer_limit != 0 && si91x_socket->data_buffer_count >= si91x_socket->data_buffer_limit) {
1100 osDelay(2);
1101 if ((osKernelGetTickCount() - start) > SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME) {
1102 return SL_STATUS_WIFI_BUFFER_ALLOC_FAIL;
1103 }
1104 }
1105
1106 // Allocate a buffer for the socket data with appropriate size
1107 status = sl_si91x_host_allocate_buffer(
1108 &buffer,
1109 SL_WIFI_TX_FRAME_BUFFER,
1110 sizeof(sl_si91x_packet_t) + sizeof(sli_si91x_socket_send_request_t) + header_length + data_length,
1111 SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME);
1112 VERIFY_STATUS_AND_RETURN(status);
1113
1114 packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
1115 if (packet == NULL) {
1116 return SL_STATUS_WIFI_BUFFER_ALLOC_FAIL;
1117 }
1118 ++si91x_socket->data_buffer_count;
1119
1120 memset(packet->desc, 0, sizeof(packet->desc));
1121
1122 send = (sli_si91x_socket_send_request_t *)packet->data;
1123 memcpy(send, request, sizeof(sli_si91x_socket_send_request_t));
1124 memcpy((send->send_buffer + header_length), data, data_length);
1125
1126 // Fill frame type
1127 packet->length = (sizeof(sli_si91x_socket_send_request_t) + header_length + data_length) & 0xFFF;
1128
1129 // ++data_queue_appended_count;
1130 CORE_irqState_t state = CORE_EnterAtomic();
1131 sli_si91x_append_to_buffer_queue(&si91x_socket->tx_data_queue, buffer);
1132 tx_socket_data_queues_status |= (1 << si91x_socket->index);
1133 sli_si91x_set_event(SL_SI91X_SOCKET_DATA_TX_PENDING_EVENT);
1134 CORE_ExitAtomic(state);
1135
1136 return SL_STATUS_OK;
1137 }
1138
sli_si91x_get_socket_id(sl_si91x_packet_t * packet)1139 int sli_si91x_get_socket_id(sl_si91x_packet_t *packet)
1140 {
1141 // Handle connection establishment response
1142 switch (packet->command) {
1143 case RSI_WLAN_RSP_CONN_ESTABLISH:
1144 return ((sl_si91x_rsp_ltcp_est_t *)packet->data)->socket_id;
1145 case RSI_WLAN_RSP_REMOTE_TERMINATE:
1146 return ((sl_si91x_socket_close_response_t *)packet->data)->socket_id;
1147 case RSI_RECEIVE_RAW_DATA:
1148 return *((uint8_t *)&(((sl_si91x_socket_metadata_t *)packet->data)->socket_id));
1149 case RSI_WLAN_RSP_SOCKET_READ_DATA:
1150 return packet->data[0];
1151 case RSI_WLAN_RSP_TCP_ACK_INDICATION:
1152 return ((sl_si91x_rsp_tcp_ack_t *)packet->data)->socket_id;
1153 case RSI_WLAN_RSP_SOCKET_CREATE:
1154 return (((sl_si91x_socket_create_response_t *)packet->data)->socket_id[0]
1155 + (((sl_si91x_socket_create_response_t *)packet->data)->socket_id[1] << 8));
1156 case RSI_WLAN_RSP_SOCKET_CLOSE:
1157 if (((sl_si91x_socket_close_response_t *)packet->data)->socket_id == 0) {
1158 const uint16_t port = ((sl_si91x_socket_close_response_t *)packet->data)->port_number;
1159 for (int i = 0; i < NUMBER_OF_SOCKETS; ++i) {
1160 if (sli_si91x_sockets[i] != NULL && sli_si91x_sockets[i]->local_address.sin6_port == port) {
1161 return sli_si91x_sockets[i]->id;
1162 }
1163 }
1164 return -1;
1165 } else {
1166 return ((sl_si91x_socket_close_response_t *)packet->data)->socket_id;
1167 }
1168 case RSI_WLAN_RSP_SELECT_REQUEST:
1169 default:
1170 return -1;
1171 }
1172
1173 return -1;
1174 }
1175
sli_si91x_connect(int socket,const struct sockaddr * addr,socklen_t addr_len)1176 int sli_si91x_connect(int socket, const struct sockaddr *addr, socklen_t addr_len)
1177 {
1178 errno = 0;
1179
1180 sl_status_t status = SL_STATUS_FAIL;
1181 sli_si91x_socket_t *si91x_socket;
1182
1183 // Retrieve the socket using the socket index
1184 si91x_socket = get_si91x_socket(socket);
1185
1186 // Check if the socket is valid.
1187 SET_ERRNO_AND_RETURN_IF_TRUE(si91x_socket == NULL, EBADF);
1188
1189 // Check if the socket is already connected
1190 SET_ERRNO_AND_RETURN_IF_TRUE(si91x_socket->type == SOCK_STREAM && si91x_socket->state == CONNECTED, EISCONN);
1191
1192 // Check the socket state based on its type
1193 SET_ERRNO_AND_RETURN_IF_TRUE(si91x_socket->type == SOCK_STREAM && si91x_socket->state > BOUND, EBADF);
1194 SET_ERRNO_AND_RETURN_IF_TRUE(si91x_socket->type == SOCK_DGRAM && si91x_socket->state != INITIALIZED
1195 && si91x_socket->state != BOUND && si91x_socket->state != UDP_UNCONNECTED_READY,
1196 EBADF);
1197
1198 // Check if the provided sockaddr length is sufficient
1199 SET_ERRNO_AND_RETURN_IF_TRUE(
1200 (si91x_socket->local_address.sin6_family == AF_INET && addr_len < sizeof(struct sockaddr_in))
1201 || (si91x_socket->local_address.sin6_family == AF_INET6 && addr_len < sizeof(struct sockaddr_in6)),
1202 EINVAL);
1203
1204 // Check if the provided sockaddr pointer is valid
1205 SET_ERRNO_AND_RETURN_IF_TRUE(addr == NULL, EFAULT);
1206
1207 SET_ERRNO_AND_RETURN_IF_TRUE(si91x_socket->local_address.sin6_family != addr->sa_family, EAFNOSUPPORT);
1208
1209 memcpy(&si91x_socket->remote_address,
1210 addr,
1211 (addr_len > sizeof(struct sockaddr_in6)) ? sizeof(struct sockaddr_in6) : addr_len);
1212
1213 // Since socket is already created, there is no need to send create request again.
1214 if (si91x_socket->type == SOCK_DGRAM && si91x_socket->state == UDP_UNCONNECTED_READY) {
1215 si91x_socket->state = CONNECTED;
1216
1217 return SI91X_NO_ERROR;
1218 }
1219
1220 // Prepare socket request based on socket type and send the request to the bus driver
1221 if (si91x_socket->type == SOCK_STREAM) {
1222 status = create_and_send_socket_request(socket, SI91X_SOCKET_TCP_CLIENT, NULL);
1223 } else if (si91x_socket->type == SOCK_DGRAM) {
1224 status = create_and_send_socket_request(socket, SI91X_SOCKET_UDP_CLIENT, NULL);
1225 }
1226
1227 // Verify the status of the socket operation and return errors if necessary
1228 SOCKET_VERIFY_STATUS_AND_RETURN(status, SL_STATUS_OK, SI91X_UNDEFINED_ERROR);
1229
1230 // Update the socket state to "CONNECTED" and return success
1231 si91x_socket->state = CONNECTED;
1232 return SI91X_NO_ERROR;
1233 }
1234
sli_si91x_bind(int socket_id,const struct sockaddr * addr,socklen_t addr_len)1235 int sli_si91x_bind(int socket_id, const struct sockaddr *addr, socklen_t addr_len)
1236 {
1237 errno = 0;
1238
1239 // Retrieve the SI91X socket associated with the given socket ID.
1240 sli_si91x_socket_t *si91x_socket = get_si91x_socket(socket_id);
1241 const struct sockaddr_in *socket_address = (const struct sockaddr_in *)addr;
1242
1243 // Validate socket, address, and address length
1244 SET_ERRNO_AND_RETURN_IF_TRUE(si91x_socket == NULL || si91x_socket->state != INITIALIZED, EBADF);
1245 SET_ERRNO_AND_RETURN_IF_TRUE(
1246 (si91x_socket->local_address.sin6_family == AF_INET && addr_len < sizeof(struct sockaddr_in))
1247 || (si91x_socket->local_address.sin6_family == AF_INET6 && addr_len < sizeof(struct sockaddr_in6)),
1248 EINVAL);
1249
1250 SET_ERRNO_AND_RETURN_IF_TRUE(addr == NULL, EFAULT);
1251
1252 // Check whether local port is already used or not
1253 if (!is_port_available(socket_address->sin_port)) {
1254 SET_ERROR_AND_RETURN(EADDRINUSE);
1255 }
1256
1257 // Copy the provided address to the local address structure
1258 memcpy(&si91x_socket->local_address,
1259 addr,
1260 (addr_len > sizeof(struct sockaddr_in6)) ? sizeof(struct sockaddr_in6) : addr_len);
1261
1262 si91x_socket->state = BOUND;
1263
1264 // For UDP sockets, create and send a socket request.
1265 if (si91x_socket->type == SOCK_DGRAM) {
1266 sl_status_t socket_create_request_status = create_and_send_socket_request(socket_id, SI91X_SOCKET_UDP_CLIENT, NULL);
1267 SOCKET_VERIFY_STATUS_AND_RETURN(socket_create_request_status, SI91X_NO_ERROR, SI91X_UNDEFINED_ERROR);
1268
1269 si91x_socket->state = UDP_UNCONNECTED_READY;
1270 }
1271
1272 return SI91X_NO_ERROR;
1273 }
1274
sli_si91x_select(int nfds,sl_si91x_fd_set * readfds,sl_si91x_fd_set * writefds,sl_si91x_fd_set * exceptfds,const struct timeval * timeout,sl_si91x_socket_select_callback_t callback)1275 int sli_si91x_select(int nfds,
1276 sl_si91x_fd_set *readfds,
1277 sl_si91x_fd_set *writefds,
1278 sl_si91x_fd_set *exceptfds,
1279 const struct timeval *timeout,
1280 sl_si91x_socket_select_callback_t callback)
1281 {
1282 UNUSED_PARAMETER(exceptfds); // exceptfds is not supported by the firmware, so it is unused
1283 sl_status_t status = SL_STATUS_OK; // Initialize status
1284 uint32_t select_response_wait_time = 0; // Time to wait for the select response
1285
1286 // Define a structure to hold the select request parameters
1287 sl_si91x_socket_select_req_t request = { 0 };
1288
1289 // Check if all file descriptor sets are NULL
1290 if ((readfds == NULL) && (writefds == NULL)) {
1291 SET_ERROR_AND_RETURN(EINVAL); // Invalid argument, no sets specified
1292 }
1293
1294 // Check if the number of file descriptors (nfds) is within a valid range
1295 if (nfds < 0 || nfds > NUMBER_OF_SOCKETS) {
1296 SET_ERROR_AND_RETURN(EINVAL); // Invalid argument, nfds out of range
1297 }
1298
1299 // Check if the provided timeout is valid
1300 if ((timeout != NULL) && ((timeout->tv_sec < 0) || (timeout->tv_usec < 0))) {
1301 SET_ERROR_AND_RETURN(EINVAL); // Invalid argument, negative timeout
1302 }
1303
1304 // Loop through the provided file descriptor sets and populate the select request structure
1305 for (uint8_t host_socket_index = 0; host_socket_index < nfds; host_socket_index++) {
1306 const sli_si91x_socket_t *socket =
1307 get_si91x_socket(host_socket_index); // Retrieve the si91x_socket associated with the index
1308
1309 // Throw error if the socket file descriptor set is invalid
1310 if (socket == NULL
1311 && ((readfds != NULL && SL_SI91X_FD_ISSET(host_socket_index, readfds))
1312 || (writefds != NULL && SL_SI91X_FD_ISSET(host_socket_index, writefds)))) {
1313 SET_ERROR_AND_RETURN(EBADF); // Bad file descriptor
1314 }
1315
1316 // The code will reach this if clause in the case of a socket being NULL and the socket being neither set in readfds nor writefds.
1317 // Continue to next socket if this one is not in use
1318 if (socket == NULL) {
1319 continue;
1320 }
1321
1322 // Check if the socket is set for read operations in the readfds set
1323 // Set the corresponding bit in the read file descriptor set
1324 if ((readfds != NULL) && (SL_SI91X_FD_ISSET(host_socket_index, readfds))) {
1325 request.read_fds.fd_array[0] |= (1U << socket->id);
1326 }
1327
1328 // Check if the socket is set for write operations in the writefds set
1329 // Set the corresponding bit in the write file descriptor set
1330 if ((writefds != NULL) && (SL_SI91X_FD_ISSET(host_socket_index, writefds))) {
1331 request.write_fds.fd_array[0] |= (1U << socket->id);
1332 }
1333
1334 // Update the maximum file descriptor number encountered
1335 if (request.num_fd <= socket->id) {
1336 request.num_fd = (uint8_t)(socket->id + 1);
1337 }
1338 }
1339
1340 // Handle timeout: If a timeout is provided, calculate the wait time
1341 if (timeout != NULL) {
1342 request.select_timeout.tv_sec = timeout->tv_sec;
1343 request.select_timeout.tv_usec = timeout->tv_usec;
1344 // Convert timeout to milliseconds and add extra wait time for the response
1345 select_response_wait_time = ((request.select_timeout.tv_sec * 1000) + (request.select_timeout.tv_usec / 1000)
1346 + SI91X_HOST_WAIT_FOR_SELECT_RSP);
1347 } else {
1348 // If no timeout is specified, set the request to indicate no timeout and wait indefinitely
1349 request.no_timeout = 1;
1350 select_response_wait_time = osWaitForever;
1351 }
1352
1353 // Get an available select ID from the internal table
1354 sli_si91x_select_request_t *select_request = sli_si91x_get_available_select_id();
1355 // If no select ID is available, return an error
1356 SET_ERRNO_AND_RETURN_IF_TRUE((select_request == NULL), EPERM);
1357 // Assign the callback function for this select request
1358 select_request->select_callback = callback;
1359
1360 // Set the select_id in the request structure
1361 request.select_id = select_request->select_id;
1362
1363 // Send the select request asynchronously to the firmware
1364 status = sl_si91x_driver_send_async_command(RSI_WLAN_REQ_SELECT_REQUEST, SI91X_SOCKET_CMD, &request, sizeof(request));
1365 if (status != SL_STATUS_OK) {
1366 // If sending the command fails, clear the select ID and return
1367 sli_si91x_clear_select_id(request.select_id);
1368 }
1369 // Verify that the command was sent successfully
1370 SOCKET_VERIFY_STATUS_AND_RETURN(status, SL_STATUS_OK, SI91X_UNDEFINED_ERROR);
1371
1372 // If a callback was provided, return immediately (non-blocking)
1373 if (callback != NULL) {
1374 return SL_SI91X_RETURN_IMMEDIATELY;
1375 }
1376
1377 // Start measuring the time for the select operation
1378 uint32_t start_time = osKernelGetTickCount();
1379 uint32_t elapsed_time = 0;
1380
1381 do {
1382 // Wait for the select response event (using the select_id)
1383 uint32_t events = osEventFlagsWait(si91x_socket_select_events,
1384 BIT(request.select_id),
1385 osFlagsWaitAny,
1386 (select_response_wait_time - elapsed_time));
1387
1388 // Handle cases where the wait times out or resources are unavailable
1389 if (events == (uint32_t)osErrorTimeout || events == (uint32_t)osErrorResource) {
1390 status = SL_STATUS_TIMEOUT; // Set status to timeout if no response was received
1391 break;
1392 } else {
1393 status = SL_STATUS_OK; // Set status to OK if response was received
1394 }
1395
1396 // Check if the response data for the select request is available
1397 if (select_request_table[request.select_id].response_data != NULL) {
1398 break; // Exit the loop if response is received
1399 }
1400
1401 // Update the elapsed time
1402 elapsed_time = sl_si91x_host_elapsed_time(start_time);
1403 } while (elapsed_time <= select_response_wait_time);
1404
1405 // If the select operation timed out or failed, clear the select ID and exit
1406 if (status != SL_STATUS_OK) {
1407 sli_si91x_clear_select_id(request.select_id);
1408 }
1409 // Verify the status and return if an error occurred
1410 SOCKET_VERIFY_STATUS_AND_RETURN(status, SL_STATUS_OK, SI91X_UNDEFINED_ERROR);
1411
1412 // Convert and save the firmware status from the select request
1413 convert_and_save_firmware_status(select_request_table[request.select_id].frame_status);
1414
1415 // Initialize the total file descriptor count
1416 int32_t total_fd_set_count = -1;
1417 // If the firmware status is OK, process the select response and update the file descriptor sets
1418 if (select_request_table[request.select_id].frame_status == SL_STATUS_OK) {
1419 total_fd_set_count =
1420 handle_select_response(select_request_table[request.select_id].response_data, readfds, writefds, exceptfds);
1421 }
1422
1423 // Free the memory allocated for the response data
1424 free(select_request_table[request.select_id].response_data);
1425 // Clear the select ID in the internal table
1426 sli_si91x_clear_select_id(request.select_id);
1427
1428 // Return the total number of file descriptors set in the read, write, or exception sets
1429 return total_fd_set_count;
1430 }
1431
sli_si91x_get_available_select_id(void)1432 static sli_si91x_select_request_t *sli_si91x_get_available_select_id(void)
1433 {
1434 // Check if there are any available select request entries.
1435 if (sli_si91x_max_select_count == 0) {
1436 return NULL; // Return NULL if no requests can be processed.
1437 }
1438
1439 // Enter atomic section to ensure thread-safe access to the select_request_table.
1440 CORE_irqState_t state = CORE_EnterAtomic();
1441
1442 // Iterate over the select request table to find an available entry.
1443 for (unsigned int i = 0; i < sli_si91x_max_select_count; i++) {
1444 // Check if the current entry is not in use.
1445 if (!select_request_table[i].in_use) {
1446 // Assign the current index as the select ID.
1447 select_request_table[i].select_id = i;
1448
1449 // Mark the entry as in use.
1450 select_request_table[i].in_use = 1;
1451
1452 // Exit atomic section after modifying the entry.
1453 CORE_ExitAtomic(state);
1454
1455 // Return the pointer to the available select request entry.
1456 return &select_request_table[i];
1457 }
1458 }
1459
1460 // Exit atomic section if no available entry was found.
1461 CORE_ExitAtomic(state);
1462
1463 // Return NULL to indicate that no available select ID was found.
1464 return NULL;
1465 }
1466
sli_si91x_clear_select_id(uint8_t id)1467 static void sli_si91x_clear_select_id(uint8_t id)
1468 {
1469 // Check if the select request table is empty or if the provided ID is out of range.
1470 if (sli_si91x_max_select_count == 0 || id >= sli_si91x_max_select_count) {
1471 return; // If no requests or invalid ID, exit early.
1472 }
1473
1474 // Enter atomic section to ensure thread-safe access to the select_request_table.
1475 CORE_irqState_t state = CORE_EnterAtomic();
1476
1477 // Mark the entry corresponding to the provided ID as not in use.
1478 select_request_table[id].in_use = 0;
1479
1480 // Exit atomic section after the operation is complete.
1481 CORE_ExitAtomic(state);
1482 }
1483
sli_si91x_set_socket_event(uint32_t event_mask)1484 void sli_si91x_set_socket_event(uint32_t event_mask)
1485 {
1486 osEventFlagsSet(si91x_socket_events, event_mask);
1487 }
1488
sli_si91x_flush_select_request_table(uint16_t error_code)1489 sl_status_t sli_si91x_flush_select_request_table(uint16_t error_code)
1490 {
1491 // Iterate over all entries in the select_request_table
1492 for (unsigned int i = 0; i < sli_si91x_max_select_count; i++) {
1493 // Check if the current select_request_table entry is in use
1494 if (select_request_table[i].in_use) {
1495 // If a callback function exists for this entry, it is async
1496 if (select_request_table[i].select_callback != NULL) {
1497 select_request_table[i].in_use = 0; // Mark as not in use
1498 } else {
1499 // If there is no callback, the request needs to be reset and so the response data pointer is cleared, indicating no data is available
1500 select_request_table[i].response_data = NULL;
1501 // Set the frame status to indicate rejoin failure in the request
1502 select_request_table[i].frame_status = error_code;
1503 // Set the appropriate event flag for the socket associated with the select_id
1504 osEventFlagsSet(si91x_socket_select_events, BIT(select_request_table[i].select_id));
1505 }
1506 }
1507 }
1508 // Return SL_STATUS_OK to indicate the function completed successfully
1509 return SL_STATUS_OK;
1510 }
1511