1 /*
2  * Copyright (c) 2019 Tobias Svehagen
3  * Copyright (c) 2020 Grinn
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT espressif_esp_at
9 
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_REGISTER(wifi_esp_at, CONFIG_WIFI_LOG_LEVEL);
12 
13 #include <zephyr/kernel.h>
14 #include <ctype.h>
15 #include <errno.h>
16 #include <zephyr/device.h>
17 #include <zephyr/init.h>
18 #include <stdlib.h>
19 
20 #include <zephyr/drivers/gpio.h>
21 #include <zephyr/drivers/uart.h>
22 
23 #include <zephyr/net/dns_resolve.h>
24 #include <zephyr/net/net_if.h>
25 #include <zephyr/net/net_ip.h>
26 #include <zephyr/net/net_offload.h>
27 #include <zephyr/net/wifi_mgmt.h>
28 
29 #include "esp.h"
30 
31 struct esp_config {
32 #if DT_INST_NODE_HAS_PROP(0, power_gpios)
33 	const struct gpio_dt_spec power;
34 #endif
35 #if DT_INST_NODE_HAS_PROP(0, reset_gpios)
36 	const struct gpio_dt_spec reset;
37 #endif
38 };
39 
40 NET_BUF_POOL_DEFINE(mdm_recv_pool, MDM_RECV_MAX_BUF, MDM_RECV_BUF_SIZE,
41 		    0, NULL);
42 
43 /* RX thread structures */
44 K_KERNEL_STACK_DEFINE(esp_rx_stack,
45 		      CONFIG_WIFI_ESP_AT_RX_STACK_SIZE);
46 struct k_thread esp_rx_thread;
47 
48 /* RX thread work queue */
49 K_KERNEL_STACK_DEFINE(esp_workq_stack,
50 		      CONFIG_WIFI_ESP_AT_WORKQ_STACK_SIZE);
51 
52 static const struct esp_config esp_driver_config = {
53 #if DT_INST_NODE_HAS_PROP(0, power_gpios)
54 	.power = GPIO_DT_SPEC_INST_GET(0, power_gpios),
55 #endif
56 #if DT_INST_NODE_HAS_PROP(0, reset_gpios)
57 	.reset = GPIO_DT_SPEC_INST_GET(0, reset_gpios),
58 #endif
59 };
60 struct esp_data esp_driver_data;
61 
esp_configure_hostname(struct esp_data * data)62 static void esp_configure_hostname(struct esp_data *data)
63 {
64 #if defined(CONFIG_NET_HOSTNAME_ENABLE)
65 	char cmd[sizeof("AT+CWHOSTNAME=\"\"") + NET_HOSTNAME_MAX_LEN];
66 
67 	snprintk(cmd, sizeof(cmd), "AT+CWHOSTNAME=\"%s\"", net_hostname_get());
68 	cmd[sizeof(cmd) - 1] = '\0';
69 
70 	esp_cmd_send(data, NULL, 0, cmd, ESP_CMD_TIMEOUT);
71 #else
72 	ARG_UNUSED(data);
73 #endif
74 }
75 
esp_mode_from_flags(struct esp_data * data)76 static inline uint8_t esp_mode_from_flags(struct esp_data *data)
77 {
78 	uint8_t flags = data->flags;
79 	uint8_t mode = 0;
80 
81 	if (flags & (EDF_STA_CONNECTED | EDF_STA_LOCK)) {
82 		mode |= ESP_MODE_STA;
83 	}
84 
85 	if (flags & EDF_AP_ENABLED) {
86 		mode |= ESP_MODE_AP;
87 	}
88 
89 	/*
90 	 * ESP AT 1.7 does not allow to disable radio, so enter STA mode
91 	 * instead.
92 	 */
93 	if (IS_ENABLED(CONFIG_WIFI_ESP_AT_VERSION_1_7) &&
94 	    mode == ESP_MODE_NONE) {
95 		mode = ESP_MODE_STA;
96 	}
97 
98 	return mode;
99 }
100 
esp_mode_switch(struct esp_data * data,uint8_t mode)101 static int esp_mode_switch(struct esp_data *data, uint8_t mode)
102 {
103 	char cmd[] = "AT+"_CWMODE"=X";
104 	int err;
105 
106 	cmd[sizeof(cmd) - 2] = ('0' + mode);
107 	LOG_DBG("Switch to mode %hhu", mode);
108 
109 	err = esp_cmd_send(data, NULL, 0, cmd, ESP_CMD_TIMEOUT);
110 	if (err) {
111 		LOG_WRN("Failed to switch to mode %d: %d", (int) mode, err);
112 	}
113 
114 	return err;
115 }
116 
esp_mode_switch_if_needed(struct esp_data * data)117 static int esp_mode_switch_if_needed(struct esp_data *data)
118 {
119 	uint8_t new_mode = esp_mode_from_flags(data);
120 	uint8_t old_mode = data->mode;
121 	int err;
122 
123 	if (old_mode == new_mode) {
124 		return 0;
125 	}
126 
127 	data->mode = new_mode;
128 
129 	err = esp_mode_switch(data, new_mode);
130 	if (err) {
131 		return err;
132 	}
133 
134 	if (!(old_mode & ESP_MODE_STA) && (new_mode & ESP_MODE_STA)) {
135 		/*
136 		 * Hostname change is applied only when STA is enabled.
137 		 */
138 		esp_configure_hostname(data);
139 	}
140 
141 	return 0;
142 }
143 
esp_mode_switch_submit_if_needed(struct esp_data * data)144 static void esp_mode_switch_submit_if_needed(struct esp_data *data)
145 {
146 	if (data->mode != esp_mode_from_flags(data)) {
147 		k_work_submit_to_queue(&data->workq, &data->mode_switch_work);
148 	}
149 }
150 
esp_mode_switch_work(struct k_work * work)151 static void esp_mode_switch_work(struct k_work *work)
152 {
153 	struct esp_data *data =
154 		CONTAINER_OF(work, struct esp_data, mode_switch_work);
155 
156 	(void)esp_mode_switch_if_needed(data);
157 }
158 
esp_mode_flags_set(struct esp_data * data,uint8_t flags)159 static inline int esp_mode_flags_set(struct esp_data *data, uint8_t flags)
160 {
161 	esp_flags_set(data, flags);
162 
163 	return esp_mode_switch_if_needed(data);
164 }
165 
esp_mode_flags_clear(struct esp_data * data,uint8_t flags)166 static inline int esp_mode_flags_clear(struct esp_data *data, uint8_t flags)
167 {
168 	esp_flags_clear(data, flags);
169 
170 	return esp_mode_switch_if_needed(data);
171 }
172 
173 /*
174  * Modem Response Command Handlers
175  */
176 
177 /* Handler: OK */
MODEM_CMD_DEFINE(on_cmd_ok)178 MODEM_CMD_DEFINE(on_cmd_ok)
179 {
180 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
181 					    cmd_handler_data);
182 
183 	modem_cmd_handler_set_error(data, 0);
184 	k_sem_give(&dev->sem_response);
185 
186 	return 0;
187 }
188 
189 /* Handler: ERROR */
MODEM_CMD_DEFINE(on_cmd_error)190 MODEM_CMD_DEFINE(on_cmd_error)
191 {
192 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
193 					    cmd_handler_data);
194 
195 	modem_cmd_handler_set_error(data, -EIO);
196 	k_sem_give(&dev->sem_response);
197 
198 	return 0;
199 }
200 
201 /* RX thread */
esp_rx(struct esp_data * data)202 static void esp_rx(struct esp_data *data)
203 {
204 	while (true) {
205 		/* wait for incoming data */
206 		modem_iface_uart_rx_wait(&data->mctx.iface, K_FOREVER);
207 
208 		modem_cmd_handler_process(&data->mctx.cmd_handler, &data->mctx.iface);
209 
210 		/* give up time if we have a solid stream of data */
211 		k_yield();
212 	}
213 }
214 
str_unquote(char * str)215 static char *str_unquote(char *str)
216 {
217 	char *end;
218 
219 	if (str[0] != '"') {
220 		return str;
221 	}
222 
223 	str++;
224 
225 	end = strrchr(str, '"');
226 	if (end != NULL) {
227 		*end = 0;
228 	}
229 
230 	return str;
231 }
232 
233 /* +CIPSTAMAC:"xx:xx:xx:xx:xx:xx" */
MODEM_CMD_DEFINE(on_cmd_cipstamac)234 MODEM_CMD_DEFINE(on_cmd_cipstamac)
235 {
236 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
237 					    cmd_handler_data);
238 	char *mac;
239 
240 	mac = str_unquote(argv[0]);
241 	net_bytes_from_str(dev->mac_addr, sizeof(dev->mac_addr), mac);
242 
243 	return 0;
244 }
245 
246 /* +CWLAP:(sec,ssid,rssi,channel) */
247 /* with: CONFIG_WIFI_ESP_AT_SCAN_MAC_ADDRESS: +CWLAP:<ecn>,<ssid>,<rssi>,<mac>,<ch>*/
MODEM_CMD_DEFINE(on_cmd_cwlap)248 MODEM_CMD_DEFINE(on_cmd_cwlap)
249 {
250 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
251 					    cmd_handler_data);
252 	struct wifi_scan_result res = { 0 };
253 	int i;
254 
255 	i = strtol(&argv[0][1], NULL, 10);
256 	if (i == 0) {
257 		res.security = WIFI_SECURITY_TYPE_NONE;
258 	} else {
259 		res.security = WIFI_SECURITY_TYPE_PSK;
260 	}
261 
262 	argv[1] = str_unquote(argv[1]);
263 	i = strlen(argv[1]);
264 	if (i > sizeof(res.ssid)) {
265 		i = sizeof(res.ssid);
266 	}
267 
268 	memcpy(res.ssid, argv[1], i);
269 	res.ssid_length = i;
270 	res.rssi = strtol(argv[2], NULL, 10);
271 
272 	if (IS_ENABLED(CONFIG_WIFI_ESP_AT_SCAN_MAC_ADDRESS)) {
273 		argv[3] = str_unquote(argv[3]);
274 		res.mac_length = WIFI_MAC_ADDR_LEN;
275 		if (net_bytes_from_str(res.mac, sizeof(res.mac), argv[3]) < 0) {
276 			LOG_ERR("Invalid MAC address");
277 			res.mac_length = 0;
278 		}
279 		res.channel = (argc > 4) ? strtol(argv[4], NULL, 10) : -1;
280 	} else {
281 		res.channel = strtol(argv[3], NULL, 10);
282 	}
283 
284 	if (dev->scan_cb) {
285 		dev->scan_cb(dev->net_iface, 0, &res);
286 	}
287 
288 	return 0;
289 }
290 
291 /* +CWJAP:(ssid,bssid,channel,rssi) */
MODEM_CMD_DEFINE(on_cmd_cwjap)292 MODEM_CMD_DEFINE(on_cmd_cwjap)
293 {
294 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
295 					    cmd_handler_data);
296 	struct wifi_iface_status *status = dev->wifi_status;
297 	const char *ssid = str_unquote(argv[0]);
298 	const char *bssid = str_unquote(argv[1]);
299 	const char *channel = argv[2];
300 	const char *rssi = argv[3];
301 	uint8_t flags = dev->flags;
302 	int err;
303 
304 	status->band = WIFI_FREQ_BAND_2_4_GHZ;
305 	status->iface_mode = WIFI_MODE_INFRA;
306 
307 	if (flags & EDF_STA_CONNECTED) {
308 		status->state = WIFI_STATE_COMPLETED;
309 	} else if (flags & EDF_STA_CONNECTING) {
310 		status->state = WIFI_STATE_SCANNING;
311 	} else {
312 		status->state = WIFI_STATE_DISCONNECTED;
313 	}
314 
315 	strncpy(status->ssid, ssid, sizeof(status->ssid));
316 	status->ssid_len = strlen(status->ssid);
317 
318 	err = net_bytes_from_str(status->bssid, sizeof(status->bssid), bssid);
319 	if (err) {
320 		LOG_WRN("Invalid MAC address");
321 		memset(status->bssid, 0x0, sizeof(status->bssid));
322 	}
323 
324 	status->channel = strtol(channel, NULL, 10);
325 	status->rssi = strtol(rssi, NULL, 10);
326 
327 	return 0;
328 }
329 
esp_dns_work(struct k_work * work)330 static void esp_dns_work(struct k_work *work)
331 {
332 #if defined(ESP_MAX_DNS)
333 	struct esp_data *data = CONTAINER_OF(work, struct esp_data, dns_work);
334 	struct dns_resolve_context *dnsctx;
335 	struct sockaddr_in *addrs = data->dns_addresses;
336 	const struct sockaddr *dns_servers[ESP_MAX_DNS + 1] = {};
337 	size_t i;
338 	int err;
339 
340 	for (i = 0; i < ESP_MAX_DNS; i++) {
341 		if (!addrs[i].sin_addr.s_addr) {
342 			break;
343 		}
344 		dns_servers[i] = (struct sockaddr *) &addrs[i];
345 	}
346 
347 	dnsctx = dns_resolve_get_default();
348 	err = dns_resolve_reconfigure(dnsctx, NULL, dns_servers);
349 	if (err) {
350 		LOG_ERR("Could not set DNS servers: %d", err);
351 	}
352 
353 	LOG_DBG("DNS resolver reconfigured");
354 #endif
355 }
356 
357 /* +CIPDNS:enable[,"DNS IP1"[,"DNS IP2"[,"DNS IP3"]]] */
MODEM_CMD_DEFINE(on_cmd_cipdns)358 MODEM_CMD_DEFINE(on_cmd_cipdns)
359 {
360 #if defined(ESP_MAX_DNS)
361 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
362 					    cmd_handler_data);
363 	struct sockaddr_in *addrs = dev->dns_addresses;
364 	char **servers = (char **)argv + 1;
365 	size_t num_servers = argc - 1;
366 	size_t valid_servers = 0;
367 	size_t i;
368 	int err;
369 
370 	for (i = 0; i < ESP_MAX_DNS; i++) {
371 		if (i >= num_servers) {
372 			addrs[i].sin_addr.s_addr = 0;
373 			break;
374 		}
375 
376 		servers[i] = str_unquote(servers[i]);
377 		LOG_DBG("DNS[%zu]: %s", i, servers[i]);
378 
379 		err = net_addr_pton(AF_INET, servers[i], &addrs[i].sin_addr);
380 		if (err) {
381 			LOG_ERR("Invalid DNS address: %s",
382 				servers[i]);
383 			addrs[i].sin_addr.s_addr = 0;
384 			break;
385 		}
386 
387 		addrs[i].sin_family = AF_INET;
388 		addrs[i].sin_port = htons(53);
389 
390 		valid_servers++;
391 	}
392 
393 	if (valid_servers) {
394 		k_work_submit(&dev->dns_work);
395 	}
396 #endif
397 
398 	return 0;
399 }
400 
401 static const struct modem_cmd response_cmds[] = {
402 	MODEM_CMD("OK", on_cmd_ok, 0U, ""), /* 3GPP */
403 	MODEM_CMD("ERROR", on_cmd_error, 0U, ""), /* 3GPP */
404 };
405 
MODEM_CMD_DEFINE(on_cmd_wifi_connected)406 MODEM_CMD_DEFINE(on_cmd_wifi_connected)
407 {
408 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
409 					    cmd_handler_data);
410 
411 	if (esp_flags_are_set(dev, EDF_STA_CONNECTED)) {
412 		return 0;
413 	}
414 
415 	esp_flags_set(dev, EDF_STA_CONNECTED);
416 	wifi_mgmt_raise_connect_result_event(dev->net_iface, 0);
417 	net_if_dormant_off(dev->net_iface);
418 
419 	return 0;
420 }
421 
esp_mgmt_disconnect_work(struct k_work * work)422 static void esp_mgmt_disconnect_work(struct k_work *work)
423 {
424 	struct esp_socket *sock;
425 	struct esp_data *dev;
426 
427 	dev = CONTAINER_OF(work, struct esp_data, disconnect_work);
428 
429 	/* Cleanup any sockets that weren't closed */
430 	for (int i = 0; i < ARRAY_SIZE(dev->sockets); i++) {
431 		sock = &dev->sockets[i];
432 		if (esp_socket_connected(sock)) {
433 			LOG_WRN("Socket %d left open, manually closing", i);
434 			esp_socket_close(sock);
435 		}
436 	}
437 
438 	esp_flags_clear(dev, EDF_STA_CONNECTED);
439 	esp_mode_switch_submit_if_needed(dev);
440 
441 	net_if_ipv4_addr_rm(dev->net_iface, &dev->ip);
442 	net_if_dormant_on(dev->net_iface);
443 	wifi_mgmt_raise_disconnect_result_event(dev->net_iface, 0);
444 }
445 
MODEM_CMD_DEFINE(on_cmd_wifi_disconnected)446 MODEM_CMD_DEFINE(on_cmd_wifi_disconnected)
447 {
448 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
449 					    cmd_handler_data);
450 
451 	if (esp_flags_are_set(dev, EDF_STA_CONNECTED)) {
452 		k_work_submit_to_queue(&dev->workq, &dev->disconnect_work);
453 	}
454 
455 	return 0;
456 }
457 
458 /*
459  * +CIPSTA:ip:"<ip>"
460  * +CIPSTA:gateway:"<ip>"
461  * +CIPSTA:netmask:"<ip>"
462  */
MODEM_CMD_DEFINE(on_cmd_cipsta)463 MODEM_CMD_DEFINE(on_cmd_cipsta)
464 {
465 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
466 					    cmd_handler_data);
467 	char *ip;
468 
469 	ip = str_unquote(argv[1]);
470 
471 	if (!strcmp(argv[0], "ip")) {
472 		net_addr_pton(AF_INET, ip, &dev->ip);
473 	} else if (!strcmp(argv[0], "gateway")) {
474 		net_addr_pton(AF_INET, ip, &dev->gw);
475 	} else if (!strcmp(argv[0], "netmask")) {
476 		net_addr_pton(AF_INET, ip, &dev->nm);
477 	} else {
478 		LOG_WRN("Unknown IP type %s", argv[0]);
479 	}
480 
481 	return 0;
482 }
483 
esp_ip_addr_work(struct k_work * work)484 static void esp_ip_addr_work(struct k_work *work)
485 {
486 	struct k_work_delayable *dwork = k_work_delayable_from_work(work);
487 	struct esp_data *dev = CONTAINER_OF(dwork, struct esp_data,
488 					    ip_addr_work);
489 	int ret;
490 
491 	static const struct modem_cmd cmds[] = {
492 		MODEM_CMD("+"_CIPSTA":", on_cmd_cipsta, 2U, ":"),
493 	};
494 	static const struct modem_cmd dns_cmds[] = {
495 		MODEM_CMD_ARGS_MAX("+CIPDNS:", on_cmd_cipdns, 1U, 3U, ","),
496 	};
497 
498 	ret = esp_cmd_send(dev, cmds, ARRAY_SIZE(cmds), "AT+"_CIPSTA"?",
499 			   ESP_CMD_TIMEOUT);
500 	if (ret < 0) {
501 		LOG_WRN("Failed to query IP settings: ret %d", ret);
502 		k_work_reschedule_for_queue(&dev->workq, &dev->ip_addr_work,
503 					    K_SECONDS(5));
504 		return;
505 	}
506 
507 	/* update interface addresses */
508 	net_if_ipv4_set_gw(dev->net_iface, &dev->gw);
509 	net_if_ipv4_set_netmask(dev->net_iface, &dev->nm);
510 #if defined(CONFIG_WIFI_ESP_AT_IP_STATIC)
511 	net_if_ipv4_addr_add(dev->net_iface, &dev->ip, NET_ADDR_MANUAL, 0);
512 #else
513 	net_if_ipv4_addr_add(dev->net_iface, &dev->ip, NET_ADDR_DHCP, 0);
514 #endif
515 
516 	if (IS_ENABLED(CONFIG_WIFI_ESP_AT_DNS_USE)) {
517 		ret = esp_cmd_send(dev, dns_cmds, ARRAY_SIZE(dns_cmds),
518 				   "AT+CIPDNS?", ESP_CMD_TIMEOUT);
519 		if (ret) {
520 			LOG_WRN("DNS fetch failed: %d", ret);
521 		}
522 	}
523 }
524 
MODEM_CMD_DEFINE(on_cmd_got_ip)525 MODEM_CMD_DEFINE(on_cmd_got_ip)
526 {
527 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
528 					    cmd_handler_data);
529 
530 	k_work_reschedule_for_queue(&dev->workq, &dev->ip_addr_work,
531 				    K_SECONDS(1));
532 
533 	return 0;
534 }
535 
MODEM_CMD_DEFINE(on_cmd_connect)536 MODEM_CMD_DEFINE(on_cmd_connect)
537 {
538 	struct esp_socket *sock;
539 	struct esp_data *dev;
540 	uint8_t link_id;
541 
542 	link_id = data->match_buf[0] - '0';
543 
544 	dev = CONTAINER_OF(data, struct esp_data, cmd_handler_data);
545 	sock = esp_socket_ref_from_link_id(dev, link_id);
546 	if (!sock) {
547 		LOG_ERR("No socket for link %d", link_id);
548 		return 0;
549 	}
550 
551 	esp_socket_unref(sock);
552 
553 	return 0;
554 }
555 
MODEM_CMD_DEFINE(on_cmd_closed)556 MODEM_CMD_DEFINE(on_cmd_closed)
557 {
558 	struct esp_socket *sock;
559 	struct esp_data *dev;
560 	uint8_t link_id;
561 	atomic_val_t old_flags;
562 
563 	link_id = data->match_buf[0] - '0';
564 
565 	LOG_DBG("Link %d closed", link_id);
566 
567 	dev = CONTAINER_OF(data, struct esp_data, cmd_handler_data);
568 	sock = esp_socket_ref_from_link_id(dev, link_id);
569 	if (!sock) {
570 		LOG_ERR("No socket for link %d", link_id);
571 		return 0;
572 	}
573 
574 	old_flags = esp_socket_flags_clear_and_set(sock,
575 				ESP_SOCK_CONNECTED, ESP_SOCK_CLOSE_PENDING);
576 
577 	if (!(old_flags & ESP_SOCK_CONNECTED)) {
578 		LOG_DBG("Link %d already closed", link_id);
579 		goto socket_unref;
580 	}
581 
582 	if (!(old_flags & ESP_SOCK_CLOSE_PENDING)) {
583 		esp_socket_work_submit(sock, &sock->close_work);
584 	}
585 
586 socket_unref:
587 	esp_socket_unref(sock);
588 
589 	return 0;
590 }
591 
592 /*
593  * Passive mode: "+IPD,<id>,<len>\r\n"
594  * Other:        "+IPD,<id>,<len>:<data>"
595  */
596 #define MIN_IPD_LEN (sizeof("+IPD,I,0E") - 1)
597 #define MAX_IPD_LEN (sizeof("+IPD,I,4294967295E") - 1)
598 
cmd_ipd_parse_hdr(struct net_buf * buf,uint16_t len,uint8_t * link_id,int * data_offset,int * data_len,char * end)599 static int cmd_ipd_parse_hdr(struct net_buf *buf, uint16_t len,
600 			     uint8_t *link_id,
601 			     int *data_offset, int *data_len,
602 			     char *end)
603 {
604 	char *endptr, ipd_buf[MAX_IPD_LEN + 1];
605 	size_t frags_len;
606 	size_t match_len;
607 
608 	frags_len = net_buf_frags_len(buf);
609 
610 	/* Wait until minimum cmd length is available */
611 	if (frags_len < MIN_IPD_LEN) {
612 		return -EAGAIN;
613 	}
614 
615 	match_len = net_buf_linearize(ipd_buf, MAX_IPD_LEN,
616 				      buf, 0, MAX_IPD_LEN);
617 
618 	ipd_buf[match_len] = 0;
619 	if (ipd_buf[len] != ',' || ipd_buf[len + 2] != ',') {
620 		LOG_ERR("Invalid IPD: %s", ipd_buf);
621 		return -EBADMSG;
622 	}
623 
624 	*link_id = ipd_buf[len + 1] - '0';
625 
626 	*data_len = strtol(&ipd_buf[len + 3], &endptr, 10);
627 
628 	if (endptr == &ipd_buf[len + 3] ||
629 	    (*endptr == 0 && match_len >= MAX_IPD_LEN)) {
630 		LOG_ERR("Invalid IPD len: %s", ipd_buf);
631 		return -EBADMSG;
632 	} else if (*endptr == 0) {
633 		return -EAGAIN;
634 	}
635 
636 	*end = *endptr;
637 	*data_offset = (endptr - ipd_buf) + 1;
638 
639 	return 0;
640 }
641 
cmd_ipd_check_hdr_end(struct esp_socket * sock,char actual)642 static int cmd_ipd_check_hdr_end(struct esp_socket *sock, char actual)
643 {
644 	char expected;
645 
646 	/* When using passive mode, the +IPD command ends with \r\n */
647 	if (ESP_PROTO_PASSIVE(esp_socket_ip_proto(sock))) {
648 		expected = '\r';
649 	} else {
650 		expected = ':';
651 	}
652 
653 	if (expected != actual) {
654 		LOG_ERR("Invalid cmd end 0x%02x, expected 0x%02x", actual,
655 			expected);
656 		return -EBADMSG;
657 	}
658 
659 	return 0;
660 }
661 
MODEM_CMD_DIRECT_DEFINE(on_cmd_ipd)662 MODEM_CMD_DIRECT_DEFINE(on_cmd_ipd)
663 {
664 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
665 					    cmd_handler_data);
666 	struct esp_socket *sock;
667 	int data_offset, data_len;
668 	uint8_t link_id;
669 	char cmd_end;
670 	int err;
671 	int ret;
672 
673 	err = cmd_ipd_parse_hdr(data->rx_buf, len, &link_id, &data_offset,
674 				&data_len, &cmd_end);
675 	if (err) {
676 		if (err == -EAGAIN) {
677 			return -EAGAIN;
678 		}
679 
680 		return len;
681 	}
682 
683 	sock = esp_socket_ref_from_link_id(dev, link_id);
684 	if (!sock) {
685 		LOG_ERR("No socket for link %d", link_id);
686 		return len;
687 	}
688 
689 	err = cmd_ipd_check_hdr_end(sock, cmd_end);
690 	if (err) {
691 		ret = len;
692 		goto socket_unref;
693 	}
694 
695 	/*
696 	 * When using passive TCP, the data itself is not included in the +IPD
697 	 * command but must be polled with AT+CIPRECVDATA.
698 	 */
699 	if (ESP_PROTO_PASSIVE(esp_socket_ip_proto(sock))) {
700 		esp_socket_work_submit(sock, &sock->recvdata_work);
701 		ret = data_offset;
702 		goto socket_unref;
703 	}
704 
705 	/* Do we have the whole message? */
706 	if (data_offset + data_len > net_buf_frags_len(data->rx_buf)) {
707 		ret = -EAGAIN;
708 		goto socket_unref;
709 	}
710 
711 	esp_socket_rx(sock, data->rx_buf, data_offset, data_len);
712 
713 	ret = data_offset + data_len;
714 
715 socket_unref:
716 	esp_socket_unref(sock);
717 
718 	return ret;
719 }
720 
MODEM_CMD_DEFINE(on_cmd_busy_sending)721 MODEM_CMD_DEFINE(on_cmd_busy_sending)
722 {
723 	LOG_WRN("Busy sending");
724 	return 0;
725 }
726 
MODEM_CMD_DEFINE(on_cmd_busy_processing)727 MODEM_CMD_DEFINE(on_cmd_busy_processing)
728 {
729 	LOG_WRN("Busy processing");
730 	return 0;
731 }
732 
733 /*
734  * The 'ready' command is sent when device has booted and is ready to receive
735  * commands. It is only expected after a reset of the device.
736  */
MODEM_CMD_DEFINE(on_cmd_ready)737 MODEM_CMD_DEFINE(on_cmd_ready)
738 {
739 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
740 					    cmd_handler_data);
741 	k_sem_give(&dev->sem_if_ready);
742 
743 
744 	if (net_if_is_carrier_ok(dev->net_iface)) {
745 		net_if_dormant_on(dev->net_iface);
746 		net_if_carrier_off(dev->net_iface);
747 		LOG_ERR("Unexpected reset");
748 	}
749 
750 	if (esp_flags_are_set(dev, EDF_STA_CONNECTING)) {
751 		wifi_mgmt_raise_connect_result_event(dev->net_iface, -1);
752 	} else if (esp_flags_are_set(dev, EDF_STA_CONNECTED)) {
753 		wifi_mgmt_raise_disconnect_result_event(dev->net_iface, 0);
754 	}
755 
756 	dev->flags = 0;
757 	dev->mode = 0;
758 
759 	net_if_ipv4_addr_rm(dev->net_iface, &dev->ip);
760 	k_work_submit_to_queue(&dev->workq, &dev->init_work);
761 
762 	return 0;
763 }
764 
765 #if defined(CONFIG_WIFI_ESP_AT_FETCH_VERSION)
766 
cmd_version_log(struct modem_cmd_handler_data * data,const char * type,const char * version)767 static int cmd_version_log(struct modem_cmd_handler_data *data,
768 			   const char *type, const char *version)
769 {
770 	LOG_INF("%s: %s", type, version);
771 
772 	return 0;
773 }
774 
MODEM_CMD_DEFINE(on_cmd_at_version)775 MODEM_CMD_DEFINE(on_cmd_at_version)
776 {
777 	return cmd_version_log(data, "AT version", argv[0]);
778 }
779 
MODEM_CMD_DEFINE(on_cmd_sdk_version)780 MODEM_CMD_DEFINE(on_cmd_sdk_version)
781 {
782 	return cmd_version_log(data, "SDK version", argv[0]);
783 }
784 
MODEM_CMD_DEFINE(on_cmd_compile_time)785 MODEM_CMD_DEFINE(on_cmd_compile_time)
786 {
787 	return cmd_version_log(data, "compile time", argv[0]);
788 }
789 
MODEM_CMD_DEFINE(on_cmd_bin_version)790 MODEM_CMD_DEFINE(on_cmd_bin_version)
791 {
792 	return cmd_version_log(data, "Bin version", argv[0]);
793 }
794 
795 #endif /* CONFIG_WIFI_ESP_AT_FETCH_VERSION */
796 
797 static const struct modem_cmd unsol_cmds[] = {
798 	MODEM_CMD("WIFI CONNECTED", on_cmd_wifi_connected, 0U, ""),
799 	MODEM_CMD("WIFI DISCONNECT", on_cmd_wifi_disconnected, 0U, ""),
800 	MODEM_CMD("WIFI GOT IP", on_cmd_got_ip, 0U, ""),
801 	MODEM_CMD("0,CONNECT", on_cmd_connect, 0U, ""),
802 	MODEM_CMD("1,CONNECT", on_cmd_connect, 0U, ""),
803 	MODEM_CMD("2,CONNECT", on_cmd_connect, 0U, ""),
804 	MODEM_CMD("3,CONNECT", on_cmd_connect, 0U, ""),
805 	MODEM_CMD("4,CONNECT", on_cmd_connect, 0U, ""),
806 	MODEM_CMD("0,CLOSED", on_cmd_closed, 0U, ""),
807 	MODEM_CMD("1,CLOSED", on_cmd_closed, 0U, ""),
808 	MODEM_CMD("2,CLOSED", on_cmd_closed, 0U, ""),
809 	MODEM_CMD("3,CLOSED", on_cmd_closed, 0U, ""),
810 	MODEM_CMD("4,CLOSED", on_cmd_closed, 0U, ""),
811 	MODEM_CMD("busy s...", on_cmd_busy_sending, 0U, ""),
812 	MODEM_CMD("busy p...", on_cmd_busy_processing, 0U, ""),
813 	MODEM_CMD("ready", on_cmd_ready, 0U, ""),
814 #if defined(CONFIG_WIFI_ESP_AT_FETCH_VERSION)
815 	MODEM_CMD("AT version:", on_cmd_at_version, 1U, ""),
816 	MODEM_CMD("SDK version:", on_cmd_sdk_version, 1U, ""),
817 	MODEM_CMD("Compile time", on_cmd_compile_time, 1U, ""),
818 	MODEM_CMD("Bin version:", on_cmd_bin_version, 1U, ""),
819 #endif
820 	MODEM_CMD_DIRECT("+IPD", on_cmd_ipd),
821 };
822 
esp_mgmt_iface_status_work(struct k_work * work)823 static void esp_mgmt_iface_status_work(struct k_work *work)
824 {
825 	struct esp_data *data = CONTAINER_OF(work, struct esp_data, iface_status_work);
826 	struct wifi_iface_status *status = data->wifi_status;
827 	int ret;
828 	static const struct modem_cmd cmds[] = {
829 		MODEM_CMD("+CWJAP:", on_cmd_cwjap, 4U, ","),
830 	};
831 
832 	ret = esp_cmd_send(data, cmds, ARRAY_SIZE(cmds), "AT+CWJAP?",
833 			   ESP_IFACE_STATUS_TIMEOUT);
834 	if (ret < 0) {
835 		LOG_WRN("Failed to request STA status: ret %d", ret);
836 		status->state = WIFI_STATE_UNKNOWN;
837 	}
838 
839 	k_sem_give(&data->wifi_status_sem);
840 }
841 
esp_mgmt_iface_status(const struct device * dev,struct wifi_iface_status * status)842 static int esp_mgmt_iface_status(const struct device *dev,
843 				 struct wifi_iface_status *status)
844 {
845 	struct esp_data *data = dev->data;
846 
847 	memset(status, 0x0, sizeof(*status));
848 
849 	status->state = WIFI_STATE_UNKNOWN;
850 	status->band = WIFI_FREQ_BAND_UNKNOWN;
851 	status->iface_mode = WIFI_MODE_UNKNOWN;
852 	status->link_mode = WIFI_LINK_MODE_UNKNOWN;
853 	status->security = WIFI_SECURITY_TYPE_UNKNOWN;
854 	status->mfp = WIFI_MFP_UNKNOWN;
855 
856 	if (!net_if_is_carrier_ok(data->net_iface)) {
857 		status->state = WIFI_STATE_INTERFACE_DISABLED;
858 		return 0;
859 	}
860 
861 	data->wifi_status = status;
862 	k_sem_init(&data->wifi_status_sem, 0, 1);
863 
864 	k_work_submit_to_queue(&data->workq, &data->iface_status_work);
865 
866 	k_sem_take(&data->wifi_status_sem, K_FOREVER);
867 
868 	return 0;
869 }
870 
esp_mgmt_scan_work(struct k_work * work)871 static void esp_mgmt_scan_work(struct k_work *work)
872 {
873 	struct esp_data *dev;
874 	int ret;
875 	static const struct modem_cmd cmds[] = {
876 #if defined(CONFIG_WIFI_ESP_AT_SCAN_MAC_ADDRESS)
877 		MODEM_CMD("+CWLAP:", on_cmd_cwlap, 5U, ","),
878 #else
879 		MODEM_CMD("+CWLAP:", on_cmd_cwlap, 4U, ","),
880 #endif
881 	};
882 
883 	dev = CONTAINER_OF(work, struct esp_data, scan_work);
884 
885 	ret = esp_mode_flags_set(dev, EDF_STA_LOCK);
886 	if (ret < 0) {
887 		goto out;
888 	}
889 	ret = esp_cmd_send(dev,
890 			   cmds, ARRAY_SIZE(cmds),
891 			   ESP_CMD_CWLAP,
892 			   ESP_SCAN_TIMEOUT);
893 	esp_mode_flags_clear(dev, EDF_STA_LOCK);
894 	LOG_DBG("ESP Wi-Fi scan: cmd = %s", ESP_CMD_CWLAP);
895 
896 	if (ret < 0) {
897 		LOG_ERR("Failed to scan: ret %d", ret);
898 	}
899 
900 out:
901 	dev->scan_cb(dev->net_iface, 0, NULL);
902 	dev->scan_cb = NULL;
903 }
904 
esp_mgmt_scan(const struct device * dev,struct wifi_scan_params * params,scan_result_cb_t cb)905 static int esp_mgmt_scan(const struct device *dev,
906 			 struct wifi_scan_params *params,
907 			 scan_result_cb_t cb)
908 {
909 	struct esp_data *data = dev->data;
910 
911 	ARG_UNUSED(params);
912 
913 	if (data->scan_cb != NULL) {
914 		return -EINPROGRESS;
915 	}
916 
917 	if (!net_if_is_carrier_ok(data->net_iface)) {
918 		return -EIO;
919 	}
920 
921 	data->scan_cb = cb;
922 
923 	k_work_submit_to_queue(&data->workq, &data->scan_work);
924 
925 	return 0;
926 };
927 
MODEM_CMD_DEFINE(on_cmd_fail)928 MODEM_CMD_DEFINE(on_cmd_fail)
929 {
930 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
931 					    cmd_handler_data);
932 
933 	modem_cmd_handler_set_error(data, -EIO);
934 	k_sem_give(&dev->sem_response);
935 
936 	return 0;
937 }
938 
esp_mgmt_connect_work(struct k_work * work)939 static void esp_mgmt_connect_work(struct k_work *work)
940 {
941 	struct esp_data *dev;
942 	int ret;
943 	static const struct modem_cmd cmds[] = {
944 		MODEM_CMD("FAIL", on_cmd_fail, 0U, ""),
945 	};
946 
947 	dev = CONTAINER_OF(work, struct esp_data, connect_work);
948 
949 	ret = esp_mode_flags_set(dev, EDF_STA_LOCK);
950 	if (ret < 0) {
951 		goto out;
952 	}
953 
954 	ret = esp_cmd_send(dev, cmds, ARRAY_SIZE(cmds), dev->conn_cmd,
955 			   ESP_CONNECT_TIMEOUT);
956 
957 	memset(dev->conn_cmd, 0, sizeof(dev->conn_cmd));
958 
959 	if (ret < 0) {
960 		net_if_dormant_on(dev->net_iface);
961 		if (esp_flags_are_set(dev, EDF_STA_CONNECTED)) {
962 			esp_flags_clear(dev, EDF_STA_CONNECTED);
963 			wifi_mgmt_raise_disconnect_result_event(dev->net_iface,
964 								0);
965 		} else {
966 			wifi_mgmt_raise_connect_result_event(dev->net_iface,
967 							     ret);
968 		}
969 	} else if (!esp_flags_are_set(dev, EDF_STA_CONNECTED)) {
970 		esp_flags_set(dev, EDF_STA_CONNECTED);
971 		wifi_mgmt_raise_connect_result_event(dev->net_iface, 0);
972 		net_if_dormant_off(dev->net_iface);
973 	}
974 
975 	esp_mode_flags_clear(dev, EDF_STA_LOCK);
976 
977 out:
978 	esp_flags_clear(dev, EDF_STA_CONNECTING);
979 }
980 
esp_mgmt_connect(const struct device * dev,struct wifi_connect_req_params * params)981 static int esp_mgmt_connect(const struct device *dev,
982 			    struct wifi_connect_req_params *params)
983 {
984 	struct esp_data *data = dev->data;
985 	int len;
986 
987 	if (!net_if_is_carrier_ok(data->net_iface) ||
988 	    !net_if_is_admin_up(data->net_iface)) {
989 		return -EIO;
990 	}
991 
992 	if (esp_flags_are_set(data, EDF_STA_CONNECTED | EDF_STA_CONNECTING)) {
993 		return -EALREADY;
994 	}
995 
996 	esp_flags_set(data, EDF_STA_CONNECTING);
997 
998 	len = snprintk(data->conn_cmd, sizeof(data->conn_cmd),
999 		       "AT+"_CWJAP"=\"");
1000 	memcpy(&data->conn_cmd[len], params->ssid, params->ssid_length);
1001 	len += params->ssid_length;
1002 
1003 	len += snprintk(&data->conn_cmd[len],
1004 				sizeof(data->conn_cmd) - len, "\",\"");
1005 
1006 	if (params->security == WIFI_SECURITY_TYPE_PSK) {
1007 		memcpy(&data->conn_cmd[len], params->psk, params->psk_length);
1008 		len += params->psk_length;
1009 	}
1010 
1011 	len += snprintk(&data->conn_cmd[len], sizeof(data->conn_cmd) - len,
1012 			"\"");
1013 
1014 	k_work_submit_to_queue(&data->workq, &data->connect_work);
1015 
1016 	return 0;
1017 }
1018 
esp_mgmt_disconnect(const struct device * dev)1019 static int esp_mgmt_disconnect(const struct device *dev)
1020 {
1021 	struct esp_data *data = dev->data;
1022 	int ret;
1023 
1024 	ret = esp_cmd_send(data, NULL, 0, "AT+CWQAP", ESP_CMD_TIMEOUT);
1025 
1026 	return ret;
1027 }
1028 
esp_mgmt_ap_enable(const struct device * dev,struct wifi_connect_req_params * params)1029 static int esp_mgmt_ap_enable(const struct device *dev,
1030 			      struct wifi_connect_req_params *params)
1031 {
1032 	char cmd[sizeof("AT+"_CWSAP"=\"\",\"\",xx,x") + WIFI_SSID_MAX_LEN +
1033 		 WIFI_PSK_MAX_LEN];
1034 	struct esp_data *data = dev->data;
1035 	int ecn = 0, len, ret;
1036 
1037 	ret = esp_mode_flags_set(data, EDF_AP_ENABLED);
1038 	if (ret < 0) {
1039 		LOG_ERR("Failed to enable AP mode, ret %d", ret);
1040 		return ret;
1041 	}
1042 
1043 	len = snprintk(cmd, sizeof(cmd), "AT+"_CWSAP"=\"");
1044 	memcpy(&cmd[len], params->ssid, params->ssid_length);
1045 	len += params->ssid_length;
1046 
1047 	if (params->security == WIFI_SECURITY_TYPE_PSK) {
1048 		len += snprintk(&cmd[len], sizeof(cmd) - len, "\",\"");
1049 		memcpy(&cmd[len], params->psk, params->psk_length);
1050 		len += params->psk_length;
1051 		ecn = 3;
1052 	} else {
1053 		len += snprintk(&cmd[len], sizeof(cmd) - len, "\",\"");
1054 	}
1055 
1056 	snprintk(&cmd[len], sizeof(cmd) - len, "\",%d,%d", params->channel,
1057 		 ecn);
1058 
1059 	ret = esp_cmd_send(data, NULL, 0, cmd, ESP_CMD_TIMEOUT);
1060 
1061 	return ret;
1062 }
1063 
esp_mgmt_ap_disable(const struct device * dev)1064 static int esp_mgmt_ap_disable(const struct device *dev)
1065 {
1066 	struct esp_data *data = dev->data;
1067 
1068 	return esp_mode_flags_clear(data, EDF_AP_ENABLED);
1069 }
1070 
esp_init_work(struct k_work * work)1071 static void esp_init_work(struct k_work *work)
1072 {
1073 	struct esp_data *dev;
1074 	int ret;
1075 	static const struct setup_cmd setup_cmds[] = {
1076 		SETUP_CMD_NOHANDLE("AT"),
1077 		/* turn off echo */
1078 		SETUP_CMD_NOHANDLE("ATE0"),
1079 		SETUP_CMD_NOHANDLE("AT+UART_CUR="_UART_CUR),
1080 #if DT_INST_NODE_HAS_PROP(0, target_speed)
1081 	};
1082 	static const struct setup_cmd setup_cmds_target_baudrate[] = {
1083 		SETUP_CMD_NOHANDLE("AT"),
1084 #endif
1085 #if defined(CONFIG_WIFI_ESP_AT_FETCH_VERSION)
1086 		SETUP_CMD_NOHANDLE("AT+GMR"),
1087 #endif
1088 #if defined(CONFIG_WIFI_ESP_AT_VERSION_1_7)
1089 		SETUP_CMD_NOHANDLE(ESP_CMD_CWMODE(STA)),
1090 #endif
1091 #if defined(CONFIG_WIFI_ESP_AT_IP_STATIC)
1092 		/* enable Static IP Config */
1093 		SETUP_CMD_NOHANDLE(ESP_CMD_DHCP_ENABLE(STATION, 0)),
1094 		SETUP_CMD_NOHANDLE(ESP_CMD_SET_IP(CONFIG_WIFI_ESP_AT_IP_ADDRESS,
1095 						  CONFIG_WIFI_ESP_AT_IP_GATEWAY,
1096 						  CONFIG_WIFI_ESP_AT_IP_MASK)),
1097 #else
1098 		/* enable DHCP */
1099 		SETUP_CMD_NOHANDLE(ESP_CMD_DHCP_ENABLE(STATION, 1)),
1100 #endif
1101 		/* enable multiple socket support */
1102 		SETUP_CMD_NOHANDLE("AT+CIPMUX=1"),
1103 
1104 		SETUP_CMD_NOHANDLE(
1105 			ESP_CMD_CWLAPOPT(ESP_CMD_CWLAPOPT_ORDERED, ESP_CMD_CWLAPOPT_MASK)),
1106 
1107 #if !defined(CONFIG_WIFI_ESP_AT_VERSION_1_7)
1108 		SETUP_CMD_NOHANDLE(ESP_CMD_CWMODE(STA)),
1109 		SETUP_CMD_NOHANDLE("AT+CWAUTOCONN=0"),
1110 		SETUP_CMD_NOHANDLE(ESP_CMD_CWMODE(NONE)),
1111 #endif
1112 #if defined(CONFIG_WIFI_ESP_AT_PASSIVE_MODE)
1113 		SETUP_CMD_NOHANDLE("AT+CIPRECVMODE=1"),
1114 #endif
1115 		SETUP_CMD("AT+"_CIPSTAMAC"?", "+"_CIPSTAMAC":",
1116 			  on_cmd_cipstamac, 1U, ""),
1117 	};
1118 
1119 	dev = CONTAINER_OF(work, struct esp_data, init_work);
1120 
1121 	ret = modem_cmd_handler_setup_cmds(&dev->mctx.iface,
1122 					   &dev->mctx.cmd_handler, setup_cmds,
1123 					   ARRAY_SIZE(setup_cmds),
1124 					   &dev->sem_response,
1125 					   ESP_INIT_TIMEOUT);
1126 	if (ret < 0) {
1127 		LOG_ERR("Init failed %d", ret);
1128 		return;
1129 	}
1130 
1131 #if DT_INST_NODE_HAS_PROP(0, target_speed)
1132 	static const struct uart_config uart_config = {
1133 		.baudrate = DT_INST_PROP(0, target_speed),
1134 		.parity = UART_CFG_PARITY_NONE,
1135 		.stop_bits = UART_CFG_STOP_BITS_1,
1136 		.data_bits = UART_CFG_DATA_BITS_8,
1137 		.flow_ctrl = DT_PROP(ESP_BUS, hw_flow_control) ?
1138 			UART_CFG_FLOW_CTRL_RTS_CTS : UART_CFG_FLOW_CTRL_NONE,
1139 	};
1140 
1141 	ret = uart_configure(DEVICE_DT_GET(DT_INST_BUS(0)), &uart_config);
1142 	if (ret < 0) {
1143 		LOG_ERR("Baudrate change failed %d", ret);
1144 		return;
1145 	}
1146 
1147 	/* arbitrary sleep period to give ESP enough time to reconfigure */
1148 	k_sleep(K_MSEC(100));
1149 
1150 	ret = modem_cmd_handler_setup_cmds(&dev->mctx.iface,
1151 				&dev->mctx.cmd_handler,
1152 				setup_cmds_target_baudrate,
1153 				ARRAY_SIZE(setup_cmds_target_baudrate),
1154 				&dev->sem_response,
1155 				ESP_INIT_TIMEOUT);
1156 	if (ret < 0) {
1157 		LOG_ERR("Init failed %d", ret);
1158 		return;
1159 	}
1160 #endif
1161 
1162 	net_if_set_link_addr(dev->net_iface, dev->mac_addr,
1163 			     sizeof(dev->mac_addr), NET_LINK_ETHERNET);
1164 
1165 	if (IS_ENABLED(CONFIG_WIFI_ESP_AT_VERSION_1_7)) {
1166 		/* This is the mode entered in above setup commands */
1167 		dev->mode = ESP_MODE_STA;
1168 
1169 		/*
1170 		 * In case of ESP 1.7 this is the first time CWMODE is entered
1171 		 * STA mode, so request hostname change now.
1172 		 */
1173 		esp_configure_hostname(dev);
1174 	}
1175 
1176 	LOG_INF("ESP Wi-Fi ready");
1177 
1178 	/* L1 network layer (physical layer) is up */
1179 	net_if_carrier_on(dev->net_iface);
1180 
1181 	k_sem_give(&dev->sem_if_up);
1182 }
1183 
esp_reset(const struct device * dev)1184 static int esp_reset(const struct device *dev)
1185 {
1186 	struct esp_data *data = dev->data;
1187 	int ret = -EAGAIN;
1188 
1189 	if (net_if_is_carrier_ok(data->net_iface)) {
1190 		net_if_carrier_off(data->net_iface);
1191 	}
1192 
1193 #if DT_INST_NODE_HAS_PROP(0, power_gpios)
1194 	const struct esp_config *config = dev->config;
1195 
1196 	gpio_pin_set_dt(&config->power, 0);
1197 	k_sleep(K_MSEC(100));
1198 	gpio_pin_set_dt(&config->power, 1);
1199 #elif DT_INST_NODE_HAS_PROP(0, reset_gpios)
1200 	const struct esp_config *config = dev->config;
1201 
1202 	gpio_pin_set_dt(&config->reset, 1);
1203 	k_sleep(K_MSEC(100));
1204 	gpio_pin_set_dt(&config->reset, 0);
1205 #else
1206 #if DT_INST_NODE_HAS_PROP(0, external_reset)
1207 	/* Wait to see if the interface comes up by itself */
1208 	ret = k_sem_take(&data->sem_if_ready, K_MSEC(CONFIG_WIFI_ESP_AT_RESET_TIMEOUT));
1209 #endif
1210 	int retries = 3;
1211 
1212 	/* Don't need to run this if the interface came up by itself */
1213 	while ((ret != 0) && retries--) {
1214 		ret = modem_cmd_send(&data->mctx.iface, &data->mctx.cmd_handler,
1215 				     NULL, 0, "AT+RST", &data->sem_if_ready,
1216 				     K_MSEC(CONFIG_WIFI_ESP_AT_RESET_TIMEOUT));
1217 		if (ret == 0 || ret != -ETIMEDOUT) {
1218 			break;
1219 		}
1220 	}
1221 
1222 	if (ret < 0) {
1223 		LOG_ERR("Failed to reset device: %d", ret);
1224 		return -EAGAIN;
1225 	}
1226 #endif
1227 	LOG_INF("Waiting for interface to come up");
1228 
1229 	ret = k_sem_take(&data->sem_if_up, ESP_INIT_TIMEOUT);
1230 	if (ret == -EAGAIN) {
1231 		LOG_ERR("Timeout waiting for interface");
1232 	}
1233 
1234 	return ret;
1235 }
1236 
esp_iface_init(struct net_if * iface)1237 static void esp_iface_init(struct net_if *iface)
1238 {
1239 	esp_offload_init(iface);
1240 
1241 	/* Not currently connected to a network */
1242 	net_if_dormant_on(iface);
1243 }
1244 
esp_offload_get_type(void)1245 static enum offloaded_net_if_types esp_offload_get_type(void)
1246 {
1247 	return L2_OFFLOADED_NET_IF_TYPE_WIFI;
1248 }
1249 
1250 static const struct wifi_mgmt_ops esp_mgmt_ops = {
1251 	.scan		   = esp_mgmt_scan,
1252 	.connect	   = esp_mgmt_connect,
1253 	.disconnect	   = esp_mgmt_disconnect,
1254 	.ap_enable	   = esp_mgmt_ap_enable,
1255 	.ap_disable	   = esp_mgmt_ap_disable,
1256 	.iface_status	   = esp_mgmt_iface_status,
1257 };
1258 
1259 static const struct net_wifi_mgmt_offload esp_api = {
1260 	.wifi_iface.iface_api.init = esp_iface_init,
1261 	.wifi_iface.get_type = esp_offload_get_type,
1262 	.wifi_mgmt_api = &esp_mgmt_ops,
1263 };
1264 
1265 static int esp_init(const struct device *dev);
1266 
1267 /* The network device must be instantiated above the init function in order
1268  * for the struct net_if that the macro declares to be visible inside the
1269  * function. An `extern` declaration does not work as the struct is static.
1270  */
1271 NET_DEVICE_DT_INST_OFFLOAD_DEFINE(0, esp_init, NULL,
1272 				  &esp_driver_data, &esp_driver_config,
1273 				  CONFIG_WIFI_INIT_PRIORITY, &esp_api,
1274 				  ESP_MTU);
1275 
esp_init(const struct device * dev)1276 static int esp_init(const struct device *dev)
1277 {
1278 #if DT_INST_NODE_HAS_PROP(0, power_gpios) || DT_INST_NODE_HAS_PROP(0, reset_gpios)
1279 	const struct esp_config *config = dev->config;
1280 #endif
1281 	struct esp_data *data = dev->data;
1282 	int ret = 0;
1283 
1284 	k_sem_init(&data->sem_tx_ready, 0, 1);
1285 	k_sem_init(&data->sem_response, 0, 1);
1286 	k_sem_init(&data->sem_if_ready, 0, 1);
1287 	k_sem_init(&data->sem_if_up, 0, 1);
1288 
1289 	k_work_init(&data->init_work, esp_init_work);
1290 	k_work_init_delayable(&data->ip_addr_work, esp_ip_addr_work);
1291 	k_work_init(&data->scan_work, esp_mgmt_scan_work);
1292 	k_work_init(&data->connect_work, esp_mgmt_connect_work);
1293 	k_work_init(&data->disconnect_work, esp_mgmt_disconnect_work);
1294 	k_work_init(&data->iface_status_work, esp_mgmt_iface_status_work);
1295 	k_work_init(&data->mode_switch_work, esp_mode_switch_work);
1296 	if (IS_ENABLED(CONFIG_WIFI_ESP_AT_DNS_USE)) {
1297 		k_work_init(&data->dns_work, esp_dns_work);
1298 	}
1299 
1300 	esp_socket_init(data);
1301 
1302 	/* initialize the work queue */
1303 	k_work_queue_start(&data->workq, esp_workq_stack,
1304 			   K_KERNEL_STACK_SIZEOF(esp_workq_stack),
1305 			   K_PRIO_COOP(CONFIG_WIFI_ESP_AT_WORKQ_THREAD_PRIORITY),
1306 			   NULL);
1307 	k_thread_name_set(&data->workq.thread, "esp_workq");
1308 
1309 	/* cmd handler */
1310 	const struct modem_cmd_handler_config cmd_handler_config = {
1311 		.match_buf = &data->cmd_match_buf[0],
1312 		.match_buf_len = sizeof(data->cmd_match_buf),
1313 		.buf_pool = &mdm_recv_pool,
1314 		.alloc_timeout = K_NO_WAIT,
1315 		.eol = "\r\n",
1316 		.user_data = NULL,
1317 		.response_cmds = response_cmds,
1318 		.response_cmds_len = ARRAY_SIZE(response_cmds),
1319 		.unsol_cmds = unsol_cmds,
1320 		.unsol_cmds_len = ARRAY_SIZE(unsol_cmds),
1321 	};
1322 
1323 	ret = modem_cmd_handler_init(&data->mctx.cmd_handler, &data->cmd_handler_data,
1324 				     &cmd_handler_config);
1325 	if (ret < 0) {
1326 		goto error;
1327 	}
1328 
1329 	/* modem interface */
1330 	const struct modem_iface_uart_config uart_config = {
1331 		.rx_rb_buf = &data->iface_rb_buf[0],
1332 		.rx_rb_buf_len = sizeof(data->iface_rb_buf),
1333 		.dev = DEVICE_DT_GET(DT_INST_BUS(0)),
1334 		.hw_flow_control = DT_PROP(ESP_BUS, hw_flow_control),
1335 	};
1336 
1337 	ret = modem_iface_uart_init(&data->mctx.iface, &data->iface_data, &uart_config);
1338 	if (ret < 0) {
1339 		goto error;
1340 	}
1341 
1342 	/* pin setup */
1343 #if DT_INST_NODE_HAS_PROP(0, power_gpios)
1344 	ret = gpio_pin_configure_dt(&config->power, GPIO_OUTPUT_INACTIVE);
1345 	if (ret < 0) {
1346 		LOG_ERR("Failed to configure %s pin", "power");
1347 		goto error;
1348 	}
1349 #endif
1350 #if DT_INST_NODE_HAS_PROP(0, reset_gpios)
1351 	ret = gpio_pin_configure_dt(&config->reset, GPIO_OUTPUT_INACTIVE);
1352 	if (ret < 0) {
1353 		LOG_ERR("Failed to configure %s pin", "reset");
1354 		goto error;
1355 	}
1356 #endif
1357 
1358 	data->mctx.driver_data = data;
1359 
1360 	ret = modem_context_register(&data->mctx);
1361 	if (ret < 0) {
1362 		LOG_ERR("Error registering modem context: %d", ret);
1363 		goto error;
1364 	}
1365 
1366 	/* start RX thread */
1367 	k_thread_create(&esp_rx_thread, esp_rx_stack,
1368 			K_KERNEL_STACK_SIZEOF(esp_rx_stack),
1369 			(k_thread_entry_t)esp_rx,
1370 			data, NULL, NULL,
1371 			K_PRIO_COOP(CONFIG_WIFI_ESP_AT_RX_THREAD_PRIORITY), 0,
1372 			K_NO_WAIT);
1373 	k_thread_name_set(&esp_rx_thread, "esp_rx");
1374 
1375 	/* Retrieve associated network interface so asynchronous messages can be processed early */
1376 	data->net_iface = NET_IF_GET(Z_DEVICE_DT_DEV_ID(DT_DRV_INST(0)), 0);
1377 
1378 	/* Reset the modem */
1379 	ret = esp_reset(dev);
1380 
1381 error:
1382 	return ret;
1383 }
1384