1 /*
2 * Copyright (c) 2024 Muhammad Haziq
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/logging/log.h>
9 #include <zephyr/net/wifi_mgmt.h>
10 #include <zephyr/net/dhcpv4_server.h>
11
12 LOG_MODULE_REGISTER(MAIN);
13
14 #define MACSTR "%02X:%02X:%02X:%02X:%02X:%02X"
15
16 #define NET_EVENT_WIFI_MASK \
17 (NET_EVENT_WIFI_CONNECT_RESULT | NET_EVENT_WIFI_DISCONNECT_RESULT | \
18 NET_EVENT_WIFI_AP_ENABLE_RESULT | NET_EVENT_WIFI_AP_DISABLE_RESULT | \
19 NET_EVENT_WIFI_AP_STA_CONNECTED | NET_EVENT_WIFI_AP_STA_DISCONNECTED)
20
21 /* AP Mode Configuration */
22 #define WIFI_AP_SSID "ESP32-AP"
23 #define WIFI_AP_PSK ""
24 #define WIFI_AP_IP_ADDRESS "192.168.4.1"
25 #define WIFI_AP_NETMASK "255.255.255.0"
26
27 /* STA Mode Configuration */
28 #define WIFI_SSID "SSID" /* Replace `SSID` with WiFi ssid. */
29 #define WIFI_PSK "PASSWORD" /* Replace `PASSWORD` with Router password. */
30
31 static struct net_if *ap_iface;
32 static struct net_if *sta_iface;
33
34 static struct wifi_connect_req_params ap_config;
35 static struct wifi_connect_req_params sta_config;
36
37 static struct net_mgmt_event_callback cb;
38
wifi_event_handler(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)39 static void wifi_event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event,
40 struct net_if *iface)
41 {
42 switch (mgmt_event) {
43 case NET_EVENT_WIFI_CONNECT_RESULT: {
44 LOG_INF("Connected to %s", WIFI_SSID);
45 break;
46 }
47 case NET_EVENT_WIFI_DISCONNECT_RESULT: {
48 LOG_INF("Disconnected from %s", WIFI_SSID);
49 break;
50 }
51 case NET_EVENT_WIFI_AP_ENABLE_RESULT: {
52 LOG_INF("AP Mode is enabled. Waiting for station to connect");
53 break;
54 }
55 case NET_EVENT_WIFI_AP_DISABLE_RESULT: {
56 LOG_INF("AP Mode is disabled.");
57 break;
58 }
59 case NET_EVENT_WIFI_AP_STA_CONNECTED: {
60 struct wifi_ap_sta_info *sta_info = (struct wifi_ap_sta_info *)cb->info;
61
62 LOG_INF("station: " MACSTR " joined ", sta_info->mac[0], sta_info->mac[1],
63 sta_info->mac[2], sta_info->mac[3], sta_info->mac[4], sta_info->mac[5]);
64 break;
65 }
66 case NET_EVENT_WIFI_AP_STA_DISCONNECTED: {
67 struct wifi_ap_sta_info *sta_info = (struct wifi_ap_sta_info *)cb->info;
68
69 LOG_INF("station: " MACSTR " leave ", sta_info->mac[0], sta_info->mac[1],
70 sta_info->mac[2], sta_info->mac[3], sta_info->mac[4], sta_info->mac[5]);
71 break;
72 }
73 default:
74 break;
75 }
76 }
77
enable_dhcpv4_server(void)78 static void enable_dhcpv4_server(void)
79 {
80 static struct in_addr addr;
81 static struct in_addr netmaskAddr;
82
83 if (net_addr_pton(AF_INET, WIFI_AP_IP_ADDRESS, &addr)) {
84 LOG_ERR("Invalid address: %s", WIFI_AP_IP_ADDRESS);
85 return;
86 }
87
88 if (net_addr_pton(AF_INET, WIFI_AP_NETMASK, &netmaskAddr)) {
89 LOG_ERR("Invalid netmask: %s", WIFI_AP_NETMASK);
90 return;
91 }
92
93 net_if_ipv4_set_gw(ap_iface, &addr);
94
95 if (net_if_ipv4_addr_add(ap_iface, &addr, NET_ADDR_MANUAL, 0) == NULL) {
96 LOG_ERR("unable to set IP address for AP interface");
97 }
98
99 if (!net_if_ipv4_set_netmask_by_addr(ap_iface, &addr, &netmaskAddr)) {
100 LOG_ERR("Unable to set netmask for AP interface: %s", WIFI_AP_NETMASK);
101 }
102
103 addr.s4_addr[3] += 10; /* Starting IPv4 address for DHCPv4 address pool. */
104
105 if (net_dhcpv4_server_start(ap_iface, &addr) != 0) {
106 LOG_ERR("DHCP server is not started for desired IP");
107 return;
108 }
109
110 LOG_INF("DHCPv4 server started...\n");
111 }
112
enable_ap_mode(void)113 static int enable_ap_mode(void)
114 {
115 if (!ap_iface) {
116 LOG_INF("AP: is not initialized");
117 return -EIO;
118 }
119
120 LOG_INF("Turning on AP Mode");
121 ap_config.ssid = (const uint8_t *)WIFI_AP_SSID;
122 ap_config.ssid_length = strlen(WIFI_AP_SSID);
123 ap_config.psk = (const uint8_t *)WIFI_AP_PSK;
124 ap_config.psk_length = strlen(WIFI_AP_PSK);
125 ap_config.channel = WIFI_CHANNEL_ANY;
126 ap_config.band = WIFI_FREQ_BAND_2_4_GHZ;
127
128 if (strlen(WIFI_AP_PSK) == 0) {
129 ap_config.security = WIFI_SECURITY_TYPE_NONE;
130 } else {
131
132 ap_config.security = WIFI_SECURITY_TYPE_PSK;
133 }
134
135 enable_dhcpv4_server();
136
137 int ret = net_mgmt(NET_REQUEST_WIFI_AP_ENABLE, ap_iface, &ap_config,
138 sizeof(struct wifi_connect_req_params));
139 if (ret) {
140 LOG_ERR("NET_REQUEST_WIFI_AP_ENABLE failed, err: %d", ret);
141 }
142
143 return ret;
144 }
145
connect_to_wifi(void)146 static int connect_to_wifi(void)
147 {
148 if (!sta_iface) {
149 LOG_INF("STA: interface no initialized");
150 return -EIO;
151 }
152
153 sta_config.ssid = (const uint8_t *)WIFI_SSID;
154 sta_config.ssid_length = strlen(WIFI_SSID);
155 sta_config.psk = (const uint8_t *)WIFI_PSK;
156 sta_config.psk_length = strlen(WIFI_PSK);
157 sta_config.security = WIFI_SECURITY_TYPE_PSK;
158 sta_config.channel = WIFI_CHANNEL_ANY;
159 sta_config.band = WIFI_FREQ_BAND_2_4_GHZ;
160
161 LOG_INF("Connecting to SSID: %s\n", sta_config.ssid);
162
163 int ret = net_mgmt(NET_REQUEST_WIFI_CONNECT, sta_iface, &sta_config,
164 sizeof(struct wifi_connect_req_params));
165 if (ret) {
166 LOG_ERR("Unable to Connect to (%s)", WIFI_SSID);
167 }
168
169 return ret;
170 }
171
main(void)172 int main(void)
173 {
174 k_sleep(K_SECONDS(5));
175
176 net_mgmt_init_event_callback(&cb, wifi_event_handler, NET_EVENT_WIFI_MASK);
177 net_mgmt_add_event_callback(&cb);
178
179 /* Get AP interface in AP-STA mode. */
180 ap_iface = net_if_get_wifi_sap();
181
182 /* Get STA interface in AP-STA mode. */
183 sta_iface = net_if_get_wifi_sta();
184
185 enable_ap_mode();
186 connect_to_wifi();
187
188 return 0;
189 }
190