From 4dc56ae808b1a351c7abc7f80dfa64371a581b12 Mon Sep 17 00:00:00 2001 From: Thomas Perl Date: Thu, 30 Jul 2026 09:27:06 +0200 Subject: [PATCH 1/2] Unified moved_monitor_wait() for moved --- src/daemon/moved.cpp | 9 +++++++++ src/daemon/moved_monitor.h | 20 +++++++++++++------- src/daemon/moved_monitor_linux.c | 17 +++++++++++++++++ src/daemon/moved_monitor_osx.mm | 19 +++++++++++++++++++ src/daemon/moved_monitor_windows.cpp | 22 +++++++++++++++------- src/psmove_port.h | 2 -- src/psmoveapi.cpp | 12 +----------- src/utils/psmovepair.c | 26 ++------------------------ 8 files changed, 76 insertions(+), 51 deletions(-) diff --git a/src/daemon/moved.cpp b/src/daemon/moved.cpp index 6912cb9f..a255d310 100644 --- a/src/daemon/moved.cpp +++ b/src/daemon/moved.cpp @@ -43,6 +43,12 @@ #include "psmove.h" +#if defined(__APPLE__) +# include +#elif defined(__linux) +# include +#endif + #include struct move_daemon; @@ -167,6 +173,9 @@ main(int argc, char *argv[]) #else while (true) { moved.handle_request(); + if (moved_monitor_wait(monitor, false)) { + moved_monitor_poll(monitor); + } moved.write_reports(); } #endif diff --git a/src/daemon/moved_monitor.h b/src/daemon/moved_monitor.h index c4ffcf3e..2e62f38c 100644 --- a/src/daemon/moved_monitor.h +++ b/src/daemon/moved_monitor.h @@ -37,6 +37,7 @@ extern "C" { #endif #include +#include enum MonitorEvent { EVENT_DEVICE_ADDED, @@ -59,13 +60,18 @@ typedef struct _moved_monitor moved_monitor; ADDAPI moved_monitor * ADDCALL moved_monitor_new(moved_event_callback callback, void *user_data); -#ifdef _WIN32 -// Block until Windows signals a device change or the fallback rescan is due. -// Call moved_monitor_poll() after this returns to process any controller -// additions or removals. -ADDAPI void -ADDCALL moved_monitor_wait(moved_monitor *monitor); -#endif +// If blocking is true: +// Block until the OS signals a device change (or in some cases, a fallback +// mechanism is used, e.g. interval-based polling), and return true. +// +// If blocking is false: +// Will immediately return true if there are outstanding device changes, +// or immediately return false otherwise. +// +// Call moved_monitor_poll() after this returns true to process any +// controller additions or removals. +ADDAPI bool +ADDCALL moved_monitor_wait(moved_monitor *monitor, bool blocking); ADDAPI void ADDCALL moved_monitor_poll(moved_monitor *monitor); diff --git a/src/daemon/moved_monitor_linux.c b/src/daemon/moved_monitor_linux.c index ed5bfa02..0a8f6745 100644 --- a/src/daemon/moved_monitor_linux.c +++ b/src/daemon/moved_monitor_linux.c @@ -34,6 +34,8 @@ #include #include +#include +#include #include "moved_monitor.h" @@ -215,6 +217,21 @@ moved_monitor_poll(moved_monitor *monitor) } } +bool +moved_monitor_wait(moved_monitor *monitor, bool blocking) +{ + psmove_return_val_if_fail(monitor != NULL, false); + + int monitor_fd = moved_monitor_get_fd(monitor); + + struct pollfd pfd; + + pfd.fd = monitor_fd; + pfd.events = POLLIN; + + return (poll(&pfd, 1, blocking ? -1 : 0) > 0); +} + void moved_monitor_free(moved_monitor *monitor) { diff --git a/src/daemon/moved_monitor_osx.mm b/src/daemon/moved_monitor_osx.mm index 3bd13fd4..c3b79199 100644 --- a/src/daemon/moved_monitor_osx.mm +++ b/src/daemon/moved_monitor_osx.mm @@ -41,6 +41,10 @@ #import #import +#include +#include +#include + // Convenience functions copied from hidapi #include "moved_monitor_osx_hidapi.mm" @@ -160,6 +164,21 @@ static void on_device_removal(void *context, IOReturn result, void *sender, IOHI monitor->pump_loop(); } +bool +moved_monitor_wait(moved_monitor *monitor, bool blocking) +{ + psmove_return_val_if_fail(monitor != nullptr, false); + + int monitor_fd = moved_monitor_get_fd(monitor); + + struct pollfd pfd; + + pfd.fd = monitor_fd; + pfd.events = POLLIN; + + return (poll(&pfd, 1, blocking ? -1 : 0) > 0); +} + void moved_monitor_free(moved_monitor *monitor) { diff --git a/src/daemon/moved_monitor_windows.cpp b/src/daemon/moved_monitor_windows.cpp index d6a2eb0a..415b765c 100644 --- a/src/daemon/moved_monitor_windows.cpp +++ b/src/daemon/moved_monitor_windows.cpp @@ -303,14 +303,17 @@ moved_monitor_get_fd(moved_monitor *) return -1; } -void -moved_monitor_wait(moved_monitor *monitor) +bool +moved_monitor_wait(moved_monitor *monitor, bool blocking) { - psmove_return_if_fail(monitor != nullptr); + psmove_return_val_if_fail(monitor != nullptr, false); + + // TODO: This function only returns "true" for now, causing a + // rescan all the time. Eventually implement returning "false". const auto now = GetTickCount64(); if (monitor->rescan_requested.load() || now >= monitor->next_rescan) { - return; + return true; } const auto remaining = monitor->next_rescan - now; @@ -319,18 +322,23 @@ moved_monitor_wait(moved_monitor *monitor) : static_cast(remaining); if (monitor->device_event == nullptr) { - Sleep(timeout); - return; + if (blocking) { + // Simulated blocking based on timeout + Sleep(timeout); + } + return true; } // The notification callback signals the event immediately. The timeout // preserves periodic rescanning if Windows misses a notification. - const auto result = WaitForSingleObject(monitor->device_event, timeout); + const auto result = WaitForSingleObject(monitor->device_event, blocking ? timeout : 0); if (result == WAIT_FAILED) { PSMOVE_WARNING( "Could not wait for Windows device notification (%lu)", static_cast(GetLastError())); } + + return true; } diff --git a/src/psmove_port.h b/src/psmove_port.h index b29a15b3..b262cd13 100644 --- a/src/psmove_port.h +++ b/src/psmove_port.h @@ -35,13 +35,11 @@ # include # include # include -# include #endif #ifdef __linux # include # include -# include #endif #ifdef _WIN32 diff --git a/src/psmoveapi.cpp b/src/psmoveapi.cpp index 0a270bfd..156334d6 100644 --- a/src/psmoveapi.cpp +++ b/src/psmoveapi.cpp @@ -213,19 +213,9 @@ PSMoveAPI::~PSMoveAPI() void PSMoveAPI::update() { - if (moved_monitor_get_fd(monitor) == -1) { + if (moved_monitor_wait(monitor, false)) { moved_monitor_poll(monitor); } -#ifndef _WIN32 - else { - struct pollfd pfd; - pfd.fd = moved_monitor_get_fd(monitor); - pfd.events = POLLIN; - while (poll(&pfd, 1, 0) > 0) { - moved_monitor_poll(monitor); - } - } -#endif for (auto &c: controllers) { c->update_connection_flags(); diff --git a/src/utils/psmovepair.c b/src/utils/psmovepair.c index 16bb4249..d13ae3d4 100644 --- a/src/utils/psmovepair.c +++ b/src/utils/psmovepair.c @@ -106,37 +106,15 @@ on_monitor_update_pair(enum MonitorEvent event, int run_daemon() { -#if defined(_WIN32) moved_monitor *monitor = moved_monitor_new(on_monitor_update_pair, NULL); - while (1) { - moved_monitor_wait(monitor); - moved_monitor_poll(monitor); - } - moved_monitor_free(monitor); -#elif defined(__linux) || defined(__APPLE__) - // TODO: Use a blocking monitor wait here after runtime testing it on - // Linux and macOS. - moved_monitor *monitor = moved_monitor_new(on_monitor_update_pair, NULL); - int monitor_fd = moved_monitor_get_fd(monitor); - struct pollfd pfd; - - pfd.fd = monitor_fd; - pfd.events = POLLIN; - - while (1) { - if (poll(&pfd, 1, 0) > 0) { + while (true) { + if (moved_monitor_wait(monitor, true)) { moved_monitor_poll(monitor); } } moved_monitor_free(monitor); -#else - for(;;) { - psmove_port_sleep_ms(5000); - pair(NULL); - } -#endif return 0; } From ce5a21f35b044ba378c78cb5ae305931362ff3f2 Mon Sep 17 00:00:00 2001 From: Thomas Perl Date: Thu, 30 Jul 2026 10:20:16 +0200 Subject: [PATCH 2/2] Create moved_monitor also on Win32 --- src/daemon/moved.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/daemon/moved.cpp b/src/daemon/moved.cpp index a255d310..0317cee4 100644 --- a/src/daemon/moved.cpp +++ b/src/daemon/moved.cpp @@ -144,9 +144,9 @@ main(int argc, char *argv[]) moved.handle_connection(NULL, NULL); } -#if defined(__linux) || defined(__APPLE__) moved_monitor *monitor = moved_monitor_new(on_monitor_update_moved, &moved); +#if defined(__linux) || defined(__APPLE__) struct pollfd pfd[2]; pfd[0].fd = moved.get_socket(); @@ -169,7 +169,6 @@ main(int argc, char *argv[]) moved.write_reports(); } - moved_monitor_free(monitor); #else while (true) { moved.handle_request(); @@ -180,6 +179,8 @@ main(int argc, char *argv[]) } #endif + moved_monitor_free(monitor); + return 0; }