Fix receivers not seeing device connection events

This commit is contained in:
pixl 2023-04-29 18:57:09 -04:00
parent fc96bb7b40
commit f2fd967865
No known key found for this signature in database
GPG Key ID: 1866C148CD593B6E
7 changed files with 90 additions and 98 deletions

View File

@ -64,10 +64,10 @@ Receiver::Receiver(const std::string& path,
const std::shared_ptr<DeviceManager>& manager) :
hidpp10::ReceiverMonitor(path, manager,
manager->config()->io_timeout.value_or(
defaults::io_timeout)),
defaults::io_timeout)),
_path(path), _manager(manager), _nickname(manager),
_ipc_node(manager->receiversNode()->make_child(_nickname)),
_ipc_interface(_ipc_node->make_interface<ReceiverIPC>(this)) {
_ipc_interface(_ipc_node->make_interface<IPC>(this)) {
ready();
}
@ -114,9 +114,8 @@ void Receiver::addDevice(hidpp::DeviceConnectionEvent event) {
if (!event.linkEstablished)
return;
hidpp::Device hidpp_device(
receiver(), event,
manager->config()->io_timeout.value_or(defaults::io_timeout));
hidpp::Device hidpp_device(receiver(), event,
manager->config()->io_timeout.value_or(defaults::io_timeout));
auto version = hidpp_device.version();
@ -132,9 +131,8 @@ void Receiver::addDevice(hidpp::DeviceConnectionEvent event) {
manager->addExternalDevice(device);
} catch (hidpp10::Error& e) {
logPrintf(ERROR,
"Caught HID++ 1.0 error while trying to initialize "
"%s:%d: %s", _path.c_str(), event.index, e.what());
logPrintf(ERROR, "Caught HID++ 1.0 error while trying to initialize %s:%d: %s",
_path.c_str(), event.index, e.what());
} catch (hidpp20::Error& e) {
logPrintf(ERROR, "Caught HID++ 2.0 error while trying to initialize "
"%s:%d: %s", _path.c_str(), event.index, e.what());
@ -167,6 +165,6 @@ std::shared_ptr<hidpp10::Receiver> Receiver::rawReceiver() {
return receiver();
}
Receiver::ReceiverIPC::ReceiverIPC(Receiver* receiver) :
Receiver::IPC::IPC(Receiver* receiver) :
ipcgull::interface(SERVICE_ROOT_NAME ".Receiver", {}, {}, {}) {
}

View File

@ -78,9 +78,9 @@ namespace logid {
const ReceiverNickname _nickname;
std::shared_ptr<ipcgull::node> _ipc_node;
class ReceiverIPC : public ipcgull::interface {
class IPC : public ipcgull::interface {
public:
explicit ReceiverIPC(Receiver* receiver);
explicit IPC(Receiver* receiver);
};
std::shared_ptr<ipcgull::interface> _ipc_interface;

View File

@ -117,21 +117,19 @@ void Device::_init() {
*/
if (_index == hidpp::DefaultDevice) {
_raw_handler = _raw_device->addEventHandler(
{
[](
const std::vector<uint8_t>& report) -> bool {
return (report[Offset::Type] == Report::Type::Short ||
report[Offset::Type] == Report::Type::Long);
},
[this](const std::vector<uint8_t>& report) -> void {
Report _report(report);
this->handleEvent(_report);
}});
{[](const std::vector<uint8_t>& report) -> bool {
return (report[Offset::Type] == Report::Type::Short ||
report[Offset::Type] == Report::Type::Long);
},
[this](const std::vector<uint8_t>& report) -> void {
Report _report(report);
this->handleEvent(_report);
}});
try {
auto rsp = sendReport({ReportType::Short, _index,
hidpp20::FeatureID::ROOT, hidpp20::Root::Ping,
hidpp::softwareID});
hidpp20::FeatureID::ROOT, hidpp20::Root::Ping,
hidpp::softwareID});
if (rsp.deviceIndex() != _index) {
throw InvalidDevice(InvalidDevice::VirtualNode);
}
@ -146,18 +144,16 @@ void Device::_init() {
}
_raw_handler = _raw_device->addEventHandler(
{
[index = this->_index](
const std::vector<uint8_t>& report) -> bool {
return (report[Offset::Type] == Report::Type::Short ||
report[Offset::Type] == Report::Type::Long) &&
(report[Offset::DeviceIndex] == index);
},
[this](const std::vector<uint8_t>& report) -> void {
Report _report(report);
this->handleEvent(_report);
}});
{[index = this->_index](
const std::vector<uint8_t>& report) -> bool {
return (report[Offset::Type] == Report::Type::Short ||
report[Offset::Type] == Report::Type::Long) &&
(report[Offset::DeviceIndex] == index);
},
[this](const std::vector<uint8_t>& report) -> void {
Report _report(report);
this->handleEvent(_report);
}});
try {
try {
@ -250,9 +246,9 @@ Report Device::sendReport(const Report& report) {
if (std::holds_alternative<Report>(response)) {
return std::get<Report>(response);
} else if(std::holds_alternative<Report::Hidpp10Error>(response)) {
} else if (std::holds_alternative<Report::Hidpp10Error>(response)) {
throw hidpp10::Error(std::get<Report::Hidpp10Error>(response).error_code);
} else if(std::holds_alternative<Report::Hidpp20Error>(response)) {
} else if (std::holds_alternative<Report::Hidpp20Error>(response)) {
throw hidpp20::Error(std::get<Report::Hidpp20Error>(response).error_code);
}

View File

@ -57,8 +57,7 @@ hidpp::Report Device::sendReport(const hidpp::Report& report) {
response_slot.sub_id = report.subId();
_sendReport(report);
bool valid = _response_cv.wait_for(
lock, io_timeout,
bool valid = _response_cv.wait_for(lock, io_timeout,
[&response_slot]() {
return response_slot.response.has_value();
});

View File

@ -175,8 +175,7 @@ std::string Receiver::getDeviceName(hidpp::DeviceIndex index) {
return name;
}
hidpp::DeviceIndex Receiver::deviceDisconnectionEvent(const hidpp::Report&
report) {
hidpp::DeviceIndex Receiver::deviceDisconnectionEvent(const hidpp::Report& report) {
assert(report.subId() == DeviceDisconnection);
return report.deviceIndex();
}

View File

@ -34,46 +34,48 @@ ReceiverMonitor::ReceiverMonitor(const std::string& path,
ReceiverMonitor::~ReceiverMonitor() {
if (ev_handler.has_value())
_receiver->removeEventHandler(ev_handler.value());
_receiver->rawDevice()->removeEventHandler(ev_handler.value());
}
void ReceiverMonitor::ready() {
if (!ev_handler.has_value()) {
hidpp::EventHandler event_handler;
event_handler.condition = [](hidpp::Report& report) -> bool {
return (report.subId() == Receiver::DeviceConnection ||
report.subId() == Receiver::DeviceDisconnection);
};
ev_handler = _receiver->rawDevice()->addEventHandler(
{[](const std::vector<uint8_t>& report) -> bool {
if (report[Offset::Type] == Report::Type::Short ||
report[Offset::Type] == Report::Type::Long) {
uint8_t sub_id = report[Offset::SubID];
return (sub_id == Receiver::DeviceConnection ||
sub_id == Receiver::DeviceDisconnection);
}
return false;
}, [this](const std::vector<uint8_t>& raw) -> void {
/* Running in a new thread prevents deadlocks since the
* receiver may be enumerating.
*/
hidpp::Report report(raw);
event_handler.callback = [this](hidpp::Report& report) -> void {
/* Running in a new thread prevents deadlocks since the
* receiver may be enumerating.
*/
spawn_task([this, report,
path = this->_receiver->rawDevice()->rawPath()]() {
if (report.subId() == Receiver::DeviceConnection) {
try {
this->addDevice(this->_receiver->deviceConnectionEvent
(report));
} catch (std::exception& e) {
logPrintf(ERROR, "Failed to add device %d to receiver "
"on %s: %s", report.deviceIndex(),
path.c_str(), e.what());
}
} else if (report.subId() == Receiver::DeviceDisconnection) {
try {
this->removeDevice(this->_receiver->
deviceDisconnectionEvent(report));
} catch (std::exception& e) {
logPrintf(ERROR, "Failed to remove device %d from "
"receiver on %s: %s", report.deviceIndex(),
path.c_str(), e.what());
}
spawn_task([this, report, path = this->_receiver->rawDevice()->rawPath()]() {
if (report.subId() == Receiver::DeviceConnection) {
try {
this->addDevice(this->_receiver->deviceConnectionEvent(report));
} catch (std::exception& e) {
logPrintf(ERROR, "Failed to add device %d to receiver on %s: %s",
report.deviceIndex(), path.c_str(), e.what());
}
} else if (report.subId() == Receiver::DeviceDisconnection) {
try {
this->removeDevice(
this->_receiver->deviceDisconnectionEvent(report));
} catch (std::exception& e) {
logPrintf(ERROR, "Failed to remove device %d from "
"receiver on %s: %s", report.deviceIndex(),
path.c_str(), e.what());
}
}
});
}
});
};
ev_handler = _receiver->addEventHandler(event_handler);
});
}
enumerate();
@ -87,30 +89,28 @@ void ReceiverMonitor::waitForDevice(hidpp::DeviceIndex index) {
auto handler_id = std::make_shared<raw::RawDevice::EvHandlerId>();
*handler_id = _receiver->rawDevice()->addEventHandler(
{
[index](const std::vector<uint8_t>& report) -> bool {
return report[Offset::DeviceIndex] == index;
},
[this, index, handler_id](
[[maybe_unused]] const std::vector<uint8_t>& report) {
hidpp::DeviceConnectionEvent event{};
event.withPayload = false;
event.linkEstablished = true;
event.index = index;
event.fromTimeoutCheck = true;
{[index](const std::vector<uint8_t>& report) -> bool {
return report[Offset::DeviceIndex] == index;
},
[this, index, handler_id]([[maybe_unused]] const std::vector<uint8_t>& report) {
hidpp::DeviceConnectionEvent event{};
event.withPayload = false;
event.linkEstablished = true;
event.index = index;
event.fromTimeoutCheck = true;
spawn_task([this, event, handler_id]() {
assert(handler_id);
try {
_receiver->rawDevice()->removeEventHandler(*handler_id);
addDevice(event);
} catch (std::exception& e) {
logPrintf(ERROR, "Failed to add device %d to receiver on %s: %s",
event.index, _receiver->rawDevice()->rawPath().c_str(),
e.what());
}
});
}
spawn_task([this, event, handler_id]() {
assert(handler_id);
try {
_receiver->rawDevice()->removeEventHandler(*handler_id);
addDevice(event);
} catch (std::exception& e) {
logPrintf(ERROR, "Failed to add device %d to receiver on %s: %s",
event.index, _receiver->rawDevice()->rawPath().c_str(),
e.what());
}
});
}
});
}

View File

@ -57,7 +57,7 @@ namespace logid::backend::hidpp10 {
private:
std::shared_ptr<Receiver> _receiver;
std::optional<hidpp::Device::EvHandlerId> ev_handler;
std::optional<raw::RawDevice::EvHandlerId> ev_handler;
};
}