1d4afb5ceSopenharmony_ci/*
2d4afb5ceSopenharmony_ci * libwebsockets - esp32 wifi -> lws_netdev_wifi
3d4afb5ceSopenharmony_ci *
4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
5d4afb5ceSopenharmony_ci *
6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to
8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the
9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions:
12d4afb5ceSopenharmony_ci *
13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in
14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software.
15d4afb5ceSopenharmony_ci *
16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22d4afb5ceSopenharmony_ci * IN THE SOFTWARE.
23d4afb5ceSopenharmony_ci *
24d4afb5ceSopenharmony_ci *
25d4afb5ceSopenharmony_ci * These are the esp platform wifi-specific netdev pieces.  Nothing else should
26d4afb5ceSopenharmony_ci * know any esp-specific apis.
27d4afb5ceSopenharmony_ci *
28d4afb5ceSopenharmony_ci * Operations happen via the generic lws_detdev instantiation for the platform
29d4afb5ceSopenharmony_ci * wifi device, which point in here for operations.  We also set up native OS
30d4afb5ceSopenharmony_ci * event hooks per device for wifi and IP stack events, and post them as lws_smd
31d4afb5ceSopenharmony_ci * NETWORK events on the if in the "platform private" namespace.  We then
32d4afb5ceSopenharmony_ci * service the events in the lws event loop thread context, which may again
33d4afb5ceSopenharmony_ci * generate lws_smd NETWORK events in the public namespace depending on what
34d4afb5ceSopenharmony_ci * happened.
35d4afb5ceSopenharmony_ci *
36d4afb5ceSopenharmony_ci * Scan requests go through a sul to make sure we don't get "piling on" from
37d4afb5ceSopenharmony_ci * scheduled, timed scans.  Scan results go through the lws_smd "washing" and
38d4afb5ceSopenharmony_ci * are actually parsed in lws thread context, where they are converted to lws
39d4afb5ceSopenharmony_ci * netdev scan results and processed by generic code.
40d4afb5ceSopenharmony_ci */
41d4afb5ceSopenharmony_ci
42d4afb5ceSopenharmony_ci#include "private-lib-core.h"
43d4afb5ceSopenharmony_ci
44d4afb5ceSopenharmony_ci#include "esp_system.h"
45d4afb5ceSopenharmony_ci#include "esp_spi_flash.h"
46d4afb5ceSopenharmony_ci#include "esp_wifi.h"
47d4afb5ceSopenharmony_ci#include <nvs_flash.h>
48d4afb5ceSopenharmony_ci#include <esp_netif.h>
49d4afb5ceSopenharmony_ci
50d4afb5ceSopenharmony_ci/*
51d4afb5ceSopenharmony_ci * lws_netdev_instance_t:
52d4afb5ceSopenharmony_ci *   lws_netdev_instance_wifi_t:
53d4afb5ceSopenharmony_ci *     lws_netdev_instance_wifi_esp32_t
54d4afb5ceSopenharmony_ci */
55d4afb5ceSopenharmony_ci
56d4afb5ceSopenharmony_citypedef struct lws_netdev_instance_wifi_esp32 {
57d4afb5ceSopenharmony_ci	lws_netdev_instance_wifi_t		wnd;
58d4afb5ceSopenharmony_ci	esp_event_handler_instance_t		instance_any_id;
59d4afb5ceSopenharmony_ci	esp_event_handler_instance_t		instance_got_ip;
60d4afb5ceSopenharmony_ci	wifi_config_t				sta_config;
61d4afb5ceSopenharmony_ci} lws_netdev_instance_wifi_esp32_t;
62d4afb5ceSopenharmony_ci
63d4afb5ceSopenharmony_ci/*
64d4afb5ceSopenharmony_cistatic wifi_config_t config = {
65d4afb5ceSopenharmony_ci	.ap = {
66d4afb5ceSopenharmony_ci	    .channel = 6,
67d4afb5ceSopenharmony_ci	    .authmode = WIFI_AUTH_OPEN,
68d4afb5ceSopenharmony_ci	    .max_connection = 1,
69d4afb5ceSopenharmony_ci	} };
70d4afb5ceSopenharmony_ci	*/
71d4afb5ceSopenharmony_ci
72d4afb5ceSopenharmony_ci/*
73d4afb5ceSopenharmony_ci * Platform-specific connect / associate
74d4afb5ceSopenharmony_ci */
75d4afb5ceSopenharmony_ci
76d4afb5ceSopenharmony_ciint
77d4afb5ceSopenharmony_cilws_netdev_wifi_connect_plat(lws_netdev_instance_t *nd, const char *ssid,
78d4afb5ceSopenharmony_ci			     const char *passphrase, uint8_t *bssid)
79d4afb5ceSopenharmony_ci{
80d4afb5ceSopenharmony_ci	lws_netdev_instance_wifi_esp32_t *wnde32 =
81d4afb5ceSopenharmony_ci					(lws_netdev_instance_wifi_esp32_t *)nd;
82d4afb5ceSopenharmony_ci
83d4afb5ceSopenharmony_ci	wnde32->wnd.inst.ops->up(&wnde32->wnd.inst);
84d4afb5ceSopenharmony_ci
85d4afb5ceSopenharmony_ci	wnde32->wnd.flags |= LNDIW_MODE_STA;
86d4afb5ceSopenharmony_ci	esp_wifi_set_mode(WIFI_MODE_STA);
87d4afb5ceSopenharmony_ci
88d4afb5ceSopenharmony_ci#if 0
89d4afb5ceSopenharmony_ci	/* we will do our own dhcp */
90d4afb5ceSopenharmony_ci	tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA);
91d4afb5ceSopenharmony_ci#endif
92d4afb5ceSopenharmony_ci
93d4afb5ceSopenharmony_ci	lws_strncpy((char *)wnde32->sta_config.sta.ssid, ssid,
94d4afb5ceSopenharmony_ci		    sizeof(wnde32->sta_config.sta.ssid));
95d4afb5ceSopenharmony_ci	lws_strncpy((char *)wnde32->sta_config.sta.password, passphrase,
96d4afb5ceSopenharmony_ci		    sizeof(wnde32->sta_config.sta.password));
97d4afb5ceSopenharmony_ci
98d4afb5ceSopenharmony_ci	esp_wifi_set_config(WIFI_IF_STA, &wnde32->sta_config);
99d4afb5ceSopenharmony_ci	esp_wifi_connect();
100d4afb5ceSopenharmony_ci
101d4afb5ceSopenharmony_ci	return 0;
102d4afb5ceSopenharmony_ci}
103d4afb5ceSopenharmony_ci
104d4afb5ceSopenharmony_ci/*
105d4afb5ceSopenharmony_ci * This is called from the SMD / lws thread context, after we heard there were
106d4afb5ceSopenharmony_ci * scan results on this netdev
107d4afb5ceSopenharmony_ci */
108d4afb5ceSopenharmony_ci
109d4afb5ceSopenharmony_cistatic void
110d4afb5ceSopenharmony_cilws_esp32_scan_update(lws_netdev_instance_wifi_t *wnd)
111d4afb5ceSopenharmony_ci{
112d4afb5ceSopenharmony_ci//	lws_netdevs_t *netdevs = lws_netdevs_from_ndi(&wnd->inst);
113d4afb5ceSopenharmony_ci	wifi_ap_record_t ap_records[LWS_WIFI_MAX_SCAN_TRACK], *ar;
114d4afb5ceSopenharmony_ci	uint32_t now = lws_now_secs();
115d4afb5ceSopenharmony_ci	uint16_t count_ap_records;
116d4afb5ceSopenharmony_ci	int n;
117d4afb5ceSopenharmony_ci
118d4afb5ceSopenharmony_ci	count_ap_records = LWS_ARRAY_SIZE(ap_records);
119d4afb5ceSopenharmony_ci	if (esp_wifi_scan_get_ap_records(&count_ap_records, ap_records)) {
120d4afb5ceSopenharmony_ci		lwsl_err("%s: failed\n", __func__);
121d4afb5ceSopenharmony_ci		return;
122d4afb5ceSopenharmony_ci	}
123d4afb5ceSopenharmony_ci
124d4afb5ceSopenharmony_ci	if (!count_ap_records)
125d4afb5ceSopenharmony_ci		return;
126d4afb5ceSopenharmony_ci
127d4afb5ceSopenharmony_ci	if (wnd->state != LWSNDVWIFI_STATE_SCAN)
128d4afb5ceSopenharmony_ci		return;
129d4afb5ceSopenharmony_ci
130d4afb5ceSopenharmony_ci	/*
131d4afb5ceSopenharmony_ci	 * ... let's collect the OS-specific scan results, and convert then to
132d4afb5ceSopenharmony_ci	 * lws_netdev sorted by rssi.  If we already have it in the scan list,
133d4afb5ceSopenharmony_ci	 * keep it and keep a little ringbuffer of its rssi along with an
134d4afb5ceSopenharmony_ci	 * averaging.  If it's new, add it into the linked-list sorted by rssi.
135d4afb5ceSopenharmony_ci	 */
136d4afb5ceSopenharmony_ci
137d4afb5ceSopenharmony_ci	ar = &ap_records[0];
138d4afb5ceSopenharmony_ci	for (n = 0; n < count_ap_records; n++) {
139d4afb5ceSopenharmony_ci		lws_wifi_sta_t *w;
140d4afb5ceSopenharmony_ci		int m;
141d4afb5ceSopenharmony_ci
142d4afb5ceSopenharmony_ci		m = strlen((const char *)ar->ssid);
143d4afb5ceSopenharmony_ci		if (!m)
144d4afb5ceSopenharmony_ci			goto next;
145d4afb5ceSopenharmony_ci
146d4afb5ceSopenharmony_ci		/*
147d4afb5ceSopenharmony_ci		 * We know this guy from before?
148d4afb5ceSopenharmony_ci		 */
149d4afb5ceSopenharmony_ci
150d4afb5ceSopenharmony_ci		w = lws_netdev_wifi_scan_find(wnd, (const char *)ar->ssid,
151d4afb5ceSopenharmony_ci						ar->bssid);
152d4afb5ceSopenharmony_ci		if (!w) {
153d4afb5ceSopenharmony_ci			w = lws_zalloc(sizeof(*w) + m + 1, __func__);
154d4afb5ceSopenharmony_ci			if (!w)
155d4afb5ceSopenharmony_ci				goto next;
156d4afb5ceSopenharmony_ci
157d4afb5ceSopenharmony_ci			w->ssid = (char *)&w[1];
158d4afb5ceSopenharmony_ci			memcpy(w->ssid, ar->ssid, m + 1);
159d4afb5ceSopenharmony_ci			w->ssid_len = m;
160d4afb5ceSopenharmony_ci
161d4afb5ceSopenharmony_ci			memcpy(w->bssid, ar->bssid, 6);
162d4afb5ceSopenharmony_ci
163d4afb5ceSopenharmony_ci			lws_dll2_add_sorted(&w->list, &wnd->scan,
164d4afb5ceSopenharmony_ci					    lws_netdev_wifi_rssi_sort_compare);
165d4afb5ceSopenharmony_ci		}
166d4afb5ceSopenharmony_ci
167d4afb5ceSopenharmony_ci		if (w->rssi_count == LWS_ARRAY_SIZE(w->rssi))
168d4afb5ceSopenharmony_ci			w->rssi_avg -= w->rssi[w->rssi_next];
169d4afb5ceSopenharmony_ci		else
170d4afb5ceSopenharmony_ci			w->rssi_count++;
171d4afb5ceSopenharmony_ci		w->rssi[w->rssi_next] = ar->rssi;
172d4afb5ceSopenharmony_ci		w->rssi_avg += w->rssi[w->rssi_next++];
173d4afb5ceSopenharmony_ci		w->rssi_next = w->rssi_next & (LWS_ARRAY_SIZE(w->rssi) - 1);
174d4afb5ceSopenharmony_ci
175d4afb5ceSopenharmony_ci		w->ch = ar->primary;
176d4afb5ceSopenharmony_ci		w->authmode = ar->authmode;
177d4afb5ceSopenharmony_ci		w->last_seen = now;
178d4afb5ceSopenharmony_ci
179d4afb5ceSopenharmony_cinext:
180d4afb5ceSopenharmony_ci		ar++;
181d4afb5ceSopenharmony_ci	}
182d4afb5ceSopenharmony_ci
183d4afb5ceSopenharmony_ci	/*
184d4afb5ceSopenharmony_ci	 * We can do the rest of it using the generic scan list and credentials
185d4afb5ceSopenharmony_ci	 */
186d4afb5ceSopenharmony_ci
187d4afb5ceSopenharmony_ci	lws_netdev_wifi_scan_select(wnd);
188d4afb5ceSopenharmony_ci}
189d4afb5ceSopenharmony_ci
190d4afb5ceSopenharmony_cistatic wifi_scan_config_t scan_config = {
191d4afb5ceSopenharmony_ci        .ssid = 0,
192d4afb5ceSopenharmony_ci        .bssid = 0,
193d4afb5ceSopenharmony_ci        .channel = 0,
194d4afb5ceSopenharmony_ci        .show_hidden = true
195d4afb5ceSopenharmony_ci};
196d4afb5ceSopenharmony_ci
197d4afb5ceSopenharmony_civoid
198d4afb5ceSopenharmony_cilws_netdev_wifi_scan_plat(lws_netdev_instance_t *nd)
199d4afb5ceSopenharmony_ci{
200d4afb5ceSopenharmony_ci	lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)nd;
201d4afb5ceSopenharmony_ci
202d4afb5ceSopenharmony_ci	if (esp_wifi_scan_start(&scan_config, false))
203d4afb5ceSopenharmony_ci		lwsl_err("%s: %s scan failed\n", __func__, wnd->inst.name);
204d4afb5ceSopenharmony_ci}
205d4afb5ceSopenharmony_ci
206d4afb5ceSopenharmony_ci/*
207d4afb5ceSopenharmony_ci * Platform-private interface events turn up here after going through SMD and
208d4afb5ceSopenharmony_ci * passed down by matching network interface name via generic lws_netdev.  All
209d4afb5ceSopenharmony_ci * that messing around gets us from an OS-specific thread with an event to back
210d4afb5ceSopenharmony_ci * here in lws event loop thread context, with the same event bound to a the
211d4afb5ceSopenharmony_ci * netdev it belongs to.
212d4afb5ceSopenharmony_ci */
213d4afb5ceSopenharmony_ci
214d4afb5ceSopenharmony_ciint
215d4afb5ceSopenharmony_cilws_netdev_wifi_event_plat(struct lws_netdev_instance *nd, lws_usec_t timestamp,
216d4afb5ceSopenharmony_ci			   void *buf, size_t len)
217d4afb5ceSopenharmony_ci{
218d4afb5ceSopenharmony_ci	lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)nd;
219d4afb5ceSopenharmony_ci	struct lws_context *ctx = netdev_instance_to_ctx(&wnd->inst);
220d4afb5ceSopenharmony_ci	size_t al;
221d4afb5ceSopenharmony_ci
222d4afb5ceSopenharmony_ci	/*
223d4afb5ceSopenharmony_ci	 * netdev-private sync messages?
224d4afb5ceSopenharmony_ci	 */
225d4afb5ceSopenharmony_ci
226d4afb5ceSopenharmony_ci	if (!lws_json_simple_strcmp(buf, len, "\"type\":", "priv")) {
227d4afb5ceSopenharmony_ci		const char *ev = lws_json_simple_find(buf, len, "\"ev\":", &al);
228d4afb5ceSopenharmony_ci
229d4afb5ceSopenharmony_ci		if (!ev)
230d4afb5ceSopenharmony_ci			return 0;
231d4afb5ceSopenharmony_ci
232d4afb5ceSopenharmony_ci		lwsl_notice("%s: smd priv ev %.*s\n", __func__, (int)al, ev);
233d4afb5ceSopenharmony_ci
234d4afb5ceSopenharmony_ci		switch (atoi(ev)) {
235d4afb5ceSopenharmony_ci		case WIFI_EVENT_STA_START:
236d4afb5ceSopenharmony_ci			wnd->state = LWSNDVWIFI_STATE_INITIAL;
237d4afb5ceSopenharmony_ci			if (!lws_netdev_wifi_redo_last(wnd))
238d4afb5ceSopenharmony_ci				break;
239d4afb5ceSopenharmony_ci
240d4afb5ceSopenharmony_ci			/*
241d4afb5ceSopenharmony_ci			 * if the "try last successful" one fails, start the
242d4afb5ceSopenharmony_ci			 * scan by falling through
243d4afb5ceSopenharmony_ci			 */
244d4afb5ceSopenharmony_ci
245d4afb5ceSopenharmony_ci		case WIFI_EVENT_STA_DISCONNECTED:
246d4afb5ceSopenharmony_ci			lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK,
247d4afb5ceSopenharmony_ci					   "{\"type\":\"linkdown\","
248d4afb5ceSopenharmony_ci					   "\"if\":\"%s\"}", wnd->inst.name);
249d4afb5ceSopenharmony_ci			wnd->state = LWSNDVWIFI_STATE_SCAN;
250d4afb5ceSopenharmony_ci			/*
251d4afb5ceSopenharmony_ci			 * We do it via the sul so we don't get timed scans
252d4afb5ceSopenharmony_ci			 * on top of each other
253d4afb5ceSopenharmony_ci			 */
254d4afb5ceSopenharmony_ci			lws_sul_schedule(ctx, 0, &wnd->sul_scan,
255d4afb5ceSopenharmony_ci					 lws_netdev_wifi_scan, 1);
256d4afb5ceSopenharmony_ci			break;
257d4afb5ceSopenharmony_ci
258d4afb5ceSopenharmony_ci		case WIFI_EVENT_STA_CONNECTED:
259d4afb5ceSopenharmony_ci			lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK,
260d4afb5ceSopenharmony_ci					   "{\"type\":\"linkup\","
261d4afb5ceSopenharmony_ci					   "\"if\":\"%s\"}", wnd->inst.name);
262d4afb5ceSopenharmony_ci			break;
263d4afb5ceSopenharmony_ci
264d4afb5ceSopenharmony_ci		case WIFI_EVENT_SCAN_DONE:
265d4afb5ceSopenharmony_ci			lws_esp32_scan_update(wnd);
266d4afb5ceSopenharmony_ci			break;
267d4afb5ceSopenharmony_ci		default:
268d4afb5ceSopenharmony_ci			return 0;
269d4afb5ceSopenharmony_ci		}
270d4afb5ceSopenharmony_ci
271d4afb5ceSopenharmony_ci		return 0;
272d4afb5ceSopenharmony_ci	}
273d4afb5ceSopenharmony_ci
274d4afb5ceSopenharmony_ci	return 0;
275d4afb5ceSopenharmony_ci}
276d4afb5ceSopenharmony_ci
277d4afb5ceSopenharmony_ci/*
278d4afb5ceSopenharmony_ci * This is coming from a thread context unrelated to lws... the first order is
279d4afb5ceSopenharmony_ci * to turn these into lws_smd events synchronized on lws thread, since we want
280d4afb5ceSopenharmony_ci * to change correspsonding lws netdev object states without locking.
281d4afb5ceSopenharmony_ci */
282d4afb5ceSopenharmony_ci
283d4afb5ceSopenharmony_cistatic void
284d4afb5ceSopenharmony_ci_event_handler_wifi(void *arg, esp_event_base_t event_base, int32_t event_id,
285d4afb5ceSopenharmony_ci		   void *event_data)
286d4afb5ceSopenharmony_ci{
287d4afb5ceSopenharmony_ci	lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)arg;
288d4afb5ceSopenharmony_ci	struct lws_context *ctx = netdev_instance_to_ctx(&wnd->inst);
289d4afb5ceSopenharmony_ci
290d4afb5ceSopenharmony_ci	switch (event_id) {
291d4afb5ceSopenharmony_ci	case WIFI_EVENT_STA_START:
292d4afb5ceSopenharmony_ci	case WIFI_EVENT_STA_DISCONNECTED:
293d4afb5ceSopenharmony_ci	case WIFI_EVENT_SCAN_DONE:
294d4afb5ceSopenharmony_ci	case WIFI_EVENT_STA_CONNECTED:
295d4afb5ceSopenharmony_ci		/*
296d4afb5ceSopenharmony_ci		 * These are events in the platform's private namespace,
297d4afb5ceSopenharmony_ci		 * interpreted only by the lws_smd handler above, ** in the lws
298d4afb5ceSopenharmony_ci		 * event thread context **.  The point of this is to requeue the
299d4afb5ceSopenharmony_ci		 * event in the lws thread context like a bottom-half.
300d4afb5ceSopenharmony_ci		 *
301d4afb5ceSopenharmony_ci		 * To save on registrations, the context's NETWORK smd
302d4afb5ceSopenharmony_ci		 * participant passes messages to lws_netdev, who passes ones
303d4afb5ceSopenharmony_ci		 * that have if matching the netdev name to that netdev's
304d4afb5ceSopenharmony_ci		 * (*event) handler.
305d4afb5ceSopenharmony_ci		 *
306d4afb5ceSopenharmony_ci		 * The other handler may emit generic network state SMD events
307d4afb5ceSopenharmony_ci		 * for other things to consume.
308d4afb5ceSopenharmony_ci		 */
309d4afb5ceSopenharmony_ci
310d4afb5ceSopenharmony_ci		lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK,
311d4afb5ceSopenharmony_ci				   "{\"type\":\"priv\",\"if\":\"%s\",\"ev\":%d}",
312d4afb5ceSopenharmony_ci				   wnd->inst.name, (int)event_id);
313d4afb5ceSopenharmony_ci		break;
314d4afb5ceSopenharmony_ci	default:
315d4afb5ceSopenharmony_ci		return;
316d4afb5ceSopenharmony_ci	}
317d4afb5ceSopenharmony_ci}
318d4afb5ceSopenharmony_ci
319d4afb5ceSopenharmony_ci#if 0
320d4afb5ceSopenharmony_cistatic int
321d4afb5ceSopenharmony_ciespip_to_sa46(lws_sockaddr46 *sa46, esp_ip_addr_t *eip)
322d4afb5ceSopenharmony_ci{
323d4afb5ceSopenharmony_ci	memset(sa46, 0, sizeof(sa46));
324d4afb5ceSopenharmony_ci
325d4afb5ceSopenharmony_ci	switch (eip->type) {
326d4afb5ceSopenharmony_ci	case ESP_IPADDR_TYPE_V4:
327d4afb5ceSopenharmony_ci		sa46->sa4.sin_family = AF_INET;
328d4afb5ceSopenharmony_ci		memcpy(sa46->sa4.sin_addr, &eip->u_addr.ip4.addr, );
329d4afb5ceSopenharmony_ci		return;
330d4afb5ceSopenharmony_ci	case ESP_IPADDR_TYPE_V6:
331d4afb5ceSopenharmony_ci	}
332d4afb5ceSopenharmony_ci}
333d4afb5ceSopenharmony_ci#endif
334d4afb5ceSopenharmony_ci
335d4afb5ceSopenharmony_ci/*
336d4afb5ceSopenharmony_ci * This is coming from a thread context unrelated to lws
337d4afb5ceSopenharmony_ci */
338d4afb5ceSopenharmony_ci
339d4afb5ceSopenharmony_cistatic void
340d4afb5ceSopenharmony_ci_event_handler_ip(void *arg, esp_event_base_t event_base, int32_t event_id,
341d4afb5ceSopenharmony_ci	      void *event_data)
342d4afb5ceSopenharmony_ci{
343d4afb5ceSopenharmony_ci	lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)arg;
344d4afb5ceSopenharmony_ci	lws_netdevs_t *netdevs = lws_netdevs_from_ndi(&wnd->inst);
345d4afb5ceSopenharmony_ci	struct lws_context *ctx = lws_context_from_netdevs(netdevs);
346d4afb5ceSopenharmony_ci
347d4afb5ceSopenharmony_ci	if (event_id == IP_EVENT_STA_GOT_IP) {
348d4afb5ceSopenharmony_ci		ip_event_got_ip_t *e = (ip_event_got_ip_t *)event_data;
349d4afb5ceSopenharmony_ci		char ip[16];
350d4afb5ceSopenharmony_ci#if 0
351d4afb5ceSopenharmony_ci		tcpip_adapter_dns_info_t e32ip;
352d4afb5ceSopenharmony_ci
353d4afb5ceSopenharmony_ci		/*
354d4afb5ceSopenharmony_ci		 * Since atm we get this via DHCP, presumably we can get ahold
355d4afb5ceSopenharmony_ci		 * of related info set by the router
356d4afb5ceSopenharmony_ci		 */
357d4afb5ceSopenharmony_ci
358d4afb5ceSopenharmony_ci		if (tcpip_adapter_get_dns_info(TCPIP_ADAPTER_IF_STA,
359d4afb5ceSopenharmony_ci					   TCPIP_ADAPTER_DNS_MAIN,
360d4afb5ceSopenharmony_ci					   /* also _BACKUP, _FALLBACK */
361d4afb5ceSopenharmony_ci					   &e32ip)) {
362d4afb5ceSopenharmony_ci			lwsl_err("%s: there's no dns server set\n", __func__);
363d4afb5ceSopenharmony_ci			e32ip.ip.u_addr.ipv4 = 0x08080808;
364d4afb5ceSopenharmony_ci			e32ip.ip.type = ESP_IPADDR_TYPE_V4;
365d4afb5ceSopenharmony_ci		}
366d4afb5ceSopenharmony_ci
367d4afb5ceSopenharmony_ci		netdevs->sa46_dns_resolver.
368d4afb5ceSopenharmony_ci#endif
369d4afb5ceSopenharmony_ci
370d4afb5ceSopenharmony_ci		lws_write_numeric_address((void *)&e->ip_info.ip, 4, ip,
371d4afb5ceSopenharmony_ci				sizeof(ip));
372d4afb5ceSopenharmony_ci		lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK,
373d4afb5ceSopenharmony_ci				   "{\"type\":\"ipacq\",\"if\":\"%s\","
374d4afb5ceSopenharmony_ci				   "\"ipv4\":\"%s\"}", wnd->inst.name, ip);
375d4afb5ceSopenharmony_ci	}
376d4afb5ceSopenharmony_ci}
377d4afb5ceSopenharmony_ci
378d4afb5ceSopenharmony_ci/*
379d4afb5ceSopenharmony_ci * This is the platform (esp-idf) init for any kind of networking to be
380d4afb5ceSopenharmony_ci * available at all
381d4afb5ceSopenharmony_ci */
382d4afb5ceSopenharmony_ciint
383d4afb5ceSopenharmony_cilws_netdev_plat_init(void)
384d4afb5ceSopenharmony_ci{
385d4afb5ceSopenharmony_ci        nvs_flash_init();
386d4afb5ceSopenharmony_ci	esp_netif_init();
387d4afb5ceSopenharmony_ci	ESP_ERROR_CHECK(esp_event_loop_create_default());
388d4afb5ceSopenharmony_ci
389d4afb5ceSopenharmony_ci	return 0;
390d4afb5ceSopenharmony_ci}
391d4afb5ceSopenharmony_ci
392d4afb5ceSopenharmony_ci/*
393d4afb5ceSopenharmony_ci * This is the platform (esp-idf) init for any wifi to be available at all
394d4afb5ceSopenharmony_ci */
395d4afb5ceSopenharmony_ciint
396d4afb5ceSopenharmony_cilws_netdev_plat_wifi_init(void)
397d4afb5ceSopenharmony_ci{
398d4afb5ceSopenharmony_ci	wifi_init_config_t wic = WIFI_INIT_CONFIG_DEFAULT();
399d4afb5ceSopenharmony_ci	int n;
400d4afb5ceSopenharmony_ci
401d4afb5ceSopenharmony_ci	esp_netif_create_default_wifi_sta();
402d4afb5ceSopenharmony_ci
403d4afb5ceSopenharmony_ci	n = esp_wifi_init(&wic);
404d4afb5ceSopenharmony_ci	if (n) {
405d4afb5ceSopenharmony_ci		lwsl_err("%s: wifi init fail: %d\n", __func__, n);
406d4afb5ceSopenharmony_ci		return 1;
407d4afb5ceSopenharmony_ci	}
408d4afb5ceSopenharmony_ci
409d4afb5ceSopenharmony_ci	return 0;
410d4afb5ceSopenharmony_ci}
411d4afb5ceSopenharmony_ci
412d4afb5ceSopenharmony_ci
413d4afb5ceSopenharmony_cistruct lws_netdev_instance *
414d4afb5ceSopenharmony_cilws_netdev_wifi_create_plat(struct lws_context *ctx,
415d4afb5ceSopenharmony_ci			    const lws_netdev_ops_t *ops,
416d4afb5ceSopenharmony_ci			    const char *name, void *platinfo)
417d4afb5ceSopenharmony_ci{
418d4afb5ceSopenharmony_ci	lws_netdev_instance_wifi_esp32_t *wnde32 = lws_zalloc(
419d4afb5ceSopenharmony_ci						sizeof(*wnde32), __func__);
420d4afb5ceSopenharmony_ci
421d4afb5ceSopenharmony_ci	if (!wnde32)
422d4afb5ceSopenharmony_ci		return NULL;
423d4afb5ceSopenharmony_ci
424d4afb5ceSopenharmony_ci	wnde32->wnd.inst.type = LWSNDTYP_WIFI;
425d4afb5ceSopenharmony_ci	lws_netdev_instance_create(&wnde32->wnd.inst, ctx, ops, name, platinfo);
426d4afb5ceSopenharmony_ci
427d4afb5ceSopenharmony_ci	return &wnde32->wnd.inst;
428d4afb5ceSopenharmony_ci}
429d4afb5ceSopenharmony_ci
430d4afb5ceSopenharmony_ciint
431d4afb5ceSopenharmony_cilws_netdev_wifi_configure_plat(struct lws_netdev_instance *nd,
432d4afb5ceSopenharmony_ci			       lws_netdev_config_t *config)
433d4afb5ceSopenharmony_ci{
434d4afb5ceSopenharmony_ci	return 0;
435d4afb5ceSopenharmony_ci}
436d4afb5ceSopenharmony_ci
437d4afb5ceSopenharmony_ciint
438d4afb5ceSopenharmony_cilws_netdev_wifi_up_plat(struct lws_netdev_instance *nd)
439d4afb5ceSopenharmony_ci{
440d4afb5ceSopenharmony_ci	lws_netdev_instance_wifi_esp32_t *wnde32 =
441d4afb5ceSopenharmony_ci					(lws_netdev_instance_wifi_esp32_t *)nd;
442d4afb5ceSopenharmony_ci	struct lws_context *ctx = netdev_instance_to_ctx(&wnde32->wnd.inst);
443d4afb5ceSopenharmony_ci
444d4afb5ceSopenharmony_ci	if (wnde32->wnd.flags & LNDIW_UP)
445d4afb5ceSopenharmony_ci		return 0;
446d4afb5ceSopenharmony_ci
447d4afb5ceSopenharmony_ci	ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
448d4afb5ceSopenharmony_ci			  IP_EVENT_STA_GOT_IP, &_event_handler_ip, nd,
449d4afb5ceSopenharmony_ci			  &wnde32->instance_got_ip));
450d4afb5ceSopenharmony_ci
451d4afb5ceSopenharmony_ci	ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
452d4afb5ceSopenharmony_ci			  ESP_EVENT_ANY_ID, &_event_handler_wifi, nd,
453d4afb5ceSopenharmony_ci			  &wnde32->instance_any_id));
454d4afb5ceSopenharmony_ci
455d4afb5ceSopenharmony_ci	esp_wifi_start();
456d4afb5ceSopenharmony_ci	wnde32->wnd.flags |= LNDIW_UP;
457d4afb5ceSopenharmony_ci
458d4afb5ceSopenharmony_ci	lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK,
459d4afb5ceSopenharmony_ci			   "{\"type\":\"up\",\"if\":\"%s\"}",
460d4afb5ceSopenharmony_ci			   wnde32->wnd.inst.name);
461d4afb5ceSopenharmony_ci
462d4afb5ceSopenharmony_ci	return 0;
463d4afb5ceSopenharmony_ci}
464d4afb5ceSopenharmony_ci
465d4afb5ceSopenharmony_ciint
466d4afb5ceSopenharmony_cilws_netdev_wifi_down_plat(struct lws_netdev_instance *nd)
467d4afb5ceSopenharmony_ci{
468d4afb5ceSopenharmony_ci	lws_netdev_instance_wifi_esp32_t *wnde32 =
469d4afb5ceSopenharmony_ci					(lws_netdev_instance_wifi_esp32_t *)nd;
470d4afb5ceSopenharmony_ci	struct lws_context *ctx = netdev_instance_to_ctx(&wnde32->wnd.inst);
471d4afb5ceSopenharmony_ci
472d4afb5ceSopenharmony_ci	if (!(wnde32->wnd.flags & LNDIW_UP))
473d4afb5ceSopenharmony_ci		return 0;
474d4afb5ceSopenharmony_ci
475d4afb5ceSopenharmony_ci	lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK,
476d4afb5ceSopenharmony_ci			   "{\"type\":\"down\",\"if\":\"%s\"}",
477d4afb5ceSopenharmony_ci			   wnde32->wnd.inst.name);
478d4afb5ceSopenharmony_ci
479d4afb5ceSopenharmony_ci	esp_wifi_stop();
480d4afb5ceSopenharmony_ci
481d4afb5ceSopenharmony_ci	esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP,
482d4afb5ceSopenharmony_ci						&wnde32->instance_got_ip);
483d4afb5ceSopenharmony_ci	esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID,
484d4afb5ceSopenharmony_ci						&wnde32->instance_any_id);
485d4afb5ceSopenharmony_ci
486d4afb5ceSopenharmony_ci	wnde32->wnd.flags &= ~LNDIW_UP;
487d4afb5ceSopenharmony_ci
488d4afb5ceSopenharmony_ci	return 0;
489d4afb5ceSopenharmony_ci}
490d4afb5ceSopenharmony_ci
491d4afb5ceSopenharmony_civoid
492d4afb5ceSopenharmony_cilws_netdev_wifi_destroy_plat(struct lws_netdev_instance **pnd)
493d4afb5ceSopenharmony_ci{
494d4afb5ceSopenharmony_ci	lws_free(*pnd);
495d4afb5ceSopenharmony_ci	*pnd = NULL;
496d4afb5ceSopenharmony_ci}
497