|
| 1 | +/* |
| 2 | + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: Unlicense OR CC0-1.0 |
| 5 | + */ |
| 6 | +#include <stdio.h> |
| 7 | +#include <stdint.h> |
| 8 | +#include <stddef.h> |
| 9 | +#include <string.h> |
| 10 | +#include "esp_system.h" |
| 11 | +#include "esp_event.h" |
| 12 | +#include "esp_netif.h" |
| 13 | +#include "eppp_link.h" |
| 14 | +#include "esp_log.h" |
| 15 | +#include "esp_check.h" |
| 16 | +#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT |
| 17 | +#if __has_include("esp_wifi_remote.h") |
| 18 | +#include "esp_wifi_remote.h" |
| 19 | +#define HAVE_WIFI_REMOTE |
| 20 | +#endif |
| 21 | +#endif |
| 22 | + |
| 23 | +#define CHAT_CHANNEL 1 |
| 24 | +#define WIFI_CHANNEL 2 |
| 25 | + |
| 26 | +typedef enum { |
| 27 | + UNKNOWN, |
| 28 | + HELLO, |
| 29 | + START, |
| 30 | + ERROR, |
| 31 | +} state_t; |
| 32 | + |
| 33 | +typedef struct context { |
| 34 | + eppp_channel_fn_t transmit; |
| 35 | + EventGroupHandle_t flags; |
| 36 | + state_t state; |
| 37 | +// esp_netif_t *wifi; |
| 38 | + esp_netif_t *eppp; |
| 39 | +} context_t; |
| 40 | + |
| 41 | +#define HELLO_BIT BIT0 |
| 42 | +#define START_BIT BIT1 |
| 43 | +#define CONNECT_BIT BIT2 |
| 44 | +#define SERVER_UP_BIT BIT3 |
| 45 | + |
| 46 | +#define ALL_BITS (HELLO_BIT | START_BIT | CONNECT_BIT | SERVER_UP_BIT) |
| 47 | + |
| 48 | +static uint8_t s_wifi_mac_addr[6] = { 0 }; |
| 49 | +static const char *TAG = "eppp_host_example_with_channels"; |
| 50 | + |
| 51 | +esp_netif_t* esp_wifi_remote_create_default_sta(void); |
| 52 | + |
| 53 | +static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) |
| 54 | +{ |
| 55 | + ESP_LOGI(TAG, "IP event_handler: event_base=%s event_id=%d", event_base, event_id); |
| 56 | + if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { |
| 57 | + ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data; |
| 58 | + ESP_LOGI(TAG, "Got IP:" IPSTR, IP2STR(&event->ip_info.ip)); |
| 59 | + } |
| 60 | +} |
| 61 | + |
| 62 | +esp_err_t esp_wifi_remote_get_mac(wifi_interface_t ifx, uint8_t mac[6]) |
| 63 | +{ |
| 64 | + if (ifx != WIFI_IF_STA) { |
| 65 | + return ESP_ERR_INVALID_STATE; |
| 66 | + |
| 67 | + } |
| 68 | + for (int i = 0; i < sizeof(s_wifi_mac_addr); i++) { |
| 69 | + if (s_wifi_mac_addr[i] == 0) { |
| 70 | + return ESP_ERR_INVALID_STATE; |
| 71 | + } |
| 72 | + } |
| 73 | + memcpy(mac, s_wifi_mac_addr, sizeof(s_wifi_mac_addr)); |
| 74 | + return ESP_OK; |
| 75 | +} |
| 76 | + |
| 77 | +static esp_err_t eppp_receive(esp_netif_t *netif, int nr, void *buffer, size_t len) |
| 78 | +{ |
| 79 | + context_t *ctx = eppp_get_context(netif); |
| 80 | + if (nr == CHAT_CHANNEL) { |
| 81 | + ESP_LOGI(TAG, "Received channel=%d len=%d %.*s", nr, (int)len, (int)len, (char *)buffer); |
| 82 | + const char hello[] = "Hello client"; |
| 83 | + const char mac[] = "MAC: "; |
| 84 | + const char connected[] = "Connected"; |
| 85 | + const char server_up[] = "Server up"; |
| 86 | + size_t mac_len = 5 /* MAC: */ + 6 * 2 /* 6 bytes per char */ + 5 /* : */ + 1 /* \0 */; |
| 87 | + if (len == sizeof(server_up) && memcmp(buffer, server_up, len) == 0) { |
| 88 | + if (ctx->state == UNKNOWN) { |
| 89 | + ESP_LOGI(TAG, "Server is up"); |
| 90 | + ctx->state = HELLO; |
| 91 | + } else { |
| 92 | + ESP_LOGE(TAG, "Received server up in unexpected state %d", ctx->state); |
| 93 | + ctx->state = ERROR; |
| 94 | + } |
| 95 | + xEventGroupSetBits(ctx->flags, SERVER_UP_BIT); |
| 96 | + } else if (len == sizeof(hello) && memcmp(buffer, hello, len) == 0) { |
| 97 | + if (ctx->state == HELLO) { |
| 98 | + xEventGroupSetBits(ctx->flags, HELLO_BIT); |
| 99 | + } else { |
| 100 | + ESP_LOGE(TAG, "Received hello in unexpected state %d", ctx->state); |
| 101 | + ctx->state = ERROR; |
| 102 | + } |
| 103 | + } else if (len == mac_len && memcmp(buffer, mac, 5) == 0) { |
| 104 | + if (ctx->state == HELLO) { |
| 105 | + uint8_t mac_addr[6]; |
| 106 | + sscanf((char *)buffer + 5, "%2" PRIx8 ":%2" PRIx8 ":%2" PRIx8 ":%2" PRIx8 ":%2" PRIx8 ":%2" PRIx8, |
| 107 | + &mac_addr[0], &mac_addr[1], &mac_addr[2], &mac_addr[3], &mac_addr[4], &mac_addr[5]); |
| 108 | + ESP_LOGI(TAG, "Parsed MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); |
| 109 | + memcpy(s_wifi_mac_addr, mac_addr, sizeof(s_wifi_mac_addr)); |
| 110 | + xEventGroupSetBits(ctx->flags, START_BIT); |
| 111 | + } else { |
| 112 | + ESP_LOGE(TAG, "Received MAC in unexpected state %d", ctx->state); |
| 113 | + ctx->state = ERROR; |
| 114 | + } |
| 115 | + } else if (len == sizeof(connected) && memcmp(buffer, connected, len) == 0) { |
| 116 | + if (ctx->state == START) { |
| 117 | + xEventGroupSetBits(ctx->flags, CONNECT_BIT); |
| 118 | + } else { |
| 119 | + ESP_LOGE(TAG, "Received connected in unexpected state %d", ctx->state); |
| 120 | + ctx->state = ERROR; |
| 121 | + } |
| 122 | + } |
| 123 | + } else if (nr == WIFI_CHANNEL) { |
| 124 | + ESP_LOGD(TAG, "Received WIFI channel=%d len=%d", nr, (int)len); |
| 125 | + ESP_LOG_BUFFER_HEXDUMP("wifi-receive", buffer, len, ESP_LOG_VERBOSE); |
| 126 | + return esp_wifi_remote_channel_rx(ctx->eppp, buffer, NULL, len); |
| 127 | + } else { |
| 128 | + ESP_LOGE(TAG, "Incorrect channel number %d", nr); |
| 129 | + return ESP_FAIL; |
| 130 | + } |
| 131 | + return ESP_OK; |
| 132 | +} |
| 133 | + |
| 134 | +static esp_err_t wifi_transmit(void *h, void *buffer, size_t len) |
| 135 | +{ |
| 136 | + esp_netif_t *eppp = (esp_netif_t *)h; |
| 137 | + context_t *ctx = eppp_get_context(eppp); |
| 138 | + ESP_LOG_BUFFER_HEXDUMP("wifi-transmit", buffer, len, ESP_LOG_VERBOSE); |
| 139 | + return ctx->transmit(eppp, WIFI_CHANNEL, buffer, len); |
| 140 | +} |
| 141 | + |
| 142 | +void esp_netif_destroy_wifi_remote(void *esp_netif); |
| 143 | + |
| 144 | +void station_over_eppp_channel(void *arg) |
| 145 | +{ |
| 146 | + __attribute__((unused)) esp_err_t ret; |
| 147 | + esp_netif_t *wifi = NULL; |
| 148 | + context_t ctx = { |
| 149 | + .transmit = NULL, |
| 150 | + .flags = NULL, |
| 151 | + .state = UNKNOWN, |
| 152 | + .eppp = (esp_netif_t *)arg |
| 153 | + }; |
| 154 | + ESP_GOTO_ON_FALSE(ctx.eppp != NULL, ESP_FAIL, err, TAG, "Incorrect EPPP netif"); |
| 155 | + ESP_GOTO_ON_FALSE(ctx.flags = xEventGroupCreate(), ESP_FAIL, err, TAG, "Failed to create event group"); |
| 156 | + ESP_GOTO_ON_ERROR(eppp_add_channels(ctx.eppp, &ctx.transmit, eppp_receive, &ctx), err, TAG, "Failed to add channels"); |
| 157 | + ESP_GOTO_ON_FALSE(ctx.transmit, ESP_FAIL, err, TAG, "Channel tx function is not set"); |
| 158 | + ESP_GOTO_ON_ERROR(esp_wifi_remote_channel_set(WIFI_IF_STA, ctx.eppp, wifi_transmit), err, TAG, "Failed to set wifi channel tx function"); |
| 159 | + esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, event_handler, &ctx); |
| 160 | + |
| 161 | + while (1) { |
| 162 | + EventBits_t bits = xEventGroupWaitBits(ctx.flags, ALL_BITS, pdTRUE, pdFALSE, pdMS_TO_TICKS(1000)); |
| 163 | + if (bits & HELLO_BIT) { |
| 164 | + ESP_LOGI(TAG, "Hello done"); |
| 165 | + if (wifi == NULL) { |
| 166 | + wifi = esp_wifi_remote_create_default_sta(); |
| 167 | + } |
| 168 | + const char command[] = "Get MAC"; |
| 169 | + ctx.transmit(ctx.eppp, CHAT_CHANNEL, (void*)command, sizeof(command)); |
| 170 | + } else if (bits & START_BIT) { |
| 171 | + ctx.state = START; |
| 172 | + ESP_LOGI(TAG, "Starting WIFI"); |
| 173 | + esp_event_post(WIFI_REMOTE_EVENT, WIFI_EVENT_STA_START, NULL, 0, 0); |
| 174 | + } else if (bits & CONNECT_BIT) { |
| 175 | + ESP_LOGI(TAG, "WIFI connected"); |
| 176 | + esp_event_post(WIFI_REMOTE_EVENT, WIFI_EVENT_STA_CONNECTED, NULL, 0, 0); |
| 177 | + } else if ((bits & SERVER_UP_BIT) == SERVER_UP_BIT || ctx.state != START) { |
| 178 | + if (ctx.state == ERROR) { |
| 179 | + esp_netif_destroy_wifi_remote(wifi); |
| 180 | + wifi = NULL; |
| 181 | + ESP_LOGI(TAG, "WiFi netif has been destroyed"); |
| 182 | + } |
| 183 | + const char hello[] = "Hello server"; |
| 184 | + ctx.transmit(ctx.eppp, CHAT_CHANNEL, (void*)hello, sizeof(hello)); |
| 185 | + ctx.state = HELLO; |
| 186 | + } |
| 187 | + } |
| 188 | + |
| 189 | +err: |
| 190 | + vTaskDelete(NULL); |
| 191 | +} |
0 commit comments