forked from espressif/arduino-esp32
Update IDF to 3.2-3276a13 and esptool.py to 2.5.0 (#1878)
* TX Flow Control and Code cleanup * Use semaphore instead of delay TX functionality is done. * Use single buffer and empty queue on exit * Fix compile issues because of LwIP code relocation * Add temporary header to fix Azure not compiling * Fix AsyncUDP early init * AsyncUDP Multicast fixes * Add source mac address and rework multicast * Allow redefinition of default pins for Serials 1 and 2 * Update IDF to 3276a13 * Update esptool.py to 2.5.0 * Fix sketches * Fix log level in BluetoothSetial
This commit is contained in:
@ -8,6 +8,7 @@ extern "C" {
|
||||
#include "lwip/igmp.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/mld6.h"
|
||||
#include "lwip/prot/ethernet.h"
|
||||
#include <esp_err.h>
|
||||
#include <esp_wifi.h>
|
||||
}
|
||||
@ -15,7 +16,7 @@ extern "C" {
|
||||
#include "lwip/priv/tcpip_priv.h"
|
||||
|
||||
typedef struct {
|
||||
struct tcpip_api_call call;
|
||||
struct tcpip_api_call_data call;
|
||||
udp_pcb * pcb;
|
||||
const ip_addr_t *addr;
|
||||
uint16_t port;
|
||||
@ -24,7 +25,7 @@ typedef struct {
|
||||
err_t err;
|
||||
} udp_api_call_t;
|
||||
|
||||
static err_t _udp_connect_api(struct tcpip_api_call *api_call_msg){
|
||||
static err_t _udp_connect_api(struct tcpip_api_call_data *api_call_msg){
|
||||
udp_api_call_t * msg = (udp_api_call_t *)api_call_msg;
|
||||
msg->err = udp_connect(msg->pcb, msg->addr, msg->port);
|
||||
return msg->err;
|
||||
@ -35,11 +36,11 @@ static err_t _udp_connect(struct udp_pcb *pcb, const ip_addr_t *addr, u16_t port
|
||||
msg.pcb = pcb;
|
||||
msg.addr = addr;
|
||||
msg.port = port;
|
||||
tcpip_api_call(_udp_connect_api, (struct tcpip_api_call*)&msg);
|
||||
tcpip_api_call(_udp_connect_api, (struct tcpip_api_call_data*)&msg);
|
||||
return msg.err;
|
||||
}
|
||||
|
||||
static err_t _udp_disconnect_api(struct tcpip_api_call *api_call_msg){
|
||||
static err_t _udp_disconnect_api(struct tcpip_api_call_data *api_call_msg){
|
||||
udp_api_call_t * msg = (udp_api_call_t *)api_call_msg;
|
||||
msg->err = 0;
|
||||
udp_disconnect(msg->pcb);
|
||||
@ -49,10 +50,10 @@ static err_t _udp_disconnect_api(struct tcpip_api_call *api_call_msg){
|
||||
static void _udp_disconnect(struct udp_pcb *pcb){
|
||||
udp_api_call_t msg;
|
||||
msg.pcb = pcb;
|
||||
tcpip_api_call(_udp_disconnect_api, (struct tcpip_api_call*)&msg);
|
||||
tcpip_api_call(_udp_disconnect_api, (struct tcpip_api_call_data*)&msg);
|
||||
}
|
||||
|
||||
static err_t _udp_remove_api(struct tcpip_api_call *api_call_msg){
|
||||
static err_t _udp_remove_api(struct tcpip_api_call_data *api_call_msg){
|
||||
udp_api_call_t * msg = (udp_api_call_t *)api_call_msg;
|
||||
msg->err = 0;
|
||||
udp_remove(msg->pcb);
|
||||
@ -62,10 +63,10 @@ static err_t _udp_remove_api(struct tcpip_api_call *api_call_msg){
|
||||
static void _udp_remove(struct udp_pcb *pcb){
|
||||
udp_api_call_t msg;
|
||||
msg.pcb = pcb;
|
||||
tcpip_api_call(_udp_remove_api, (struct tcpip_api_call*)&msg);
|
||||
tcpip_api_call(_udp_remove_api, (struct tcpip_api_call_data*)&msg);
|
||||
}
|
||||
|
||||
static err_t _udp_bind_api(struct tcpip_api_call *api_call_msg){
|
||||
static err_t _udp_bind_api(struct tcpip_api_call_data *api_call_msg){
|
||||
udp_api_call_t * msg = (udp_api_call_t *)api_call_msg;
|
||||
msg->err = udp_bind(msg->pcb, msg->addr, msg->port);
|
||||
return msg->err;
|
||||
@ -76,11 +77,11 @@ static err_t _udp_bind(struct udp_pcb *pcb, const ip_addr_t *addr, u16_t port){
|
||||
msg.pcb = pcb;
|
||||
msg.addr = addr;
|
||||
msg.port = port;
|
||||
tcpip_api_call(_udp_bind_api, (struct tcpip_api_call*)&msg);
|
||||
tcpip_api_call(_udp_bind_api, (struct tcpip_api_call_data*)&msg);
|
||||
return msg.err;
|
||||
}
|
||||
|
||||
static err_t _udp_sendto_api(struct tcpip_api_call *api_call_msg){
|
||||
static err_t _udp_sendto_api(struct tcpip_api_call_data *api_call_msg){
|
||||
udp_api_call_t * msg = (udp_api_call_t *)api_call_msg;
|
||||
msg->err = udp_sendto(msg->pcb, msg->pb, msg->addr, msg->port);
|
||||
return msg->err;
|
||||
@ -92,11 +93,11 @@ static err_t _udp_sendto(struct udp_pcb *pcb, struct pbuf *pb, const ip_addr_t *
|
||||
msg.addr = addr;
|
||||
msg.port = port;
|
||||
msg.pb = pb;
|
||||
tcpip_api_call(_udp_sendto_api, (struct tcpip_api_call*)&msg);
|
||||
tcpip_api_call(_udp_sendto_api, (struct tcpip_api_call_data*)&msg);
|
||||
return msg.err;
|
||||
}
|
||||
|
||||
static err_t _udp_sendto_if_api(struct tcpip_api_call *api_call_msg){
|
||||
static err_t _udp_sendto_if_api(struct tcpip_api_call_data *api_call_msg){
|
||||
udp_api_call_t * msg = (udp_api_call_t *)api_call_msg;
|
||||
msg->err = udp_sendto_if(msg->pcb, msg->pb, msg->addr, msg->port, msg->netif);
|
||||
return msg->err;
|
||||
@ -109,7 +110,7 @@ static err_t _udp_sendto_if(struct udp_pcb *pcb, struct pbuf *pb, const ip_addr_
|
||||
msg.port = port;
|
||||
msg.pb = pb;
|
||||
msg.netif = netif;
|
||||
tcpip_api_call(_udp_sendto_if_api, (struct tcpip_api_call*)&msg);
|
||||
tcpip_api_call(_udp_sendto_if_api, (struct tcpip_api_call_data*)&msg);
|
||||
return msg.err;
|
||||
}
|
||||
|
||||
@ -292,19 +293,23 @@ AsyncUDPPacket::AsyncUDPPacket(AsyncUDP *udp, pbuf *pb, const ip_addr_t *raddr,
|
||||
_remoteIp.type = raddr->type;
|
||||
_localIp.type = _remoteIp.type;
|
||||
|
||||
eth_hdr* eth = NULL;
|
||||
udp_hdr* udphdr = reinterpret_cast<udp_hdr*>(_data - UDP_HLEN);
|
||||
_localPort = ntohs(udphdr->dest);
|
||||
_remotePort = ntohs(udphdr->src);
|
||||
|
||||
|
||||
if (_remoteIp.type == IPADDR_TYPE_V4) {
|
||||
eth = (eth_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP_HLEN - SIZEOF_ETH_HDR);
|
||||
struct ip_hdr * iphdr = (struct ip_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP_HLEN);
|
||||
_localIp.u_addr.ip4.addr = iphdr->dest.addr;
|
||||
_remoteIp.u_addr.ip4.addr = iphdr->src.addr;
|
||||
} else {
|
||||
eth = (eth_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP6_HLEN - SIZEOF_ETH_HDR);
|
||||
struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP6_HLEN);
|
||||
memcpy(&_localIp.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16);
|
||||
memcpy(&_remoteIp.u_addr.ip6.addr, (uint8_t *)ip6hdr->src.addr, 16);
|
||||
}
|
||||
memcpy(_remoteMac, eth->src.addr, 6);
|
||||
|
||||
struct netif * netif = NULL;
|
||||
void * nif = NULL;
|
||||
@ -415,6 +420,11 @@ uint16_t AsyncUDPPacket::remotePort()
|
||||
return _remotePort;
|
||||
}
|
||||
|
||||
void AsyncUDPPacket::remoteMac(uint8_t * mac)
|
||||
{
|
||||
memcpy(mac, _remoteMac, 6);
|
||||
}
|
||||
|
||||
bool AsyncUDPPacket::isIPv6()
|
||||
{
|
||||
return _localIp.type == IPADDR_TYPE_V6;
|
||||
@ -452,16 +462,24 @@ size_t AsyncUDPPacket::send(AsyncUDPMessage &message)
|
||||
return write(message.data(), message.length());
|
||||
}
|
||||
|
||||
AsyncUDP::AsyncUDP()
|
||||
{
|
||||
bool AsyncUDP::_init(){
|
||||
if(_pcb){
|
||||
return true;
|
||||
}
|
||||
_pcb = udp_new();
|
||||
_connected = false;
|
||||
_handler = NULL;
|
||||
if(!_pcb){
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
//_lock = xSemaphoreCreateMutex();
|
||||
udp_recv(_pcb, &_udp_recv, (void *) this);
|
||||
return true;
|
||||
}
|
||||
|
||||
AsyncUDP::AsyncUDP()
|
||||
{
|
||||
_pcb = NULL;
|
||||
_connected = false;
|
||||
_handler = NULL;
|
||||
}
|
||||
|
||||
AsyncUDP::~AsyncUDP()
|
||||
@ -483,8 +501,7 @@ void AsyncUDP::close()
|
||||
_udp_disconnect(_pcb);
|
||||
}
|
||||
_connected = false;
|
||||
_pcb->multicast_ip.type = IPADDR_TYPE_V4;
|
||||
_pcb->multicast_ip.u_addr.ip4.addr = 0;
|
||||
//todo: unjoin multicast group
|
||||
}
|
||||
UDP_MUTEX_UNLOCK();
|
||||
}
|
||||
@ -495,7 +512,7 @@ bool AsyncUDP::connect(const ip_addr_t *addr, uint16_t port)
|
||||
log_e("failed to start task");
|
||||
return false;
|
||||
}
|
||||
if(_pcb == NULL) {
|
||||
if(!_init()) {
|
||||
return false;
|
||||
}
|
||||
close();
|
||||
@ -516,7 +533,7 @@ bool AsyncUDP::listen(const ip_addr_t *addr, uint16_t port)
|
||||
log_e("failed to start task");
|
||||
return false;
|
||||
}
|
||||
if(_pcb == NULL) {
|
||||
if(!_init()) {
|
||||
return false;
|
||||
}
|
||||
close();
|
||||
@ -534,57 +551,53 @@ bool AsyncUDP::listen(const ip_addr_t *addr, uint16_t port)
|
||||
return true;
|
||||
}
|
||||
|
||||
static esp_err_t joinMulticastGroup(const ip_addr_t *addr, bool join, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX)
|
||||
{
|
||||
struct netif * netif = NULL;
|
||||
if(tcpip_if < TCPIP_ADAPTER_IF_MAX){
|
||||
void * nif = NULL;
|
||||
esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif);
|
||||
if (err) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
netif = (struct netif *)nif;
|
||||
}
|
||||
|
||||
if (addr->type == IPADDR_TYPE_V4) {
|
||||
if(join){
|
||||
if (igmp_joingroup_netif(netif, (const ip4_addr *)&(addr->u_addr.ip4))) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
} else {
|
||||
if (igmp_leavegroup_netif(netif, (const ip4_addr *)&(addr->u_addr.ip4))) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(join){
|
||||
if (mld6_joingroup_netif(netif, &(addr->u_addr.ip6))) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
} else {
|
||||
if (mld6_leavegroup_netif(netif, &(addr->u_addr.ip6))) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool AsyncUDP::listenMulticast(const ip_addr_t *addr, uint16_t port, uint8_t ttl, tcpip_adapter_if_t tcpip_if)
|
||||
{
|
||||
if(!ip_addr_ismulticast(addr)) {
|
||||
return false;
|
||||
}
|
||||
ip_addr_t multicast_if_addr;
|
||||
uint8_t mode;
|
||||
if(esp_wifi_get_mode((wifi_mode_t*)&mode)){
|
||||
mode = WIFI_MODE_NULL;
|
||||
}
|
||||
|
||||
if(addr->type == IPADDR_TYPE_V6){
|
||||
multicast_if_addr.type = IPADDR_TYPE_V6;
|
||||
|
||||
if((tcpip_if == TCPIP_ADAPTER_IF_STA && (mode & WIFI_MODE_STA))
|
||||
|| (tcpip_if == TCPIP_ADAPTER_IF_AP && (mode & WIFI_MODE_AP))
|
||||
|| (tcpip_if == TCPIP_ADAPTER_IF_ETH)) {
|
||||
if(tcpip_adapter_get_ip6_linklocal(tcpip_if, &multicast_if_addr.u_addr.ip6)){
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mld6_joingroup(&(multicast_if_addr.u_addr.ip6), &(addr->u_addr.ip6))) {
|
||||
return false;
|
||||
}
|
||||
} else if(addr->type == IPADDR_TYPE_V4){
|
||||
tcpip_adapter_ip_info_t ifIpInfo;
|
||||
|
||||
if((tcpip_if == TCPIP_ADAPTER_IF_STA && (mode & WIFI_MODE_STA))
|
||||
|| (tcpip_if == TCPIP_ADAPTER_IF_AP && (mode & WIFI_MODE_AP))
|
||||
|| (tcpip_if == TCPIP_ADAPTER_IF_ETH)) {
|
||||
if(tcpip_adapter_get_ip_info(tcpip_if, &ifIpInfo)){
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
multicast_if_addr.type = IPADDR_TYPE_V4;
|
||||
multicast_if_addr.u_addr.ip4.addr = ifIpInfo.ip.addr;
|
||||
|
||||
if (igmp_joingroup((const ip4_addr *)&multicast_if_addr.u_addr.ip4, (const ip4_addr *)&addr->u_addr.ip4)!= ERR_OK) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (joinMulticastGroup(addr, true, tcpip_if)!= ERR_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!listen(&multicast_if_addr, port)) {
|
||||
if(!listen(NULL, port)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -592,9 +605,7 @@ bool AsyncUDP::listenMulticast(const ip_addr_t *addr, uint16_t port, uint8_t ttl
|
||||
_pcb->mcast_ttl = ttl;
|
||||
_pcb->remote_port = port;
|
||||
ip_addr_copy(_pcb->remote_ip, *addr);
|
||||
if(addr->type == IPADDR_TYPE_V4){
|
||||
ip_addr_copy(_pcb->multicast_ip, multicast_if_addr);
|
||||
}
|
||||
//ip_addr_copy(_pcb->remote_ip, ip_addr_any_type);
|
||||
UDP_MUTEX_UNLOCK();
|
||||
|
||||
return true;
|
||||
@ -604,7 +615,7 @@ size_t AsyncUDP::writeTo(const uint8_t * data, size_t len, const ip_addr_t * add
|
||||
{
|
||||
if(!_pcb) {
|
||||
UDP_MUTEX_LOCK();
|
||||
_pcb = udp_new_ip_type(addr->type);
|
||||
_pcb = udp_new();
|
||||
UDP_MUTEX_UNLOCK();
|
||||
if(_pcb == NULL) {
|
||||
return 0;
|
||||
@ -619,7 +630,7 @@ size_t AsyncUDP::writeTo(const uint8_t * data, size_t len, const ip_addr_t * add
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(pbt->payload);
|
||||
memcpy(dst, data, len);
|
||||
UDP_MUTEX_LOCK();
|
||||
if(tcpip_if != TCPIP_ADAPTER_IF_MAX){
|
||||
if(tcpip_if < TCPIP_ADAPTER_IF_MAX){
|
||||
void * nif = NULL;
|
||||
tcpip_adapter_get_netif((tcpip_adapter_if_t)tcpip_if, &nif);
|
||||
if(!nif){
|
||||
|
@ -53,6 +53,7 @@ protected:
|
||||
uint16_t _localPort;
|
||||
ip_addr_t _remoteIp;
|
||||
uint16_t _remotePort;
|
||||
uint8_t _remoteMac[6];
|
||||
uint8_t *_data;
|
||||
size_t _len;
|
||||
size_t _index;
|
||||
@ -74,6 +75,7 @@ public:
|
||||
IPAddress remoteIP();
|
||||
IPv6Address remoteIPv6();
|
||||
uint16_t remotePort();
|
||||
void remoteMac(uint8_t * mac);
|
||||
|
||||
size_t send(AsyncUDPMessage &message);
|
||||
|
||||
@ -95,6 +97,7 @@ protected:
|
||||
bool _connected;
|
||||
AuPacketHandlerFunction _handler;
|
||||
|
||||
bool _init();
|
||||
void _recv(udp_pcb *upcb, pbuf *pb, const ip_addr_t *addr, uint16_t port, struct netif * netif);
|
||||
|
||||
public:
|
||||
@ -109,9 +112,9 @@ public:
|
||||
bool listen(const IPv6Address addr, uint16_t port);
|
||||
bool listen(uint16_t port);
|
||||
|
||||
bool listenMulticast(const ip_addr_t *addr, uint16_t port, uint8_t ttl=1, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_STA);
|
||||
bool listenMulticast(const IPAddress addr, uint16_t port, uint8_t ttl=1, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_STA);
|
||||
bool listenMulticast(const IPv6Address addr, uint16_t port, uint8_t ttl=1, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_STA);
|
||||
bool listenMulticast(const ip_addr_t *addr, uint16_t port, uint8_t ttl=1, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX);
|
||||
bool listenMulticast(const IPAddress addr, uint16_t port, uint8_t ttl=1, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX);
|
||||
bool listenMulticast(const IPv6Address addr, uint16_t port, uint8_t ttl=1, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX);
|
||||
|
||||
bool connect(const ip_addr_t *addr, uint16_t port);
|
||||
bool connect(const IPAddress addr, uint16_t port);
|
||||
|
@ -40,11 +40,115 @@
|
||||
#include "esp32-hal-log.h"
|
||||
#endif
|
||||
|
||||
const char * _spp_server_name = "ESP32_SPP_SERVER";
|
||||
const char * _spp_server_name = "ESP32SPP";
|
||||
|
||||
#define QUEUE_SIZE 256
|
||||
#define RX_QUEUE_SIZE 512
|
||||
#define TX_QUEUE_SIZE 32
|
||||
static uint32_t _spp_client = 0;
|
||||
static xQueueHandle _spp_queue = NULL;
|
||||
static xQueueHandle _spp_rx_queue = NULL;
|
||||
static xQueueHandle _spp_tx_queue = NULL;
|
||||
static SemaphoreHandle_t _spp_tx_done = NULL;
|
||||
static TaskHandle_t _spp_task_handle = NULL;
|
||||
static EventGroupHandle_t _spp_event_group = NULL;
|
||||
|
||||
#define SPP_RUNNING 0x01
|
||||
#define SPP_CONNECTED 0x02
|
||||
#define SPP_CONGESTED 0x04
|
||||
|
||||
typedef struct {
|
||||
size_t len;
|
||||
uint8_t data[];
|
||||
} spp_packet_t;
|
||||
|
||||
static esp_err_t _spp_queue_packet(uint8_t *data, size_t len){
|
||||
if(!data || !len){
|
||||
log_w("No data provided");
|
||||
return ESP_OK;
|
||||
}
|
||||
spp_packet_t * packet = (spp_packet_t*)malloc(sizeof(spp_packet_t) + len);
|
||||
if(!packet){
|
||||
log_e("SPP TX Packet Malloc Failed!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
packet->len = len;
|
||||
memcpy(packet->data, data, len);
|
||||
if (xQueueSend(_spp_tx_queue, &packet, portMAX_DELAY) != pdPASS) {
|
||||
log_e("SPP TX Queue Send Failed!");
|
||||
free(packet);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
const uint16_t SPP_TX_MAX = 330;
|
||||
static uint8_t _spp_tx_buffer[SPP_TX_MAX];
|
||||
static uint16_t _spp_tx_buffer_len = 0;
|
||||
|
||||
static bool _spp_send_buffer(){
|
||||
if((xEventGroupWaitBits(_spp_event_group, SPP_CONGESTED, pdFALSE, pdTRUE, portMAX_DELAY) & SPP_CONGESTED)){
|
||||
esp_err_t err = esp_spp_write(_spp_client, _spp_tx_buffer_len, _spp_tx_buffer);
|
||||
if(err != ESP_OK){
|
||||
log_e("SPP Write Failed! [0x%X]", err);
|
||||
return false;
|
||||
}
|
||||
_spp_tx_buffer_len = 0;
|
||||
if(xSemaphoreTake(_spp_tx_done, portMAX_DELAY) != pdTRUE){
|
||||
log_e("SPP Ack Failed!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void _spp_tx_task(void * arg){
|
||||
spp_packet_t *packet = NULL;
|
||||
size_t len = 0, to_send = 0;
|
||||
uint8_t * data = NULL;
|
||||
for (;;) {
|
||||
if(_spp_tx_queue && xQueueReceive(_spp_tx_queue, &packet, portMAX_DELAY) == pdTRUE && packet){
|
||||
if(packet->len <= (SPP_TX_MAX - _spp_tx_buffer_len)){
|
||||
memcpy(_spp_tx_buffer+_spp_tx_buffer_len, packet->data, packet->len);
|
||||
_spp_tx_buffer_len+=packet->len;
|
||||
free(packet);
|
||||
packet = NULL;
|
||||
if(SPP_TX_MAX == _spp_tx_buffer_len || uxQueueMessagesWaiting(_spp_tx_queue) == 0){
|
||||
_spp_send_buffer();
|
||||
}
|
||||
} else {
|
||||
len = packet->len;
|
||||
data = packet->data;
|
||||
to_send = SPP_TX_MAX - _spp_tx_buffer_len;
|
||||
memcpy(_spp_tx_buffer+_spp_tx_buffer_len, data, to_send);
|
||||
_spp_tx_buffer_len = SPP_TX_MAX;
|
||||
data += to_send;
|
||||
len -= to_send;
|
||||
_spp_send_buffer();
|
||||
while(len >= SPP_TX_MAX){
|
||||
memcpy(_spp_tx_buffer, data, SPP_TX_MAX);
|
||||
_spp_tx_buffer_len = SPP_TX_MAX;
|
||||
data += SPP_TX_MAX;
|
||||
len -= SPP_TX_MAX;
|
||||
_spp_send_buffer();
|
||||
}
|
||||
if(len){
|
||||
memcpy(_spp_tx_buffer, data, len);
|
||||
_spp_tx_buffer_len += len;
|
||||
free(packet);
|
||||
packet = NULL;
|
||||
if(uxQueueMessagesWaiting(_spp_tx_queue) == 0){
|
||||
_spp_send_buffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log_e("Something went horribly wrong");
|
||||
}
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
_spp_task_handle = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
|
||||
{
|
||||
@ -54,44 +158,66 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
|
||||
log_i("ESP_SPP_INIT_EVT");
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
|
||||
esp_spp_start_srv(ESP_SPP_SEC_NONE, ESP_SPP_ROLE_SLAVE, 0, _spp_server_name);
|
||||
xEventGroupSetBits(_spp_event_group, SPP_RUNNING);
|
||||
break;
|
||||
|
||||
case ESP_SPP_SRV_OPEN_EVT://Server connection open
|
||||
_spp_client = param->open.handle;
|
||||
xEventGroupSetBits(_spp_event_group, SPP_CONNECTED);
|
||||
log_i("ESP_SPP_SRV_OPEN_EVT");
|
||||
break;
|
||||
|
||||
case ESP_SPP_CLOSE_EVT://Client connection closed
|
||||
_spp_client = 0;
|
||||
xEventGroupClearBits(_spp_event_group, SPP_CONNECTED);
|
||||
log_i("ESP_SPP_CLOSE_EVT");
|
||||
break;
|
||||
|
||||
case ESP_SPP_CONG_EVT://connection congestion status changed
|
||||
if(param->cong.cong){
|
||||
xEventGroupClearBits(_spp_event_group, SPP_CONGESTED);
|
||||
} else {
|
||||
xEventGroupSetBits(_spp_event_group, SPP_CONGESTED);
|
||||
}
|
||||
log_v("ESP_SPP_CONG_EVT: %s", param->cong.cong?"CONGESTED":"FREE");
|
||||
break;
|
||||
|
||||
case ESP_SPP_WRITE_EVT://write operation completed
|
||||
if(param->write.cong){
|
||||
xEventGroupClearBits(_spp_event_group, SPP_CONGESTED);
|
||||
}
|
||||
xSemaphoreGive(_spp_tx_done);//we can try to send another packet
|
||||
log_v("ESP_SPP_WRITE_EVT: %u %s", param->write.len, param->write.cong?"CONGESTED":"FREE");
|
||||
break;
|
||||
|
||||
case ESP_SPP_DATA_IND_EVT://connection received data
|
||||
log_v("ESP_SPP_DATA_IND_EVT len=%d handle=%d", param->data_ind.len, param->data_ind.handle);
|
||||
//esp_log_buffer_hex("",param->data_ind.data,param->data_ind.len); //for low level debug
|
||||
//ets_printf("r:%u\n", param->data_ind.len);
|
||||
|
||||
if (_spp_rx_queue != NULL){
|
||||
for (int i = 0; i < param->data_ind.len; i++){
|
||||
if(xQueueSend(_spp_rx_queue, param->data_ind.data + i, (TickType_t)0) != pdTRUE){
|
||||
log_e("RX Full! Discarding %u bytes", param->data_ind.len - i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//should maybe delete those.
|
||||
case ESP_SPP_DISCOVERY_COMP_EVT://discovery complete
|
||||
log_i("ESP_SPP_DISCOVERY_COMP_EVT");
|
||||
break;
|
||||
case ESP_SPP_OPEN_EVT://Client connection open
|
||||
log_i("ESP_SPP_OPEN_EVT");
|
||||
break;
|
||||
case ESP_SPP_CLOSE_EVT://Client connection closed
|
||||
_spp_client = 0;
|
||||
log_i("ESP_SPP_CLOSE_EVT");
|
||||
break;
|
||||
case ESP_SPP_START_EVT://server started
|
||||
log_i("ESP_SPP_START_EVT");
|
||||
break;
|
||||
case ESP_SPP_CL_INIT_EVT://client initiated a connection
|
||||
log_i("ESP_SPP_CL_INIT_EVT");
|
||||
break;
|
||||
case ESP_SPP_DATA_IND_EVT://connection received data
|
||||
log_v("ESP_SPP_DATA_IND_EVT len=%d handle=%d", param->data_ind.len, param->data_ind.handle);
|
||||
//esp_log_buffer_hex("",param->data_ind.data,param->data_ind.len); //for low level debug
|
||||
|
||||
if (_spp_queue != NULL){
|
||||
for (int i = 0; i < param->data_ind.len; i++)
|
||||
xQueueSend(_spp_queue, param->data_ind.data + i, (TickType_t)0);
|
||||
} else {
|
||||
log_e("SerialQueueBT ERROR");
|
||||
}
|
||||
break;
|
||||
case ESP_SPP_CONG_EVT://connection congestion status changed
|
||||
log_i("ESP_SPP_CONG_EVT");
|
||||
break;
|
||||
case ESP_SPP_WRITE_EVT://write operation completed
|
||||
log_v("ESP_SPP_WRITE_EVT");
|
||||
break;
|
||||
case ESP_SPP_SRV_OPEN_EVT://Server connection open
|
||||
_spp_client = param->open.handle;
|
||||
log_i("ESP_SPP_SRV_OPEN_EVT");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -99,41 +225,76 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
|
||||
|
||||
static bool _init_bt(const char *deviceName)
|
||||
{
|
||||
if(!_spp_event_group){
|
||||
_spp_event_group = xEventGroupCreate();
|
||||
if(!_spp_event_group){
|
||||
log_e("SPP Event Group Create Failed!");
|
||||
return false;
|
||||
}
|
||||
xEventGroupClearBits(_spp_event_group, 0xFFFFFF);
|
||||
xEventGroupSetBits(_spp_event_group, SPP_CONGESTED);
|
||||
}
|
||||
if (_spp_rx_queue == NULL){
|
||||
_spp_rx_queue = xQueueCreate(RX_QUEUE_SIZE, sizeof(uint8_t)); //initialize the queue
|
||||
if (_spp_rx_queue == NULL){
|
||||
log_e("RX Queue Create Failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (_spp_tx_queue == NULL){
|
||||
_spp_tx_queue = xQueueCreate(TX_QUEUE_SIZE, sizeof(spp_packet_t*)); //initialize the queue
|
||||
if (_spp_tx_queue == NULL){
|
||||
log_e("TX Queue Create Failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(_spp_tx_done == NULL){
|
||||
_spp_tx_done = xSemaphoreCreateBinary();
|
||||
if (_spp_tx_done == NULL){
|
||||
log_e("TX Semaphore Create Failed");
|
||||
return false;
|
||||
}
|
||||
xSemaphoreTake(_spp_tx_done, 0);
|
||||
}
|
||||
|
||||
if(!_spp_task_handle){
|
||||
xTaskCreate(_spp_tx_task, "spp_tx", 4096, NULL, 2, &_spp_task_handle);
|
||||
if(!_spp_task_handle){
|
||||
log_e("Network Event Task Start Failed!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!btStarted() && !btStart()){
|
||||
log_e("%s initialize controller failed\n", __func__);
|
||||
log_e("initialize controller failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
esp_bluedroid_status_t bt_state = esp_bluedroid_get_status();
|
||||
if (bt_state == ESP_BLUEDROID_STATUS_UNINITIALIZED){
|
||||
if (esp_bluedroid_init()) {
|
||||
log_e("%s initialize bluedroid failed\n", __func__);
|
||||
log_e("initialize bluedroid failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (bt_state != ESP_BLUEDROID_STATUS_ENABLED){
|
||||
if (esp_bluedroid_enable()) {
|
||||
log_e("%s enable bluedroid failed\n", __func__);
|
||||
log_e("enable bluedroid failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (esp_spp_register_callback(esp_spp_cb) != ESP_OK){
|
||||
log_e("%s spp register failed\n", __func__);
|
||||
log_e("spp register failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (esp_spp_init(ESP_SPP_MODE_CB) != ESP_OK){
|
||||
log_e("%s spp init failed\n", __func__);
|
||||
log_e("spp init failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
_spp_queue = xQueueCreate(QUEUE_SIZE, sizeof(uint8_t)); //initialize the queue
|
||||
if (_spp_queue == NULL){
|
||||
log_e("%s Queue creation error\n", __func__);
|
||||
return false;
|
||||
}
|
||||
esp_bt_dev_set_device_name(deviceName);
|
||||
|
||||
// the default BTA_DM_COD_LOUDSPEAKER does not work with the macOS BT stack
|
||||
@ -142,7 +303,7 @@ static bool _init_bt(const char *deviceName)
|
||||
cod.minor = 0b000100;
|
||||
cod.service = 0b00000010110;
|
||||
if (esp_bt_gap_set_cod(cod, ESP_BT_INIT_COD) != ESP_OK) {
|
||||
log_e("%s set cod failed\n", __func__);
|
||||
log_e("set cod failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -159,6 +320,32 @@ static bool _stop_bt()
|
||||
esp_bluedroid_deinit();
|
||||
btStop();
|
||||
}
|
||||
_spp_client = 0;
|
||||
if(_spp_task_handle){
|
||||
vTaskDelete(_spp_task_handle);
|
||||
_spp_task_handle = NULL;
|
||||
}
|
||||
if(_spp_event_group){
|
||||
vEventGroupDelete(_spp_event_group);
|
||||
_spp_event_group = NULL;
|
||||
}
|
||||
if(_spp_rx_queue){
|
||||
vQueueDelete(_spp_rx_queue);
|
||||
//ToDo: clear RX queue when in packet mode
|
||||
_spp_rx_queue = NULL;
|
||||
}
|
||||
if(_spp_tx_queue){
|
||||
spp_packet_t *packet = NULL;
|
||||
while(xQueueReceive(_spp_tx_queue, &packet, 0) == pdTRUE){
|
||||
free(packet);
|
||||
}
|
||||
vQueueDelete(_spp_tx_queue);
|
||||
_spp_tx_queue = NULL;
|
||||
}
|
||||
if (_spp_tx_done) {
|
||||
vSemaphoreDelete(_spp_tx_done);
|
||||
_spp_tx_done = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -175,7 +362,6 @@ BluetoothSerial::BluetoothSerial()
|
||||
BluetoothSerial::~BluetoothSerial(void)
|
||||
{
|
||||
_stop_bt();
|
||||
vQueueDelete(_spp_queue);
|
||||
}
|
||||
|
||||
bool BluetoothSerial::begin(String localName)
|
||||
@ -188,60 +374,39 @@ bool BluetoothSerial::begin(String localName)
|
||||
|
||||
int BluetoothSerial::available(void)
|
||||
{
|
||||
if (!_spp_client || _spp_queue == NULL){
|
||||
if (_spp_rx_queue == NULL){
|
||||
return 0;
|
||||
}
|
||||
return uxQueueMessagesWaiting(_spp_queue);
|
||||
return uxQueueMessagesWaiting(_spp_rx_queue);
|
||||
}
|
||||
|
||||
int BluetoothSerial::peek(void)
|
||||
{
|
||||
if (available()){
|
||||
if (!_spp_client || _spp_queue == NULL){
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t c;
|
||||
if (xQueuePeek(_spp_queue, &c, 0)){
|
||||
return c;
|
||||
}
|
||||
uint8_t c;
|
||||
if (_spp_rx_queue && xQueuePeek(_spp_rx_queue, &c, 0)){
|
||||
return c;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool BluetoothSerial::hasClient(void)
|
||||
{
|
||||
if (_spp_client)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return _spp_client > 0;
|
||||
}
|
||||
|
||||
int BluetoothSerial::read(void)
|
||||
{
|
||||
if (available()){
|
||||
if (!_spp_client || _spp_queue == NULL){
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t c;
|
||||
if (xQueueReceive(_spp_queue, &c, 0)){
|
||||
return c;
|
||||
}
|
||||
uint8_t c = 0;
|
||||
if (_spp_rx_queue && xQueueReceive(_spp_rx_queue, &c, 0)){
|
||||
return c;
|
||||
}
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t BluetoothSerial::write(uint8_t c)
|
||||
{
|
||||
if (!_spp_client){
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t buffer[1];
|
||||
buffer[0] = c;
|
||||
esp_err_t err = esp_spp_write(_spp_client, 1, buffer);
|
||||
return (err == ESP_OK) ? 1 : 0;
|
||||
return write(&c, 1);
|
||||
}
|
||||
|
||||
size_t BluetoothSerial::write(const uint8_t *buffer, size_t size)
|
||||
@ -249,24 +414,17 @@ size_t BluetoothSerial::write(const uint8_t *buffer, size_t size)
|
||||
if (!_spp_client){
|
||||
return 0;
|
||||
}
|
||||
|
||||
esp_err_t err = esp_spp_write(_spp_client, size, (uint8_t *)buffer);
|
||||
return (err == ESP_OK) ? size : 0;
|
||||
return (_spp_queue_packet((uint8_t *)buffer, size) == ESP_OK) ? size : 0;
|
||||
}
|
||||
|
||||
void BluetoothSerial::flush()
|
||||
{
|
||||
if (_spp_client){
|
||||
int qsize = available();
|
||||
uint8_t buffer[qsize];
|
||||
esp_spp_write(_spp_client, qsize, buffer);
|
||||
}
|
||||
while(read() >= 0){}
|
||||
}
|
||||
|
||||
void BluetoothSerial::end()
|
||||
{
|
||||
_stop_bt();
|
||||
vQueueDelete(_spp_queue);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -6,7 +6,7 @@ hw_timer_t *timer = NULL;
|
||||
|
||||
void IRAM_ATTR resetModule() {
|
||||
ets_printf("reboot\n");
|
||||
esp_restart_noos();
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
void setup() {
|
||||
|
@ -50,12 +50,13 @@ bool SDMMCFS::begin(const char * mountpoint, bool mode1bit)
|
||||
.init = &sdmmc_host_init,
|
||||
.set_bus_width = &sdmmc_host_set_bus_width,
|
||||
.get_bus_width = &sdmmc_host_get_slot_width,
|
||||
.set_bus_ddr_mode = &sdmmc_host_set_bus_ddr_mode,
|
||||
.set_card_clk = &sdmmc_host_set_card_clk,
|
||||
.do_transaction = &sdmmc_host_do_transaction,
|
||||
.deinit = &sdmmc_host_deinit,
|
||||
.io_int_enable = sdmmc_host_io_int_enable,
|
||||
.io_int_wait = sdmmc_host_io_int_wait,
|
||||
.command_timeout_ms = 0,
|
||||
.io_int_enable = &sdmmc_host_io_int_enable,
|
||||
.io_int_wait = &sdmmc_host_io_int_wait,
|
||||
.command_timeout_ms = 0
|
||||
};
|
||||
host.max_freq_khz = SDMMC_FREQ_HIGHSPEED;
|
||||
#ifdef BOARD_HAS_1BIT_SDMMC
|
||||
|
@ -37,7 +37,7 @@ extern "C" {
|
||||
#include <esp_wifi.h>
|
||||
#include <esp_event_loop.h>
|
||||
#include <lwip/ip_addr.h>
|
||||
#include "apps/dhcpserver_options.h"
|
||||
#include "dhcpserver/dhcpserver_options.h"
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user