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_utility.h"
32 #include "sl_net.h"
33 #include "sl_wifi.h"
34 #include "sl_net_wifi_types.h"
35 #include "sl_net_si91x.h"
36 #include "sl_si91x_host_interface.h"
37 #include "sl_si91x_driver.h"
38 #include "sl_rsi_utility.h"
39 #include "sl_net_rsi_utility.h"
40 #include "sl_si91x_core_utilities.h"
41 #include <stdbool.h>
42 #include <string.h>
43
44 // Define a bit mask for DHCP unicast offer
45 #define SL_SI91X_DHCP_UNICAST_OFFER ((uint32_t)1U << 3)
46
47 // Global variable indicating if the device is initialized
48 extern bool device_initialized;
49
sli_si91x_configure_ip_address(sl_net_ip_configuration_t * ip_config,uint8_t virtual_ap_id,const uint32_t timeout)50 sl_status_t sli_si91x_configure_ip_address(sl_net_ip_configuration_t *ip_config,
51 uint8_t virtual_ap_id,
52 const uint32_t timeout)
53 {
54 sl_status_t status = SL_STATUS_INVALID_PARAMETER;
55 sl_si91x_req_ipv4_params_t ip_req = { 0 };
56 sl_si91x_req_ipv6_params_t ipv6_request = { 0 };
57 sl_si91x_packet_t *packet;
58 sl_wifi_buffer_t *buffer = NULL;
59 uint32_t wait_time = (timeout ? SL_SI91X_WAIT_FOR_RESPONSE(timeout) : SL_SI91X_RETURN_IMMEDIATELY);
60
61 // Check if the device is initialized
62 if (!device_initialized) {
63 return SL_STATUS_NOT_INITIALIZED;
64 }
65
66 // Check for NULL ip_config pointer
67 if (NULL == ip_config) {
68 return SL_STATUS_INVALID_PARAMETER;
69 }
70
71 // Check if timeout is 0
72 if (0 == timeout) {
73 return SL_STATUS_INVALID_PARAMETER;
74 }
75
76 if (SL_IPV4 & ip_config->type) {
77 // Initialize the IPv4 request structure and fill fields accordingly
78 memset(&ip_req, 0, sizeof(ip_req));
79 ip_req.vap_id = virtual_ap_id;
80
81 if (SL_IP_MANAGEMENT_STATIC_IP == ip_config->mode) {
82 ip_req.dhcp_mode = SL_SI91X_STATIC;
83 // Fill IP address
84 memcpy(ip_req.ipaddress, ip_config->ip.v4.ip_address.bytes, 4);
85
86 // Fill network mask
87 memcpy(ip_req.netmask, ip_config->ip.v4.netmask.bytes, 4);
88
89 // Fill gateway
90 memcpy(ip_req.gateway, ip_config->ip.v4.gateway.bytes, 4);
91 } else {
92 ip_req.dhcp_mode = (SL_SI91X_DHCP | SL_SI91X_DHCP_UNICAST_OFFER);
93 }
94
95 if (NULL != ip_config->host_name) {
96 // Enable DHCP hostname option and copy the hostname
97 ip_req.dhcp_mode |= SL_SI91X_DHCP_HOSTNAME;
98 memcpy(ip_req.hostname, ip_config->host_name, sizeof(ip_req.hostname));
99 }
100
101 ip_req.dhcp_discover_rtr_interval_min = ip_config->dhcp_config.min_discover_retry_interval;
102 ip_req.dhcp_request_rtr_interval_min = ip_config->dhcp_config.min_request_retry_interval;
103 ip_req.dhcp_discover_rtr_interval_max = ip_config->dhcp_config.max_discover_retry_interval;
104 ip_req.dhcp_request_rtr_interval_max = ip_config->dhcp_config.max_request_retry_interval;
105 ip_req.dhcp_discover_max_retries = ip_config->dhcp_config.min_discover_retries;
106 ip_req.dhcp_request_max_retries = ip_config->dhcp_config.max_request_retries;
107
108 status = sl_si91x_driver_send_command(RSI_WLAN_REQ_IPCONFV4,
109 SI91X_NETWORK_CMD,
110 &ip_req,
111 sizeof(sl_si91x_req_ipv4_params_t),
112 wait_time,
113 NULL,
114 &buffer);
115
116 // Check if the command failed and free the buffer if it was allocated
117 if ((status != SL_STATUS_OK) && (buffer != NULL)) {
118 sl_si91x_host_free_buffer(buffer);
119 }
120
121 // Verify the status and return it
122 VERIFY_STATUS_AND_RETURN(status);
123 packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
124
125 if (SL_IP_MANAGEMENT_DHCP == ip_config->mode) {
126 // Extract DHCP response data if in DHCP mode
127 const sl_si91x_rsp_ipv4_params_t *response_data = (sl_si91x_rsp_ipv4_params_t *)packet->data;
128 memcpy(ip_config->ip.v4.ip_address.bytes, (const uint8_t *)response_data->ipaddr, sizeof(sl_ipv4_address_t));
129 memcpy(ip_config->ip.v4.netmask.bytes, (const uint8_t *)response_data->netmask, sizeof(sl_ipv4_address_t));
130 memcpy(ip_config->ip.v4.gateway.bytes, (const uint8_t *)response_data->gateway, sizeof(sl_ipv4_address_t));
131 }
132
133 // Free the buffer and return success status
134 sl_si91x_host_free_buffer(buffer);
135 }
136
137 if (SL_IPV6 & ip_config->type) {
138 // Initialize the IPv6 request structure
139 memset(&ipv6_request, 0, sizeof(ipv6_request));
140 uint16_t prefix_length = 64;
141 memcpy(&ipv6_request.prefixLength, &prefix_length, 2);
142 ipv6_request.vap_id = virtual_ap_id;
143
144 if (SL_IP_MANAGEMENT_STATIC_IP == ip_config->mode) {
145 // Set IPv6 mode to static
146 memcpy(&ipv6_request.ipaddr6, ip_config->ip.v6.global_address.bytes, SL_IPV6_ADDRESS_LENGTH);
147 memcpy(&ipv6_request.gateway6, ip_config->ip.v6.gateway.bytes, SL_IPV6_ADDRESS_LENGTH);
148 ipv6_request.mode[0] = SL_SI91X_STATIC;
149 } else {
150 // Set IPv6 mode to dynamic
151 ipv6_request.mode[0] = (SL_SI91X_DHCP | SL_SI91X_DHCP_UNICAST_OFFER);
152 }
153
154 // Send the IPv6 configuration request to SI91X driver
155 status = sl_si91x_driver_send_command(RSI_WLAN_REQ_IPCONFV6,
156 SI91X_NETWORK_CMD,
157 &ipv6_request,
158 sizeof(sl_si91x_req_ipv6_params_t),
159 wait_time,
160 NULL,
161 &buffer);
162
163 // Check if the command failed and free the buffer if it was allocated
164 if ((status != SL_STATUS_OK) && (buffer != NULL)) {
165 sl_si91x_host_free_buffer(buffer);
166 }
167
168 VERIFY_STATUS_AND_RETURN(status);
169
170 // Extract the IPv6 configuration response data
171 packet = sl_si91x_host_get_buffer_data(buffer, 0, NULL);
172 const sl_si91x_rsp_ipv6_params_t *ipv6_response = (sl_si91x_rsp_ipv6_params_t *)packet->data;
173
174 // Copy the IPv6 addresses to the address structure
175 memcpy(&ip_config->ip.v6.link_local_address,
176 (const uint8_t *)ipv6_response->link_local_address,
177 sizeof(ipv6_response->link_local_address));
178 memcpy(&ip_config->ip.v6.global_address,
179 (const uint8_t *)ipv6_response->global_address,
180 sizeof(ipv6_response->global_address));
181 memcpy(&ip_config->ip.v6.gateway,
182 (const uint8_t *)ipv6_response->gateway_address,
183 sizeof(ipv6_response->gateway_address));
184
185 // Free the buffer and return success status
186 sl_si91x_host_free_buffer(buffer);
187 }
188
189 return status;
190 }
191
sl_si91x_ota_firmware_upgradation(sl_ip_address_t server_ip,uint16_t server_port,uint16_t chunk_number,uint16_t timeout,uint16_t tcp_retry_count,bool asynchronous)192 sl_status_t sl_si91x_ota_firmware_upgradation(sl_ip_address_t server_ip,
193 uint16_t server_port,
194 uint16_t chunk_number,
195 uint16_t timeout,
196 uint16_t tcp_retry_count,
197 bool asynchronous)
198 {
199 sl_wifi_buffer_t *buffer = NULL;
200 sl_status_t status = SL_STATUS_FAIL;
201 sl_si91x_wait_period_t wait_period = SL_SI91X_RETURN_IMMEDIATELY;
202
203 // Initialize the OTA firmware update request structure
204 sl_si91x_ota_firmware_update_request_t otaf_fwup = { 0 };
205
206 // Determine the wait period based on the 'asynchronous' flag
207 if (asynchronous == false) {
208 wait_period = SL_SI91X_WAIT_FOR_OTAF_RESPONSE;
209 }
210
211 // Check IP version
212 if (server_ip.type == SL_IPV4) {
213 // Fill the IP version
214 otaf_fwup.ip_version = SL_IPV4;
215 memcpy(otaf_fwup.server_ip_address.ipv4_address, server_ip.ip.v4.bytes, SL_IPV4_ADDRESS_LENGTH);
216 } else if (server_ip.type == SL_IPV6) {
217 otaf_fwup.ip_version = SL_IPV6;
218 memcpy(otaf_fwup.server_ip_address.ipv6_address, server_ip.ip.v6.bytes, SL_IPV6_ADDRESS_LENGTH);
219 } else {
220 return SL_STATUS_INVALID_PARAMETER;
221 }
222
223 // Fill server port number
224 memcpy(otaf_fwup.server_port, &server_port, sizeof(server_port));
225
226 // Fill chunk number
227 memcpy(otaf_fwup.chunk_number, &chunk_number, sizeof(otaf_fwup.chunk_number));
228
229 // Fill timeout
230 memcpy(otaf_fwup.timeout, &timeout, sizeof(otaf_fwup.timeout));
231
232 // Fill TCP retry count
233 memcpy(otaf_fwup.retry_count, &tcp_retry_count, sizeof(otaf_fwup.retry_count));
234
235 status = sl_si91x_driver_send_command(RSI_WLAN_REQ_OTA_FWUP,
236 SI91X_NETWORK_CMD,
237 &otaf_fwup,
238 sizeof(sl_si91x_ota_firmware_update_request_t),
239 wait_period,
240 NULL,
241 &buffer);
242
243 // Check if the command was synchronous and free the buffer if it was allocated
244 if (asynchronous == false) {
245 if (status != SL_STATUS_OK && buffer != NULL) {
246 sl_si91x_host_free_buffer(buffer);
247 }
248 VERIFY_STATUS_AND_RETURN(status);
249 }
250 sl_si91x_host_free_buffer(buffer);
251 return status;
252 }
253
sl_si91x_configure_ip_address(sl_net_ip_configuration_t * address,uint8_t virtual_ap_id)254 sl_status_t sl_si91x_configure_ip_address(sl_net_ip_configuration_t *address, uint8_t virtual_ap_id)
255 {
256 return sli_si91x_configure_ip_address(address, virtual_ap_id, 150000);
257 }