12#include <netinet/in.h>
13#include <sys/select.h>
14#include <sys/socket.h>
25static const char *
const TAG =
"wake";
39std::vector<int> s_socket_fds;
41bool s_socket_fds_changed =
false;
42fd_set s_base_read_fds{};
51 if (fd >= FD_SETSIZE) {
52 ESP_LOGE(TAG,
"fd %d exceeds FD_SETSIZE %d", fd, FD_SETSIZE);
56 s_socket_fds.push_back(fd);
57 s_socket_fds_changed =
true;
70 for (
size_t i = 0; i < s_socket_fds.size(); i++) {
71 if (s_socket_fds[i] != fd)
75 if (i < s_socket_fds.size() - 1)
76 s_socket_fds[i] = s_socket_fds.back();
77 s_socket_fds.pop_back();
78 s_socket_fds_changed =
true;
82 for (
int sock_fd : s_socket_fds) {
83 if (sock_fd > s_max_fd)
96 if (!s_socket_fds.empty()) [[likely]] {
98 if (s_socket_fds_changed) [[unlikely]] {
99 FD_ZERO(&s_base_read_fds);
101 for (
int fd : s_socket_fds) {
102 FD_SET(fd, &s_base_read_fds);
104 s_socket_fds_changed =
false;
112 tv.tv_sec = ms / 1000;
113 tv.tv_usec = (ms - tv.tv_sec * 1000) * 1000;
116 int ret = ::select(s_max_fd + 1, &
g_read_fds,
nullptr,
nullptr, &tv);
121 if (ret >= 0) [[likely]] {
123 if (ms == 0) [[unlikely]] {
129 const int err = errno;
134 ESP_LOGW(TAG,
"select() failed with errno %d", err);
146 const char dummy = 1;
155 ESP_LOGW(TAG,
"Wake socket create failed: %d", errno);
162 addr.
sin_addr.s_addr = htonl(INADDR_LOOPBACK);
166 ESP_LOGW(TAG,
"Wake socket bind failed: %d", errno);
177 ESP_LOGW(TAG,
"Wake socket address failed: %d", errno);
186 ESP_LOGW(TAG,
"Wake socket connect failed: %d", errno);
198 ESP_LOGW(TAG,
"Wake socket register failed");
void ESPHOME_ALWAYS_INLINE wakeable_delay(uint32_t ms)
Host wakeable_delay uses select() over the registered fds — defined in wake_host.cpp.
std::atomic< uint8_t > g_wake_requested
void wake_loop_threadsafe()
Non-ISR: always inline.
bool wake_register_fd(int fd)
Register a socket file descriptor with the host select() loop.
void wake_unregister_fd(int fd)
Unregister a socket file descriptor. Not thread-safe — main loop only.
void HOT delay(uint32_t ms)
void wake_setup()
One-time setup of the loopback wake socket. Called from Application::setup().
Platform-specific main loop wake primitives.