mirror of
https://github.com/PixlOne/logiops.git
synced 2025-07-14 13:22:33 +08:00
Remove DJ support requirement from receivers
Allows Logi Bolt receivers to be detected by logid but not yet used.
This commit is contained in:
parent
d13d1feb4b
commit
fc96bb7b40
@ -42,9 +42,8 @@ add_executable(logid
|
|||||||
backend/raw/DeviceMonitor.cpp
|
backend/raw/DeviceMonitor.cpp
|
||||||
backend/raw/RawDevice.cpp
|
backend/raw/RawDevice.cpp
|
||||||
backend/raw/IOMonitor.cpp
|
backend/raw/IOMonitor.cpp
|
||||||
backend/dj/Receiver.cpp
|
backend/hidpp10/Receiver.cpp
|
||||||
backend/dj/ReceiverMonitor.cpp
|
backend/hidpp10/ReceiverMonitor.cpp
|
||||||
backend/dj/Error.cpp
|
|
||||||
backend/hidpp/Device.cpp
|
backend/hidpp/Device.cpp
|
||||||
backend/hidpp/Report.cpp
|
backend/hidpp/Report.cpp
|
||||||
backend/hidpp10/Error.cpp
|
backend/hidpp10/Error.cpp
|
||||||
@ -64,7 +63,6 @@ add_executable(logid
|
|||||||
backend/hidpp20/features/ChangeHost.cpp
|
backend/hidpp20/features/ChangeHost.cpp
|
||||||
backend/hidpp20/features/WirelessDeviceStatus.cpp
|
backend/hidpp20/features/WirelessDeviceStatus.cpp
|
||||||
backend/hidpp20/features/ThumbWheel.cpp
|
backend/hidpp20/features/ThumbWheel.cpp
|
||||||
backend/dj/Report.cpp
|
|
||||||
util/task.cpp
|
util/task.cpp
|
||||||
util/ExceptionHandler.cpp)
|
util/ExceptionHandler.cpp)
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <DeviceManager.h>
|
#include <DeviceManager.h>
|
||||||
#include <backend/Error.h>
|
#include <backend/Error.h>
|
||||||
|
#include <backend/hidpp10/Error.h>
|
||||||
#include <util/log.h>
|
#include <util/log.h>
|
||||||
#include <ipcgull/function.h>
|
#include <ipcgull/function.h>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
@ -96,9 +97,8 @@ void DeviceManager::addDevice(std::string path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
hidpp::Device device(
|
hidpp::Device device(path, hidpp::DefaultDevice, _self.lock(),
|
||||||
path, hidpp::DefaultDevice, _self.lock(),
|
config()->io_timeout.value_or(defaults::io_timeout));
|
||||||
config()->io_timeout.value_or(defaults::io_timeout));
|
|
||||||
isReceiver = device.version() == std::make_tuple(1, 0);
|
isReceiver = device.version() == std::make_tuple(1, 0);
|
||||||
} catch (hidpp10::Error& e) {
|
} catch (hidpp10::Error& e) {
|
||||||
if (e.code() != hidpp10::Error::UnknownDevice)
|
if (e.code() != hidpp10::Error::UnknownDevice)
|
||||||
@ -146,14 +146,12 @@ void DeviceManager::addDevice(std::string path) {
|
|||||||
if (e.code() != hidpp10::Error::UnknownDevice)
|
if (e.code() != hidpp10::Error::UnknownDevice)
|
||||||
throw;
|
throw;
|
||||||
else
|
else
|
||||||
logPrintf(WARN,
|
logPrintf(WARN, "HID++ 1.0 error while trying to initialize %s: %s",
|
||||||
"HID++ 1.0 error while trying to initialize %s:"
|
path.c_str(), e.what());
|
||||||
"%s", path.c_str(), e.what());
|
|
||||||
} catch (hidpp::Device::InvalidDevice& e) { // Ignore
|
} catch (hidpp::Device::InvalidDevice& e) { // Ignore
|
||||||
} catch (std::system_error& e) {
|
} catch (std::system_error& e) {
|
||||||
// This error should have been thrown previously
|
// This error should have been thrown previously
|
||||||
logPrintf(WARN, "I/O error on %s: %s", path.c_str(),
|
logPrintf(WARN, "I/O error on %s: %s", path.c_str(), e.what());
|
||||||
e.what());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <Receiver.h>
|
#include <Receiver.h>
|
||||||
#include <DeviceManager.h>
|
#include <DeviceManager.h>
|
||||||
#include <backend/Error.h>
|
#include <backend/Error.h>
|
||||||
|
#include <backend/hidpp10/Error.h>
|
||||||
#include <util/log.h>
|
#include <util/log.h>
|
||||||
#include <ipc_defs.h>
|
#include <ipc_defs.h>
|
||||||
|
|
||||||
@ -61,8 +62,8 @@ std::shared_ptr<Receiver> Receiver::make(
|
|||||||
|
|
||||||
Receiver::Receiver(const std::string& path,
|
Receiver::Receiver(const std::string& path,
|
||||||
const std::shared_ptr<DeviceManager>& manager) :
|
const std::shared_ptr<DeviceManager>& manager) :
|
||||||
dj::ReceiverMonitor(path, manager,
|
hidpp10::ReceiverMonitor(path, manager,
|
||||||
manager->config()->io_timeout.value_or(
|
manager->config()->io_timeout.value_or(
|
||||||
defaults::io_timeout)),
|
defaults::io_timeout)),
|
||||||
_path(path), _manager(manager), _nickname(manager),
|
_path(path), _manager(manager), _nickname(manager),
|
||||||
_ipc_node(manager->receiversNode()->make_child(_nickname)),
|
_ipc_node(manager->receiversNode()->make_child(_nickname)),
|
||||||
@ -162,7 +163,7 @@ const std::string& Receiver::path() const {
|
|||||||
return _path;
|
return _path;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<dj::Receiver> Receiver::rawReceiver() {
|
std::shared_ptr<hidpp10::Receiver> Receiver::rawReceiver() {
|
||||||
return receiver();
|
return receiver();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <Device.h>
|
#include <Device.h>
|
||||||
#include <backend/dj/ReceiverMonitor.h>
|
#include <backend/hidpp10/ReceiverMonitor.h>
|
||||||
|
|
||||||
namespace logid {
|
namespace logid {
|
||||||
class ReceiverNickname {
|
class ReceiverNickname {
|
||||||
@ -41,7 +41,7 @@ namespace logid {
|
|||||||
const std::weak_ptr<DeviceManager> _manager;
|
const std::weak_ptr<DeviceManager> _manager;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Receiver : public backend::dj::ReceiverMonitor,
|
class Receiver : public backend::hidpp10::ReceiverMonitor,
|
||||||
public ipcgull::object {
|
public ipcgull::object {
|
||||||
public:
|
public:
|
||||||
typedef std::map<backend::hidpp::DeviceIndex, std::shared_ptr<Device>>
|
typedef std::map<backend::hidpp::DeviceIndex, std::shared_ptr<Device>>
|
||||||
@ -55,7 +55,7 @@ namespace logid {
|
|||||||
|
|
||||||
[[nodiscard]] const std::string& path() const;
|
[[nodiscard]] const std::string& path() const;
|
||||||
|
|
||||||
std::shared_ptr<backend::dj::Receiver> rawReceiver();
|
std::shared_ptr<backend::hidpp10::Receiver> rawReceiver();
|
||||||
|
|
||||||
[[nodiscard]] const DeviceList& devices() const;
|
[[nodiscard]] const DeviceList& devices() const;
|
||||||
|
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019-2023 PixlOne
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <backend/dj/Error.h>
|
|
||||||
|
|
||||||
using namespace logid::backend::dj;
|
|
||||||
|
|
||||||
Error::Error(uint8_t code) : _code(code) {
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* Error::what() const noexcept {
|
|
||||||
switch (_code) {
|
|
||||||
case Unknown:
|
|
||||||
return "Unknown";
|
|
||||||
case KeepAliveTimeout:
|
|
||||||
return "Keep-alive timeout";
|
|
||||||
default:
|
|
||||||
return "Reserved";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t Error::code() const noexcept {
|
|
||||||
return _code;
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019-2023 PixlOne
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LOGID_BACKEND_DJ_ERROR_H
|
|
||||||
#define LOGID_BACKEND_DJ_ERROR_H
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
namespace logid::backend::dj {
|
|
||||||
class Error : public std::exception {
|
|
||||||
public:
|
|
||||||
enum ErrorCode : uint8_t {
|
|
||||||
Unknown = 0x00,
|
|
||||||
KeepAliveTimeout = 0x01
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit Error(uint8_t code);
|
|
||||||
|
|
||||||
[[nodiscard]] const char* what() const noexcept override;
|
|
||||||
|
|
||||||
[[nodiscard]] uint8_t code() const noexcept;
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint8_t _code;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //LOGID_BACKEND_DJ_ERROR_H
|
|
@ -1,336 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019-2023 PixlOne
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <backend/dj/Receiver.h>
|
|
||||||
#include <cassert>
|
|
||||||
#include <backend/dj/Error.h>
|
|
||||||
|
|
||||||
using namespace logid::backend::dj;
|
|
||||||
using namespace logid::backend;
|
|
||||||
|
|
||||||
InvalidReceiver::InvalidReceiver(Reason reason) : _reason(reason) {
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* InvalidReceiver::what() const noexcept {
|
|
||||||
switch (_reason) {
|
|
||||||
case NoDJReports:
|
|
||||||
return "No DJ reports";
|
|
||||||
default:
|
|
||||||
return "Invalid receiver";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InvalidReceiver::Reason InvalidReceiver::code() const noexcept {
|
|
||||||
return _reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
Receiver::Receiver(std::string path,
|
|
||||||
const std::shared_ptr<raw::DeviceMonitor>& monitor,
|
|
||||||
double timeout) :
|
|
||||||
_raw_device(std::make_shared<raw::RawDevice>(std::move(path), monitor)),
|
|
||||||
_hidpp10_device(_raw_device, hidpp::DefaultDevice, timeout) {
|
|
||||||
if (!supportsDjReports(_raw_device->reportDescriptor()))
|
|
||||||
throw InvalidReceiver(InvalidReceiver::NoDJReports);
|
|
||||||
|
|
||||||
// Pass all HID++ events on DefaultDevice to handleHidppEvent
|
|
||||||
_raw_hidpp_handler = _raw_device->addEventHandler(
|
|
||||||
{
|
|
||||||
[](const std::vector<uint8_t>& report) -> bool {
|
|
||||||
return (report[hidpp::Offset::Type] ==
|
|
||||||
hidpp::Report::Type::Short ||
|
|
||||||
report[hidpp::Offset::Type] ==
|
|
||||||
hidpp::Report::Type::Long);
|
|
||||||
},
|
|
||||||
[this](const std::vector<uint8_t>& report) -> void {
|
|
||||||
hidpp::Report _report(report);
|
|
||||||
this->_handleHidppEvent(_report);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Pass all DJ events with device index to handleDjEvent
|
|
||||||
_raw_dj_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->_handleDjEvent(_report);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Receiver::~Receiver() {
|
|
||||||
_raw_device->removeEventHandler(_raw_dj_handler);
|
|
||||||
_raw_device->removeEventHandler(_raw_hidpp_handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Receiver::enumerateDj() {
|
|
||||||
_sendDjRequest(hidpp::DefaultDevice, GetPairedDevices, {});
|
|
||||||
}
|
|
||||||
|
|
||||||
Receiver::NotificationFlags Receiver::getHidppNotifications() {
|
|
||||||
auto response = _hidpp10_device.getRegister(EnableHidppNotifications, {},
|
|
||||||
hidpp::ReportType::Short);
|
|
||||||
|
|
||||||
NotificationFlags flags{};
|
|
||||||
flags.deviceBatteryStatus = response[0] & (1 << 4);
|
|
||||||
flags.receiverWirelessNotifications = response[1] & (1 << 0);
|
|
||||||
flags.receiverSoftwarePresent = response[1] & (1 << 3);
|
|
||||||
|
|
||||||
return flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Receiver::enableHidppNotifications(NotificationFlags flags) {
|
|
||||||
std::vector<uint8_t> request(3);
|
|
||||||
|
|
||||||
if (flags.deviceBatteryStatus)
|
|
||||||
request[0] |= (1 << 4);
|
|
||||||
if (flags.receiverWirelessNotifications)
|
|
||||||
request[1] |= 1;
|
|
||||||
if (flags.receiverSoftwarePresent)
|
|
||||||
request[1] |= (1 << 3);
|
|
||||||
|
|
||||||
_hidpp10_device.setRegister(EnableHidppNotifications, request,
|
|
||||||
hidpp::ReportType::Short);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Receiver::enumerateHidpp() {
|
|
||||||
/* This isn't in the documentation but this is how solaar does it
|
|
||||||
* All I know is that when (p0 & 2), devices are enumerated
|
|
||||||
*/
|
|
||||||
_hidpp10_device.setRegister(ConnectionState, {2},
|
|
||||||
hidpp::ReportType::Short);
|
|
||||||
}
|
|
||||||
|
|
||||||
///TODO: Investigate usage
|
|
||||||
uint8_t Receiver::getConnectionState(hidpp::DeviceIndex index) {
|
|
||||||
auto response = _hidpp10_device.getRegister(ConnectionState, {index},
|
|
||||||
hidpp::ReportType::Short);
|
|
||||||
|
|
||||||
return response[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
void Receiver::startPairing(uint8_t timeout) {
|
|
||||||
///TODO: Device number == Device index?
|
|
||||||
std::vector<uint8_t> request(3);
|
|
||||||
|
|
||||||
request[0] = 1;
|
|
||||||
request[1] = hidpp::DefaultDevice;
|
|
||||||
request[2] = timeout;
|
|
||||||
|
|
||||||
_hidpp10_device.setRegister(DevicePairing, request,
|
|
||||||
hidpp::ReportType::Short);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Receiver::stopPairing() {
|
|
||||||
///TODO: Device number == Device index?
|
|
||||||
std::vector<uint8_t> request(3);
|
|
||||||
|
|
||||||
request[0] = 2;
|
|
||||||
request[1] = hidpp::DefaultDevice;
|
|
||||||
|
|
||||||
_hidpp10_device.setRegister(DevicePairing, request,
|
|
||||||
hidpp::ReportType::Short);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Receiver::disconnect(hidpp::DeviceIndex index) {
|
|
||||||
///TODO: Device number == Device index?
|
|
||||||
std::vector<uint8_t> request(3);
|
|
||||||
|
|
||||||
request[0] = 3;
|
|
||||||
request[1] = index;
|
|
||||||
|
|
||||||
_hidpp10_device.setRegister(DevicePairing, request,
|
|
||||||
hidpp::ReportType::Short);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map<hidpp::DeviceIndex, uint8_t> Receiver::getDeviceActivity() {
|
|
||||||
auto response = _hidpp10_device.getRegister(DeviceActivity, {},
|
|
||||||
hidpp::ReportType::Long);
|
|
||||||
|
|
||||||
std::map<hidpp::DeviceIndex, uint8_t> device_activity;
|
|
||||||
for (uint8_t i = hidpp::WirelessDevice1; i <= hidpp::WirelessDevice6; i++)
|
|
||||||
device_activity[static_cast<hidpp::DeviceIndex>(i)] = response[i];
|
|
||||||
|
|
||||||
return device_activity;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Receiver::PairingInfo
|
|
||||||
Receiver::getPairingInfo(hidpp::DeviceIndex index) {
|
|
||||||
std::vector<uint8_t> request(1);
|
|
||||||
request[0] = index;
|
|
||||||
request[0] += 0x1f;
|
|
||||||
|
|
||||||
auto response = _hidpp10_device.getRegister(PairingInfo, request,
|
|
||||||
hidpp::ReportType::Long);
|
|
||||||
|
|
||||||
struct PairingInfo info{};
|
|
||||||
info.destinationId = response[1];
|
|
||||||
info.reportInterval = response[2];
|
|
||||||
info.pid = response[4];
|
|
||||||
info.pid |= (response[3] << 8);
|
|
||||||
info.deviceType = static_cast<DeviceType::DeviceType>(response[7]);
|
|
||||||
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Receiver::ExtendedPairingInfo
|
|
||||||
Receiver::getExtendedPairingInfo(hidpp::DeviceIndex index) {
|
|
||||||
std::vector<uint8_t> request(1);
|
|
||||||
request[0] = index;
|
|
||||||
request[0] += 0x2f;
|
|
||||||
|
|
||||||
auto response = _hidpp10_device.getRegister(PairingInfo, request,
|
|
||||||
hidpp::ReportType::Long);
|
|
||||||
|
|
||||||
ExtendedPairingInfo info{};
|
|
||||||
|
|
||||||
info.serialNumber = 0;
|
|
||||||
for (uint8_t i = 0; i < 4; i++)
|
|
||||||
info.serialNumber |= (response[i + 1] << 8 * i);
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 4; i++)
|
|
||||||
info.reportTypes[i] = response[i + 5];
|
|
||||||
|
|
||||||
uint8_t psl = response[8] & 0xf;
|
|
||||||
if (psl > 0xc)
|
|
||||||
info.powerSwitchLocation = PowerSwitchLocation::Reserved;
|
|
||||||
else
|
|
||||||
info.powerSwitchLocation = static_cast<PowerSwitchLocation>(psl);
|
|
||||||
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Receiver::getDeviceName(hidpp::DeviceIndex index) {
|
|
||||||
std::vector<uint8_t> request(1);
|
|
||||||
request[0] = index;
|
|
||||||
request[0] += 0x3f;
|
|
||||||
|
|
||||||
auto response = _hidpp10_device.getRegister(PairingInfo, request,
|
|
||||||
hidpp::ReportType::Long);
|
|
||||||
|
|
||||||
uint8_t size = response[1];
|
|
||||||
assert(size <= 14);
|
|
||||||
|
|
||||||
std::string name(size, ' ');
|
|
||||||
for (std::size_t i = 0; i < size; i++)
|
|
||||||
name[i] = (char) (response[i + 2]);
|
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
hidpp::DeviceIndex Receiver::deviceDisconnectionEvent(const hidpp::Report&
|
|
||||||
report) {
|
|
||||||
assert(report.subId() == DeviceDisconnection);
|
|
||||||
return report.deviceIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
hidpp::DeviceConnectionEvent Receiver::deviceConnectionEvent(const
|
|
||||||
hidpp::Report& report) {
|
|
||||||
assert(report.subId() == DeviceConnection);
|
|
||||||
|
|
||||||
hidpp::DeviceConnectionEvent event{};
|
|
||||||
|
|
||||||
event.index = report.deviceIndex();
|
|
||||||
event.unifying = ((report.address() & 0b111) == 0x04);
|
|
||||||
|
|
||||||
event.deviceType = static_cast<DeviceType::DeviceType>(
|
|
||||||
report.paramBegin()[0] & 0x0f);
|
|
||||||
event.softwarePresent = report.paramBegin()[0] & (1 << 4);
|
|
||||||
event.encrypted = report.paramBegin()[0] & (1 << 5);
|
|
||||||
event.linkEstablished = !(report.paramBegin()[0] & (1 << 6));
|
|
||||||
event.withPayload = report.paramBegin()[0] & (1 << 7);
|
|
||||||
event.fromTimeoutCheck = false;
|
|
||||||
|
|
||||||
event.pid = (report.paramBegin()[2] << 8);
|
|
||||||
event.pid |= report.paramBegin()[1];
|
|
||||||
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Receiver::_handleDjEvent(Report& report) {
|
|
||||||
for (auto& handler: _dj_event_handlers)
|
|
||||||
if (handler.second->condition(report))
|
|
||||||
handler.second->callback(report);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Receiver::_handleHidppEvent(hidpp::Report& report) {
|
|
||||||
for (auto& handler: _hidpp_event_handlers)
|
|
||||||
if (handler.second->condition(report))
|
|
||||||
handler.second->callback(report);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Receiver::addDjEventHandler(const std::string& nickname,
|
|
||||||
const std::shared_ptr<EventHandler>& handler) {
|
|
||||||
assert(_dj_event_handlers.find(nickname) == _dj_event_handlers.end());
|
|
||||||
_dj_event_handlers.emplace(nickname, handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Receiver::removeDjEventHandler(const std::string& nickname) {
|
|
||||||
_dj_event_handlers.erase(nickname);
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::map<std::string, std::shared_ptr<EventHandler>>&
|
|
||||||
Receiver::djEventHandlers() {
|
|
||||||
return _dj_event_handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Receiver::addHidppEventHandler(const std::string& nickname,
|
|
||||||
const std::shared_ptr<hidpp::EventHandler>& handler) {
|
|
||||||
assert(_hidpp_event_handlers.find(nickname) == _hidpp_event_handlers.end());
|
|
||||||
_hidpp_event_handlers.emplace(nickname, handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Receiver::removeHidppEventHandler(const std::string& nickname) {
|
|
||||||
_hidpp_event_handlers.erase(nickname);
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::map<std::string, std::shared_ptr<hidpp::EventHandler>>&
|
|
||||||
Receiver::hidppEventHandlers() {
|
|
||||||
return _hidpp_event_handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Receiver::_sendDjRequest(hidpp::DeviceIndex index, uint8_t function,
|
|
||||||
const std::vector<uint8_t>&& params) {
|
|
||||||
assert(params.size() <= LongParamLength);
|
|
||||||
|
|
||||||
Report::Type type = params.size() <= ShortParamLength ?
|
|
||||||
ReportType::Short : ReportType::Long;
|
|
||||||
|
|
||||||
Report request(type, index, function);
|
|
||||||
|
|
||||||
std::copy(params.begin(), params.end(), request.paramBegin());
|
|
||||||
|
|
||||||
_raw_device->sendReport(request.rawData());
|
|
||||||
}
|
|
||||||
|
|
||||||
Receiver::ConnectionStatusEvent Receiver::connectionStatusEvent(Report& report) {
|
|
||||||
assert(report.feature() == ConnectionStatus);
|
|
||||||
ConnectionStatusEvent event{};
|
|
||||||
event.index = report.index();
|
|
||||||
event.linkLost = report.paramBegin()[0];
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<raw::RawDevice> Receiver::rawDevice() const {
|
|
||||||
return _raw_device;
|
|
||||||
}
|
|
@ -1,127 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019-2023 PixlOne
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <backend/dj/Report.h>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <array>
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
using namespace logid::backend::dj;
|
|
||||||
using namespace logid::backend;
|
|
||||||
|
|
||||||
static const std::array<uint8_t, 34> DJReportDesc = {
|
|
||||||
0xA1, 0x01, // Collection (Application)
|
|
||||||
0x85, 0x20, // Report ID (32)
|
|
||||||
0x95, 0x0E, // Report Count (14)
|
|
||||||
0x75, 0x08, // Report Size (8)
|
|
||||||
0x15, 0x00, // Logical Minimum (0)
|
|
||||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
||||||
0x09, 0x41, // Usage (0x41)
|
|
||||||
0x81, 0x00, // Input (Data, Array, Absolute)
|
|
||||||
0x09, 0x41, // Usage (0x41)
|
|
||||||
0x91, 0x00, // Output (Data, Array, Absolute)
|
|
||||||
0x85, 0x21, // Report ID (33)
|
|
||||||
0x95, 0x1F, // Report Count (31)
|
|
||||||
0x09, 0x42, // Usage (0x42)
|
|
||||||
0x81, 0x00, // Input (Data, Array, Absolute)
|
|
||||||
0x09, 0x42, // Usage (0x42)
|
|
||||||
0x91, 0x00, // Output (Data, Array, Absolute)
|
|
||||||
0xC0 // End Collection
|
|
||||||
};
|
|
||||||
|
|
||||||
static const std::array<uint8_t, 39> DJReportDesc2 = {
|
|
||||||
0xA1, 0x01, // Collection (Application)
|
|
||||||
0x85, 0x20, // Report ID (32)
|
|
||||||
0x75, 0x08, // Report Size (8)
|
|
||||||
0x95, 0x0E, // Report Count (14)
|
|
||||||
0x15, 0x00, // Logical Minimum (0)
|
|
||||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
||||||
0x09, 0x41, // Usage (0x41)
|
|
||||||
0x81, 0x00, // Input (Data, Array, Absolute)
|
|
||||||
0x09, 0x41, // Usage (0x41)
|
|
||||||
0x91, 0x00, // Output (Data, Array, Absolute)
|
|
||||||
0x85, 0x21, // Report ID (33)
|
|
||||||
0x95, 0x1F, // Report Count (31)
|
|
||||||
0x15, 0x00, // Logical Minimum (0)
|
|
||||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
||||||
0x09, 0x42, // Usage (0x42)
|
|
||||||
0x81, 0x00, // Input (Data, Array, Absolute)
|
|
||||||
0x09, 0x42, // Usage (0x42)
|
|
||||||
0x91, 0x00, // Output (Data, Array, Absolute)
|
|
||||||
0xC0 // End Collection
|
|
||||||
};
|
|
||||||
|
|
||||||
bool dj::supportsDjReports(const std::vector<uint8_t>& report_desc) {
|
|
||||||
auto it = std::search(report_desc.begin(), report_desc.end(),
|
|
||||||
DJReportDesc.begin(), DJReportDesc.end());
|
|
||||||
if (it == report_desc.end())
|
|
||||||
it = std::search(report_desc.begin(), report_desc.end(),
|
|
||||||
DJReportDesc2.begin(), DJReportDesc2.end());
|
|
||||||
return it != report_desc.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
Report::Report(const std::vector<uint8_t>& data) : _data(data) {
|
|
||||||
switch (data[Offset::Type]) {
|
|
||||||
case ReportType::Short:
|
|
||||||
_data.resize(HeaderLength + ShortParamLength);
|
|
||||||
break;
|
|
||||||
case ReportType::Long:
|
|
||||||
_data.resize(HeaderLength + LongParamLength);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Report::Report(Report::Type type, hidpp::DeviceIndex index, uint8_t feature) {
|
|
||||||
switch (type) {
|
|
||||||
case ReportType::Short:
|
|
||||||
_data.resize(HeaderLength + ShortParamLength);
|
|
||||||
break;
|
|
||||||
case ReportType::Long:
|
|
||||||
_data.resize(HeaderLength + LongParamLength);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
_data[Offset::Type] = type;
|
|
||||||
_data[Offset::DeviceIndex] = index;
|
|
||||||
_data[Offset::Feature] = feature;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Report::Type Report::type() const {
|
|
||||||
return static_cast<Type>(_data[Offset::Type]);
|
|
||||||
}
|
|
||||||
|
|
||||||
hidpp::DeviceIndex Report::index() const {
|
|
||||||
return static_cast<hidpp::DeviceIndex>(_data[Offset::DeviceIndex]);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t Report::feature() const {
|
|
||||||
return _data[Offset::Feature];
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<uint8_t>::iterator Report::paramBegin() {
|
|
||||||
return _data.begin() + Offset::Parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<uint8_t>& Report::rawData() const {
|
|
||||||
return _data;
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019-2023 PixlOne
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LOGID_BACKEND_DJ_REPORT_H
|
|
||||||
#define LOGID_BACKEND_DJ_REPORT_H
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <vector>
|
|
||||||
#include <backend/dj/defs.h>
|
|
||||||
#include <backend/hidpp/defs.h>
|
|
||||||
|
|
||||||
namespace logid::backend::dj {
|
|
||||||
namespace Offset {
|
|
||||||
static constexpr uint8_t Type = 0;
|
|
||||||
static constexpr uint8_t DeviceIndex = 1;
|
|
||||||
static constexpr uint8_t Feature = 2;
|
|
||||||
static constexpr uint8_t Parameters = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool supportsDjReports(const std::vector<uint8_t>& report_desc);
|
|
||||||
|
|
||||||
class Report {
|
|
||||||
public:
|
|
||||||
typedef ReportType::ReportType Type;
|
|
||||||
|
|
||||||
explicit Report(const std::vector<uint8_t>& data);
|
|
||||||
|
|
||||||
Report(Type type, hidpp::DeviceIndex index, uint8_t feature);
|
|
||||||
|
|
||||||
[[nodiscard]] Type type() const;
|
|
||||||
|
|
||||||
[[nodiscard]] hidpp::DeviceIndex index() const;
|
|
||||||
|
|
||||||
[[nodiscard]] uint8_t feature() const;
|
|
||||||
|
|
||||||
std::vector<uint8_t>::iterator paramBegin();
|
|
||||||
|
|
||||||
[[nodiscard]] const std::vector<uint8_t>& rawData() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<uint8_t> _data;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //LOGID_BACKEND_DJ_REPORT_H
|
|
@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019-2023 PixlOne
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LOGID_BACKEND_DJ_DEFS_H
|
|
||||||
#define LOGID_BACKEND_DJ_DEFS_H
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace logid::backend::dj {
|
|
||||||
namespace ReportType {
|
|
||||||
enum ReportType : uint8_t {
|
|
||||||
Short = 0x20,
|
|
||||||
Long = 0x21
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace DeviceType {
|
|
||||||
enum DeviceType : uint8_t {
|
|
||||||
Unknown = 0x00,
|
|
||||||
Keyboard = 0x01,
|
|
||||||
Mouse = 0x02,
|
|
||||||
Numpad = 0x03,
|
|
||||||
Presenter = 0x04,
|
|
||||||
/* 0x05-0x07 is reserved */
|
|
||||||
Trackball = 0x08,
|
|
||||||
Touchpad = 0x09
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[maybe_unused]]
|
|
||||||
static constexpr uint8_t ErrorFeature = 0x7f;
|
|
||||||
|
|
||||||
static constexpr std::size_t HeaderLength = 3;
|
|
||||||
static constexpr std::size_t ShortParamLength = 12;
|
|
||||||
static constexpr std::size_t LongParamLength = 29;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //LOGID_BACKEND_DJ_DEFS_H
|
|
@ -20,8 +20,7 @@
|
|||||||
#include <backend/hidpp20/features/Root.h>
|
#include <backend/hidpp20/features/Root.h>
|
||||||
#include <backend/hidpp20/features/DeviceName.h>
|
#include <backend/hidpp20/features/DeviceName.h>
|
||||||
#include <backend/hidpp20/Feature.h>
|
#include <backend/hidpp20/Feature.h>
|
||||||
#include <backend/hidpp10/Error.h>
|
#include <backend/hidpp10/Receiver.h>
|
||||||
#include <backend/dj/Receiver.h>
|
|
||||||
#include <backend/Error.h>
|
#include <backend/Error.h>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -68,7 +67,7 @@ Device::Device(std::shared_ptr<raw::RawDevice> raw_device, DeviceIndex index,
|
|||||||
_init();
|
_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::Device(const std::shared_ptr<dj::Receiver>& receiver,
|
Device::Device(const std::shared_ptr<hidpp10::Receiver>& receiver,
|
||||||
hidpp::DeviceConnectionEvent event, double timeout) :
|
hidpp::DeviceConnectionEvent event, double timeout) :
|
||||||
io_timeout(duration_cast<milliseconds>(
|
io_timeout(duration_cast<milliseconds>(
|
||||||
duration<double, std::milli>(timeout))),
|
duration<double, std::milli>(timeout))),
|
||||||
@ -85,7 +84,7 @@ Device::Device(const std::shared_ptr<dj::Receiver>& receiver,
|
|||||||
_init();
|
_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::Device(const std::shared_ptr<dj::Receiver>& receiver,
|
Device::Device(const std::shared_ptr<hidpp10::Receiver>& receiver,
|
||||||
DeviceIndex index, double timeout) :
|
DeviceIndex index, double timeout) :
|
||||||
io_timeout(duration_cast<milliseconds>(
|
io_timeout(duration_cast<milliseconds>(
|
||||||
duration<double, std::milli>(timeout))),
|
duration<double, std::milli>(timeout))),
|
||||||
@ -130,8 +129,7 @@ void Device::_init() {
|
|||||||
}});
|
}});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto rsp = sendReport(
|
auto rsp = sendReport({ReportType::Short, _index,
|
||||||
{ReportType::Short, _index,
|
|
||||||
hidpp20::FeatureID::ROOT, hidpp20::Root::Ping,
|
hidpp20::FeatureID::ROOT, hidpp20::Root::Ping,
|
||||||
hidpp::softwareID});
|
hidpp::softwareID});
|
||||||
if (rsp.deviceIndex() != _index) {
|
if (rsp.deviceIndex() != _index) {
|
||||||
@ -253,7 +251,7 @@ Report Device::sendReport(const Report& report) {
|
|||||||
if (std::holds_alternative<Report>(response)) {
|
if (std::holds_alternative<Report>(response)) {
|
||||||
return std::get<Report>(response);
|
return std::get<Report>(response);
|
||||||
} else if(std::holds_alternative<Report::Hidpp10Error>(response)) {
|
} else if(std::holds_alternative<Report::Hidpp10Error>(response)) {
|
||||||
throw hidpp20::Error(std::get<Report::Hidpp10Error>(response).error_code);
|
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);
|
throw hidpp20::Error(std::get<Report::Hidpp20Error>(response).error_code);
|
||||||
}
|
}
|
||||||
@ -289,6 +287,10 @@ bool Device::responseReport(const Report& report) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::shared_ptr<raw::RawDevice>& Device::rawDevice() const {
|
||||||
|
return _raw_device;
|
||||||
|
}
|
||||||
|
|
||||||
void Device::_sendReport(Report report) {
|
void Device::_sendReport(Report report) {
|
||||||
reportFixup(report);
|
reportFixup(report);
|
||||||
_raw_device->sendReport(report.rawReport());
|
_raw_device->sendReport(report.rawReport());
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include <backend/hidpp/Report.h>
|
#include <backend/hidpp/Report.h>
|
||||||
#include <backend/hidpp/defs.h>
|
#include <backend/hidpp/defs.h>
|
||||||
|
|
||||||
namespace logid::backend::dj {
|
namespace logid::backend::hidpp10 {
|
||||||
// Need to define here for a constructor
|
// Need to define here for a constructor
|
||||||
class Receiver;
|
class Receiver;
|
||||||
}
|
}
|
||||||
@ -70,10 +70,10 @@ namespace logid::backend::hidpp {
|
|||||||
Device(std::shared_ptr<raw::RawDevice> raw_device, DeviceIndex index,
|
Device(std::shared_ptr<raw::RawDevice> raw_device, DeviceIndex index,
|
||||||
double timeout);
|
double timeout);
|
||||||
|
|
||||||
Device(const std::shared_ptr<dj::Receiver>& receiver,
|
Device(const std::shared_ptr<hidpp10::Receiver>& receiver,
|
||||||
hidpp::DeviceConnectionEvent event, double timeout);
|
hidpp::DeviceConnectionEvent event, double timeout);
|
||||||
|
|
||||||
Device(const std::shared_ptr<dj::Receiver>& receiver,
|
Device(const std::shared_ptr<hidpp10::Receiver>& receiver,
|
||||||
DeviceIndex index, double timeout);
|
DeviceIndex index, double timeout);
|
||||||
|
|
||||||
virtual ~Device();
|
virtual ~Device();
|
||||||
@ -98,6 +98,8 @@ namespace logid::backend::hidpp {
|
|||||||
|
|
||||||
void handleEvent(Report& report);
|
void handleEvent(Report& report);
|
||||||
|
|
||||||
|
[[nodiscard]] const std::shared_ptr<raw::RawDevice>& rawDevice() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Returns whether the report is a response
|
// Returns whether the report is a response
|
||||||
virtual bool responseReport(const Report& report);
|
virtual bool responseReport(const Report& report);
|
||||||
@ -116,7 +118,7 @@ namespace logid::backend::hidpp {
|
|||||||
|
|
||||||
std::shared_ptr<raw::RawDevice> _raw_device;
|
std::shared_ptr<raw::RawDevice> _raw_device;
|
||||||
raw::RawDevice::EvHandlerId _raw_handler;
|
raw::RawDevice::EvHandlerId _raw_handler;
|
||||||
std::shared_ptr<dj::Receiver> _receiver;
|
std::shared_ptr<hidpp10::Receiver> _receiver;
|
||||||
std::string _path;
|
std::string _path;
|
||||||
DeviceIndex _index;
|
DeviceIndex _index;
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ Device::Device(std::shared_ptr<raw::RawDevice> raw_dev, hidpp::DeviceIndex index
|
|||||||
assert(version() == std::make_tuple(1, 0));
|
assert(version() == std::make_tuple(1, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::Device(const std::shared_ptr<dj::Receiver>& receiver,
|
Device::Device(const std::shared_ptr<hidpp10::Receiver>& receiver,
|
||||||
hidpp::DeviceIndex index,
|
hidpp::DeviceIndex index,
|
||||||
double timeout)
|
double timeout)
|
||||||
: hidpp::Device(receiver, index, timeout) {
|
: hidpp::Device(receiver, index, timeout) {
|
||||||
|
@ -34,7 +34,7 @@ namespace logid::backend::hidpp10 {
|
|||||||
Device(std::shared_ptr<raw::RawDevice> raw_dev,
|
Device(std::shared_ptr<raw::RawDevice> raw_dev,
|
||||||
hidpp::DeviceIndex index, double timeout);
|
hidpp::DeviceIndex index, double timeout);
|
||||||
|
|
||||||
Device(const std::shared_ptr<dj::Receiver>& receiver,
|
Device(const std::shared_ptr<hidpp10::Receiver>& receiver,
|
||||||
hidpp::DeviceIndex index, double timeout);
|
hidpp::DeviceIndex index, double timeout);
|
||||||
|
|
||||||
hidpp::Report sendReport(const hidpp::Report& report) final;
|
hidpp::Report sendReport(const hidpp::Report& report) final;
|
||||||
|
203
src/logid/backend/hidpp10/Receiver.cpp
Normal file
203
src/logid/backend/hidpp10/Receiver.cpp
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2023 PixlOne
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <backend/hidpp10/Receiver.h>
|
||||||
|
#include <backend/hidpp10/Error.h>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
using namespace logid::backend::hidpp10;
|
||||||
|
using namespace logid::backend;
|
||||||
|
|
||||||
|
const char* InvalidReceiver::what() const noexcept {
|
||||||
|
return "Not a receiver";
|
||||||
|
}
|
||||||
|
|
||||||
|
Receiver::Receiver(const std::string& path, const std::shared_ptr<raw::DeviceMonitor>& monitor,
|
||||||
|
double timeout) : Device(path, hidpp::DefaultDevice, monitor, timeout) {
|
||||||
|
// Check if the device is a receiver
|
||||||
|
try {
|
||||||
|
getNotificationFlags();
|
||||||
|
} catch(hidpp10::Error& e) {
|
||||||
|
if (e.code() == Error::InvalidAddress)
|
||||||
|
throw InvalidReceiver();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Receiver::NotificationFlags Receiver::getNotificationFlags() {
|
||||||
|
auto response = getRegister(EnableHidppNotifications, {}, hidpp::ReportType::Short);
|
||||||
|
|
||||||
|
NotificationFlags flags{};
|
||||||
|
flags.deviceBatteryStatus = response[0] & (1 << 4);
|
||||||
|
flags.receiverWirelessNotifications = response[1] & (1 << 0);
|
||||||
|
flags.receiverSoftwarePresent = response[1] & (1 << 3);
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Receiver::setNotifications(NotificationFlags flags) {
|
||||||
|
std::vector<uint8_t> request(3);
|
||||||
|
|
||||||
|
if (flags.deviceBatteryStatus)
|
||||||
|
request[0] |= (1 << 4);
|
||||||
|
if (flags.receiverWirelessNotifications)
|
||||||
|
request[1] |= 1;
|
||||||
|
if (flags.receiverSoftwarePresent)
|
||||||
|
request[1] |= (1 << 3);
|
||||||
|
|
||||||
|
setRegister(EnableHidppNotifications, request, hidpp::ReportType::Short);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Receiver::enumerate() {
|
||||||
|
setRegister(ConnectionState, {2}, hidpp::ReportType::Short);
|
||||||
|
}
|
||||||
|
|
||||||
|
///TODO: Investigate usage
|
||||||
|
uint8_t Receiver::getConnectionState(hidpp::DeviceIndex index) {
|
||||||
|
auto response = getRegister(ConnectionState, {index}, hidpp::ReportType::Short);
|
||||||
|
|
||||||
|
return response[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Receiver::startPairing(uint8_t timeout) {
|
||||||
|
///TODO: Device number == Device index?
|
||||||
|
std::vector<uint8_t> request(3);
|
||||||
|
|
||||||
|
request[0] = 1;
|
||||||
|
request[1] = hidpp::DefaultDevice;
|
||||||
|
request[2] = timeout;
|
||||||
|
|
||||||
|
setRegister(DevicePairing, request, hidpp::ReportType::Short);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Receiver::stopPairing() {
|
||||||
|
///TODO: Device number == Device index?
|
||||||
|
std::vector<uint8_t> request(3);
|
||||||
|
|
||||||
|
request[0] = 2;
|
||||||
|
request[1] = hidpp::DefaultDevice;
|
||||||
|
|
||||||
|
setRegister(DevicePairing, request, hidpp::ReportType::Short);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Receiver::disconnect(hidpp::DeviceIndex index) {
|
||||||
|
///TODO: Device number == Device index?
|
||||||
|
std::vector<uint8_t> request(3);
|
||||||
|
|
||||||
|
request[0] = 3;
|
||||||
|
request[1] = index;
|
||||||
|
|
||||||
|
setRegister(DevicePairing, request, hidpp::ReportType::Short);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<hidpp::DeviceIndex, uint8_t> Receiver::getDeviceActivity() {
|
||||||
|
auto response = getRegister(DeviceActivity, {}, hidpp::ReportType::Long);
|
||||||
|
|
||||||
|
std::map<hidpp::DeviceIndex, uint8_t> device_activity;
|
||||||
|
for (uint8_t i = hidpp::WirelessDevice1; i <= hidpp::WirelessDevice6; i++)
|
||||||
|
device_activity[static_cast<hidpp::DeviceIndex>(i)] = response[i];
|
||||||
|
|
||||||
|
return device_activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Receiver::PairingInfo
|
||||||
|
Receiver::getPairingInfo(hidpp::DeviceIndex index) {
|
||||||
|
std::vector<uint8_t> request(1);
|
||||||
|
request[0] = index;
|
||||||
|
request[0] += 0x1f;
|
||||||
|
|
||||||
|
auto response = getRegister(PairingInfo, request, hidpp::ReportType::Long);
|
||||||
|
|
||||||
|
struct PairingInfo info{};
|
||||||
|
info.destinationId = response[1];
|
||||||
|
info.reportInterval = response[2];
|
||||||
|
info.pid = response[4];
|
||||||
|
info.pid |= (response[3] << 8);
|
||||||
|
info.deviceType = static_cast<hidpp::DeviceType>(response[7]);
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Receiver::ExtendedPairingInfo
|
||||||
|
Receiver::getExtendedPairingInfo(hidpp::DeviceIndex index) {
|
||||||
|
std::vector<uint8_t> request(1);
|
||||||
|
request[0] = index;
|
||||||
|
request[0] += 0x2f;
|
||||||
|
|
||||||
|
auto response = getRegister(PairingInfo, request, hidpp::ReportType::Long);
|
||||||
|
|
||||||
|
ExtendedPairingInfo info{};
|
||||||
|
|
||||||
|
info.serialNumber = 0;
|
||||||
|
for (uint8_t i = 0; i < 4; i++)
|
||||||
|
info.serialNumber |= (response[i + 1] << 8 * i);
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 4; i++)
|
||||||
|
info.reportTypes[i] = response[i + 5];
|
||||||
|
|
||||||
|
uint8_t psl = response[8] & 0xf;
|
||||||
|
if (psl > 0xc)
|
||||||
|
info.powerSwitchLocation = PowerSwitchLocation::Reserved;
|
||||||
|
else
|
||||||
|
info.powerSwitchLocation = static_cast<PowerSwitchLocation>(psl);
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Receiver::getDeviceName(hidpp::DeviceIndex index) {
|
||||||
|
std::vector<uint8_t> request(1);
|
||||||
|
request[0] = index;
|
||||||
|
request[0] += 0x3f;
|
||||||
|
|
||||||
|
auto response = getRegister(PairingInfo, request, hidpp::ReportType::Long);
|
||||||
|
|
||||||
|
uint8_t size = response[1];
|
||||||
|
assert(size <= 14);
|
||||||
|
|
||||||
|
std::string name(size, ' ');
|
||||||
|
for (std::size_t i = 0; i < size; i++)
|
||||||
|
name[i] = (char) (response[i + 2]);
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
hidpp::DeviceIndex Receiver::deviceDisconnectionEvent(const hidpp::Report&
|
||||||
|
report) {
|
||||||
|
assert(report.subId() == DeviceDisconnection);
|
||||||
|
return report.deviceIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
hidpp::DeviceConnectionEvent Receiver::deviceConnectionEvent(const hidpp::Report& report) {
|
||||||
|
assert(report.subId() == DeviceConnection);
|
||||||
|
|
||||||
|
hidpp::DeviceConnectionEvent event{};
|
||||||
|
|
||||||
|
event.index = report.deviceIndex();
|
||||||
|
event.unifying = ((report.address() & 0b111) == 0x04);
|
||||||
|
|
||||||
|
event.deviceType = static_cast<hidpp::DeviceType>(report.paramBegin()[0] & 0x0f);
|
||||||
|
event.softwarePresent = report.paramBegin()[0] & (1 << 4);
|
||||||
|
event.encrypted = report.paramBegin()[0] & (1 << 5);
|
||||||
|
event.linkEstablished = !(report.paramBegin()[0] & (1 << 6));
|
||||||
|
event.withPayload = report.paramBegin()[0] & (1 << 7);
|
||||||
|
event.fromTimeoutCheck = false;
|
||||||
|
|
||||||
|
event.pid = (report.paramBegin()[2] << 8);
|
||||||
|
event.pid |= report.paramBegin()[1];
|
||||||
|
|
||||||
|
return event;
|
||||||
|
}
|
@ -20,75 +20,59 @@
|
|||||||
#define LOGID_BACKEND_DJ_RECEIVER_H
|
#define LOGID_BACKEND_DJ_RECEIVER_H
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <backend/raw/RawDevice.h>
|
|
||||||
#include <backend/dj/Report.h>
|
|
||||||
#include <backend/hidpp/Report.h>
|
|
||||||
#include <backend/hidpp10/Device.h>
|
#include <backend/hidpp10/Device.h>
|
||||||
|
|
||||||
namespace logid::backend::dj {
|
namespace logid::backend::hidpp {
|
||||||
struct EventHandler {
|
enum DeviceType : uint8_t {
|
||||||
std::function<bool(const Report&)> condition;
|
DeviceUnknown = 0x00,
|
||||||
std::function<void(const Report&)> callback;
|
DeviceKeyboard = 0x01,
|
||||||
|
DeviceMouse = 0x02,
|
||||||
|
DeviceNumpad = 0x03,
|
||||||
|
DevicePresenter = 0x04,
|
||||||
|
/* 0x05-0x07 is reserved */
|
||||||
|
DeviceTrackball = 0x08,
|
||||||
|
DeviceTouchpad = 0x09
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DeviceConnectionEvent {
|
||||||
|
DeviceIndex index;
|
||||||
|
uint16_t pid{};
|
||||||
|
DeviceType deviceType = DeviceUnknown;
|
||||||
|
bool unifying{};
|
||||||
|
bool softwarePresent{};
|
||||||
|
bool encrypted{};
|
||||||
|
bool linkEstablished{};
|
||||||
|
bool withPayload{};
|
||||||
|
bool fromTimeoutCheck = false; // Fake field
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace logid::backend::hidpp10 {
|
||||||
|
|
||||||
class InvalidReceiver : public std::exception {
|
class InvalidReceiver : public std::exception {
|
||||||
public:
|
public:
|
||||||
enum Reason {
|
|
||||||
NoDJReports
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit InvalidReceiver(Reason reason);
|
|
||||||
|
|
||||||
[[nodiscard]] const char* what() const noexcept override;
|
[[nodiscard]] const char* what() const noexcept override;
|
||||||
|
|
||||||
[[nodiscard]] Reason code() const noexcept;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Reason _reason;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Receiver final {
|
class Receiver : public Device {
|
||||||
public:
|
public:
|
||||||
Receiver(std::string path,
|
Receiver(const std::string& path,
|
||||||
const std::shared_ptr<raw::DeviceMonitor>& monitor,
|
const std::shared_ptr<raw::DeviceMonitor>& monitor,
|
||||||
double timeout);
|
double timeout);
|
||||||
|
|
||||||
~Receiver();
|
|
||||||
|
|
||||||
enum DjEvents : uint8_t {
|
|
||||||
DeviceDisconnection = 0x40,
|
|
||||||
DeviceConnection = 0x41,
|
|
||||||
ConnectionStatus = 0x42
|
|
||||||
};
|
|
||||||
|
|
||||||
enum DjCommands : uint8_t {
|
|
||||||
/* Kernel driver should handle this */
|
|
||||||
SwitchAndKeepAlive [[maybe_unused]] = 0x80,
|
|
||||||
GetPairedDevices = 0x81
|
|
||||||
};
|
|
||||||
|
|
||||||
void enumerateDj();
|
|
||||||
|
|
||||||
struct ConnectionStatusEvent {
|
|
||||||
hidpp::DeviceIndex index;
|
|
||||||
bool linkLost;
|
|
||||||
};
|
|
||||||
|
|
||||||
ConnectionStatusEvent connectionStatusEvent(dj::Report& report);
|
|
||||||
|
|
||||||
/* The following functions deal with HID++ 1.0 features.
|
/* The following functions deal with HID++ 1.0 features.
|
||||||
* While these are not technically DJ functions, it is redundant
|
* While these are not technically DJ functions, it is redundant
|
||||||
* to have a separate hidpp10::Receiver class for these functions.
|
* to have a separate hidpp10::Receiver class for these functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum HidppEvents : uint8_t {
|
enum Events : uint8_t {
|
||||||
// These events are identical to their DJ counterparts
|
// These events are identical to their DJ counterparts
|
||||||
// DeviceDisconnection = 0x40,
|
DeviceDisconnection = 0x40,
|
||||||
// DeviceConnection = 0x41,
|
DeviceConnection = 0x41,
|
||||||
LockingChange = 0x4a
|
LockingChange = 0x4a
|
||||||
};
|
};
|
||||||
|
|
||||||
enum HidppRegisters : uint8_t {
|
enum Registers : uint8_t {
|
||||||
EnableHidppNotifications = 0x00,
|
EnableHidppNotifications = 0x00,
|
||||||
ConnectionState = 0x02,
|
ConnectionState = 0x02,
|
||||||
DevicePairing = 0xb2,
|
DevicePairing = 0xb2,
|
||||||
@ -102,11 +86,11 @@ namespace logid::backend::dj {
|
|||||||
bool receiverSoftwarePresent;
|
bool receiverSoftwarePresent;
|
||||||
};
|
};
|
||||||
|
|
||||||
NotificationFlags getHidppNotifications();
|
NotificationFlags getNotificationFlags();
|
||||||
|
|
||||||
void enableHidppNotifications(NotificationFlags flags);
|
void setNotifications(NotificationFlags flags);
|
||||||
|
|
||||||
void enumerateHidpp();
|
void enumerate();
|
||||||
|
|
||||||
uint8_t getConnectionState(hidpp::DeviceIndex index);
|
uint8_t getConnectionState(hidpp::DeviceIndex index);
|
||||||
|
|
||||||
@ -122,7 +106,7 @@ namespace logid::backend::dj {
|
|||||||
uint8_t destinationId;
|
uint8_t destinationId;
|
||||||
uint8_t reportInterval;
|
uint8_t reportInterval;
|
||||||
uint16_t pid;
|
uint16_t pid;
|
||||||
DeviceType::DeviceType deviceType;
|
hidpp::DeviceType deviceType;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class PowerSwitchLocation : uint8_t {
|
enum class PowerSwitchLocation : uint8_t {
|
||||||
@ -149,67 +133,13 @@ namespace logid::backend::dj {
|
|||||||
|
|
||||||
struct PairingInfo getPairingInfo(hidpp::DeviceIndex index);
|
struct PairingInfo getPairingInfo(hidpp::DeviceIndex index);
|
||||||
|
|
||||||
struct ExtendedPairingInfo getExtendedPairingInfo(hidpp::DeviceIndex
|
struct ExtendedPairingInfo getExtendedPairingInfo(hidpp::DeviceIndex index);
|
||||||
index);
|
|
||||||
|
|
||||||
std::string getDeviceName(hidpp::DeviceIndex index);
|
std::string getDeviceName(hidpp::DeviceIndex index);
|
||||||
|
|
||||||
static hidpp::DeviceIndex deviceDisconnectionEvent(
|
static hidpp::DeviceIndex deviceDisconnectionEvent(const hidpp::Report& report);
|
||||||
const hidpp::Report& report);
|
|
||||||
|
|
||||||
static hidpp::DeviceConnectionEvent deviceConnectionEvent(
|
static hidpp::DeviceConnectionEvent deviceConnectionEvent(const hidpp::Report& report);
|
||||||
const hidpp::Report& report);
|
|
||||||
|
|
||||||
void addDjEventHandler(const std::string& nickname,
|
|
||||||
const std::shared_ptr<EventHandler>& handler);
|
|
||||||
|
|
||||||
void removeDjEventHandler(const std::string& nickname);
|
|
||||||
|
|
||||||
const std::map<std::string, std::shared_ptr<EventHandler>>&
|
|
||||||
djEventHandlers();
|
|
||||||
|
|
||||||
void addHidppEventHandler(const std::string& nickname,
|
|
||||||
const std::shared_ptr<hidpp::EventHandler>& handler);
|
|
||||||
|
|
||||||
void removeHidppEventHandler(const std::string& nickname);
|
|
||||||
|
|
||||||
const std::map<std::string, std::shared_ptr<hidpp::EventHandler>>&
|
|
||||||
hidppEventHandlers();
|
|
||||||
|
|
||||||
[[nodiscard]] std::shared_ptr<raw::RawDevice> rawDevice() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void _sendDjRequest(hidpp::DeviceIndex index, uint8_t function,
|
|
||||||
const std::vector<uint8_t>&& params);
|
|
||||||
|
|
||||||
void _handleDjEvent(dj::Report& report);
|
|
||||||
|
|
||||||
void _handleHidppEvent(hidpp::Report& report);
|
|
||||||
|
|
||||||
raw::RawDevice::EvHandlerId _raw_hidpp_handler;
|
|
||||||
raw::RawDevice::EvHandlerId _raw_dj_handler;
|
|
||||||
|
|
||||||
std::map<std::string, std::shared_ptr<EventHandler>>
|
|
||||||
_dj_event_handlers;
|
|
||||||
std::map<std::string, std::shared_ptr<hidpp::EventHandler>>
|
|
||||||
_hidpp_event_handlers;
|
|
||||||
|
|
||||||
std::shared_ptr<raw::RawDevice> _raw_device;
|
|
||||||
hidpp10::Device _hidpp10_device;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace logid::backend::hidpp {
|
|
||||||
struct DeviceConnectionEvent {
|
|
||||||
hidpp::DeviceIndex index;
|
|
||||||
uint16_t pid{};
|
|
||||||
dj::DeviceType::DeviceType deviceType;
|
|
||||||
bool unifying{};
|
|
||||||
bool softwarePresent{};
|
|
||||||
bool encrypted{};
|
|
||||||
bool linkEstablished{};
|
|
||||||
bool withPayload{};
|
|
||||||
bool fromTimeoutCheck = false; // Fake field
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -16,43 +16,36 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <backend/dj/ReceiverMonitor.h>
|
#include <backend/hidpp10/ReceiverMonitor.h>
|
||||||
#include <utility>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <util/task.h>
|
#include <util/task.h>
|
||||||
#include <util/log.h>
|
#include <util/log.h>
|
||||||
|
|
||||||
using namespace logid::backend::dj;
|
using namespace logid::backend::hidpp10;
|
||||||
|
using namespace logid::backend::hidpp;
|
||||||
|
|
||||||
ReceiverMonitor::ReceiverMonitor(std::string path,
|
ReceiverMonitor::ReceiverMonitor(const std::string& path,
|
||||||
const std::shared_ptr<raw::DeviceMonitor>& monitor,
|
const std::shared_ptr<raw::DeviceMonitor>& monitor, double timeout)
|
||||||
double timeout) :
|
: _receiver(std::make_shared<Receiver>(path, monitor, timeout)) {
|
||||||
_receiver(std::make_shared<Receiver>(
|
|
||||||
std::move(path), monitor, timeout)) {
|
|
||||||
assert(!_receiver->hidppEventHandlers().contains(ev_handler_name));
|
|
||||||
assert(!_receiver->djEventHandlers().contains(ev_handler_name));
|
|
||||||
|
|
||||||
Receiver::NotificationFlags notification_flags{
|
Receiver::NotificationFlags notification_flags{true, true, true};
|
||||||
true,
|
_receiver->setNotifications(notification_flags);
|
||||||
true,
|
|
||||||
true};
|
|
||||||
_receiver->enableHidppNotifications(notification_flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReceiverMonitor::~ReceiverMonitor() {
|
ReceiverMonitor::~ReceiverMonitor() {
|
||||||
_receiver->removeHidppEventHandler(ev_handler_name);
|
if (ev_handler.has_value())
|
||||||
|
_receiver->removeEventHandler(ev_handler.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReceiverMonitor::ready() {
|
void ReceiverMonitor::ready() {
|
||||||
if (!_receiver->hidppEventHandlers().contains(ev_handler_name)) {
|
if (!ev_handler.has_value()) {
|
||||||
std::shared_ptr<hidpp::EventHandler> event_handler =
|
hidpp::EventHandler event_handler;
|
||||||
std::make_shared<hidpp::EventHandler>();
|
event_handler.condition = [](hidpp::Report& report) -> bool {
|
||||||
event_handler->condition = [](hidpp::Report& report) -> bool {
|
|
||||||
return (report.subId() == Receiver::DeviceConnection ||
|
return (report.subId() == Receiver::DeviceConnection ||
|
||||||
report.subId() == Receiver::DeviceDisconnection);
|
report.subId() == Receiver::DeviceDisconnection);
|
||||||
};
|
};
|
||||||
|
|
||||||
event_handler->callback = [this](hidpp::Report& report) -> void {
|
event_handler.callback = [this](hidpp::Report& report) -> void {
|
||||||
/* Running in a new thread prevents deadlocks since the
|
/* Running in a new thread prevents deadlocks since the
|
||||||
* receiver may be enumerating.
|
* receiver may be enumerating.
|
||||||
*/
|
*/
|
||||||
@ -80,14 +73,14 @@ void ReceiverMonitor::ready() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
_receiver->addHidppEventHandler(ev_handler_name, event_handler);
|
ev_handler = _receiver->addEventHandler(event_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
enumerate();
|
enumerate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReceiverMonitor::enumerate() {
|
void ReceiverMonitor::enumerate() {
|
||||||
_receiver->enumerateHidpp();
|
_receiver->enumerate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReceiverMonitor::waitForDevice(hidpp::DeviceIndex index) {
|
void ReceiverMonitor::waitForDevice(hidpp::DeviceIndex index) {
|
||||||
@ -96,8 +89,7 @@ void ReceiverMonitor::waitForDevice(hidpp::DeviceIndex index) {
|
|||||||
*handler_id = _receiver->rawDevice()->addEventHandler(
|
*handler_id = _receiver->rawDevice()->addEventHandler(
|
||||||
{
|
{
|
||||||
[index](const std::vector<uint8_t>& report) -> bool {
|
[index](const std::vector<uint8_t>& report) -> bool {
|
||||||
return report[Offset::DeviceIndex] ==
|
return report[Offset::DeviceIndex] == index;
|
||||||
index;
|
|
||||||
},
|
},
|
||||||
[this, index, handler_id](
|
[this, index, handler_id](
|
||||||
[[maybe_unused]] const std::vector<uint8_t>& report) {
|
[[maybe_unused]] const std::vector<uint8_t>& report) {
|
||||||
@ -107,25 +99,17 @@ void ReceiverMonitor::waitForDevice(hidpp::DeviceIndex index) {
|
|||||||
event.index = index;
|
event.index = index;
|
||||||
event.fromTimeoutCheck = true;
|
event.fromTimeoutCheck = true;
|
||||||
|
|
||||||
spawn_task(
|
spawn_task([this, event, handler_id]() {
|
||||||
[this, event, handler_id]() {
|
assert(handler_id);
|
||||||
assert(handler_id);
|
try {
|
||||||
try {
|
_receiver->rawDevice()->removeEventHandler(*handler_id);
|
||||||
_receiver->rawDevice()->removeEventHandler(
|
addDevice(event);
|
||||||
*handler_id);
|
} catch (std::exception& e) {
|
||||||
addDevice(
|
logPrintf(ERROR, "Failed to add device %d to receiver on %s: %s",
|
||||||
event);
|
event.index, _receiver->rawDevice()->rawPath().c_str(),
|
||||||
} catch (
|
e.what());
|
||||||
std::exception& e) {
|
}
|
||||||
logPrintf(
|
});
|
||||||
ERROR,
|
|
||||||
"Failed to add device %d to receiver "
|
|
||||||
"on %s: %s",
|
|
||||||
event.index,
|
|
||||||
_receiver->rawDevice()->rawPath().c_str(),
|
|
||||||
e.what());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
@ -19,16 +19,16 @@
|
|||||||
#ifndef LOGID_BACKEND_DJ_RECEIVERMONITOR_H
|
#ifndef LOGID_BACKEND_DJ_RECEIVERMONITOR_H
|
||||||
#define LOGID_BACKEND_DJ_RECEIVERMONITOR_H
|
#define LOGID_BACKEND_DJ_RECEIVERMONITOR_H
|
||||||
|
|
||||||
|
#include <backend/hidpp10/Receiver.h>
|
||||||
|
#include <backend/hidpp/defs.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <backend/dj/Receiver.h>
|
|
||||||
#include <backend/hidpp/defs.h>
|
|
||||||
|
|
||||||
namespace logid::backend::dj {
|
namespace logid::backend::hidpp10 {
|
||||||
// This class will run on the RawDevice thread,
|
// This class will run on the RawDevice thread,
|
||||||
class ReceiverMonitor {
|
class ReceiverMonitor {
|
||||||
public:
|
public:
|
||||||
ReceiverMonitor(std::string path,
|
ReceiverMonitor(const std::string& path,
|
||||||
const std::shared_ptr<raw::DeviceMonitor>& monitor,
|
const std::shared_ptr<raw::DeviceMonitor>& monitor,
|
||||||
double timeout);
|
double timeout);
|
||||||
|
|
||||||
@ -55,9 +55,9 @@ namespace logid::backend::dj {
|
|||||||
[[nodiscard]] std::shared_ptr<Receiver> receiver() const;
|
[[nodiscard]] std::shared_ptr<Receiver> receiver() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr const char* ev_handler_name = "receiver_monitor";
|
|
||||||
|
|
||||||
std::shared_ptr<Receiver> _receiver;
|
std::shared_ptr<Receiver> _receiver;
|
||||||
|
|
||||||
|
std::optional<hidpp::Device::EvHandlerId> ev_handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -19,7 +19,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <backend/hidpp20/Device.h>
|
#include <backend/hidpp20/Device.h>
|
||||||
#include <backend/Error.h>
|
#include <backend/Error.h>
|
||||||
#include <backend/dj/Receiver.h>
|
#include <backend/hidpp10/Receiver.h>
|
||||||
|
|
||||||
using namespace logid::backend;
|
using namespace logid::backend;
|
||||||
using namespace logid::backend::hidpp20;
|
using namespace logid::backend::hidpp20;
|
||||||
@ -39,14 +39,14 @@ Device::Device(std::shared_ptr<raw::RawDevice> raw_device,
|
|||||||
throw std::runtime_error("Invalid HID++ version");
|
throw std::runtime_error("Invalid HID++ version");
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::Device(const std::shared_ptr<dj::Receiver>& receiver,
|
Device::Device(const std::shared_ptr<hidpp10::Receiver>& receiver,
|
||||||
hidpp::DeviceConnectionEvent event, double timeout) :
|
hidpp::DeviceConnectionEvent event, double timeout) :
|
||||||
hidpp::Device(receiver, event, timeout) {
|
hidpp::Device(receiver, event, timeout) {
|
||||||
if (std::get<0>(version()) < 2)
|
if (std::get<0>(version()) < 2)
|
||||||
throw std::runtime_error("Invalid HID++ version");
|
throw std::runtime_error("Invalid HID++ version");
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::Device(const std::shared_ptr<dj::Receiver>& receiver,
|
Device::Device(const std::shared_ptr<hidpp10::Receiver>& receiver,
|
||||||
hidpp::DeviceIndex index, double timeout)
|
hidpp::DeviceIndex index, double timeout)
|
||||||
: hidpp::Device(receiver, index, timeout) {
|
: hidpp::Device(receiver, index, timeout) {
|
||||||
if (std::get<0>(version()) < 2)
|
if (std::get<0>(version()) < 2)
|
||||||
|
@ -34,10 +34,10 @@ namespace logid::backend::hidpp20 {
|
|||||||
Device(std::shared_ptr<raw::RawDevice> raw_device,
|
Device(std::shared_ptr<raw::RawDevice> raw_device,
|
||||||
hidpp::DeviceIndex index, double timeout);
|
hidpp::DeviceIndex index, double timeout);
|
||||||
|
|
||||||
Device(const std::shared_ptr<dj::Receiver>& receiver,
|
Device(const std::shared_ptr<hidpp10::Receiver>& receiver,
|
||||||
hidpp::DeviceConnectionEvent event, double timeout);
|
hidpp::DeviceConnectionEvent event, double timeout);
|
||||||
|
|
||||||
Device(const std::shared_ptr<dj::Receiver>& receiver,
|
Device(const std::shared_ptr<hidpp10::Receiver>& receiver,
|
||||||
hidpp::DeviceIndex index, double timeout);
|
hidpp::DeviceIndex index, double timeout);
|
||||||
|
|
||||||
std::vector<uint8_t> callFunction(uint8_t feature_index,
|
std::vector<uint8_t> callFunction(uint8_t feature_index,
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include <Device.h>
|
#include <Device.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include "ipc_defs.h"
|
#include <ipc_defs.h>
|
||||||
|
|
||||||
using namespace logid::features;
|
using namespace logid::features;
|
||||||
using namespace logid::backend;
|
using namespace logid::backend;
|
||||||
|
Loading…
Reference in New Issue
Block a user