zephyr/drivers/wifi/esp/esp.h

242 lines
5.5 KiB
C

/*
* Copyright (c) 2019 Tobias Svehagen
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_WIFI_ESP_H_
#define ZEPHYR_INCLUDE_DRIVERS_WIFI_ESP_H_
#include <kernel.h>
#include <net/net_context.h>
#include <net/net_if.h>
#include <net/net_ip.h>
#include <net/net_pkt.h>
#include <net/wifi_mgmt.h>
#include "modem_context.h"
#include "modem_cmd_handler.h"
#include "modem_iface_uart.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Define the commands that differ between the AT versions */
#if defined(CONFIG_WIFI_ESP_AT_VERSION_1_7)
#define _CWMODE "CWMODE_CUR"
#define _CWSAP "CWSAP_CUR"
#define _CWJAP "CWJAP_CUR"
#define _CIPSTA "CIPSTA_CUR"
#define _CIPSTAMAC "CIPSTAMAC_CUR"
#define _CIPRECVDATA "+CIPRECVDATA,"
#define _CIPRECVDATA_END ':'
#else
#define _CWMODE "CWMODE"
#define _CWSAP "CWSAP"
#define _CWJAP "CWJAP"
#define _CIPSTA "CIPSTA"
#define _CIPSTAMAC "CIPSTAMAC"
#define _CIPRECVDATA "+CIPRECVDATA:"
#define _CIPRECVDATA_END ','
#endif
/*
* Passive mode differs a bit between firmware versions and the macro
* ESP_PROTO_PASSIVE is therefore used to determine what protocol operates in
* passive mode. For AT version 1.7 passive mode only affects TCP but in AT
* version 2.0 it affects both TCP and UDP.
*/
#if defined(CONFIG_WIFI_ESP_PASSIVE_MODE)
#if defined(CONFIG_WIFI_ESP_AT_VERSION_1_7)
#define ESP_PROTO_PASSIVE(proto) (proto == IPPROTO_TCP)
#else
#define ESP_PROTO_PASSIVE(proto) \
(proto == IPPROTO_TCP || proto == IPPROTO_UDP)
#endif /* CONFIG_WIFI_ESP_AT_VERSION_1_7 */
#else
#define ESP_PROTO_PASSIVE(proto) 0
#endif /* CONFIG_WIFI_ESP_PASSIVE_MODE */
#define ESP_BUS DT_BUS(DT_DRV_INST(0))
#if DT_PROP(ESP_BUS, hw_flow_control) == 1
#define _FLOW_CONTROL "3"
#else
#define _FLOW_CONTROL "0"
#endif
#define _UART_CUR \
STRINGIFY(DT_PROP(ESP_BUS, current_speed))",8,1,0,"_FLOW_CONTROL
#define CONN_CMD_MAX_LEN (sizeof("AT+"_CWJAP"=\"\",\"\"") + \
WIFI_SSID_MAX_LEN + WIFI_PSK_MAX_LEN)
#define ESP_MAX_SOCKETS 5
/* Maximum amount that can be sent with CIPSEND and read with CIPRECVDATA */
#define ESP_MTU 2048
#define CIPRECVDATA_MAX_LEN ESP_MTU
#define INVALID_LINK_ID 255
#define MDM_RING_BUF_SIZE 1024
#define MDM_RECV_MAX_BUF 30
#define MDM_RECV_BUF_SIZE 128
#define CMD_BUF_ALLOC_TIMEOUT K_SECONDS(1)
#define ESP_CMD_TIMEOUT K_SECONDS(10)
#define ESP_SCAN_TIMEOUT K_SECONDS(10)
#define ESP_CONNECT_TIMEOUT K_SECONDS(20)
#define ESP_INIT_TIMEOUT K_SECONDS(10)
extern struct esp_data esp_driver_data;
enum esp_socket_flags {
ESP_SOCK_IN_USE = BIT(1),
ESP_SOCK_CONNECTING = BIT(2),
ESP_SOCK_CONNECTED = BIT(3)
};
struct esp_socket {
/* internal */
uint8_t idx;
uint8_t link_id;
uint8_t flags;
/* socket info */
sa_family_t family;
enum net_sock_type type;
enum net_ip_protocol ip_proto;
struct sockaddr src;
struct sockaddr dst;
/* for +CIPRECVDATA */
size_t bytes_avail;
/* packets */
struct k_fifo fifo_rx_pkt;
struct net_pkt *tx_pkt;
/* sem */
struct k_sem sem_data_ready;
/* work */
struct k_work connect_work;
struct k_work send_work;
struct k_work recv_work;
struct k_work recvdata_work;
/* net context */
struct net_context *context;
net_context_connect_cb_t connect_cb;
net_context_send_cb_t send_cb;
net_context_recv_cb_t recv_cb;
/* callback data */
void *conn_user_data;
void *send_user_data;
void *recv_user_data;
};
enum esp_data_flag {
EDF_STA_CONNECTING = BIT(1),
EDF_STA_CONNECTED = BIT(2)
};
/* driver data */
struct esp_data {
struct net_if *net_iface;
uint8_t flags;
char conn_cmd[CONN_CMD_MAX_LEN];
/* addresses */
struct in_addr ip;
struct in_addr gw;
struct in_addr nm;
uint8_t mac_addr[6];
/* modem context */
struct modem_context mctx;
/* modem interface */
struct modem_iface_uart_data iface_data;
uint8_t iface_isr_buf[MDM_RECV_BUF_SIZE];
uint8_t iface_rb_buf[MDM_RING_BUF_SIZE];
/* modem cmds */
struct modem_cmd_handler_data cmd_handler_data;
uint8_t cmd_read_buf[MDM_RECV_BUF_SIZE];
uint8_t cmd_match_buf[MDM_RECV_BUF_SIZE];
/* socket data */
struct esp_socket sockets[ESP_MAX_SOCKETS];
struct esp_socket *rx_sock;
/* work */
struct k_work_q workq;
struct k_work init_work;
struct k_delayed_work ip_addr_work;
struct k_work scan_work;
struct k_work connect_work;
scan_result_cb_t scan_cb;
/* semaphores */
struct k_sem sem_tx_ready;
struct k_sem sem_response;
struct k_sem sem_if_ready;
struct k_sem sem_if_up;
};
int esp_offload_init(struct net_if *iface);
struct net_pkt *esp_prepare_pkt(struct esp_data *dev, struct net_buf *src,
size_t offset, size_t len);
struct esp_socket *esp_socket_get();
int esp_socket_put(struct esp_socket *sock);
struct esp_socket *esp_socket_from_link_id(struct esp_data *data,
uint8_t link_id);
void esp_socket_init(struct esp_data *data);
static inline struct esp_data *esp_socket_to_dev(struct esp_socket *sock)
{
return CONTAINER_OF(sock - sock->idx, struct esp_data, sockets);
}
static inline bool esp_socket_in_use(struct esp_socket *sock)
{
return (sock->flags & ESP_SOCK_IN_USE) != 0;
}
static inline bool esp_socket_connected(struct esp_socket *sock)
{
return (sock->flags & ESP_SOCK_CONNECTED) != 0;
}
static inline void esp_flag_set(struct esp_data *dev,
enum esp_data_flag flag)
{
dev->flags |= flag;
}
static inline void esp_flag_clear(struct esp_data *dev,
enum esp_data_flag flag)
{
dev->flags &= (~flag);
}
static inline bool esp_flag_is_set(struct esp_data *dev,
enum esp_data_flag flag)
{
return (dev->flags & flag) != 0;
}
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_INCLUDE_DRIVERS_WIFI_ESP_H_ */