From 331313db4fe86e4d2945780b8d81afdb9dceacc1 Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Tue, 24 Mar 2020 05:57:46 +0100 Subject: [PATCH 1/2] cpu/esp: NETOPT_CHANNEL for esp_wifi and esp_now --- cpu/esp32/doc.txt | 6 ++++++ cpu/esp8266/doc.txt | 6 ++++++ cpu/esp_common/esp-now/doc.txt | 3 +++ cpu/esp_common/esp-now/esp_now_netdev.c | 6 ++++++ cpu/esp_common/esp-wifi/doc.txt | 4 ++++ cpu/esp_common/esp-wifi/esp_wifi_netdev.c | 9 +++++++++ 6 files changed, 34 insertions(+) diff --git a/cpu/esp32/doc.txt b/cpu/esp32/doc.txt index c2cdfbea10..e56d63f2bd 100644 --- a/cpu/esp32/doc.txt +++ b/cpu/esp32/doc.txt @@ -1260,6 +1260,9 @@ the verification of the AP certificate is not yet supported. [ESP-NOW network interface](#esp32_esp_now_network_interface) (module `esp_now`) can be used simultaneously, for example, to realize a border router for a mesh network which uses ESP-NOW. +In this case the ESP-NOW interface must use the same channel as the AP of the +infrastructure WiFi network. All ESP-NOW nodes must therefore be compiled with +the channel of the AP as value for the parameter 'ESP_NOW_CHANNEL'. \anchor esp32_esp_now_network_interface ## ESP-NOW Network Interface  [[TOC](#esp32_toc)] @@ -1294,6 +1297,9 @@ ESP_NOW_KEY | NULL | Defines a key that is used for encrypted communication betw [Wifi network interface](#esp32_wifi_network_interface) (module `esp_wifi` or `esp_wifi_enterprise`) can be used simultaneously, for example, to realize a border router for a mesh network which uses ESP-NOW. +In this case the ESP-NOW interface must use the same channel as the AP of the +infrastructure WiFi network. All ESP-NOW nodes must therefore be compiled with +the channel of the AP asvalue for the parameter 'ESP_NOW_CHANNEL'. ## Other Network Devices  [[TOC](#esp32_toc)] diff --git a/cpu/esp8266/doc.txt b/cpu/esp8266/doc.txt index 1ff4fa90fa..943dccb30b 100644 --- a/cpu/esp8266/doc.txt +++ b/cpu/esp8266/doc.txt @@ -710,6 +710,9 @@ make -C examples/gnrc_networking BOARD=... [ESP-NOW network interface](#esp8266_esp_now_network_interface) (module `esp_now`) can be used simultaneously, for example, to realize a border router for a mesh network which uses ESP-NOW. +In this case the ESP-NOW interface must use the same channel as the AP of the +infrastructure WiFi network. All ESP-NOW nodes must therefore be compiled with +the channel of the AP asvalue for the parameter 'ESP_NOW_CHANNEL'. \anchor esp8266_esp_now_network_interface ## ESP-NOW Network Interface  [[TOC](#esp8266_toc)] @@ -756,6 +759,9 @@ Parameter | Default | Description [Wifi network interface](#esp8266_wifi_network_interface) (module `esp_wifi`) can be used simultaneously, for example, to realize a border router for a mesh network which uses ESP-NOW. +In this case the ESP-NOW interface must use the same channel as the AP of the +infrastructure WiFi network. All ESP-NOW nodes must therefore be compiled with +the channel of the AP asvalue for the parameter 'ESP_NOW_CHANNEL'. # Preconfigured Devices  [[TOC](#esp8266_toc)] diff --git a/cpu/esp_common/esp-now/doc.txt b/cpu/esp_common/esp-now/doc.txt index 61cd86e9f5..e0403853b6 100644 --- a/cpu/esp_common/esp-now/doc.txt +++ b/cpu/esp_common/esp-now/doc.txt @@ -45,5 +45,8 @@ ESP_NOW_KEY | NULL | Defines a key that is used for encrypted communication betw Wifi network interface (module `esp_wifi`) can be used simultaneously, for example, to realize a border router for a mesh network which uses ESP-NOW. +In this case the ESP-NOW interface must use the same channel as the AP of the +infrastructure WiFi network. All ESP-NOW nodes must therefore be compiled with +the channel of the AP asvalue for the parameter 'ESP_NOW_CHANNEL'. */ diff --git a/cpu/esp_common/esp-now/esp_now_netdev.c b/cpu/esp_common/esp-now/esp_now_netdev.c index 2cdc9f698c..674751830f 100644 --- a/cpu/esp_common/esp-now/esp_now_netdev.c +++ b/cpu/esp_common/esp-now/esp_now_netdev.c @@ -636,6 +636,12 @@ static int _get(netdev_t *netdev, netopt_t opt, void *val, size_t max_len) res = sizeof(dev->addr); break; + case NETOPT_CHANNEL: + CHECK_PARAM_RET(max_len >= sizeof(uint16_t), -EOVERFLOW); + *((uint16_t *)val) = ESP_NOW_CHANNEL; + res = sizeof(uint16_t); + break; + default: DEBUG("%s: %s not supported\n", __func__, netopt2str(opt)); break; diff --git a/cpu/esp_common/esp-wifi/doc.txt b/cpu/esp_common/esp-wifi/doc.txt index 86532f0bdd..670698cfb5 100644 --- a/cpu/esp_common/esp-wifi/doc.txt +++ b/cpu/esp_common/esp-wifi/doc.txt @@ -114,4 +114,8 @@ the verification of the AP certificate is not yet supported. ESP-NOW network interface (module `esp_now`) can be used simultaneously, for example, to realize a border router for a mesh network which uses ESP-NOW. +In this case the ESP-NOW interface must use the same channel as the AP of the +infrastructure WiFi network. All ESP-NOW nodes must therefore be compiled with +the channel of the AP asvalue for the parameter 'ESP_NOW_CHANNEL'. + */ diff --git a/cpu/esp_common/esp-wifi/esp_wifi_netdev.c b/cpu/esp_common/esp-wifi/esp_wifi_netdev.c index 3a11995387..1490185262 100644 --- a/cpu/esp_common/esp-wifi/esp_wifi_netdev.c +++ b/cpu/esp_common/esp-wifi/esp_wifi_netdev.c @@ -402,8 +402,12 @@ static const char *_esp_wifi_disc_reasons [] = { "HANDSHAKE_TIMEOUT" /* 204 */ }; +/* indicator whether the WiFi interface is started */ static unsigned _esp_wifi_started = 0; +/* current channel used by the WiFi interface */ +static unsigned _esp_wifi_channel = 0; + /* * Event handler for esp system events. */ @@ -440,6 +444,7 @@ static esp_err_t IRAM_ATTR _esp_system_event_handler(void *ctx, system_event_t * ESP_WIFI_LOG_INFO("WiFi connected to ssid %s, channel %d", event->event_info.connected.ssid, event->event_info.connected.channel); + _esp_wifi_channel = event->event_info.connected.channel; /* register RX callback function */ esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, _esp_wifi_rx_cb); @@ -623,6 +628,10 @@ static int _esp_wifi_get(netdev_t *netdev, netopt_t opt, void *val, size_t max_l switch (opt) { case NETOPT_IS_WIRED: return -ENOTSUP; + case NETOPT_CHANNEL: + CHECK_PARAM_RET(max_len >= sizeof(uint16_t), -EOVERFLOW); + *((uint16_t *)val) = _esp_wifi_channel; + return sizeof(uint16_t); case NETOPT_ADDRESS: assert(max_len >= ETHERNET_ADDR_LEN); esp_wifi_get_mac(ESP_MAC_WIFI_STA,(uint8_t *)val); From f90d230b00e0b46d853fe6865a961ae3b207cead Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Tue, 24 Mar 2020 07:09:00 +0100 Subject: [PATCH 2/2] cpu/esp: set NETOPT_CHANNEL for esp_wifi/esp_now --- cpu/esp_common/esp-now/esp_now_netdev.c | 45 ++++++++++++++++++++--- cpu/esp_common/esp-now/esp_now_netdev.h | 14 +++++-- cpu/esp_common/esp-wifi/esp_wifi_netdev.c | 5 ++- 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/cpu/esp_common/esp-now/esp_now_netdev.c b/cpu/esp_common/esp-now/esp_now_netdev.c index 674751830f..e988326e6c 100644 --- a/cpu/esp_common/esp-now/esp_now_netdev.c +++ b/cpu/esp_common/esp-now/esp_now_netdev.c @@ -100,7 +100,7 @@ static bool _esp_now_scan_peers_done = false; static wifi_ap_record_t* aps = NULL; static uint32_t aps_size = 0; -static const wifi_scan_config_t scan_cfg = { +static wifi_scan_config_t scan_cfg = { .ssid = NULL, .bssid = NULL, .channel = ESP_NOW_CHANNEL, @@ -290,6 +290,9 @@ static esp_err_t IRAM_ATTR _esp_system_event_handler(void *ctx, system_event_t * extern esp_err_t esp_system_event_add_handler(system_event_cb_t handler, void *arg); +/* ESP-NOW SoftAP configuration */ +static wifi_config_t wifi_config_ap = {}; + esp_now_netdev_t *netdev_esp_now_setup(void) { esp_now_netdev_t* dev = &_esp_now_dev; @@ -360,9 +363,7 @@ esp_now_netdev_t *netdev_esp_now_setup(void) /* get SoftAP interface mac address and store it as device address */ esp_read_mac(dev->addr, ESP_MAC_WIFI_SOFTAP); - /* prepare the ESP_NOW configuration for SoftAP */ - wifi_config_t wifi_config_ap = {}; - + /* prepare initial ESP_NOW configuration for SoftAP */ strcpy ((char*)wifi_config_ap.ap.password, esp_now_params.softap_pass); sprintf((char*)wifi_config_ap.ap.ssid, "%s%02x%02x%02x%02x%02x%02x", ESP_NOW_AP_PREFIX, @@ -452,6 +453,31 @@ esp_now_netdev_t *netdev_esp_now_setup(void) return dev; } +int esp_now_set_channel(uint8_t channel) +{ +#ifdef ESP_NOW_UNICAST + scan_cfg.channel = channel; +#endif +#ifdef MODULE_ESP_WIFI + /* channel is controlled by `esp_wifi`, only update SoftAP info */ + wifi_config_ap.ap.channel = channel; + return ESP_ERR_NOT_SUPPORTED; +#else + /* channel is controlled by `esp_now`, try to reconfigure SoftAP */ + uint8_t old_channel = wifi_config_ap.ap.channel; + wifi_config_ap.ap.channel = channel; + esp_err_t result = esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config_ap); + if (result != ESP_OK) { + LOG_TAG_ERROR("esp_now", + "esp_wifi_set_config softap failed with return value %d\n", + result); + wifi_config_ap.ap.channel = old_channel; + return result; + } + return ESP_OK; +#endif +} + static int _init(netdev_t *netdev) { DEBUG("%s: %p\n", __func__, netdev); @@ -638,7 +664,7 @@ static int _get(netdev_t *netdev, netopt_t opt, void *val, size_t max_len) case NETOPT_CHANNEL: CHECK_PARAM_RET(max_len >= sizeof(uint16_t), -EOVERFLOW); - *((uint16_t *)val) = ESP_NOW_CHANNEL; + *((uint16_t *)val) = wifi_config_ap.ap.channel; res = sizeof(uint16_t); break; @@ -675,6 +701,15 @@ static int _set(netdev_t *netdev, netopt_t opt, const void *val, size_t max_len) res = sizeof(dev->addr); break; + case NETOPT_CHANNEL: + CHECK_PARAM_RET(max_len >= sizeof(uint16_t), -EOVERFLOW); + uint16_t channel = *((uint16_t *)val); + if (esp_now_set_channel(channel) != ESP_OK) { + return -ENOTSUP; + } + res = sizeof(uint16_t); + break; + default: DEBUG("%s: %s not supported\n", __func__, netopt2str(opt)); break; diff --git a/cpu/esp_common/esp-now/esp_now_netdev.h b/cpu/esp_common/esp-now/esp_now_netdev.h index c2637e3477..547c4758af 100644 --- a/cpu/esp_common/esp-now/esp_now_netdev.h +++ b/cpu/esp_common/esp-now/esp_now_netdev.h @@ -94,17 +94,25 @@ typedef struct mutex_t dev_lock; /**< device is already in use */ - uint8_t scan_event; /**< ESP-NOW peers have to be scannged */ + uint8_t scan_event; /**< ESP-NOW peers have to be scanned */ } esp_now_netdev_t; /** - * @brief netdev <-> esp_npw glue code initialization function + * @brief ESP-NOW netdev initialization function * - * @return NULL on error, pointer to esp_now_netdev on success + * @return NULL on error, pointer to esp_now_netdev on success */ esp_now_netdev_t *netdev_esp_now_setup(void); +/** + * @brief Set the channel used by ESP-NOW netdev + * + * @param channel Channel to be used + * @return ESP_OK on success, an ESP error code otherwise + */ +int esp_now_set_channel(uint8_t channel); + #ifdef __cplusplus } #endif diff --git a/cpu/esp_common/esp-wifi/esp_wifi_netdev.c b/cpu/esp_common/esp-wifi/esp_wifi_netdev.c index 1490185262..bf41a2127a 100644 --- a/cpu/esp_common/esp-wifi/esp_wifi_netdev.c +++ b/cpu/esp_common/esp-wifi/esp_wifi_netdev.c @@ -445,7 +445,10 @@ static esp_err_t IRAM_ATTR _esp_system_event_handler(void *ctx, system_event_t * event->event_info.connected.ssid, event->event_info.connected.channel); _esp_wifi_channel = event->event_info.connected.channel; - +#ifdef MODULE_ESP_NOW + extern void esp_now_set_channel(uint8_t channel); + esp_now_set_channel(_esp_wifi_channel); +#endif /* register RX callback function */ esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, _esp_wifi_rx_cb);