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 	int err;
250 
251 	mac = str_unquote(argv[0]);
252 	err = net_bytes_from_str(dev->mac_addr, sizeof(dev->mac_addr), mac);
253 	if (err) {
254 		LOG_ERR("Failed to parse MAC address");
255 	}
256 
257 	return 0;
258 }
259 
esp_pull_quoted(char ** str,char * str_end,char ** unquoted)260 static int esp_pull_quoted(char **str, char *str_end, char **unquoted)
261 {
262 	if (**str != '"') {
263 		return -EAGAIN;
264 	}
265 
266 	(*str)++;
267 
268 	*unquoted = *str;
269 
270 	while (*str < str_end) {
271 		if (**str == '"') {
272 			**str = '\0';
273 			(*str)++;
274 
275 			if (**str == ',') {
276 				(*str)++;
277 			}
278 
279 			return 0;
280 		}
281 
282 		(*str)++;
283 	}
284 
285 	return -EAGAIN;
286 }
287 
esp_pull(char ** str,char * str_end)288 static int esp_pull(char **str, char *str_end)
289 {
290 	while (*str < str_end) {
291 		if (**str == ',' || **str == ':' || **str == '\r' || **str == '\n') {
292 			char last_c = **str;
293 
294 			**str = '\0';
295 
296 			if (last_c == ',' || last_c == ':') {
297 				(*str)++;
298 			}
299 
300 			return 0;
301 		}
302 
303 		(*str)++;
304 	}
305 
306 	return -EAGAIN;
307 }
308 
esp_pull_raw(char ** str,char * str_end,char ** raw)309 static int esp_pull_raw(char **str, char *str_end, char **raw)
310 {
311 	*raw = *str;
312 
313 	return esp_pull(str, str_end);
314 }
315 
esp_pull_long(char ** str,char * str_end,long * value)316 static int esp_pull_long(char **str, char *str_end, long *value)
317 {
318 	char *str_begin = *str;
319 	int err;
320 	char *endptr;
321 
322 	err = esp_pull(str, str_end);
323 	if (err) {
324 		return err;
325 	}
326 
327 	*value = strtol(str_begin, &endptr, 10);
328 	if (endptr == str_begin) {
329 		LOG_ERR("endptr == str_begin");
330 		return -EBADMSG;
331 	}
332 
333 	return 0;
334 }
335 
336 /* +CWLAP:(sec,ssid,rssi,channel) */
337 /* with: CONFIG_WIFI_ESP_AT_SCAN_MAC_ADDRESS: +CWLAP:<ecn>,<ssid>,<rssi>,<mac>,<ch>*/
MODEM_CMD_DIRECT_DEFINE(on_cmd_cwlap)338 MODEM_CMD_DIRECT_DEFINE(on_cmd_cwlap)
339 {
340 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
341 					    cmd_handler_data);
342 	struct wifi_scan_result res = { 0 };
343 	char cwlap_buf[sizeof("\"0\",\"\",-100,\"xx:xx:xx:xx:xx:xx\",12") +
344 		       WIFI_SSID_MAX_LEN * 2 + 1];
345 	char *ecn;
346 	char *ssid;
347 	char *mac;
348 	char *channel;
349 	long rssi;
350 	long ecn_id;
351 	int err;
352 
353 	len = net_buf_linearize(cwlap_buf, sizeof(cwlap_buf) - 1,
354 				data->rx_buf, 0, sizeof(cwlap_buf) - 1);
355 	cwlap_buf[len] = '\0';
356 
357 	char *str = &cwlap_buf[sizeof("+CWJAP:(") - 1];
358 	char *str_end = cwlap_buf + len;
359 
360 	err = esp_pull_raw(&str, str_end, &ecn);
361 	if (err) {
362 		return err;
363 	}
364 
365 	ecn_id = strtol(ecn, NULL, 10);
366 	if (ecn_id == 0) {
367 		res.security = WIFI_SECURITY_TYPE_NONE;
368 	} else {
369 		res.security = WIFI_SECURITY_TYPE_PSK;
370 	}
371 
372 	err = esp_pull_quoted(&str, str_end, &ssid);
373 	if (err) {
374 		return err;
375 	}
376 
377 	err = esp_pull_long(&str, str_end, &rssi);
378 	if (err) {
379 		return err;
380 	}
381 
382 	if (strlen(ssid) > WIFI_SSID_MAX_LEN) {
383 		return -EBADMSG;
384 	}
385 
386 	res.ssid_length = MIN(sizeof(res.ssid), strlen(ssid));
387 	memcpy(res.ssid, ssid, res.ssid_length);
388 
389 	res.rssi = rssi;
390 
391 	if (IS_ENABLED(CONFIG_WIFI_ESP_AT_SCAN_MAC_ADDRESS)) {
392 		err = esp_pull_quoted(&str, str_end, &mac);
393 		if (err) {
394 			return err;
395 		}
396 
397 		res.mac_length = WIFI_MAC_ADDR_LEN;
398 		if (net_bytes_from_str(res.mac, sizeof(res.mac), mac) < 0) {
399 			LOG_ERR("Invalid MAC address");
400 			res.mac_length = 0;
401 		}
402 	}
403 
404 	err = esp_pull_raw(&str, str_end, &channel);
405 	if (err) {
406 		return err;
407 	}
408 
409 	res.channel = strtol(channel, NULL, 10);
410 
411 	if (dev->scan_cb) {
412 		dev->scan_cb(dev->net_iface, 0, &res);
413 	}
414 
415 	return str - cwlap_buf;
416 }
417 
418 /* +CWJAP:(ssid,bssid,channel,rssi) */
MODEM_CMD_DIRECT_DEFINE(on_cmd_cwjap)419 MODEM_CMD_DIRECT_DEFINE(on_cmd_cwjap)
420 {
421 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
422 					    cmd_handler_data);
423 	struct wifi_iface_status *status = dev->wifi_status;
424 	char cwjap_buf[sizeof("\"\",\"xx:xx:xx:xx:xx:xx\",12,-100") +
425 		       WIFI_SSID_MAX_LEN * 2 + 1];
426 	uint8_t flags = dev->flags;
427 	char *ssid;
428 	char *bssid;
429 	char *channel;
430 	char *rssi;
431 	int err;
432 
433 	len = net_buf_linearize(cwjap_buf, sizeof(cwjap_buf) - 1,
434 				data->rx_buf, 0, sizeof(cwjap_buf) - 1);
435 	cwjap_buf[len] = '\0';
436 
437 	char *str = &cwjap_buf[sizeof("+CWJAP:") - 1];
438 	char *str_end = cwjap_buf + len;
439 
440 	status->band = WIFI_FREQ_BAND_2_4_GHZ;
441 	status->iface_mode = WIFI_MODE_INFRA;
442 
443 	if (flags & EDF_STA_CONNECTED) {
444 		status->state = WIFI_STATE_COMPLETED;
445 	} else if (flags & EDF_STA_CONNECTING) {
446 		status->state = WIFI_STATE_SCANNING;
447 	} else {
448 		status->state = WIFI_STATE_DISCONNECTED;
449 	}
450 
451 	err = esp_pull_quoted(&str, str_end, &ssid);
452 	if (err) {
453 		return err;
454 	}
455 
456 	err = esp_pull_quoted(&str, str_end, &bssid);
457 	if (err) {
458 		return err;
459 	}
460 
461 	err = esp_pull_raw(&str, str_end, &channel);
462 	if (err) {
463 		return err;
464 	}
465 
466 	err = esp_pull_raw(&str, str_end, &rssi);
467 	if (err) {
468 		return err;
469 	}
470 
471 	strncpy(status->ssid, ssid, sizeof(status->ssid));
472 	status->ssid_len = strnlen(status->ssid, sizeof(status->ssid));
473 
474 	err = net_bytes_from_str(status->bssid, sizeof(status->bssid), bssid);
475 	if (err) {
476 		LOG_WRN("Invalid MAC address");
477 		memset(status->bssid, 0x0, sizeof(status->bssid));
478 	}
479 
480 	status->channel = strtol(channel, NULL, 10);
481 	status->rssi = strtol(rssi, NULL, 10);
482 
483 	return str - cwjap_buf;
484 }
485 
esp_dns_work(struct k_work * work)486 static void esp_dns_work(struct k_work *work)
487 {
488 #if defined(ESP_MAX_DNS)
489 	struct esp_data *data = CONTAINER_OF(work, struct esp_data, dns_work);
490 	struct dns_resolve_context *dnsctx;
491 	struct sockaddr_in *addrs = data->dns_addresses;
492 	const struct sockaddr *dns_servers[ESP_MAX_DNS + 1] = {};
493 	size_t i;
494 	int err;
495 
496 	for (i = 0; i < ESP_MAX_DNS; i++) {
497 		if (!addrs[i].sin_addr.s_addr) {
498 			break;
499 		}
500 		dns_servers[i] = (struct sockaddr *) &addrs[i];
501 	}
502 
503 	dnsctx = dns_resolve_get_default();
504 	err = dns_resolve_reconfigure(dnsctx, NULL, dns_servers);
505 	if (err) {
506 		LOG_ERR("Could not set DNS servers: %d", err);
507 	}
508 
509 	LOG_DBG("DNS resolver reconfigured");
510 #endif
511 }
512 
513 /* +CIPDNS:enable[,"DNS IP1"[,"DNS IP2"[,"DNS IP3"]]] */
MODEM_CMD_DEFINE(on_cmd_cipdns)514 MODEM_CMD_DEFINE(on_cmd_cipdns)
515 {
516 #if defined(ESP_MAX_DNS)
517 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
518 					    cmd_handler_data);
519 	struct sockaddr_in *addrs = dev->dns_addresses;
520 	char **servers = (char **)argv + 1;
521 	size_t num_servers = argc - 1;
522 	size_t valid_servers = 0;
523 	size_t i;
524 	int err;
525 
526 	for (i = 0; i < ESP_MAX_DNS; i++) {
527 		if (i >= num_servers) {
528 			addrs[i].sin_addr.s_addr = 0;
529 			break;
530 		}
531 
532 		servers[i] = str_unquote(servers[i]);
533 		LOG_DBG("DNS[%zu]: %s", i, servers[i]);
534 
535 		err = net_addr_pton(AF_INET, servers[i], &addrs[i].sin_addr);
536 		if (err) {
537 			LOG_ERR("Invalid DNS address: %s",
538 				servers[i]);
539 			addrs[i].sin_addr.s_addr = 0;
540 			break;
541 		}
542 
543 		addrs[i].sin_family = AF_INET;
544 		addrs[i].sin_port = htons(53);
545 
546 		valid_servers++;
547 	}
548 
549 	if (valid_servers) {
550 		k_work_submit(&dev->dns_work);
551 	}
552 #endif
553 
554 	return 0;
555 }
556 
557 static const struct modem_cmd response_cmds[] = {
558 	MODEM_CMD("OK", on_cmd_ok, 0U, ""), /* 3GPP */
559 	MODEM_CMD("ERROR", on_cmd_error, 0U, ""), /* 3GPP */
560 };
561 
MODEM_CMD_DEFINE(on_cmd_wifi_connected)562 MODEM_CMD_DEFINE(on_cmd_wifi_connected)
563 {
564 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
565 					    cmd_handler_data);
566 
567 	if (esp_flags_are_set(dev, EDF_STA_CONNECTED)) {
568 		return 0;
569 	}
570 
571 	esp_flags_set(dev, EDF_STA_CONNECTED);
572 	wifi_mgmt_raise_connect_result_event(dev->net_iface, 0);
573 	net_if_dormant_off(dev->net_iface);
574 
575 	return 0;
576 }
577 
esp_mgmt_disconnect_work(struct k_work * work)578 static void esp_mgmt_disconnect_work(struct k_work *work)
579 {
580 	struct esp_socket *sock;
581 	struct esp_data *dev;
582 
583 	dev = CONTAINER_OF(work, struct esp_data, disconnect_work);
584 
585 	/* Cleanup any sockets that weren't closed */
586 	for (int i = 0; i < ARRAY_SIZE(dev->sockets); i++) {
587 		sock = &dev->sockets[i];
588 		if (esp_socket_connected(sock)) {
589 			LOG_WRN("Socket %d left open, manually closing", i);
590 			esp_socket_close(sock);
591 		}
592 	}
593 
594 	esp_flags_clear(dev, EDF_STA_CONNECTED);
595 	esp_mode_switch_submit_if_needed(dev);
596 
597 #if defined(CONFIG_NET_NATIVE_IPV4)
598 	net_if_ipv4_addr_rm(dev->net_iface, &dev->ip);
599 #endif
600 	if (!esp_flags_are_set(dev, EDF_AP_ENABLED)) {
601 		net_if_dormant_on(dev->net_iface);
602 	}
603 	wifi_mgmt_raise_disconnect_result_event(dev->net_iface, 0);
604 }
605 
MODEM_CMD_DEFINE(on_cmd_wifi_disconnected)606 MODEM_CMD_DEFINE(on_cmd_wifi_disconnected)
607 {
608 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
609 					    cmd_handler_data);
610 
611 	if (esp_flags_are_set(dev, EDF_STA_CONNECTED)) {
612 		k_work_submit_to_queue(&dev->workq, &dev->disconnect_work);
613 	}
614 
615 	return 0;
616 }
617 
618 /*
619  * +CIPSTA:ip:"<ip>"
620  * +CIPSTA:gateway:"<ip>"
621  * +CIPSTA:netmask:"<ip>"
622  */
MODEM_CMD_DEFINE(on_cmd_cipsta)623 MODEM_CMD_DEFINE(on_cmd_cipsta)
624 {
625 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
626 					    cmd_handler_data);
627 	char *ip;
628 
629 	ip = str_unquote(argv[1]);
630 
631 	if (!strcmp(argv[0], "ip")) {
632 		net_addr_pton(AF_INET, ip, &dev->ip);
633 	} else if (!strcmp(argv[0], "gateway")) {
634 		net_addr_pton(AF_INET, ip, &dev->gw);
635 	} else if (!strcmp(argv[0], "netmask")) {
636 		net_addr_pton(AF_INET, ip, &dev->nm);
637 	} else {
638 		LOG_WRN("Unknown IP type %s", argv[0]);
639 	}
640 
641 	return 0;
642 }
643 
esp_ip_addr_work(struct k_work * work)644 static void esp_ip_addr_work(struct k_work *work)
645 {
646 	struct k_work_delayable *dwork = k_work_delayable_from_work(work);
647 	struct esp_data *dev = CONTAINER_OF(dwork, struct esp_data,
648 					    ip_addr_work);
649 	int ret;
650 
651 	static const struct modem_cmd cmds[] = {
652 		MODEM_CMD("+"_CIPSTA":", on_cmd_cipsta, 2U, ":"),
653 	};
654 	static const struct modem_cmd dns_cmds[] = {
655 		MODEM_CMD_ARGS_MAX("+CIPDNS:", on_cmd_cipdns, 1U, 3U, ","),
656 	};
657 
658 	ret = esp_cmd_send(dev, cmds, ARRAY_SIZE(cmds), "AT+"_CIPSTA"?",
659 			   ESP_CMD_TIMEOUT);
660 	if (ret < 0) {
661 		LOG_WRN("Failed to query IP settings: ret %d", ret);
662 		k_work_reschedule_for_queue(&dev->workq, &dev->ip_addr_work,
663 					    K_SECONDS(5));
664 		return;
665 	}
666 
667 #if defined(CONFIG_NET_NATIVE_IPV4)
668 	/* update interface addresses */
669 #if defined(CONFIG_WIFI_ESP_AT_IP_STATIC)
670 	net_if_ipv4_addr_add(dev->net_iface, &dev->ip, NET_ADDR_MANUAL, 0);
671 #else
672 	net_if_ipv4_addr_add(dev->net_iface, &dev->ip, NET_ADDR_DHCP, 0);
673 #endif
674 	net_if_ipv4_set_gw(dev->net_iface, &dev->gw);
675 	net_if_ipv4_set_netmask_by_addr(dev->net_iface, &dev->ip, &dev->nm);
676 #endif
677 
678 	if (IS_ENABLED(CONFIG_WIFI_ESP_AT_DNS_USE)) {
679 		ret = esp_cmd_send(dev, dns_cmds, ARRAY_SIZE(dns_cmds),
680 				   "AT+CIPDNS?", ESP_CMD_TIMEOUT);
681 		if (ret) {
682 			LOG_WRN("DNS fetch failed: %d", ret);
683 		}
684 	}
685 }
686 
MODEM_CMD_DEFINE(on_cmd_got_ip)687 MODEM_CMD_DEFINE(on_cmd_got_ip)
688 {
689 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
690 					    cmd_handler_data);
691 
692 	k_work_reschedule_for_queue(&dev->workq, &dev->ip_addr_work,
693 				    K_SECONDS(1));
694 
695 	return 0;
696 }
697 
MODEM_CMD_DEFINE(on_cmd_connect)698 MODEM_CMD_DEFINE(on_cmd_connect)
699 {
700 	struct esp_socket *sock;
701 	struct esp_data *dev;
702 	uint8_t link_id;
703 
704 	link_id = data->match_buf[0] - '0';
705 
706 	dev = CONTAINER_OF(data, struct esp_data, cmd_handler_data);
707 	sock = esp_socket_ref_from_link_id(dev, link_id);
708 	if (!sock) {
709 		LOG_ERR("No socket for link %d", link_id);
710 		return 0;
711 	}
712 
713 	esp_socket_unref(sock);
714 
715 	return 0;
716 }
717 
MODEM_CMD_DEFINE(on_cmd_closed)718 MODEM_CMD_DEFINE(on_cmd_closed)
719 {
720 	struct esp_socket *sock;
721 	struct esp_data *dev;
722 	uint8_t link_id;
723 	atomic_val_t old_flags;
724 
725 	link_id = data->match_buf[0] - '0';
726 
727 	LOG_DBG("Link %d closed", link_id);
728 
729 	dev = CONTAINER_OF(data, struct esp_data, cmd_handler_data);
730 	sock = esp_socket_ref_from_link_id(dev, link_id);
731 	if (!sock) {
732 		LOG_ERR("No socket for link %d", link_id);
733 		return 0;
734 	}
735 
736 	old_flags = esp_socket_flags_clear_and_set(sock,
737 				ESP_SOCK_CONNECTED, ESP_SOCK_CLOSE_PENDING);
738 
739 	if (!(old_flags & ESP_SOCK_CONNECTED)) {
740 		LOG_DBG("Link %d already closed", link_id);
741 		goto socket_unref;
742 	}
743 
744 	if (!(old_flags & ESP_SOCK_CLOSE_PENDING)) {
745 		esp_socket_work_submit(sock, &sock->close_work);
746 	}
747 
748 socket_unref:
749 	esp_socket_unref(sock);
750 
751 	return 0;
752 }
753 
754 /*
755  * Passive mode: "+IPD,<id>,<len>\r\n"
756  * Other:        "+IPD,<id>,<len>:<data>"
757  */
758 #define MIN_IPD_LEN (sizeof("+IPD,I,0E") - 1)
759 #define MAX_IPD_LEN (sizeof("+IPD,I,4294967295,\"\",65535E") - 1) + NET_IPV4_ADDR_LEN
760 
cmd_ipd_parse_hdr(struct esp_data * dev,struct esp_socket ** sock,struct net_buf * buf,uint16_t len,int * data_offset,long * data_len)761 static int cmd_ipd_parse_hdr(struct esp_data *dev,
762 			     struct esp_socket **sock,
763 			     struct net_buf *buf, uint16_t len,
764 			     int *data_offset, long *data_len)
765 {
766 	char ipd_buf[MAX_IPD_LEN + 1];
767 	char *str;
768 	char *str_end;
769 	long link_id;
770 	size_t frags_len;
771 	size_t match_len;
772 	int err;
773 
774 	frags_len = net_buf_frags_len(buf);
775 
776 	/* Wait until minimum cmd length is available */
777 	if (frags_len < MIN_IPD_LEN) {
778 		return -EAGAIN;
779 	}
780 
781 	match_len = net_buf_linearize(ipd_buf, MAX_IPD_LEN,
782 				      buf, 0, MAX_IPD_LEN);
783 
784 	ipd_buf[match_len] = 0;
785 	if (ipd_buf[len] != ',' || ipd_buf[len + 2] != ',') {
786 		LOG_ERR("Invalid IPD: %s", ipd_buf);
787 		return -EBADMSG;
788 	}
789 
790 	str = &ipd_buf[len + 1];
791 	str_end = &ipd_buf[match_len];
792 
793 	err = esp_pull_long(&str, str_end, &link_id);
794 	if (err) {
795 		if (err == -EAGAIN && match_len >= MAX_IPD_LEN) {
796 			LOG_ERR("Failed to pull %s", "link_id");
797 			return -EBADMSG;
798 		}
799 
800 		return err;
801 	}
802 
803 	err = esp_pull_long(&str, str_end, data_len);
804 	if (err) {
805 		if (err == -EAGAIN && match_len >= MAX_IPD_LEN) {
806 			LOG_ERR("Failed to pull %s", "data_len");
807 			return -EBADMSG;
808 		}
809 
810 		return err;
811 	}
812 
813 	*sock = esp_socket_ref_from_link_id(dev, link_id);
814 
815 	if (!*sock) {
816 		LOG_ERR("No socket for link %ld", link_id);
817 		*data_offset = (str - ipd_buf);
818 		return -ENOTCONN;
819 	}
820 
821 	if (!ESP_PROTO_PASSIVE(esp_socket_ip_proto(*sock)) &&
822 	    IS_ENABLED(CONFIG_WIFI_ESP_AT_CIPDINFO_USE)) {
823 		struct sockaddr_in *recv_addr =
824 			(struct sockaddr_in *) &(*sock)->context->remote;
825 		char *remote_ip;
826 		long port;
827 
828 		if (IS_ENABLED(CONFIG_WIFI_ESP_AT_VERSION_1_7)) {
829 			/* NOT quoted per AT version 1.7.0 */
830 			err = esp_pull_raw(&str, str_end, &remote_ip);
831 		} else {
832 			/* Quoted per AT version 2.1.0/2.2.0 */
833 			err = esp_pull_quoted(&str, str_end, &remote_ip);
834 		}
835 		if (err) {
836 			if (err == -EAGAIN && match_len >= MAX_IPD_LEN) {
837 				LOG_ERR("Failed to pull remote_ip");
838 				err = -EBADMSG;
839 			}
840 			goto socket_unref;
841 		}
842 
843 		err = esp_pull_long(&str, str_end, &port);
844 		if (err) {
845 			if (err == -EAGAIN && match_len >= MAX_IPD_LEN) {
846 				LOG_ERR("Failed to pull port");
847 				err = -EBADMSG;
848 			}
849 			goto socket_unref;
850 		}
851 
852 		err = net_addr_pton(AF_INET, remote_ip, &recv_addr->sin_addr);
853 		if (err) {
854 			LOG_ERR("Invalid IP address");
855 			err = -EBADMSG;
856 			goto socket_unref;
857 		}
858 
859 		recv_addr->sin_family = AF_INET;
860 		recv_addr->sin_port = htons(port);
861 	}
862 
863 	*data_offset = (str - ipd_buf);
864 
865 	return 0;
866 
867 socket_unref:
868 	esp_socket_unref(*sock);
869 
870 	return err;
871 }
872 
MODEM_CMD_DIRECT_DEFINE(on_cmd_ipd)873 MODEM_CMD_DIRECT_DEFINE(on_cmd_ipd)
874 {
875 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
876 					    cmd_handler_data);
877 	struct esp_socket *sock;
878 	int data_offset;
879 	long data_len;
880 	int err;
881 	int ret;
882 
883 	err = cmd_ipd_parse_hdr(dev, &sock, data->rx_buf, len,
884 				&data_offset, &data_len);
885 	if (err) {
886 		if (err == -EAGAIN) {
887 			return -EAGAIN;
888 		}
889 
890 		return len;
891 	}
892 
893 	/*
894 	 * When using passive TCP, the data itself is not included in the +IPD
895 	 * command but must be polled with AT+CIPRECVDATA.
896 	 */
897 	if (ESP_PROTO_PASSIVE(esp_socket_ip_proto(sock))) {
898 		esp_socket_work_submit(sock, &sock->recvdata_work);
899 		ret = data_offset;
900 		goto socket_unref;
901 	}
902 
903 	/* Do we have the whole message? */
904 	if (data_offset + data_len > net_buf_frags_len(data->rx_buf)) {
905 		ret = -EAGAIN;
906 		goto socket_unref;
907 	}
908 
909 	esp_socket_rx(sock, data->rx_buf, data_offset, data_len);
910 
911 	ret = data_offset + data_len;
912 
913 socket_unref:
914 	esp_socket_unref(sock);
915 
916 	return ret;
917 }
918 
MODEM_CMD_DEFINE(on_cmd_busy_sending)919 MODEM_CMD_DEFINE(on_cmd_busy_sending)
920 {
921 	LOG_WRN("Busy sending");
922 	return 0;
923 }
924 
MODEM_CMD_DEFINE(on_cmd_busy_processing)925 MODEM_CMD_DEFINE(on_cmd_busy_processing)
926 {
927 	LOG_WRN("Busy processing");
928 	return 0;
929 }
930 
931 /*
932  * The 'ready' command is sent when device has booted and is ready to receive
933  * commands. It is only expected after a reset of the device.
934  */
MODEM_CMD_DEFINE(on_cmd_ready)935 MODEM_CMD_DEFINE(on_cmd_ready)
936 {
937 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
938 					    cmd_handler_data);
939 	k_sem_give(&dev->sem_if_ready);
940 
941 
942 	if (net_if_is_carrier_ok(dev->net_iface)) {
943 		net_if_dormant_on(dev->net_iface);
944 		net_if_carrier_off(dev->net_iface);
945 		LOG_ERR("Unexpected reset");
946 	}
947 
948 	if (esp_flags_are_set(dev, EDF_STA_CONNECTING)) {
949 		wifi_mgmt_raise_connect_result_event(dev->net_iface, -1);
950 	} else if (esp_flags_are_set(dev, EDF_STA_CONNECTED)) {
951 		wifi_mgmt_raise_disconnect_result_event(dev->net_iface, 0);
952 	}
953 
954 	dev->flags = 0;
955 	dev->mode = 0;
956 
957 #if defined(CONFIG_NET_NATIVE_IPV4)
958 	net_if_ipv4_addr_rm(dev->net_iface, &dev->ip);
959 #endif
960 	k_work_submit_to_queue(&dev->workq, &dev->init_work);
961 
962 	return 0;
963 }
964 
965 #if defined(CONFIG_WIFI_ESP_AT_FETCH_VERSION)
966 
cmd_version_log(struct modem_cmd_handler_data * data,const char * type,const char * version)967 static int cmd_version_log(struct modem_cmd_handler_data *data,
968 			   const char *type, const char *version)
969 {
970 	LOG_INF("%s: %s", type, version);
971 
972 	return 0;
973 }
974 
MODEM_CMD_DEFINE(on_cmd_at_version)975 MODEM_CMD_DEFINE(on_cmd_at_version)
976 {
977 	return cmd_version_log(data, "AT version", argv[0]);
978 }
979 
MODEM_CMD_DEFINE(on_cmd_sdk_version)980 MODEM_CMD_DEFINE(on_cmd_sdk_version)
981 {
982 	return cmd_version_log(data, "SDK version", argv[0]);
983 }
984 
MODEM_CMD_DEFINE(on_cmd_compile_time)985 MODEM_CMD_DEFINE(on_cmd_compile_time)
986 {
987 	return cmd_version_log(data, "compile time", argv[0]);
988 }
989 
MODEM_CMD_DEFINE(on_cmd_bin_version)990 MODEM_CMD_DEFINE(on_cmd_bin_version)
991 {
992 	return cmd_version_log(data, "Bin version", argv[0]);
993 }
994 
995 #endif /* CONFIG_WIFI_ESP_AT_FETCH_VERSION */
996 
997 static const struct modem_cmd unsol_cmds[] = {
998 	MODEM_CMD("WIFI CONNECTED", on_cmd_wifi_connected, 0U, ""),
999 	MODEM_CMD("WIFI DISCONNECT", on_cmd_wifi_disconnected, 0U, ""),
1000 	MODEM_CMD("WIFI GOT IP", on_cmd_got_ip, 0U, ""),
1001 	MODEM_CMD("0,CONNECT", on_cmd_connect, 0U, ""),
1002 	MODEM_CMD("1,CONNECT", on_cmd_connect, 0U, ""),
1003 	MODEM_CMD("2,CONNECT", on_cmd_connect, 0U, ""),
1004 	MODEM_CMD("3,CONNECT", on_cmd_connect, 0U, ""),
1005 	MODEM_CMD("4,CONNECT", on_cmd_connect, 0U, ""),
1006 	MODEM_CMD("0,CLOSED", on_cmd_closed, 0U, ""),
1007 	MODEM_CMD("1,CLOSED", on_cmd_closed, 0U, ""),
1008 	MODEM_CMD("2,CLOSED", on_cmd_closed, 0U, ""),
1009 	MODEM_CMD("3,CLOSED", on_cmd_closed, 0U, ""),
1010 	MODEM_CMD("4,CLOSED", on_cmd_closed, 0U, ""),
1011 	MODEM_CMD("busy s...", on_cmd_busy_sending, 0U, ""),
1012 	MODEM_CMD("busy p...", on_cmd_busy_processing, 0U, ""),
1013 	MODEM_CMD("ready", on_cmd_ready, 0U, ""),
1014 #if defined(CONFIG_WIFI_ESP_AT_FETCH_VERSION)
1015 	MODEM_CMD("AT version:", on_cmd_at_version, 1U, ""),
1016 	MODEM_CMD("SDK version:", on_cmd_sdk_version, 1U, ""),
1017 	MODEM_CMD("Compile time", on_cmd_compile_time, 1U, ""),
1018 	MODEM_CMD("Bin version:", on_cmd_bin_version, 1U, ""),
1019 #endif
1020 	MODEM_CMD_DIRECT("+IPD", on_cmd_ipd),
1021 };
1022 
esp_mgmt_iface_status_work(struct k_work * work)1023 static void esp_mgmt_iface_status_work(struct k_work *work)
1024 {
1025 	struct esp_data *data = CONTAINER_OF(work, struct esp_data, iface_status_work);
1026 	struct wifi_iface_status *status = data->wifi_status;
1027 	int ret;
1028 	static const struct modem_cmd cmds[] = {
1029 		MODEM_CMD_DIRECT("+CWJAP:", on_cmd_cwjap),
1030 	};
1031 
1032 	ret = esp_cmd_send(data, cmds, ARRAY_SIZE(cmds), "AT+CWJAP?",
1033 			   ESP_IFACE_STATUS_TIMEOUT);
1034 	if (ret < 0) {
1035 		LOG_WRN("Failed to request STA status: ret %d", ret);
1036 		status->state = WIFI_STATE_UNKNOWN;
1037 	}
1038 
1039 	k_sem_give(&data->wifi_status_sem);
1040 }
1041 
esp_mgmt_iface_status(const struct device * dev,struct wifi_iface_status * status)1042 static int esp_mgmt_iface_status(const struct device *dev,
1043 				 struct wifi_iface_status *status)
1044 {
1045 	struct esp_data *data = dev->data;
1046 
1047 	memset(status, 0x0, sizeof(*status));
1048 
1049 	status->state = WIFI_STATE_UNKNOWN;
1050 	status->band = WIFI_FREQ_BAND_UNKNOWN;
1051 	status->iface_mode = WIFI_MODE_UNKNOWN;
1052 	status->link_mode = WIFI_LINK_MODE_UNKNOWN;
1053 	status->security = WIFI_SECURITY_TYPE_UNKNOWN;
1054 	status->mfp = WIFI_MFP_UNKNOWN;
1055 
1056 	if (!net_if_is_carrier_ok(data->net_iface)) {
1057 		status->state = WIFI_STATE_INTERFACE_DISABLED;
1058 		return 0;
1059 	}
1060 
1061 	data->wifi_status = status;
1062 	k_sem_init(&data->wifi_status_sem, 0, 1);
1063 
1064 	k_work_submit_to_queue(&data->workq, &data->iface_status_work);
1065 
1066 	k_sem_take(&data->wifi_status_sem, K_FOREVER);
1067 
1068 	return 0;
1069 }
1070 
esp_mgmt_scan_work(struct k_work * work)1071 static void esp_mgmt_scan_work(struct k_work *work)
1072 {
1073 	struct esp_data *dev;
1074 	int ret;
1075 	static const struct modem_cmd cmds[] = {
1076 		MODEM_CMD_DIRECT("+CWLAP:", on_cmd_cwlap),
1077 	};
1078 
1079 	dev = CONTAINER_OF(work, struct esp_data, scan_work);
1080 
1081 	ret = esp_mode_flags_set(dev, EDF_STA_LOCK);
1082 	if (ret < 0) {
1083 		goto out;
1084 	}
1085 	ret = esp_cmd_send(dev,
1086 			   cmds, ARRAY_SIZE(cmds),
1087 			   ESP_CMD_CWLAP,
1088 			   ESP_SCAN_TIMEOUT);
1089 	esp_mode_flags_clear(dev, EDF_STA_LOCK);
1090 	LOG_DBG("ESP Wi-Fi scan: cmd = %s", ESP_CMD_CWLAP);
1091 
1092 	if (ret < 0) {
1093 		LOG_ERR("Failed to scan: ret %d", ret);
1094 	}
1095 
1096 out:
1097 	dev->scan_cb(dev->net_iface, 0, NULL);
1098 	dev->scan_cb = NULL;
1099 }
1100 
esp_mgmt_scan(const struct device * dev,struct wifi_scan_params * params,scan_result_cb_t cb)1101 static int esp_mgmt_scan(const struct device *dev,
1102 			 struct wifi_scan_params *params,
1103 			 scan_result_cb_t cb)
1104 {
1105 	struct esp_data *data = dev->data;
1106 
1107 	ARG_UNUSED(params);
1108 
1109 	if (data->scan_cb != NULL) {
1110 		return -EINPROGRESS;
1111 	}
1112 
1113 	if (!net_if_is_carrier_ok(data->net_iface)) {
1114 		return -EIO;
1115 	}
1116 
1117 	data->scan_cb = cb;
1118 
1119 	k_work_submit_to_queue(&data->workq, &data->scan_work);
1120 
1121 	return 0;
1122 };
1123 
MODEM_CMD_DEFINE(on_cmd_fail)1124 MODEM_CMD_DEFINE(on_cmd_fail)
1125 {
1126 	struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
1127 					    cmd_handler_data);
1128 
1129 	modem_cmd_handler_set_error(data, -EIO);
1130 	k_sem_give(&dev->sem_response);
1131 
1132 	return 0;
1133 }
1134 
esp_mgmt_connect_work(struct k_work * work)1135 static void esp_mgmt_connect_work(struct k_work *work)
1136 {
1137 	struct esp_data *dev;
1138 	int ret;
1139 	static const struct modem_cmd cmds[] = {
1140 		MODEM_CMD("FAIL", on_cmd_fail, 0U, ""),
1141 	};
1142 
1143 	dev = CONTAINER_OF(work, struct esp_data, connect_work);
1144 
1145 	ret = esp_mode_flags_set(dev, EDF_STA_LOCK);
1146 	if (ret < 0) {
1147 		goto out;
1148 	}
1149 
1150 	ret = esp_cmd_send(dev, cmds, ARRAY_SIZE(cmds), dev->conn_cmd,
1151 			   ESP_CONNECT_TIMEOUT);
1152 
1153 	memset(dev->conn_cmd, 0, sizeof(dev->conn_cmd));
1154 
1155 	if (ret < 0) {
1156 		net_if_dormant_on(dev->net_iface);
1157 		if (esp_flags_are_set(dev, EDF_STA_CONNECTED)) {
1158 			esp_flags_clear(dev, EDF_STA_CONNECTED);
1159 			wifi_mgmt_raise_disconnect_result_event(dev->net_iface,
1160 								0);
1161 		} else {
1162 			wifi_mgmt_raise_connect_result_event(dev->net_iface,
1163 							     ret);
1164 		}
1165 	} else if (!esp_flags_are_set(dev, EDF_STA_CONNECTED)) {
1166 		esp_flags_set(dev, EDF_STA_CONNECTED);
1167 		wifi_mgmt_raise_connect_result_event(dev->net_iface, 0);
1168 		net_if_dormant_off(dev->net_iface);
1169 	}
1170 
1171 	esp_mode_flags_clear(dev, EDF_STA_LOCK);
1172 
1173 out:
1174 	esp_flags_clear(dev, EDF_STA_CONNECTING);
1175 }
1176 
esp_conn_cmd_append(struct esp_data * data,size_t * off,const char * chunk,size_t chunk_len)1177 static int esp_conn_cmd_append(struct esp_data *data, size_t *off,
1178 			       const char *chunk, size_t chunk_len)
1179 {
1180 	char *str_end = &data->conn_cmd[sizeof(data->conn_cmd)];
1181 	char *str = &data->conn_cmd[*off];
1182 	const char *chunk_end = chunk + chunk_len;
1183 
1184 	for (; chunk < chunk_end; chunk++) {
1185 		if (str_end - str < 1) {
1186 			return -ENOSPC;
1187 		}
1188 
1189 		*str = *chunk;
1190 		str++;
1191 	}
1192 
1193 	*off = str - data->conn_cmd;
1194 
1195 	return 0;
1196 }
1197 
1198 #define esp_conn_cmd_append_literal(data, off, chunk)			\
1199 	esp_conn_cmd_append(data, off, chunk, sizeof(chunk) - 1)
1200 
esp_conn_cmd_escape_and_append(struct esp_data * data,size_t * off,const char * chunk,size_t chunk_len)1201 static int esp_conn_cmd_escape_and_append(struct esp_data *data, size_t *off,
1202 					  const char *chunk, size_t chunk_len)
1203 {
1204 	char *str_end = &data->conn_cmd[sizeof(data->conn_cmd)];
1205 	char *str = &data->conn_cmd[*off];
1206 	const char *chunk_end = chunk + chunk_len;
1207 
1208 	for (; chunk < chunk_end; chunk++) {
1209 		switch (*chunk) {
1210 		case ',':
1211 		case '\\':
1212 		case '"':
1213 			if (str_end - str < 2) {
1214 				return -ENOSPC;
1215 			}
1216 
1217 			*str = '\\';
1218 			str++;
1219 
1220 			break;
1221 		}
1222 
1223 		if (str_end - str < 1) {
1224 			return -ENOSPC;
1225 		}
1226 
1227 		*str = *chunk;
1228 		str++;
1229 	}
1230 
1231 	*off = str - data->conn_cmd;
1232 
1233 	return 0;
1234 }
1235 
esp_mgmt_connect(const struct device * dev,struct wifi_connect_req_params * params)1236 static int esp_mgmt_connect(const struct device *dev,
1237 			    struct wifi_connect_req_params *params)
1238 {
1239 	struct esp_data *data = dev->data;
1240 	size_t off = 0;
1241 	int err;
1242 
1243 	if (!net_if_is_carrier_ok(data->net_iface) ||
1244 	    !net_if_is_admin_up(data->net_iface)) {
1245 		return -EIO;
1246 	}
1247 
1248 	if (esp_flags_are_set(data, EDF_STA_CONNECTED | EDF_STA_CONNECTING)) {
1249 		return -EALREADY;
1250 	}
1251 
1252 	esp_flags_set(data, EDF_STA_CONNECTING);
1253 
1254 	err = esp_conn_cmd_append_literal(data, &off, "AT+"_CWJAP"=\"");
1255 	if (err) {
1256 		return err;
1257 	}
1258 
1259 	err = esp_conn_cmd_escape_and_append(data, &off,
1260 					     params->ssid, params->ssid_length);
1261 	if (err) {
1262 		return err;
1263 	}
1264 
1265 	err = esp_conn_cmd_append_literal(data, &off, "\",\"");
1266 	if (err) {
1267 		return err;
1268 	}
1269 
1270 	if (params->security == WIFI_SECURITY_TYPE_PSK) {
1271 		err = esp_conn_cmd_escape_and_append(data, &off,
1272 						     params->psk, params->psk_length);
1273 		if (err) {
1274 			return err;
1275 		}
1276 	}
1277 
1278 	err = esp_conn_cmd_append_literal(data, &off, "\"");
1279 	if (err) {
1280 		return err;
1281 	}
1282 
1283 	k_work_submit_to_queue(&data->workq, &data->connect_work);
1284 
1285 	return 0;
1286 }
1287 
esp_mgmt_disconnect(const struct device * dev)1288 static int esp_mgmt_disconnect(const struct device *dev)
1289 {
1290 	struct esp_data *data = dev->data;
1291 	int ret;
1292 
1293 	ret = esp_cmd_send(data, NULL, 0, "AT+CWQAP", ESP_CMD_TIMEOUT);
1294 
1295 	return ret;
1296 }
1297 
esp_mgmt_ap_enable(const struct device * dev,struct wifi_connect_req_params * params)1298 static int esp_mgmt_ap_enable(const struct device *dev,
1299 			      struct wifi_connect_req_params *params)
1300 {
1301 	char cmd[sizeof("AT+"_CWSAP"=\"\",\"\",xx,x") + WIFI_SSID_MAX_LEN +
1302 		 WIFI_PSK_MAX_LEN];
1303 	struct esp_data *data = dev->data;
1304 	int ecn = 0, len, ret;
1305 
1306 	ret = esp_mode_flags_set(data, EDF_AP_ENABLED);
1307 	if (ret < 0) {
1308 		LOG_ERR("Failed to enable AP mode, ret %d", ret);
1309 		return ret;
1310 	}
1311 
1312 	len = snprintk(cmd, sizeof(cmd), "AT+"_CWSAP"=\"");
1313 	memcpy(&cmd[len], params->ssid, params->ssid_length);
1314 	len += params->ssid_length;
1315 
1316 	if (params->security == WIFI_SECURITY_TYPE_PSK) {
1317 		len += snprintk(&cmd[len], sizeof(cmd) - len, "\",\"");
1318 		memcpy(&cmd[len], params->psk, params->psk_length);
1319 		len += params->psk_length;
1320 		ecn = 3;
1321 	} else {
1322 		len += snprintk(&cmd[len], sizeof(cmd) - len, "\",\"");
1323 	}
1324 
1325 	snprintk(&cmd[len], sizeof(cmd) - len, "\",%d,%d", params->channel,
1326 		 ecn);
1327 
1328 	ret = esp_cmd_send(data, NULL, 0, cmd, ESP_CMD_TIMEOUT);
1329 
1330 	net_if_dormant_off(data->net_iface);
1331 
1332 	return ret;
1333 }
1334 
esp_mgmt_ap_disable(const struct device * dev)1335 static int esp_mgmt_ap_disable(const struct device *dev)
1336 {
1337 	struct esp_data *data = dev->data;
1338 
1339 	if (!esp_flags_are_set(data, EDF_STA_CONNECTED)) {
1340 		net_if_dormant_on(data->net_iface);
1341 	}
1342 
1343 	return esp_mode_flags_clear(data, EDF_AP_ENABLED);
1344 }
1345 
esp_init_work(struct k_work * work)1346 static void esp_init_work(struct k_work *work)
1347 {
1348 	struct esp_data *dev;
1349 	int ret;
1350 	static const struct setup_cmd setup_cmds[] = {
1351 		SETUP_CMD_NOHANDLE("AT"),
1352 		/* turn off echo */
1353 		SETUP_CMD_NOHANDLE("ATE0"),
1354 		SETUP_CMD_NOHANDLE("AT+UART_CUR="_UART_CUR),
1355 #if DT_INST_NODE_HAS_PROP(0, target_speed)
1356 	};
1357 	static const struct setup_cmd setup_cmds_target_baudrate[] = {
1358 		SETUP_CMD_NOHANDLE("AT"),
1359 #endif
1360 #if defined(CONFIG_WIFI_ESP_AT_FETCH_VERSION)
1361 		SETUP_CMD_NOHANDLE("AT+GMR"),
1362 #endif
1363 #if defined(CONFIG_WIFI_ESP_AT_VERSION_1_7)
1364 		SETUP_CMD_NOHANDLE(ESP_CMD_CWMODE(STA)),
1365 #endif
1366 #if defined(CONFIG_WIFI_ESP_AT_IP_STATIC)
1367 		/* enable Static IP Config */
1368 		SETUP_CMD_NOHANDLE(ESP_CMD_DHCP_ENABLE(STATION, 0)),
1369 		SETUP_CMD_NOHANDLE(ESP_CMD_SET_IP(CONFIG_WIFI_ESP_AT_IP_ADDRESS,
1370 						  CONFIG_WIFI_ESP_AT_IP_GATEWAY,
1371 						  CONFIG_WIFI_ESP_AT_IP_MASK)),
1372 #else
1373 		/* enable DHCP */
1374 		SETUP_CMD_NOHANDLE(ESP_CMD_DHCP_ENABLE(STATION, 1)),
1375 #endif
1376 		/* enable multiple socket support */
1377 		SETUP_CMD_NOHANDLE("AT+CIPMUX=1"),
1378 
1379 		SETUP_CMD_NOHANDLE(
1380 			ESP_CMD_CWLAPOPT(ESP_CMD_CWLAPOPT_ORDERED, ESP_CMD_CWLAPOPT_MASK)),
1381 
1382 #if !defined(CONFIG_WIFI_ESP_AT_VERSION_1_7)
1383 		SETUP_CMD_NOHANDLE(ESP_CMD_CWMODE(STA)),
1384 		SETUP_CMD_NOHANDLE("AT+CWAUTOCONN=0"),
1385 		SETUP_CMD_NOHANDLE(ESP_CMD_CWMODE(NONE)),
1386 #endif
1387 #if defined(CONFIG_WIFI_ESP_AT_PASSIVE_MODE)
1388 		SETUP_CMD_NOHANDLE("AT+CIPRECVMODE=1"),
1389 #endif
1390 #if defined(CONFIG_WIFI_ESP_AT_CIPDINFO_USE)
1391 		SETUP_CMD_NOHANDLE("AT+CIPDINFO=1"),
1392 #endif
1393 		SETUP_CMD("AT+"_CIPSTAMAC"?", "+"_CIPSTAMAC":",
1394 			  on_cmd_cipstamac, 1U, ""),
1395 	};
1396 
1397 	dev = CONTAINER_OF(work, struct esp_data, init_work);
1398 
1399 	ret = modem_cmd_handler_setup_cmds(&dev->mctx.iface,
1400 					   &dev->mctx.cmd_handler, setup_cmds,
1401 					   ARRAY_SIZE(setup_cmds),
1402 					   &dev->sem_response,
1403 					   ESP_INIT_TIMEOUT);
1404 	if (ret < 0) {
1405 		LOG_ERR("Init failed %d", ret);
1406 		return;
1407 	}
1408 
1409 #if DT_INST_NODE_HAS_PROP(0, target_speed)
1410 	static const struct uart_config uart_config = {
1411 		.baudrate = DT_INST_PROP(0, target_speed),
1412 		.parity = UART_CFG_PARITY_NONE,
1413 		.stop_bits = UART_CFG_STOP_BITS_1,
1414 		.data_bits = UART_CFG_DATA_BITS_8,
1415 		.flow_ctrl = DT_PROP(ESP_BUS, hw_flow_control) ?
1416 			UART_CFG_FLOW_CTRL_RTS_CTS : UART_CFG_FLOW_CTRL_NONE,
1417 	};
1418 
1419 	ret = uart_configure(DEVICE_DT_GET(DT_INST_BUS(0)), &uart_config);
1420 	if (ret < 0) {
1421 		LOG_ERR("Baudrate change failed %d", ret);
1422 		return;
1423 	}
1424 
1425 	/* arbitrary sleep period to give ESP enough time to reconfigure */
1426 	k_sleep(K_MSEC(100));
1427 
1428 	ret = modem_cmd_handler_setup_cmds(&dev->mctx.iface,
1429 				&dev->mctx.cmd_handler,
1430 				setup_cmds_target_baudrate,
1431 				ARRAY_SIZE(setup_cmds_target_baudrate),
1432 				&dev->sem_response,
1433 				ESP_INIT_TIMEOUT);
1434 	if (ret < 0) {
1435 		LOG_ERR("Init failed %d", ret);
1436 		return;
1437 	}
1438 #endif
1439 
1440 	net_if_set_link_addr(dev->net_iface, dev->mac_addr,
1441 			     sizeof(dev->mac_addr), NET_LINK_ETHERNET);
1442 
1443 	if (IS_ENABLED(CONFIG_WIFI_ESP_AT_VERSION_1_7)) {
1444 		/* This is the mode entered in above setup commands */
1445 		dev->mode = ESP_MODE_STA;
1446 
1447 		/*
1448 		 * In case of ESP 1.7 this is the first time CWMODE is entered
1449 		 * STA mode, so request hostname change now.
1450 		 */
1451 		esp_configure_hostname(dev);
1452 	}
1453 
1454 	LOG_INF("ESP Wi-Fi ready");
1455 
1456 	/* L1 network layer (physical layer) is up */
1457 	net_if_carrier_on(dev->net_iface);
1458 
1459 	k_sem_give(&dev->sem_if_up);
1460 }
1461 
esp_reset(const struct device * dev)1462 static int esp_reset(const struct device *dev)
1463 {
1464 	struct esp_data *data = dev->data;
1465 	int ret = -EAGAIN;
1466 
1467 	if (net_if_is_carrier_ok(data->net_iface)) {
1468 		net_if_carrier_off(data->net_iface);
1469 	}
1470 
1471 #if DT_INST_NODE_HAS_PROP(0, power_gpios)
1472 	const struct esp_config *config = dev->config;
1473 
1474 	gpio_pin_set_dt(&config->power, 0);
1475 	k_sleep(K_MSEC(100));
1476 	gpio_pin_set_dt(&config->power, 1);
1477 #elif DT_INST_NODE_HAS_PROP(0, reset_gpios)
1478 	const struct esp_config *config = dev->config;
1479 
1480 	gpio_pin_set_dt(&config->reset, 1);
1481 	k_sleep(K_MSEC(100));
1482 	gpio_pin_set_dt(&config->reset, 0);
1483 #else
1484 #if DT_INST_NODE_HAS_PROP(0, external_reset)
1485 	/* Wait to see if the interface comes up by itself */
1486 	ret = k_sem_take(&data->sem_if_ready, K_MSEC(CONFIG_WIFI_ESP_AT_RESET_TIMEOUT));
1487 #endif
1488 	int retries = 3;
1489 
1490 	/* Don't need to run this if the interface came up by itself */
1491 	while ((ret != 0) && retries--) {
1492 		ret = modem_cmd_send(&data->mctx.iface, &data->mctx.cmd_handler,
1493 				     NULL, 0, "AT+RST", &data->sem_if_ready,
1494 				     K_MSEC(CONFIG_WIFI_ESP_AT_RESET_TIMEOUT));
1495 		if (ret == 0 || ret != -ETIMEDOUT) {
1496 			break;
1497 		}
1498 	}
1499 
1500 	if (ret < 0) {
1501 		LOG_ERR("Failed to reset device: %d", ret);
1502 		return -EAGAIN;
1503 	}
1504 #endif
1505 	LOG_INF("Waiting for interface to come up");
1506 
1507 	ret = k_sem_take(&data->sem_if_up, ESP_INIT_TIMEOUT);
1508 	if (ret == -EAGAIN) {
1509 		LOG_ERR("Timeout waiting for interface");
1510 	}
1511 
1512 	return ret;
1513 }
1514 
esp_iface_init(struct net_if * iface)1515 static void esp_iface_init(struct net_if *iface)
1516 {
1517 	esp_offload_init(iface);
1518 
1519 	/* Not currently connected to a network */
1520 	net_if_dormant_on(iface);
1521 }
1522 
esp_offload_get_type(void)1523 static enum offloaded_net_if_types esp_offload_get_type(void)
1524 {
1525 	return L2_OFFLOADED_NET_IF_TYPE_WIFI;
1526 }
1527 
1528 static const struct wifi_mgmt_ops esp_mgmt_ops = {
1529 	.scan		   = esp_mgmt_scan,
1530 	.connect	   = esp_mgmt_connect,
1531 	.disconnect	   = esp_mgmt_disconnect,
1532 	.ap_enable	   = esp_mgmt_ap_enable,
1533 	.ap_disable	   = esp_mgmt_ap_disable,
1534 	.iface_status	   = esp_mgmt_iface_status,
1535 };
1536 
1537 static const struct net_wifi_mgmt_offload esp_api = {
1538 	.wifi_iface.iface_api.init = esp_iface_init,
1539 	.wifi_iface.get_type = esp_offload_get_type,
1540 	.wifi_mgmt_api = &esp_mgmt_ops,
1541 };
1542 
1543 static int esp_init(const struct device *dev);
1544 
1545 /* The network device must be instantiated above the init function in order
1546  * for the struct net_if that the macro declares to be visible inside the
1547  * function. An `extern` declaration does not work as the struct is static.
1548  */
1549 NET_DEVICE_DT_INST_OFFLOAD_DEFINE(0, esp_init, NULL,
1550 				  &esp_driver_data, &esp_driver_config,
1551 				  CONFIG_WIFI_INIT_PRIORITY, &esp_api,
1552 				  ESP_MTU);
1553 
1554 CONNECTIVITY_WIFI_MGMT_BIND(Z_DEVICE_DT_DEV_ID(DT_DRV_INST(0)));
1555 
esp_init(const struct device * dev)1556 static int esp_init(const struct device *dev)
1557 {
1558 #if DT_INST_NODE_HAS_PROP(0, power_gpios) || DT_INST_NODE_HAS_PROP(0, reset_gpios)
1559 	const struct esp_config *config = dev->config;
1560 #endif
1561 	struct esp_data *data = dev->data;
1562 	int ret = 0;
1563 
1564 	k_sem_init(&data->sem_tx_ready, 0, 1);
1565 	k_sem_init(&data->sem_response, 0, 1);
1566 	k_sem_init(&data->sem_if_ready, 0, 1);
1567 	k_sem_init(&data->sem_if_up, 0, 1);
1568 
1569 	k_work_init(&data->init_work, esp_init_work);
1570 	k_work_init_delayable(&data->ip_addr_work, esp_ip_addr_work);
1571 	k_work_init(&data->scan_work, esp_mgmt_scan_work);
1572 	k_work_init(&data->connect_work, esp_mgmt_connect_work);
1573 	k_work_init(&data->disconnect_work, esp_mgmt_disconnect_work);
1574 	k_work_init(&data->iface_status_work, esp_mgmt_iface_status_work);
1575 	k_work_init(&data->mode_switch_work, esp_mode_switch_work);
1576 	if (IS_ENABLED(CONFIG_WIFI_ESP_AT_DNS_USE)) {
1577 		k_work_init(&data->dns_work, esp_dns_work);
1578 	}
1579 
1580 	esp_socket_init(data);
1581 
1582 	/* initialize the work queue */
1583 	k_work_queue_start(&data->workq, esp_workq_stack,
1584 			   K_KERNEL_STACK_SIZEOF(esp_workq_stack),
1585 			   K_PRIO_COOP(CONFIG_WIFI_ESP_AT_WORKQ_THREAD_PRIORITY),
1586 			   NULL);
1587 	k_thread_name_set(&data->workq.thread, "esp_workq");
1588 
1589 	/* cmd handler */
1590 	const struct modem_cmd_handler_config cmd_handler_config = {
1591 		.match_buf = &data->cmd_match_buf[0],
1592 		.match_buf_len = sizeof(data->cmd_match_buf),
1593 		.buf_pool = &mdm_recv_pool,
1594 		.alloc_timeout = K_NO_WAIT,
1595 		.eol = "\r\n",
1596 		.user_data = NULL,
1597 		.response_cmds = response_cmds,
1598 		.response_cmds_len = ARRAY_SIZE(response_cmds),
1599 		.unsol_cmds = unsol_cmds,
1600 		.unsol_cmds_len = ARRAY_SIZE(unsol_cmds),
1601 	};
1602 
1603 	ret = modem_cmd_handler_init(&data->mctx.cmd_handler, &data->cmd_handler_data,
1604 				     &cmd_handler_config);
1605 	if (ret < 0) {
1606 		goto error;
1607 	}
1608 
1609 	/* modem interface */
1610 	const struct modem_iface_uart_config uart_config = {
1611 		.rx_rb_buf = &data->iface_rb_buf[0],
1612 		.rx_rb_buf_len = sizeof(data->iface_rb_buf),
1613 		.dev = DEVICE_DT_GET(DT_INST_BUS(0)),
1614 		.hw_flow_control = DT_PROP(ESP_BUS, hw_flow_control),
1615 	};
1616 
1617 	/* The context must be registered before the serial port is initialised. */
1618 	data->mctx.driver_data = data;
1619 	ret = modem_context_register(&data->mctx);
1620 	if (ret < 0) {
1621 		LOG_ERR("Error registering modem context: %d", ret);
1622 		goto error;
1623 	}
1624 
1625 	ret = modem_iface_uart_init(&data->mctx.iface, &data->iface_data, &uart_config);
1626 	if (ret < 0) {
1627 		goto error;
1628 	}
1629 
1630 	/* pin setup */
1631 #if DT_INST_NODE_HAS_PROP(0, power_gpios)
1632 	ret = gpio_pin_configure_dt(&config->power, GPIO_OUTPUT_INACTIVE);
1633 	if (ret < 0) {
1634 		LOG_ERR("Failed to configure %s pin", "power");
1635 		goto error;
1636 	}
1637 #endif
1638 #if DT_INST_NODE_HAS_PROP(0, reset_gpios)
1639 	ret = gpio_pin_configure_dt(&config->reset, GPIO_OUTPUT_INACTIVE);
1640 	if (ret < 0) {
1641 		LOG_ERR("Failed to configure %s pin", "reset");
1642 		goto error;
1643 	}
1644 #endif
1645 
1646 	/* start RX thread */
1647 	k_thread_create(&esp_rx_thread, esp_rx_stack,
1648 			K_KERNEL_STACK_SIZEOF(esp_rx_stack),
1649 			esp_rx,
1650 			data, NULL, NULL,
1651 			K_PRIO_COOP(CONFIG_WIFI_ESP_AT_RX_THREAD_PRIORITY), 0,
1652 			K_NO_WAIT);
1653 	k_thread_name_set(&esp_rx_thread, "esp_rx");
1654 
1655 	/* Retrieve associated network interface so asynchronous messages can be processed early */
1656 	data->net_iface = NET_IF_GET(Z_DEVICE_DT_DEV_ID(DT_DRV_INST(0)), 0);
1657 
1658 	/* Reset the modem */
1659 	ret = esp_reset(dev);
1660 
1661 error:
1662 	return ret;
1663 }
1664