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