Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers: esp_at: implement bind() and recvfrom() for UDP sockets #68586

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions drivers/wifi/esp_at/Kconfig.esp_at
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@ config WIFI_ESP_AT_DNS_USE
Fetch DNS servers from ESP chip with AT+CIPDNS? command and apply that
list to system DNS resolver.

config WIFI_ESP_AT_CIPDINFO_USE
bool "Use CIPDINFO to get peer ip and port"
help
Enable AT+CIPDINFO got get peer ip-address and port.

config WIFI_ESP_AT_FETCH_VERSION
bool "Fetch and log ESP-AT firmware version"
default y
Expand Down
13 changes: 12 additions & 1 deletion drivers/wifi/esp_at/esp.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,9 @@ static void esp_mgmt_disconnect_work(struct k_work *work)
#if defined(CONFIG_NET_NATIVE_IPV4)
net_if_ipv4_addr_rm(dev->net_iface, &dev->ip);
#endif
net_if_dormant_on(dev->net_iface);
if (!esp_flags_are_set(dev, EDF_AP_ENABLED)) {
net_if_dormant_on(dev->net_iface);
}
wifi_mgmt_raise_disconnect_result_event(dev->net_iface, 0);
}

Expand Down Expand Up @@ -1070,13 +1072,19 @@ static int esp_mgmt_ap_enable(const struct device *dev,

ret = esp_cmd_send(data, NULL, 0, cmd, ESP_CMD_TIMEOUT);

net_if_dormant_off(data->net_iface);

return ret;
}

static int esp_mgmt_ap_disable(const struct device *dev)
{
struct esp_data *data = dev->data;

if (!esp_flags_are_set(data, EDF_STA_CONNECTED)) {
net_if_dormant_on(data->net_iface);
}

return esp_mode_flags_clear(data, EDF_AP_ENABLED);
}

Expand Down Expand Up @@ -1123,6 +1131,9 @@ static void esp_init_work(struct k_work *work)
#endif
#if defined(CONFIG_WIFI_ESP_AT_PASSIVE_MODE)
SETUP_CMD_NOHANDLE("AT+CIPRECVMODE=1"),
#endif
#if defined(CONFIG_WIFI_ESP_AT_CIPDINFO_USE)
SETUP_CMD_NOHANDLE("AT+CIPDINFO=1"),
#endif
SETUP_CMD("AT+"_CIPSTAMAC"?", "+"_CIPSTAMAC":",
on_cmd_cipstamac, 1U, ""),
Expand Down
121 changes: 99 additions & 22 deletions drivers/wifi/esp_at/esp_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,6 @@ LOG_MODULE_REGISTER(wifi_esp_at_offload, CONFIG_WIFI_LOG_LEVEL);

#include "esp.h"

static int esp_bind(struct net_context *context, const struct sockaddr *addr,
socklen_t addrlen)
{
if (IS_ENABLED(CONFIG_NET_IPV4) && addr->sa_family == AF_INET) {
return 0;
}

return -EAFNOSUPPORT;
}

static int esp_listen(struct net_context *context, int backlog)
{
return -ENOTSUP;
Expand All @@ -43,7 +33,7 @@ static int _sock_connect(struct esp_data *dev, struct esp_socket *sock)
struct sockaddr dst;
int ret;

if (!esp_flags_are_set(dev, EDF_STA_CONNECTED)) {
if (!esp_flags_are_set(dev, EDF_STA_CONNECTED | EDF_AP_ENABLED)) {
return -ENETUNREACH;
}

Expand All @@ -62,9 +52,9 @@ static int _sock_connect(struct esp_data *dev, struct esp_socket *sock)
ntohs(net_sin(&dst)->sin_port));
} else {
snprintk(connect_msg, sizeof(connect_msg),
"AT+CIPSTART=%d,\"UDP\",\"%s\",%d",
"AT+CIPSTART=%d,\"UDP\",\"%s\",%d,%d",
sock->link_id, addr_str,
ntohs(net_sin(&dst)->sin_port));
ntohs(net_sin(&dst)->sin_port), ntohs(net_sin(&dst)->sin_port));
}

LOG_DBG("link %d, ip_proto %s, addr %s", sock->link_id,
Expand Down Expand Up @@ -106,6 +96,40 @@ void esp_connect_work(struct k_work *work)
k_mutex_unlock(&sock->lock);
}

static int esp_bind(struct net_context *context, const struct sockaddr *addr,
socklen_t addrlen)
{
struct esp_socket *sock;
struct esp_data *dev;

sock = (struct esp_socket *)context->offload_context;
dev = esp_socket_to_dev(sock);

if (esp_socket_ip_proto(sock) == IPPROTO_TCP) {
return 0;
}

if (IS_ENABLED(CONFIG_NET_IPV4) && addr->sa_family == AF_INET) {
LOG_DBG("link %d", sock->link_id);

if (esp_socket_connected(sock)) {
return -EISCONN;
}

k_mutex_lock(&sock->lock, K_FOREVER);
sock->dst = *addr;
sock->connect_cb = NULL;
sock->conn_user_data = NULL;
k_mutex_unlock(&sock->lock);

_sock_connect(dev, sock);

return 0;
}

return -EAFNOSUPPORT;
}

static int esp_connect(struct net_context *context,
const struct sockaddr *addr,
socklen_t addrlen,
Expand Down Expand Up @@ -204,7 +228,7 @@ static int _sock_send(struct esp_socket *sock, struct net_pkt *pkt)
};
struct sockaddr dst;

