Esempio n. 1
0
static void IRAM_ATTR esp_now_scan_peers_done (void)
{
    mutex_lock(&_esp_now_dev.dev_lock);

    esp_err_t ret;
    uint16_t ap_num;

    ret = esp_wifi_scan_get_ap_num(&ap_num);
    DEBUG("wifi_scan_get_ap_num ret=%d num=%d\n", ret ,ap_num);

    if (ret == ESP_OK && ap_num) {
        uint32_t state;
        /* reallocation of memory must not be disturbed */
        critical_enter_var(state);
        /* allocate memory for APs record list blockwise and fetch them the list */
        if (ap_num > aps_size) {
            if (aps) {
                /* free allocated AP record list memory */
                aps_size = 0;
                free (aps);
            }
            /* allocate new memory */
            aps_size = (ap_num & ~(ESP_NOW_APS_BLOCK_SIZE - 1)) + ESP_NOW_APS_BLOCK_SIZE;
            aps = malloc(sizeof(wifi_ap_record_t) * aps_size);
            ap_num = aps_size;
        }
        critical_exit_var(state);

        ret = esp_wifi_scan_get_ap_records(&ap_num, aps);

        DEBUG("wifi_scan_get_aps ret=%d num=%d\n", ret, ap_num);

        critical_enter_var(state);
        /* iterate over APs records */
        for (uint16_t i = 0; i < ap_num; i++) {

            /* check whether the AP is an ESP_NOW node which is not already a peer */
            if (strncmp((char*)aps[i].ssid, ESP_NOW_AP_PREFIX, ESP_NOW_AP_PREFIX_LEN) == 0 &&
                !esp_now_is_peer_exist(aps[i].bssid)) {
                /* add the AP as peer */
                _esp_now_add_peer(aps[i].bssid, aps[i].primary, esp_now_params.key);
            }
        }
        critical_exit_var(state);
    }

    #if ENABLE_DEBUG
    esp_now_peer_num_t peer_num;
    esp_now_get_peer_num (&peer_num);
    DEBUG("associated peers total=%d, encrypted=%d\n",
          peer_num.total_num, peer_num.encrypt_num);
    #endif

    _esp_now_scan_peers_done = true;

    /* set the time for next scan */
    xtimer_set (&_esp_now_scan_peers_timer, esp_now_params.scan_period);

    mutex_unlock(&_esp_now_dev.dev_lock);
}
Esempio n. 2
0
static int _recv(netdev_t *netdev, void *buf, size_t len, void *info)
{
    DEBUG("%s: %p %p %u %p\n", __func__, netdev, buf, len, info);

    CHECK_PARAM_RET (netdev != NULL, -ENODEV);

    esp_now_netdev_t* dev = (esp_now_netdev_t*)netdev;

    mutex_lock(&dev->dev_lock);

    uint8_t size = dev->rx_len;

    if (!buf && !len) {
        /* return the size without dropping received data */
        mutex_unlock(&dev->dev_lock);
        return size;
    }

    if (!buf && len) {
        /* return the size and drop received data */
        mutex_unlock(&dev->dev_lock);
        dev->rx_len = 0;
        return size;
    }

    if (buf && len && dev->rx_len) {
        if (dev->rx_len > len) {
            DEBUG("[esp_now] No space in receive buffers\n");
            mutex_unlock(&dev->dev_lock);
            return -ENOBUFS;
        }

        #if ENABLE_DEBUG
        printf ("%s: received %d byte from %02x:%02x:%02x:%02x:%02x:%02x\n",
                __func__, dev->rx_len,
                dev->rx_mac[0], dev->rx_mac[1], dev->rx_mac[2],
                dev->rx_mac[3], dev->rx_mac[4], dev->rx_mac[5]);
        /* esp_hexdump (dev->rx_buf, dev->rx_len, 'b', 16); */
        #endif

        if (esp_now_is_peer_exist(dev->rx_mac) <= 0) {
            _esp_now_add_peer(dev->rx_mac, esp_now_params.channel, esp_now_params.key);
        }

        memcpy(buf, dev->rx_buf, dev->rx_len);
        dev->rx_len = 0;

        #ifdef MODULE_NETSTATS_L2
        netdev->stats.rx_count++;
        netdev->stats.rx_bytes += size;
        #endif

        mutex_unlock(&dev->dev_lock);
        return size;
    }

    mutex_unlock(&dev->dev_lock);
    return -EINVAL;
}
Esempio n. 3
0
int ICACHE_FLASH_ATTR demo_send(u8 * data, u8 len)
{
	if (esp_now_is_peer_exist(slave_mac) == 0) {
		os_printf("The espnow peer does not exist\n");
		return 0;
	} else {

		/* the demo will send to two devices which added by esp_now_add_peer() */
		int ret = esp_now_send(NULL, data, len);
		return ret;
	}
}
Esempio n. 4
0
static bool _esp_now_add_peer (uint8_t* bssid, uint8_t channel, uint8_t* key)
{
    if (esp_now_is_peer_exist(bssid)) {
        return false;
    }

    esp_now_peer_info_t peer = {};

    memcpy(peer.peer_addr, bssid, ESP_NOW_ETH_ALEN);
    peer.channel = channel;
    peer.ifidx = ESP_IF_WIFI_AP;

    if (esp_now_params.key) {
        peer.encrypt = true;
        memcpy(peer.lmk, esp_now_params.key, ESP_NOW_KEY_LEN);
    }

    esp_err_t ret = esp_now_add_peer(&peer);
    DEBUG("esp_now_add_peer node %02x:%02x:%02x:%02x:%02x:%02x "
          "added with return value %d\n",
          bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5], ret);
    return (ret == ESP_OK);
}
Esempio n. 5
0
static int _send(netdev_t *netdev, const iolist_t *iolist)
{
    #if ESP_NOW_UNICAST
    if (!_esp_now_scan_peers_done) {
        return -ENODEV;
    }
    #endif

    DEBUG("%s: %p %p\n", __func__, netdev, iolist);

    CHECK_PARAM_RET (netdev != NULL, -ENODEV);
    CHECK_PARAM_RET (iolist != NULL, -EINVAL);

    esp_now_netdev_t* dev = (esp_now_netdev_t*)netdev;

    mutex_lock(&dev->dev_lock);
    dev->tx_len = 0;

    /* load packet data into TX buffer */
    for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
        if (dev->tx_len + iol->iol_len > ESP_NOW_MAX_SIZE) {
            mutex_unlock(&dev->dev_lock);
            return -EOVERFLOW;
        }
        memcpy (dev->tx_buf + dev->tx_len, iol->iol_base, iol->iol_len);
        dev->tx_len += iol->iol_len;
    }

    #if ENABLE_DEBUG
    printf ("%s: send %d byte\n", __func__, dev->tx_len);
    /* esp_hexdump (dev->tx_buf, dev->tx_len, 'b', 16); */
    #endif

    _esp_now_sending = 1;

    uint8_t* _esp_now_dst = 0;

    #if ESP_NOW_UNICAST
    ipv6_hdr_t* ipv6_hdr = (ipv6_hdr_t*)dev->tx_buf;
    uint8_t  _esp_now_dst_from_iid[6];

    if (ipv6_hdr->dst.u8[0] == 0xff) {
        /* packets to multicast prefix ff::/8 are sent to all peers */
        DEBUG("multicast to all peers\n");
        _esp_now_dst = 0;
        _esp_now_sending = dev->peers_all;

        #ifdef MODULE_NETSTATS_L2
        netdev->stats.tx_mcast_count++;
        #endif
    }

    else if ((byteorder_ntohs(ipv6_hdr->dst.u16[0]) & 0xffc0) == 0xfe80) {
        /* for link local addresses fe80::/10, the MAC address is derived from dst address */
        _get_mac_from_iid(&ipv6_hdr->dst.u8[8], _esp_now_dst_from_iid);
        DEBUG("link local to %02x:%02x:%02x:%02x:%02x:%02x\n",
              _esp_now_dst_from_iid[0], _esp_now_dst_from_iid[1],
              _esp_now_dst_from_iid[2], _esp_now_dst_from_iid[3],
              _esp_now_dst_from_iid[4], _esp_now_dst_from_iid[5]);
        _esp_now_dst = _esp_now_dst_from_iid;
        _esp_now_sending = 1;
    }

    else {
        #ifdef MODULE_GNRC_IPV6_NIB
        /* for other addresses, try to find an entry in NIB cache */
        gnrc_ipv6_nib_nc_t nce;
        int ret = gnrc_ipv6_nib_get_next_hop_l2addr (&ipv6_hdr->dst, dev->netif,
                                                     NULL, &nce);
        if (ret == 0) {
            /* entry was found in NIB, use MAC adress from the NIB cache entry */
            DEBUG("global, next hop to neighbor %02x:%02x:%02x:%02x:%02x:%02x\n",
                  nce.l2addr[0], nce.l2addr[1], nce.l2addr[2],
                  nce.l2addr[3], nce.l2addr[4], nce.l2addr[5]);
            _esp_now_dst = nce.l2addr;
            _esp_now_sending = 1;
        }
        else {
        #endif
            /* entry was not found in NIB, send to all peers */
            DEBUG("global, no neibhbor found, multicast to all peers\n");
            _esp_now_dst = 0;
            _esp_now_sending = dev->peers_all;

            #ifdef MODULE_NETSTATS_L2
            netdev->stats.tx_mcast_count++;
            #endif

        #ifdef MODULE_GNRC_IPV6_NIB
        }
        #endif
    }

    #else /* ESP_NOW_UNICAST */

    ipv6_hdr_t* ipv6_hdr = (ipv6_hdr_t*)dev->tx_buf;
    uint8_t  _esp_now_dst_from_iid[6];

    _esp_now_dst = (uint8_t*)_esp_now_mac;
    _esp_now_sending = 1;

    if (ipv6_hdr->dst.u8[0] == 0xff) {
        /* packets to multicast prefix ff::/8 are sent to all peers */
        DEBUG("multicast to all peers\n");

        #ifdef MODULE_NETSTATS_L2
        netdev->stats.tx_mcast_count++;
        #endif
    }

    else if ((byteorder_ntohs(ipv6_hdr->dst.u16[0]) & 0xffc0) == 0xfe80) {
        /* for link local addresses fe80::/10, the MAC address is derived from dst address */
        _get_mac_from_iid(&ipv6_hdr->dst.u8[8], _esp_now_dst_from_iid);
        DEBUG("link local to %02x:%02x:%02x:%02x:%02x:%02x\n",
              _esp_now_dst_from_iid[0], _esp_now_dst_from_iid[1],
              _esp_now_dst_from_iid[2], _esp_now_dst_from_iid[3],
              _esp_now_dst_from_iid[4], _esp_now_dst_from_iid[5]);
        if (esp_now_is_peer_exist(_esp_now_dst_from_iid) > 0) {
            _esp_now_dst = _esp_now_dst_from_iid;
        }
    }

    else
    {
        /* for other addresses, try to find an entry in NIB cache */
          gnrc_ipv6_nib_nc_t nce;
        int ret = gnrc_ipv6_nib_get_next_hop_l2addr (&ipv6_hdr->dst, dev->netif,
                                                     NULL, &nce);
        if (ret == 0 && esp_now_is_peer_exist(nce.l2addr) > 0) {
            /* entry was found in NIB, use MAC adress from the NIB cache entry */
            DEBUG("global, next hop to neighbor %02x:%02x:%02x:%02x:%02x:%02x\n",
                  nce.l2addr[0], nce.l2addr[1], nce.l2addr[2],
                  nce.l2addr[3], nce.l2addr[4], nce.l2addr[5]);
            _esp_now_dst = nce.l2addr;
        }
        else {
            /* entry was not found in NIB, send to all peers */
            DEBUG("global, no neibhbor found, multicast to all peers\n");

            #ifdef MODULE_NETSTATS_L2
            netdev->stats.tx_mcast_count++;
            #endif
        }
    }

    #endif /* ESP_NOW_UNICAST */
    if (_esp_now_dst) {
        DEBUG("%s: send to esp_now addr %02x:%02x:%02x:%02x:%02x:%02x\n", __func__,
              _esp_now_dst[0], _esp_now_dst[1], _esp_now_dst[2],
              _esp_now_dst[3], _esp_now_dst[4], _esp_now_dst[5]);
    }

    /* send the the packet to the peer(s) mac address */
    if (esp_now_send (_esp_now_dst, dev->tx_buf, dev->tx_len) == 0) {
        while (_esp_now_sending > 0) {
            thread_yield_higher();
        }

        #ifdef MODULE_NETSTATS_L2
        netdev->stats.tx_bytes += dev->tx_len;
        netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE);
        #endif

        mutex_unlock(&dev->dev_lock);
        return dev->tx_len;
    }
    else {
        #ifdef MODULE_NETSTATS_L2
        netdev->stats.tx_failed++;
        #endif
    }

    mutex_unlock(&dev->dev_lock);
    return -EIO;
}