1 /***************************************************************************/ /**
2 * @file
3 * @brief
4 *******************************************************************************
5 * # License
6 * <b>Copyright 2019 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_status.h"
31 #include "sl_wifi_types.h"
32 #include "sl_net.h"
33 #include "stddef.h"
34 #include "sl_status.h"
35 #include "sl_utility.h"
36 #include "sl_net.h"
37 #include "sl_wifi.h"
38 #include "sl_net_wifi_types.h"
39 #include "sl_net_si91x.h"
40 #include "sl_si91x_host_interface.h"
41 #include "sl_si91x_driver.h"
42 #include "sl_rsi_utility.h"
43 #include "sl_net_rsi_utility.h"
44 #include "sl_si91x_core_utilities.h"
45 #include <stdbool.h>
46 #include <string.h>
47 #include "sl_wifi_callback_framework.h"
48 #include "sl_net_dns.h"
49
50 typedef enum { SLI_SI91X_CLIENT = 0, SLI_SI91X_AP = 1, SLI_SI91X_MAX_INTERFACES } sli_si91x_interfaces_t;
51
52 static sl_status_t sli_si91x_send_multicast_request(sl_wifi_interface_t interface,
53 const sl_ip_address_t *ip_address,
54 uint8_t command_type);
55 sl_status_t sl_net_dns_resolve_hostname(const char *host_name,
56 const uint32_t timeout,
57 const sl_net_dns_resolution_ip_type_t dns_resolution_ip,
58 sl_ip_address_t *sl_ip_address);
59
60 extern bool device_initialized;
61
62 static sl_ip_management_t dhcp_type[SLI_SI91X_MAX_INTERFACES] = { 0 };
63
sl_net_wifi_client_init(sl_net_interface_t interface,const void * configuration,void * context,sl_net_event_handler_t event_handler)64 sl_status_t sl_net_wifi_client_init(sl_net_interface_t interface,
65 const void *configuration,
66 void *context,
67 sl_net_event_handler_t event_handler)
68 {
69 UNUSED_PARAMETER(interface);
70 UNUSED_PARAMETER(context);
71 sl_status_t status = SL_STATUS_FAIL;
72
73 // Set the user-defined event handler for client mode
74 sl_si91x_register_event_handler(event_handler);
75
76 status = sl_wifi_init(configuration, NULL, sl_wifi_default_event_handler);
77 // Verify the initialization status and return it
78 VERIFY_STATUS_AND_RETURN(status);
79 return status;
80 }
81
sl_net_wifi_client_deinit(sl_net_interface_t interface)82 sl_status_t sl_net_wifi_client_deinit(sl_net_interface_t interface)
83 {
84 UNUSED_PARAMETER(interface);
85 return sl_wifi_deinit();
86 }
87
sl_net_wifi_client_up(sl_net_interface_t interface,sl_net_profile_id_t profile_id)88 sl_status_t sl_net_wifi_client_up(sl_net_interface_t interface, sl_net_profile_id_t profile_id)
89 {
90 UNUSED_PARAMETER(interface);
91 sl_status_t status;
92 sl_net_wifi_client_profile_t profile;
93
94 // Get the client profile using the provided profile_id
95 status = sl_net_get_profile(SL_NET_WIFI_CLIENT_INTERFACE, profile_id, &profile);
96 VERIFY_STATUS_AND_RETURN(status);
97
98 // Connect to the Wi-Fi network
99 status = sl_wifi_connect(SL_WIFI_CLIENT_INTERFACE, &profile.config, 18000);
100 VERIFY_STATUS_AND_RETURN(status);
101
102 // Configure the IP address settings
103 status = sl_si91x_configure_ip_address(&profile.ip, SL_SI91X_WIFI_CLIENT_VAP_ID);
104 VERIFY_STATUS_AND_RETURN(status);
105 dhcp_type[SLI_SI91X_CLIENT] = profile.ip.mode;
106
107 // Set the client profile
108 status = sl_net_set_profile(SL_NET_WIFI_CLIENT_INTERFACE, profile_id, &profile);
109 return status;
110 }
111
sl_net_wifi_client_down(sl_net_interface_t interface)112 sl_status_t sl_net_wifi_client_down(sl_net_interface_t interface)
113 {
114 UNUSED_PARAMETER(interface);
115
116 // Disconnect from the Wi-Fi network
117 return sl_wifi_disconnect(SL_WIFI_CLIENT_INTERFACE);
118 }
119
sl_net_wifi_ap_init(sl_net_interface_t interface,const void * configuration,const void * workspace,sl_net_event_handler_t event_handler)120 sl_status_t sl_net_wifi_ap_init(sl_net_interface_t interface,
121 const void *configuration,
122 const void *workspace,
123 sl_net_event_handler_t event_handler)
124 {
125 UNUSED_PARAMETER(interface);
126 UNUSED_PARAMETER(workspace);
127 sl_status_t status = SL_STATUS_FAIL;
128
129 // Set the user-defined event handler for AP mode
130 sl_si91x_register_event_handler(event_handler);
131
132 status = sl_wifi_init(configuration, NULL, sl_wifi_default_event_handler);
133 VERIFY_STATUS_AND_RETURN(status);
134 return status;
135 }
136
sl_net_wifi_ap_deinit(sl_net_interface_t interface)137 sl_status_t sl_net_wifi_ap_deinit(sl_net_interface_t interface)
138 {
139 UNUSED_PARAMETER(interface);
140 return sl_wifi_deinit();
141 }
142
sl_net_wifi_ap_up(sl_net_interface_t interface,sl_net_profile_id_t profile_id)143 sl_status_t sl_net_wifi_ap_up(sl_net_interface_t interface, sl_net_profile_id_t profile_id)
144 {
145 UNUSED_PARAMETER(interface);
146 sl_status_t status;
147 sl_net_wifi_ap_profile_t profile;
148
149 status = sl_net_get_profile(SL_NET_WIFI_AP_INTERFACE, profile_id, &profile);
150 VERIFY_STATUS_AND_RETURN(status);
151
152 // Validate if profile configuration is valid
153 // AP + DHCP client not supported
154 // AP + link local not supported
155 if (profile.ip.mode != SL_IP_MANAGEMENT_STATIC_IP) {
156 return SL_STATUS_INVALID_CONFIGURATION;
157 }
158 status = sl_si91x_configure_ip_address(&profile.ip, SL_SI91X_WIFI_AP_VAP_ID);
159 VERIFY_STATUS_AND_RETURN(status);
160 dhcp_type[SLI_SI91X_AP] = profile.ip.mode;
161
162 // Set the AP profile
163 status = sl_net_set_profile(SL_NET_WIFI_AP_INTERFACE, profile_id, &profile);
164 VERIFY_STATUS_AND_RETURN(status);
165
166 status = sl_wifi_start_ap(SL_WIFI_AP_2_4GHZ_INTERFACE, &profile.config);
167 VERIFY_STATUS_AND_RETURN(status);
168
169 return status;
170 }
171
sl_net_wifi_ap_down(sl_net_interface_t interface)172 sl_status_t sl_net_wifi_ap_down(sl_net_interface_t interface)
173 {
174 UNUSED_PARAMETER(interface);
175 return sl_wifi_stop_ap(SL_WIFI_AP_INTERFACE);
176 }
177
sl_net_join_multicast_address(sl_net_interface_t interface,const sl_ip_address_t * ip_address)178 sl_status_t sl_net_join_multicast_address(sl_net_interface_t interface, const sl_ip_address_t *ip_address)
179 {
180 return sli_si91x_send_multicast_request((sl_wifi_interface_t)interface, ip_address, SL_WIFI_MULTICAST_JOIN);
181 }
182
sl_net_leave_multicast_address(sl_net_interface_t interface,const sl_ip_address_t * ip_address)183 sl_status_t sl_net_leave_multicast_address(sl_net_interface_t interface, const sl_ip_address_t *ip_address)
184 {
185 return sli_si91x_send_multicast_request((sl_wifi_interface_t)interface, ip_address, SL_WIFI_MULTICAST_LEAVE);
186 }
187
sli_si91x_send_multicast_request(sl_wifi_interface_t interface,const sl_ip_address_t * ip_address,uint8_t command_type)188 static sl_status_t sli_si91x_send_multicast_request(sl_wifi_interface_t interface,
189 const sl_ip_address_t *ip_address,
190 uint8_t command_type)
191 {
192 UNUSED_PARAMETER(interface);
193 si91x_req_multicast_t multicast = { 0 };
194 sl_status_t status = SL_STATUS_OK;
195
196 if (!device_initialized) {
197 return SL_STATUS_NOT_INITIALIZED;
198 }
199
200 //Fill IP version and IP address
201 if (ip_address->type == SL_IPV6) {
202 multicast.ip_version[0] = 6;
203 memcpy(multicast.multicast_address.ipv6_address, ip_address->ip.v6.bytes, RSI_IP_ADDRESS_LEN * 4);
204 } else {
205 multicast.ip_version[0] = 4;
206 memcpy(multicast.multicast_address.ipv4_address, ip_address->ip.v4.bytes, RSI_IP_ADDRESS_LEN);
207 }
208 multicast.type[0] = command_type;
209
210 status = sl_si91x_driver_send_command(RSI_WLAN_REQ_MULTICAST,
211 SI91X_NETWORK_CMD,
212 &multicast,
213 sizeof(multicast),
214 SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
215 NULL,
216 NULL);
217
218 VERIFY_STATUS_AND_RETURN(status);
219 return SL_STATUS_OK;
220 }
221
222 // Resolve a host name to an IP address using DNS
sl_net_dns_resolve_hostname(const char * host_name,const uint32_t timeout,const sl_net_dns_resolution_ip_type_t dns_resolution_ip,sl_ip_address_t * sl_ip_address)223 sl_status_t sl_net_dns_resolve_hostname(const char *host_name,
224 const uint32_t timeout,
225 const sl_net_dns_resolution_ip_type_t dns_resolution_ip,
226 sl_ip_address_t *sl_ip_address)
227 {
228 // Check for a NULL pointer for sl_ip_address
229 SL_WIFI_ARGS_CHECK_NULL_POINTER(sl_ip_address);
230
231 sl_status_t status;
232 sl_si91x_packet_t *packet;
233 sl_wifi_buffer_t *buffer = NULL;
234 const sl_si91x_dns_response_t *dns_response = { 0 };
235 sl_si91x_dns_query_request_t dns_query_request = { 0 };
236
237 // Determine the wait period based on the timeout value
238 sl_si91x_wait_period_t wait_period = timeout == 0 ? SL_SI91X_RETURN_IMMEDIATELY : SL_SI91X_WAIT_FOR_RESPONSE(timeout);
239 // Determine the IP version to be used (IPv4 or IPv6)
240 dns_query_request.ip_version[0] = (dns_resolution_ip == SL_NET_DNS_TYPE_IPV4) ? 4 : 6;
241 memcpy(dns_query_request.url_name, host_name, sizeof(dns_query_request.url_name));
242
243 status = sl_si91x_driver_send_command(RSI_WLAN_REQ_DNS_QUERY,
244 SI91X_NETWORK_CMD,
245 &dns_query_request,
246 sizeof(dns_query_request),
247 wait_period,
248 NULL,
249 &buffer);
250
251 // Check if the command failed and free the buffer if it was allocated
252 if ((status != SL_STATUS_OK) && (buffer != NULL)) {
253 sl_si91x_host_free_buffer(buffer);
254 }
255 VERIFY_STATUS_AND_RETURN(status);
256
257 // Extract the DNS response from the SI91X packet buffer
258 packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
259 dns_response = (sl_si91x_dns_response_t *)packet->data;
260
261 // Convert the SI91X DNS response to the sl_ip_address format
262 convert_si91x_dns_response(sl_ip_address, dns_response);
263 sl_si91x_host_free_buffer(buffer);
264 return SL_STATUS_OK;
265 }
266
sl_net_set_dns_server(sl_net_interface_t interface,const sl_net_dns_address_t * address)267 sl_status_t sl_net_set_dns_server(sl_net_interface_t interface, const sl_net_dns_address_t *address)
268 {
269 UNUSED_PARAMETER(interface);
270 sl_status_t status = 0;
271 sli_dns_server_add_request_t dns_server_add_request = { 0 };
272
273 if (!device_initialized) {
274 return SL_STATUS_NOT_INITIALIZED;
275 }
276
277 //! Check for invalid parameters
278 if ((address->primary_server_address && address->primary_server_address->type != SL_IPV4
279 && address->primary_server_address->type != SL_IPV6)
280 || (address->secondary_server_address && address->secondary_server_address->type != SL_IPV4
281 && address->secondary_server_address->type != SL_IPV6)) {
282 //! Throw error in case of invalid parameters
283 return SL_STATUS_INVALID_PARAMETER;
284 }
285
286 //! Set DNS mode
287 dns_server_add_request.dns_mode[0] =
288 (address->primary_server_address == NULL && address->secondary_server_address == NULL) ? 1 /*dhcp*/ : 0 /*static*/;
289
290 if (address->primary_server_address && address->primary_server_address->type == SL_IPV4) {
291 dns_server_add_request.ip_version[0] = SL_IPV4_VERSION;
292 //! Fill Primary IP address
293 memcpy(dns_server_add_request.sli_ip_address1.primary_dns_ipv4,
294 address->primary_server_address->ip.v4.bytes,
295 SL_IPV4_ADDRESS_LENGTH);
296 } else if (address->primary_server_address && address->primary_server_address->type == SL_IPV6) {
297 dns_server_add_request.ip_version[0] = SL_IPV6_VERSION;
298 //! Fill Primary IP address
299 memcpy(dns_server_add_request.sli_ip_address1.primary_dns_ipv6,
300 address->primary_server_address->ip.v6.bytes,
301 SL_IPV6_ADDRESS_LENGTH);
302 }
303
304 if (address->secondary_server_address && address->secondary_server_address->type == SL_IPV4) {
305 dns_server_add_request.ip_version[0] = SL_IPV4_VERSION;
306 //! Fill Secondary IP address
307 memcpy(dns_server_add_request.sli_ip_address2.secondary_dns_ipv4,
308 address->secondary_server_address->ip.v4.bytes,
309 SL_IPV4_ADDRESS_LENGTH);
310 } else if (address->secondary_server_address && address->secondary_server_address->type == SL_IPV6) {
311 dns_server_add_request.ip_version[0] = SL_IPV6_VERSION;
312 //! Fill Secondary IP address
313 memcpy(dns_server_add_request.sli_ip_address2.secondary_dns_ipv6,
314 address->secondary_server_address->ip.v6.bytes,
315 SL_IPV6_ADDRESS_LENGTH);
316 }
317
318 status = sl_si91x_driver_send_command(RSI_WLAN_REQ_DNS_SERVER_ADD,
319 SI91X_NETWORK_CMD,
320 &dns_server_add_request,
321 sizeof(dns_server_add_request),
322 SL_SI91X_WAIT_FOR_COMMAND_SUCCESS,
323 NULL,
324 NULL);
325
326 return status;
327 }
328
sl_net_configure_ip(sl_net_interface_t interface,const sl_net_ip_configuration_t * ip_config,uint32_t timeout)329 sl_status_t sl_net_configure_ip(sl_net_interface_t interface,
330 const sl_net_ip_configuration_t *ip_config,
331 uint32_t timeout)
332 {
333 uint8_t vap_id = 0;
334 sl_net_ip_configuration_t config = { 0 };
335
336 if (SL_NET_WIFI_CLIENT_INTERFACE == SL_NET_INTERFACE_TYPE(interface)) {
337 vap_id = SL_SI91X_WIFI_CLIENT_VAP_ID;
338 dhcp_type[SLI_SI91X_CLIENT] = ip_config->mode;
339 } else if (SL_NET_WIFI_AP_INTERFACE == SL_NET_INTERFACE_TYPE(interface)) {
340 vap_id = SL_SI91X_WIFI_AP_VAP_ID;
341 dhcp_type[SLI_SI91X_AP] = ip_config->mode;
342 } else {
343 return SL_STATUS_WIFI_UNSUPPORTED;
344 }
345
346 memcpy(&config, ip_config, sizeof(sl_net_ip_configuration_t));
347 return sli_si91x_configure_ip_address(&config, vap_id, timeout);
348 }
349
sl_net_get_ip_address(sl_net_interface_t interface,sl_net_ip_address_t * ip_address,uint32_t timeout)350 sl_status_t sl_net_get_ip_address(sl_net_interface_t interface, sl_net_ip_address_t *ip_address, uint32_t timeout)
351 {
352 uint8_t vap_id = 0;
353 sl_status_t status = 0;
354 sl_net_ip_configuration_t ip_config = { 0 };
355
356 if (SL_NET_WIFI_CLIENT_INTERFACE == SL_NET_INTERFACE_TYPE(interface)) {
357 vap_id = SL_SI91X_WIFI_CLIENT_VAP_ID;
358 ip_address->mode = dhcp_type[SLI_SI91X_CLIENT];
359 } else if (SL_NET_WIFI_AP_INTERFACE == SL_NET_INTERFACE_TYPE(interface)) {
360 vap_id = SL_SI91X_WIFI_AP_VAP_ID;
361 ip_address->mode = dhcp_type[SLI_SI91X_AP];
362 return SL_STATUS_OK;
363 } else {
364 return SL_STATUS_WIFI_UNSUPPORTED;
365 }
366
367 ip_config.mode = SL_IP_MANAGEMENT_DHCP;
368 #ifdef SLI_SI91X_ENABLE_IPV6
369 ip_config.type = SL_IPV6;
370 #else
371 ip_config.type = SL_IPV4;
372 #endif
373 status = sli_si91x_configure_ip_address(&ip_config, vap_id, timeout);
374 if (status != SL_STATUS_OK) {
375 return status;
376 }
377
378 ip_address->type = ip_config.type;
379 // Copy the IPv4 addresses to the address structure
380 memcpy(ip_address->v4.ip_address.bytes, (const uint8_t *)ip_config.ip.v4.ip_address.bytes, sizeof(sl_ipv4_address_t));
381 memcpy(ip_address->v4.netmask.bytes, (const uint8_t *)ip_config.ip.v4.netmask.bytes, sizeof(sl_ipv4_address_t));
382 memcpy(ip_address->v4.gateway.bytes, (const uint8_t *)ip_config.ip.v4.gateway.bytes, sizeof(sl_ipv4_address_t));
383
384 // Copy the IPv6 addresses to the address structure
385 memcpy(&ip_address->v6.link_local_address.bytes,
386 (const uint8_t *)ip_config.ip.v6.link_local_address.bytes,
387 sizeof(sl_ipv6_address_t));
388 memcpy(&ip_address->v6.global_address.bytes,
389 (const uint8_t *)ip_config.ip.v6.global_address.bytes,
390 sizeof(sl_ipv6_address_t));
391 memcpy(&ip_address->v6.gateway.bytes, (const uint8_t *)ip_config.ip.v6.gateway.bytes, sizeof(sl_ipv6_address_t));
392
393 return SL_STATUS_OK;
394 }
395