|
| 1 | +/* |
| 2 | + * Copyright (c) 2012-2014 Wind River Systems, Inc. |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: Apache-2.0 |
| 5 | + */ |
| 6 | + |
| 7 | +#include <stdio.h> |
| 8 | +#include <stdlib.h> |
| 9 | +#include <zephyr/net/wifi_mgmt.h> |
| 10 | +#include <zephyr/net/net_if.h> |
| 11 | + |
| 12 | +#include "sl_net_ip_types.h" |
| 13 | +#include "sl_si91x_types.h" |
| 14 | +#include "sl_net_si91x.h" |
| 15 | +#include "sl_net_dns.h" |
| 16 | +#ifdef CONFIG_WIFI_SILABS_SIWX91X_PING |
| 17 | +#include "sl_net_ping.h" |
| 18 | +#endif |
| 19 | +#include "sl_net.h" |
| 20 | +#include "app_config.h" |
| 21 | + |
| 22 | +volatile uint8_t state = 0; |
| 23 | +static K_SEM_DEFINE(wlan_sem, 0, 1); |
| 24 | +K_THREAD_STACK_DEFINE(wifi_stack, STACK_SIZE); |
| 25 | + |
| 26 | +typedef enum siwx91x_app_state_e { |
| 27 | + SIWX91X_WIFI_CONNECT_STATE = 0, |
| 28 | + SIWX91X_IP_CONFIG_STATE, |
| 29 | + SIWX91X_PING_HOSTNAME_STATE |
| 30 | +} siwx91x_app_state_t; |
| 31 | + |
| 32 | +void application_start(void); |
| 33 | +static void wifi_mgmt_event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event, |
| 34 | + struct net_if *iface); |
| 35 | +static void handle_wifi_connect_result(struct net_mgmt_event_callback *cb); |
| 36 | +static sl_status_t network_event_handler(sl_net_event_t event, sl_status_t status, void *data, |
| 37 | + uint32_t data_length); |
| 38 | + |
| 39 | +static void dhcp_callback_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event, |
| 40 | + struct net_if *iface) |
| 41 | +{ |
| 42 | + uint8_t ipv4_addr[NET_IPV4_ADDR_LEN] = {0}; |
| 43 | + uint8_t subnet[NET_IPV4_ADDR_LEN] = {0}; |
| 44 | + uint8_t gateway[NET_IPV4_ADDR_LEN] = {0}; |
| 45 | + int i = 0; |
| 46 | + |
| 47 | + if (mgmt_event != NET_EVENT_IPV4_ADDR_ADD) { |
| 48 | + return; |
| 49 | + } |
| 50 | + |
| 51 | + for (i = 0; i < ARRAY_SIZE(iface->config.ip.ipv4->unicast); i++) { |
| 52 | + |
| 53 | + if (iface->config.ip.ipv4->unicast[i].ipv4.addr_type != NET_ADDR_DHCP) { |
| 54 | + continue; |
| 55 | + } |
| 56 | + |
| 57 | + printf("Address[%d]: %s", net_if_get_by_iface(iface), |
| 58 | + net_addr_ntop(AF_INET, |
| 59 | + &iface->config.ip.ipv4->unicast[i].ipv4.address.in_addr, |
| 60 | + ipv4_addr, sizeof(ipv4_addr))); |
| 61 | + printf(" Subnet[%d]: %s", net_if_get_by_iface(iface), |
| 62 | + net_addr_ntop(AF_INET, &iface->config.ip.ipv4->unicast[i].netmask, subnet, |
| 63 | + sizeof(subnet))); |
| 64 | + printf(" Router[%d]: %s", net_if_get_by_iface(iface), |
| 65 | + net_addr_ntop(AF_INET, &iface->config.ip.ipv4->gw, gateway, |
| 66 | + sizeof(gateway))); |
| 67 | + |
| 68 | + k_sem_give(&wlan_sem); |
| 69 | + } |
| 70 | +} |
| 71 | + |
| 72 | +void application_start(void) |
| 73 | +{ |
| 74 | + int32_t status = -1; |
| 75 | + uint8_t ping_count = 0; |
| 76 | + struct net_if *iface; |
| 77 | + |
| 78 | + printf("\r\nApplication started\r\n"); |
| 79 | + state = SIWX91X_WIFI_CONNECT_STATE; |
| 80 | + |
| 81 | + while (1) { |
| 82 | + switch (state) { |
| 83 | + case SIWX91X_WIFI_CONNECT_STATE: { |
| 84 | + struct wifi_connect_req_params cnx_params; |
| 85 | + |
| 86 | + iface = net_if_get_first_wifi(); |
| 87 | + memset(&cnx_params, 0, sizeof(struct wifi_connect_req_params)); |
| 88 | + context.connecting = true; |
| 89 | + cnx_params.channel = CHANNEL_NO; |
| 90 | + cnx_params.band = 0; |
| 91 | + cnx_params.security = SECURITY_TYPE; |
| 92 | + cnx_params.psk_length = strlen(PSK); |
| 93 | + cnx_params.psk = PSK; |
| 94 | + cnx_params.ssid_length = strlen(SSID); |
| 95 | + cnx_params.ssid = SSID; |
| 96 | + |
| 97 | + status = net_mgmt(NET_REQUEST_WIFI_CONNECT, iface, &cnx_params, |
| 98 | + sizeof(struct wifi_connect_req_params)); |
| 99 | + if (status != STATUS_OK) { |
| 100 | + printf("Connection request failed with error: %d\n", status); |
| 101 | + context.connecting = false; |
| 102 | + state = SIWX91X_WIFI_CONNECT_STATE; |
| 103 | + break; |
| 104 | + } |
| 105 | + printf("Connection requested\n"); |
| 106 | + |
| 107 | + if (k_sem_take(&wlan_sem, K_MSEC(CMD_WAIT_TIME)) != STATUS_OK) { |
| 108 | + printf("\r\nWi-Fi connect failed\r\n"); |
| 109 | + state = SIWX91X_WIFI_CONNECT_STATE; |
| 110 | + } |
| 111 | + } break; |
| 112 | + case SIWX91X_IP_CONFIG_STATE: { |
| 113 | + if (k_sem_take(&wlan_sem, K_MSEC(CMD_WAIT_TIME)) != STATUS_OK) { |
| 114 | + printf("\r\nIP config failed\r\n"); |
| 115 | + state = SIWX91X_IP_CONFIG_STATE; |
| 116 | + break; |
| 117 | + } |
| 118 | + state = SIWX91X_PING_HOSTNAME_STATE; |
| 119 | + } break; |
| 120 | + case SIWX91X_PING_HOSTNAME_STATE: { |
| 121 | + sl_ip_address_t dns_ip = {0}; |
| 122 | + sli_net_register_event_handler(network_event_handler); |
| 123 | + dns_ip.type = SL_IPV4; |
| 124 | + status = sl_net_dns_resolve_hostname(HOSTNAME, DNS_TIMEOUT, |
| 125 | + SL_NET_DNS_TYPE_IPV4, &dns_ip); |
| 126 | + if (status != STATUS_OK) { |
| 127 | + printf("\r\nDNS Query failed:0x%x\r\n", status); |
| 128 | + break; |
| 129 | + } |
| 130 | + printf("\r\nDNS Query successful\r\n"); |
| 131 | + printf("\r\nIP address = %d.%d.%d.%d\r\n", dns_ip.ip.v4.bytes[0], |
| 132 | + dns_ip.ip.v4.bytes[1], dns_ip.ip.v4.bytes[2], dns_ip.ip.v4.bytes[3]); |
| 133 | + while (ping_count < PING_PACKETS) { |
| 134 | + status = sl_si91x_send_ping(dns_ip, PING_PACKET_SIZE); |
| 135 | + if (status != SL_STATUS_IN_PROGRESS) { |
| 136 | + printf("\r\nPing request failed with status 0x%X\r\n", |
| 137 | + status); |
| 138 | + return; |
| 139 | + } |
| 140 | + ping_count++; |
| 141 | + k_sleep(K_MSEC(1000)); |
| 142 | + } |
| 143 | + return; |
| 144 | + } break; |
| 145 | + } |
| 146 | + } |
| 147 | +} |
| 148 | + |
| 149 | +static void wifi_mgmt_event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event, |
| 150 | + struct net_if *iface) |
| 151 | +{ |
| 152 | + switch (mgmt_event) { |
| 153 | + case NET_EVENT_WIFI_CONNECT_RESULT: |
| 154 | + handle_wifi_connect_result(cb); |
| 155 | + break; |
| 156 | + case NET_EVENT_WIFI_DISCONNECT_RESULT: |
| 157 | + break; |
| 158 | + default: |
| 159 | + break; |
| 160 | + } |
| 161 | +} |
| 162 | + |
| 163 | +static void handle_wifi_connect_result(struct net_mgmt_event_callback *cb) |
| 164 | +{ |
| 165 | + const struct wifi_status *status = (const struct wifi_status *)cb->info; |
| 166 | + int st = status->status; |
| 167 | + |
| 168 | + if (st) { |
| 169 | + if (st < 0) { |
| 170 | + /* Errno values are negative, try to map to |
| 171 | + * wifi status values. |
| 172 | + */ |
| 173 | + if (st == -ETIMEDOUT) { |
| 174 | + st = WIFI_STATUS_CONN_TIMEOUT; |
| 175 | + } |
| 176 | + } |
| 177 | + |
| 178 | + printf("Connection request failed (%s/%d)\n", wifi_conn_status_txt(st), st); |
| 179 | + state = SIWX91X_WIFI_CONNECT_STATE; |
| 180 | + } else { |
| 181 | + printf("Connected to Wi-Fi\n"); |
| 182 | + state = SIWX91X_IP_CONFIG_STATE; |
| 183 | + } |
| 184 | + |
| 185 | + context.connecting = false; |
| 186 | + k_sem_give(&wlan_sem); |
| 187 | +} |
| 188 | + |
| 189 | +static sl_status_t network_event_handler(sl_net_event_t event, sl_status_t status, void *data, |
| 190 | + uint32_t data_length) |
| 191 | +{ |
| 192 | + UNUSED_PARAMETER(data_length); |
| 193 | + switch (event) { |
| 194 | + case SL_NET_PING_RESPONSE_EVENT: { |
| 195 | + sl_si91x_ping_response_t *response = (sl_si91x_ping_response_t *)data; |
| 196 | + |
| 197 | + if (status != SL_STATUS_OK) { |
| 198 | + printf("\r\nPing request failed!\r\n"); |
| 199 | + return status; |
| 200 | + } |
| 201 | + printf("\n%u bytes received from %u.%u.%u.%u\n", response->ping_size, |
| 202 | + response->ping_address.ipv4_address[0], |
| 203 | + response->ping_address.ipv4_address[1], |
| 204 | + response->ping_address.ipv4_address[2], |
| 205 | + response->ping_address.ipv4_address[3]); |
| 206 | + break; |
| 207 | + } |
| 208 | + default: |
| 209 | + break; |
| 210 | + } |
| 211 | + |
| 212 | + return SL_STATUS_OK; |
| 213 | +} |
| 214 | + |
| 215 | +int main(void) |
| 216 | +{ |
| 217 | + struct net_mgmt_event_callback wifi_mgmt_cb; |
| 218 | + struct net_mgmt_event_callback mgmt_cb; |
| 219 | + struct k_thread wifi_task_handle; |
| 220 | + |
| 221 | + printf("siwx91x sample application for ICMP\r\n"); |
| 222 | + net_mgmt_init_event_callback(&wifi_mgmt_cb, wifi_mgmt_event_handler, |
| 223 | + (WIFI_SHELL_MGMT_EVENTS)); |
| 224 | + net_mgmt_add_event_callback(&wifi_mgmt_cb); |
| 225 | + net_mgmt_init_event_callback(&mgmt_cb, dhcp_callback_handler, NET_EVENT_IPV4_ADDR_ADD); |
| 226 | + |
| 227 | + net_mgmt_add_event_callback(&mgmt_cb); |
| 228 | + |
| 229 | + k_tid_t application_tid = k_thread_create(&wifi_task_handle, wifi_stack, STACK_SIZE, |
| 230 | + (k_thread_entry_t)application_start, NULL, NULL, |
| 231 | + NULL, K_PRIO_PREEMPT(10), 0, K_NO_WAIT); |
| 232 | + |
| 233 | + k_thread_start(application_tid); |
| 234 | + k_thread_join(application_tid, K_FOREVER); |
| 235 | + printf("\r\nApplication exit\r\n"); |
| 236 | + return 0; |
| 237 | +} |
0 commit comments