Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions src/bluez/horipad_steam/horipad_steam.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ HoripadSteam::HoripadSteam(sdbus::IConnection& connection)
sub_system ? sub_system : "");
if (std::strcmp(sub_system, "hidraw") == 0) {
if (std::strcmp(action, "remove") == 0) {
std::scoped_lock reader_lock(input_reader_mutex_);
if (input_reader_) {
input_reader_->stop();
input_reader_.reset();
Expand All @@ -67,7 +66,6 @@ HoripadSteam::HoripadSteam(sdbus::IConnection& connection)
}

HoripadSteam::~HoripadSteam() {
stop();
unregisterProxy();
}

Expand All @@ -82,7 +80,6 @@ void HoripadSteam::onInterfacesAdded(
continue;
}
if (interface == org::bluez::Adapter1_proxy::INTERFACE_NAME) {
std::scoped_lock lock(adapters_mutex_);
if (!adapters_.contains(objectPath)) {
if (resource_limits::IsAtCapacity(adapters_.size(),
resource_limits::kMaxAdapters)) {
Expand Down Expand Up @@ -122,7 +119,6 @@ void HoripadSteam::onInterfacesAdded(

std::string hidraw_device_key;
{
std::scoped_lock lock(devices_mutex_);
if (devices_.contains(objectPath)) {
continue;
}
Expand Down Expand Up @@ -156,15 +152,13 @@ void HoripadSteam::onInterfacesAdded(
if (const std::string hidraw_device = FindHidDevice(hidraw_device_key);
!hidraw_device.empty()) {
LOG_INFO("Adding hidraw device: {}", hidraw_device_key);
std::scoped_lock reader_lock(input_reader_mutex_);
if (!input_reader_) {
input_reader_ = std::make_unique<InputReader>(hidraw_device);
input_reader_->start();
}
}
}
} else if (interface == org::bluez::Input1_proxy::INTERFACE_NAME) {
std::lock_guard lock(input1_mutex_);
if (!input1_.contains(objectPath)) {
if (resource_limits::IsAtCapacity(input1_.size(),
resource_limits::kMaxInputEntries)) {
Expand All @@ -187,19 +181,16 @@ void HoripadSteam::onInterfacesRemoved(
const std::vector<sdbus::InterfaceName>& interfaces) {
for (const auto& interface : interfaces) {
if (interface == org::bluez::Adapter1_proxy::INTERFACE_NAME) {
std::scoped_lock lock(adapters_mutex_);
if (adapters_.contains(objectPath)) {
adapters_[objectPath].reset();
adapters_.erase(objectPath);
}
} else if (interface == org::bluez::Device1_proxy::INTERFACE_NAME) {
std::scoped_lock devices_lock(devices_mutex_);
if (devices_.contains(objectPath)) {
devices_[objectPath].reset();
devices_.erase(objectPath);
}
} else if (interface == org::bluez::Input1_proxy::INTERFACE_NAME) {
std::lock_guard lock(input1_mutex_);
if (input1_.contains(objectPath)) {
input1_[objectPath].reset();
input1_.erase(objectPath);
Expand Down
16 changes: 3 additions & 13 deletions src/bluez/horipad_steam/horipad_steam.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,12 @@ class HoripadSteam final
static constexpr auto INTROSPECTABLE_INTERFACE_NAME =
"org.freedesktop.DBus.Introspectable";

// Locking policy: avoid nested locking where possible.
// If nested locking is required, always acquire in this order:
// adapters_mutex_ -> devices_mutex_ -> input1_mutex_.
std::mutex adapters_mutex_;
// All of the state below is only ever touched from the single EventLoop
// thread: the D-Bus object-manager callbacks and the UdevMonitor callback
// are both dispatched by the loop, so no locking is required.
std::map<sdbus::ObjectPath, std::unique_ptr<Adapter1>> adapters_;

std::mutex devices_mutex_;
std::map<sdbus::ObjectPath, std::unique_ptr<Device1>> devices_;

std::mutex input1_mutex_;
std::map<sdbus::ObjectPath, std::unique_ptr<Input1>> input1_;

// Guards input_reader_, which is created/started from onInterfacesAdded
// (D-Bus event-loop or main thread) and stopped/reset from the udev monitor
// worker thread.
std::mutex input_reader_mutex_;
std::unique_ptr<InputReader> input_reader_;

void onInterfacesAdded(
Expand Down
32 changes: 17 additions & 15 deletions src/bluez/horipad_steam/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,36 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#include "../../utils/signal_handler.h"
#include <chrono>

#include "../../utils/event_loop.h"
#include "../../utils/signal_source.h"
#include "horipad_steam.h"

int main() {
try {
installSignalHandlers();
// Single-threaded loop: it drives the D-Bus connection, the udev monitor,
// and signal delivery, so every callback runs on this thread. Construct the
// SignalSource first so SIGINT/SIGTERM are blocked before any thread is
// started (e.g. spdlog's periodic flush thread) and can only be delivered
// via the loop's signalfd.
EventLoop loop;
SignalSource signals(loop);
loop.add(&signals);

spdlog::set_level(spdlog::level::debug);
spdlog::flush_every(kLogFlushInterval);
spdlog::flush_every(std::chrono::seconds(5));

const auto connection = sdbus::createSystemBusConnection();
connection->enterEventLoopAsync();

HoripadSteam client(*connection);
loop.add(&client); // HoripadSteam is a UdevMonitor (an EventSource)

LOG_INFO("HoriPad Steam client running - Press Ctrl+C to exit");

// Monitor loop with shared connection health timing defaults
auto result = monitorLoop(*connection);

if (result) {
LOG_ERROR("Exiting due to: {}", *result);
} else {
LOG_INFO("Shutting down...");
}

connection->leaveEventLoop();
return result ? 1 : 0;
const int rc = loop.run(*connection);
LOG_INFO("Shutting down...");
return rc;

} catch (const sdbus::Error& e) {
LOG_ERROR("D-Bus error: {} - {}", e.getName(), e.getMessage());
Expand Down
13 changes: 0 additions & 13 deletions src/bluez/ps5_dual_sense/dual_sense.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ DualSense::DualSense(sdbus::IConnection& connection)
sub_system ? sub_system : "");
if (std::strcmp(sub_system, "hidraw") == 0) {
if (std::strcmp(action, "remove") == 0) {
std::scoped_lock reader_lock(input_reader_mutex_);
if (input_reader_) {
input_reader_->stop();
input_reader_.reset();
Expand All @@ -66,7 +65,6 @@ DualSense::DualSense(sdbus::IConnection& connection)
}

DualSense::~DualSense() {
stop();
unregisterProxy();
}

Expand All @@ -81,7 +79,6 @@ void DualSense::onInterfacesAdded(
continue;
}
if (interface == org::bluez::Adapter1_proxy::INTERFACE_NAME) {
std::scoped_lock lock(adapters_mutex_);
if (!adapters_.contains(objectPath)) {
if (resource_limits::IsAtCapacity(adapters_.size(),
resource_limits::kMaxAdapters)) {
Expand Down Expand Up @@ -120,7 +117,6 @@ void DualSense::onInterfacesAdded(
std::string power_path_to_add;
std::string hidraw_device_key;
{
std::scoped_lock lock(devices_mutex_);
if (devices_.contains(objectPath)) {
continue;
}
Expand Down Expand Up @@ -158,18 +154,14 @@ void DualSense::onInterfacesAdded(
if (const std::string hidraw_device = FindHidDevice(hidraw_device_key);
!hidraw_device.empty()) {
LOG_INFO("Adding hidraw device: {}", hidraw_device_key);
std::scoped_lock reader_lock(input_reader_mutex_);
if (!input_reader_) {
input_reader_ = std::make_unique<InputReader>(hidraw_device);
input_reader_->start();
}
}
}

// Avoid nested locking with devices_mutex_ +
// upower_display_devices_mutex_.
if (!power_path_to_add.empty()) {
std::scoped_lock power_lock(upower_display_devices_mutex_);
if (!upower_clients_.contains(power_path_to_add)) {
if (resource_limits::IsAtCapacity(
upower_clients_.size(), resource_limits::kMaxUPowerClients)) {
Expand All @@ -185,7 +177,6 @@ void DualSense::onInterfacesAdded(
}
}
} else if (interface == org::bluez::Input1_proxy::INTERFACE_NAME) {
std::lock_guard lock(input1_mutex_);
if (!input1_.contains(objectPath)) {
if (resource_limits::IsAtCapacity(input1_.size(),
resource_limits::kMaxInputEntries)) {
Expand All @@ -208,15 +199,13 @@ void DualSense::onInterfacesRemoved(
const std::vector<sdbus::InterfaceName>& interfaces) {
for (const auto& interface : interfaces) {
if (interface == org::bluez::Adapter1_proxy::INTERFACE_NAME) {
std::scoped_lock lock(adapters_mutex_);
if (adapters_.contains(objectPath)) {
adapters_[objectPath].reset();
adapters_.erase(objectPath);
}
} else if (interface == org::bluez::Device1_proxy::INTERFACE_NAME) {
std::string power_path_to_remove;
{
std::scoped_lock devices_lock(devices_mutex_);
if (devices_.contains(objectPath)) {
auto& device = devices_[objectPath];
if (auto props = device->GetProperties();
Expand All @@ -233,7 +222,6 @@ void DualSense::onInterfacesRemoved(
}

if (!power_path_to_remove.empty()) {
std::scoped_lock power_lock(upower_display_devices_mutex_);
if (upower_clients_.contains(power_path_to_remove)) {
LOG_INFO("[Remove] UPower Display Device: {}", power_path_to_remove);
auto& power_device = upower_clients_[power_path_to_remove];
Expand All @@ -242,7 +230,6 @@ void DualSense::onInterfacesRemoved(
}
}
} else if (interface == org::bluez::Input1_proxy::INTERFACE_NAME) {
std::lock_guard lock(input1_mutex_);
if (input1_.contains(objectPath)) {
input1_[objectPath].reset();
input1_.erase(objectPath);
Expand Down
19 changes: 3 additions & 16 deletions src/bluez/ps5_dual_sense/dual_sense.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,26 +46,13 @@ class DualSense final
static constexpr auto INTROSPECTABLE_INTERFACE_NAME =
"org.freedesktop.DBus.Introspectable";

// Locking policy: avoid nested locking where possible.
// If nested locking is required, always acquire in this order:
// adapters_mutex_ -> devices_mutex_ -> input1_mutex_ ->
// upower_display_devices_mutex_.
std::mutex adapters_mutex_;
// All of the state below is only ever touched from the single EventLoop
// thread: the D-Bus object-manager callbacks and the UdevMonitor callback
// are both dispatched by the loop, so no locking is required.
std::map<sdbus::ObjectPath, std::unique_ptr<Adapter1>> adapters_;

std::mutex devices_mutex_;
std::map<sdbus::ObjectPath, std::unique_ptr<Device1>> devices_;

std::mutex input1_mutex_;
std::map<sdbus::ObjectPath, std::unique_ptr<Input1>> input1_;

std::mutex upower_display_devices_mutex_;
std::map<std::string, std::unique_ptr<UPowerClient>> upower_clients_;

// Guards input_reader_, which is created/started from onInterfacesAdded
// (D-Bus event-loop or main thread) and stopped/reset from the udev monitor
// worker thread.
std::mutex input_reader_mutex_;
std::unique_ptr<InputReader> input_reader_;

void onInterfacesAdded(
Expand Down
32 changes: 17 additions & 15 deletions src/bluez/ps5_dual_sense/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,36 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#include "../../utils/signal_handler.h"
#include <chrono>

#include "../../utils/event_loop.h"
#include "../../utils/signal_source.h"
#include "dual_sense.h"

int main() {
try {
installSignalHandlers();
// Single-threaded loop: it drives the D-Bus connection, the udev monitor,
// and signal delivery, so every callback runs on this thread. Construct the
// SignalSource first so SIGINT/SIGTERM are blocked before any thread is
// started (e.g. spdlog's periodic flush thread) and can only be delivered
// via the loop's signalfd.
EventLoop loop;
SignalSource signals(loop);
loop.add(&signals);

spdlog::set_level(spdlog::level::debug);
spdlog::flush_every(kLogFlushInterval);
spdlog::flush_every(std::chrono::seconds(5));

const auto connection = sdbus::createSystemBusConnection();
connection->enterEventLoopAsync();

DualSense client(*connection);
loop.add(&client); // DualSense is a UdevMonitor (an EventSource)

LOG_INFO("PS5 DualSense client running - Press Ctrl+C to exit");

// Monitor loop with shared connection health timing defaults
auto result = monitorLoop(*connection);

if (result) {
LOG_ERROR("Exiting due to: {}", *result);
} else {
LOG_INFO("Shutting down...");
}

connection->leaveEventLoop();
return result ? 1 : 0;
const int rc = loop.run(*connection);
LOG_INFO("Shutting down...");
return rc;

} catch (const sdbus::Error& e) {
LOG_ERROR("D-Bus error: {} - {}", e.getName(), e.getMessage());
Expand Down
Loading
Loading