mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
221 lines
6.2 KiB
C
221 lines
6.2 KiB
C
/*
|
|
* Copyright (C) 2018 Timo Rothenpieler
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
* directory for more details.
|
|
*/
|
|
|
|
/**
|
|
* @ingroup cpu_esp_common_esp_now
|
|
* @{
|
|
*
|
|
* @file
|
|
* @brief Netif interface for the ESP-NOW WiFi P2P protocol
|
|
*
|
|
* @author Timo Rothenpieler <timo.rothenpieler@uni-bremen.de>
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <sys/uio.h>
|
|
|
|
#include "cpu_conf.h"
|
|
#include "net/netdev.h"
|
|
#include "net/gnrc.h"
|
|
#include "esp_common_log.h"
|
|
#include "esp_now_params.h"
|
|
#include "esp_now_netdev.h"
|
|
#include "esp_now_gnrc.h"
|
|
#include "net/gnrc/netif.h"
|
|
|
|
#define ENABLE_DEBUG 0
|
|
#include "debug.h"
|
|
|
|
static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
|
|
{
|
|
uint8_t mac[ESP_NOW_ADDR_LEN];
|
|
esp_now_pkt_hdr_t esp_hdr;
|
|
netdev_t *dev = netif->dev;
|
|
|
|
assert(pkt != NULL);
|
|
|
|
if (pkt->type != GNRC_NETTYPE_NETIF) {
|
|
DEBUG("gnrc_esp_now: First header was not generic netif header\n");
|
|
gnrc_pktbuf_release(pkt);
|
|
return -EBADMSG;
|
|
}
|
|
|
|
gnrc_netif_hdr_t *netif_hdr = (gnrc_netif_hdr_t*)pkt->data;
|
|
gnrc_pktsnip_t *payload = pkt->next;
|
|
|
|
if (netif_hdr->flags & (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
|
|
/* ESP-NOW does not support multicast, always broadcast */
|
|
memset(mac, 0xff, ESP_NOW_ADDR_LEN);
|
|
} else if (netif_hdr->dst_l2addr_len == ESP_NOW_ADDR_LEN) {
|
|
memcpy(mac, gnrc_netif_hdr_get_dst_addr(netif_hdr), ESP_NOW_ADDR_LEN);
|
|
} else {
|
|
DEBUG("gnrc_esp_now: destination address had unexpected format"
|
|
"(flags=%d, dst_l2addr_len=%d)\n", netif_hdr->flags, netif_hdr->dst_l2addr_len);
|
|
gnrc_pktbuf_release(pkt);
|
|
return -EBADMSG;
|
|
}
|
|
|
|
iolist_t esp_hdr_iolist = {
|
|
.iol_base = &esp_hdr,
|
|
.iol_len = sizeof(esp_hdr),
|
|
.iol_next = (iolist_t*)payload
|
|
};
|
|
|
|
iolist_t iolist = {
|
|
.iol_base = mac,
|
|
.iol_len = sizeof(mac),
|
|
.iol_next = &esp_hdr_iolist
|
|
};
|
|
|
|
switch (payload->type) {
|
|
#ifdef MODULE_GNRC_SIXLOWPAN
|
|
case GNRC_NETTYPE_SIXLOWPAN:
|
|
esp_hdr.flags = ESP_NOW_PKT_HDR_FLAG_SIXLO;
|
|
break;
|
|
#endif
|
|
default:
|
|
esp_hdr.flags = 0;
|
|
}
|
|
|
|
DEBUG("gnrc_esp_now: sending packet to %02x:%02x:%02x:%02x:%02x:%02x with size %u\n",
|
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], (unsigned)payload->size);
|
|
|
|
int res = dev->driver->send(dev, &iolist);
|
|
|
|
gnrc_pktbuf_release(pkt);
|
|
|
|
return res;
|
|
}
|
|
|
|
static gnrc_pktsnip_t *_recv(gnrc_netif_t *netif)
|
|
{
|
|
netdev_t *dev = netif->dev;
|
|
esp_now_netdev_t *esp_now = container_of(dev, esp_now_netdev_t, netdev);
|
|
|
|
int bytes_expected = dev->driver->recv(dev, NULL, 0, NULL);
|
|
if (bytes_expected <= 0) {
|
|
DEBUG("gnrc_esp_now: failed receiving packet: %d\n", bytes_expected);
|
|
return NULL;
|
|
}
|
|
|
|
gnrc_pktsnip_t *pkt;
|
|
pkt = gnrc_pktbuf_add(NULL, NULL,
|
|
bytes_expected,
|
|
GNRC_NETTYPE_UNDEF);
|
|
if (!pkt) {
|
|
DEBUG("gnrc_esp_now: cannot allocate pktsnip.\n");
|
|
|
|
/* drop the packet */
|
|
dev->driver->recv(dev, NULL, bytes_expected, NULL);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int nread = dev->driver->recv(dev, pkt->data, bytes_expected, NULL);
|
|
if (nread <= 0) {
|
|
DEBUG("gnrc_esp_now: read error %d\n", nread);
|
|
goto err;
|
|
}
|
|
|
|
if (nread < bytes_expected) {
|
|
DEBUG("gnrc_esp_now: reallocating.\n");
|
|
gnrc_pktbuf_realloc_data(pkt, nread);
|
|
}
|
|
|
|
gnrc_pktsnip_t *mac_hdr;
|
|
mac_hdr = gnrc_pktbuf_mark(pkt, ESP_NOW_ADDR_LEN, GNRC_NETTYPE_UNDEF);
|
|
if (!mac_hdr) {
|
|
DEBUG("gnrc_esp_now: no space left in packet buffer\n");
|
|
goto err;
|
|
}
|
|
|
|
gnrc_pktsnip_t *esp_hdr;
|
|
esp_hdr = gnrc_pktbuf_mark(pkt, sizeof(esp_now_pkt_hdr_t), GNRC_NETTYPE_UNDEF);
|
|
if (!esp_hdr) {
|
|
DEBUG("gnrc_esp_now: no space left in packet buffer\n");
|
|
pkt = mac_hdr;
|
|
goto err;
|
|
}
|
|
|
|
#ifdef MODULE_L2FILTER
|
|
if (!l2filter_pass(dev->filter, mac_hdr->data, ESP_NOW_ADDR_LEN)) {
|
|
DEBUG("gnrc_esp_now: incoming packet filtered by l2filter\n");
|
|
pkt = mac_hdr;
|
|
goto err;
|
|
}
|
|
#endif
|
|
|
|
pkt->type = GNRC_NETTYPE_UNDEF;
|
|
|
|
#ifdef MODULE_GNRC_SIXLOWPAN
|
|
esp_now_pkt_hdr_t *hdr = (esp_now_pkt_hdr_t*)esp_hdr->data;
|
|
|
|
if (hdr->flags & ESP_NOW_PKT_HDR_FLAG_SIXLO) {
|
|
pkt->type = GNRC_NETTYPE_SIXLOWPAN;
|
|
}
|
|
#endif
|
|
|
|
gnrc_pktsnip_t *netif_hdr = gnrc_netif_hdr_build(mac_hdr->data, ESP_NOW_ADDR_LEN,
|
|
esp_now->addr, ESP_NOW_ADDR_LEN);
|
|
if (!netif_hdr) {
|
|
DEBUG("gnrc_esp_now: no space left in packet buffer\n");
|
|
pkt = mac_hdr;
|
|
goto err;
|
|
}
|
|
|
|
gnrc_netif_hdr_set_netif((gnrc_netif_hdr_t *)netif_hdr->data, netif);
|
|
|
|
uint8_t *mac = mac_hdr->data;
|
|
DEBUG("gnrc_esp_now: received packet from %02x:%02x:%02x:%02x:%02x:%02x of length %u\n",
|
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], pkt->size);
|
|
|
|
gnrc_pktbuf_remove_snip(pkt, mac_hdr);
|
|
gnrc_pktbuf_remove_snip(pkt, esp_hdr);
|
|
return gnrc_pkt_append(pkt, netif_hdr);
|
|
err:
|
|
gnrc_pktbuf_release(pkt);
|
|
return NULL;
|
|
}
|
|
|
|
static const gnrc_netif_ops_t _esp_now_ops = {
|
|
.init = gnrc_netif_default_init,
|
|
.send = _send,
|
|
.recv = _recv,
|
|
.get = gnrc_netif_get_from_netdev,
|
|
.set = gnrc_netif_set_from_netdev,
|
|
};
|
|
|
|
int gnrc_netif_esp_now_create(gnrc_netif_t *netif, char *stack, int stacksize, char priority,
|
|
char *name, netdev_t *dev)
|
|
{
|
|
return gnrc_netif_create(netif, stack, stacksize, priority, name, dev, &_esp_now_ops);
|
|
}
|
|
|
|
/* device thread stack */
|
|
static char _esp_now_stack[ESP_NOW_STACKSIZE];
|
|
static gnrc_netif_t _netif;
|
|
|
|
void auto_init_esp_now(void)
|
|
{
|
|
LOG_TAG_DEBUG("esp_now", "initializing ESP-NOW device\n");
|
|
|
|
esp_now_netdev_t *esp_now_dev = netdev_esp_now_setup();
|
|
if (!esp_now_dev) {
|
|
LOG_ERROR("[auto_init_netif] error initializing esp_now\n");
|
|
} else {
|
|
gnrc_netif_esp_now_create(&_netif, _esp_now_stack, sizeof(_esp_now_stack),
|
|
ESP_NOW_PRIO,
|
|
"netif-esp-now",
|
|
&esp_now_dev->netdev);
|
|
}
|
|
}
|
|
|
|
/** @} */
|