if (!esp_flags_are_set(dev, EDF_STA_CONNECTED)) {
if (!esp_flags_are_set(dev, EDF_STA_CONNECTED | EDF_AP_ENABLED)) {
return -ENETUNREACH;
}

Expand Down Expand Up @@ -360,7 +384,7 @@ static int esp_sendto(struct net_pkt *pkt,

LOG_DBG("link %d, timeout %d", sock->link_id, timeout);

if (!esp_flags_are_set(dev, EDF_STA_CONNECTED)) {
if (!esp_flags_are_set(dev, EDF_STA_CONNECTED | EDF_AP_ENABLED)) {
return -ENETUNREACH;
}

Expand All @@ -386,11 +410,8 @@ static int esp_sendto(struct net_pkt *pkt,
if (ret < 0) {
return ret;
}
} else if (dst_addr && memcmp(dst_addr, &sock->dst, addrlen)) {
/* This might be unexpected behaviour but the ESP
* doesn't support changing endpoint.
*/
return -EISCONN;
} else if (esp_socket_type(sock) == SOCK_DGRAM) {
memcpy(&sock->dst, dst_addr, addrlen);
}
}

Expand All @@ -406,11 +427,17 @@ static int esp_send(struct net_pkt *pkt,
}

#define CIPRECVDATA_CMD_MIN_LEN (sizeof("+CIPRECVDATA,L:") - 1)

#if defined(CONFIG_WIFI_ESP_AT_CIPDINFO_USE)
#define CIPRECVDATA_CMD_MAX_LEN (sizeof("+CIPRECVDATA,LLLL,\"255.255.255.255\",65535:") - 1)
#else
#define CIPRECVDATA_CMD_MAX_LEN (sizeof("+CIPRECVDATA,LLLL:") - 1)
#endif

static int cmd_ciprecvdata_parse(struct esp_socket *sock,
struct net_buf *buf, uint16_t len,
int *data_offset, int *data_len)
int *data_offset, int *data_len, char *ip_str,
int *port)
{
char cmd_buf[CIPRECVDATA_CMD_MAX_LEN + 1];
char *endptr;
Expand All @@ -427,6 +454,23 @@ static int cmd_ciprecvdata_parse(struct esp_socket *sock,
cmd_buf[match_len] = 0;

*data_len = strtol(&cmd_buf[len], &endptr, 10);

#if defined(CONFIG_WIFI_ESP_AT_CIPDINFO_USE)
char *strstart = endptr + 1;
char *strend = strchr(strstart, ',');

if (strstart == NULL || strend == NULL) {
return -EAGAIN;
}

memcpy(ip_str, strstart, strend - strstart);
ip_str[strend - strstart] = '\0';
*port = strtol(strend + 1, &endptr, 10);
#else
ARG_UNUSED(ip_str);
ARG_UNUSED(port);
#endif

if (endptr == &cmd_buf[len] ||
(*endptr == 0 && match_len >= CIPRECVDATA_CMD_MAX_LEN) ||
*data_len > CIPRECVDATA_MAX_LEN) {
Expand Down Expand Up @@ -461,8 +505,16 @@ MODEM_CMD_DIRECT_DEFINE(on_cmd_ciprecvdata)
int data_offset, data_len;
int err;

#if defined(CONFIG_WIFI_ESP_AT_CIPDINFO_USE)
char raw_remote_ip[INET_ADDRSTRLEN + 3] = {0};
int port = 0;

err = cmd_ciprecvdata_parse(sock, data->rx_buf, len, &data_offset,
&data_len, raw_remote_ip, &port);
#else
err = cmd_ciprecvdata_parse(sock, data->rx_buf, len, &data_offset,
&data_len);
&data_len, NULL, NULL);
#endif
if (err) {
if (err == -EAGAIN) {
return -EAGAIN;
Expand All @@ -471,6 +523,31 @@ MODEM_CMD_DIRECT_DEFINE(on_cmd_ciprecvdata)
return err;
}

#if defined(CONFIG_WIFI_ESP_AT_CIPDINFO_USE)
struct sockaddr_in *recv_addr =
(struct sockaddr_in *) &sock->context->remote;

recv_addr->sin_port = ntohs(port);
recv_addr->sin_family = AF_INET;

/* IP addr comes within quotation marks, which is disliked by
* conv function. So we remove them by subtraction 2 from
* raw_remote_ip length and index from &raw_remote_ip[1].
*/
char remote_ip_addr[INET_ADDRSTRLEN];
size_t remote_ip_str_len;

remote_ip_str_len = MIN(sizeof(remote_ip_addr) - 1,
strlen(raw_remote_ip) - 2);
strncpy(remote_ip_addr, &raw_remote_ip[1], remote_ip_str_len);
remote_ip_addr[remote_ip_str_len] = '\0';

if (net_addr_pton(AF_INET, remote_ip_addr, &recv_addr->sin_addr) < 0) {
LOG_ERR("Invalid src addr %s", remote_ip_addr);
err = -EIO;
return err;
}
#endif
esp_socket_rx(sock, data->rx_buf, data_offset, data_len);

return data_offset + data_len;
Expand Down
5 changes: 5 additions & 0 deletions drivers/wifi/esp_at/esp_socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ static struct net_pkt *esp_socket_prepare_pkt(struct esp_socket *sock,
net_pkt_set_context(pkt, sock->context);
net_pkt_cursor_init(pkt);

#if defined(CONFIG_WIFI_ESP_AT_CIPDINFO_USE)
memcpy(&pkt->remote, &sock->context->remote, sizeof(pkt->remote));
pkt->family = sock->dst.sa_family;
#endif

return pkt;
}

Expand Down
Loading