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