mirror of
https://github.com/PixlOne/logiops.git
synced 2025-07-14 13:22:33 +08:00
Add Device and Receiver signals to DeviceManager
This commit is contained in:
parent
daa8c37c7d
commit
918ea63755
@ -1 +1 @@
|
|||||||
Subproject commit 89c6103af33705320494043da86c4709cc938b32
|
Subproject commit 0d53465fe70ab07e07f9f9d853413a6cc82704c6
|
@ -32,37 +32,106 @@
|
|||||||
using namespace logid;
|
using namespace logid;
|
||||||
using namespace logid::backend;
|
using namespace logid::backend;
|
||||||
|
|
||||||
|
DeviceNickname::DeviceNickname(const std::shared_ptr<DeviceManager>& manager) :
|
||||||
|
_nickname (manager->newDeviceNickname()), _manager (manager)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceNickname::operator std::string() const {
|
||||||
|
return std::to_string(_nickname);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceNickname::~DeviceNickname()
|
||||||
|
{
|
||||||
|
if(auto manager = _manager.lock()) {
|
||||||
|
std::lock_guard<std::mutex> lock(manager->_nick_lock);
|
||||||
|
manager->_device_nicknames.erase(_nickname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace logid {
|
||||||
|
class _Device : public Device {
|
||||||
|
public:
|
||||||
|
template <typename... Args>
|
||||||
|
_Device(Args... args) : Device(std::forward<Args>(args)...) { }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Device> Device::make(
|
||||||
|
std::string path, backend::hidpp::DeviceIndex index,
|
||||||
|
std::shared_ptr<DeviceManager> manager)
|
||||||
|
{
|
||||||
|
auto ret = std::make_shared<_Device>(std::move(path),
|
||||||
|
index,
|
||||||
|
std::move(manager));
|
||||||
|
ret->_self = ret;
|
||||||
|
ret->_ipc_node->manage(ret);
|
||||||
|
ret->_ipc_interface = ret->_ipc_node->make_interface<DeviceIPC>(ret.get());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Device> Device::make(
|
||||||
|
std::shared_ptr<backend::raw::RawDevice> raw_device,
|
||||||
|
backend::hidpp::DeviceIndex index,
|
||||||
|
std::shared_ptr<DeviceManager> manager)
|
||||||
|
{
|
||||||
|
auto ret = std::make_shared<_Device>(std::move(raw_device),
|
||||||
|
index,
|
||||||
|
std::move(manager));
|
||||||
|
ret->_self = ret;
|
||||||
|
ret->_ipc_node->manage(ret);
|
||||||
|
ret->_ipc_interface = ret->_ipc_node->make_interface<DeviceIPC>(ret.get());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Device> Device::make(
|
||||||
|
Receiver* receiver, backend::hidpp::DeviceIndex index,
|
||||||
|
std::shared_ptr<DeviceManager> manager)
|
||||||
|
{
|
||||||
|
auto ret = std::make_shared<_Device>(receiver, index, std::move(manager));
|
||||||
|
ret->_self = ret;
|
||||||
|
ret->_ipc_node->manage(ret);
|
||||||
|
ret->_ipc_interface = ret->_ipc_node->make_interface<DeviceIPC>(ret.get());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
Device::Device(std::string path, backend::hidpp::DeviceIndex index,
|
Device::Device(std::string path, backend::hidpp::DeviceIndex index,
|
||||||
const std::shared_ptr<DeviceManager>& manager) :
|
std::shared_ptr<DeviceManager> manager) :
|
||||||
_hidpp20 (path, index,
|
_hidpp20 (path, index,
|
||||||
manager->config()->ioTimeout(), manager->workQueue()),
|
manager->config()->ioTimeout(), manager->workQueue()),
|
||||||
_path (std::move(path)), _index (index),
|
_path (std::move(path)), _index (index),
|
||||||
_config (manager->config(), this),
|
_config (manager->config(), this),
|
||||||
_receiver (nullptr),
|
_receiver (nullptr),
|
||||||
_manager (manager)
|
_manager (manager),
|
||||||
|
_nickname (manager),
|
||||||
|
_ipc_node(manager->devicesNode()->make_child(_nickname))
|
||||||
{
|
{
|
||||||
_init();
|
_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::Device(const std::shared_ptr<backend::raw::RawDevice>& raw_device,
|
Device::Device(std::shared_ptr<backend::raw::RawDevice> raw_device,
|
||||||
hidpp::DeviceIndex index,
|
hidpp::DeviceIndex index,
|
||||||
const std::shared_ptr<DeviceManager>& manager) :
|
std::shared_ptr<DeviceManager> manager) :
|
||||||
_hidpp20(raw_device, index),
|
_hidpp20(raw_device, index),
|
||||||
_path (raw_device->hidrawPath()), _index (index),
|
_path (raw_device->hidrawPath()), _index (index),
|
||||||
_config (manager->config(), this),
|
_config (manager->config(), this),
|
||||||
_receiver (nullptr),
|
_receiver (nullptr),
|
||||||
_manager (manager)
|
_manager (manager),
|
||||||
|
_nickname (manager),
|
||||||
|
_ipc_node (manager->devicesNode()->make_child(_nickname))
|
||||||
{
|
{
|
||||||
_init();
|
_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::Device(Receiver* receiver, hidpp::DeviceIndex index,
|
Device::Device(Receiver* receiver, hidpp::DeviceIndex index,
|
||||||
const std::shared_ptr<DeviceManager>& manager) :
|
std::shared_ptr<DeviceManager> manager) :
|
||||||
_hidpp20 (receiver->rawReceiver(), index),
|
_hidpp20 (receiver->rawReceiver(), index),
|
||||||
_path (receiver->path()), _index (index),
|
_path (receiver->path()), _index (index),
|
||||||
_config (manager->config(), this),
|
_config (manager->config(), this),
|
||||||
_receiver (receiver),
|
_receiver (receiver),
|
||||||
_manager (manager)
|
_manager (manager),
|
||||||
|
_nickname (manager),
|
||||||
|
_ipc_node (manager->devicesNode()->make_child(_nickname))
|
||||||
{
|
{
|
||||||
_init();
|
_init();
|
||||||
}
|
}
|
||||||
@ -173,6 +242,12 @@ void Device::_makeResetMechanism()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Device::DeviceIPC::DeviceIPC(Device* device) :
|
||||||
|
ipcgull::interface("pizza.pixl.LogiOps.Device", {}, {}, {})
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
DeviceConfig::DeviceConfig(const std::shared_ptr<Configuration>& config, Device*
|
DeviceConfig::DeviceConfig(const std::shared_ptr<Configuration>& config, Device*
|
||||||
device) : _device (device), _config (config)
|
device) : _device (device), _config (config)
|
||||||
{
|
{
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
#ifndef LOGID_DEVICE_H
|
#ifndef LOGID_DEVICE_H
|
||||||
#define LOGID_DEVICE_H
|
#define LOGID_DEVICE_H
|
||||||
|
|
||||||
|
#include <ipcgull/node.h>
|
||||||
|
#include <ipcgull/interface.h>
|
||||||
#include "backend/hidpp/defs.h"
|
#include "backend/hidpp/defs.h"
|
||||||
#include "backend/hidpp20/Device.h"
|
#include "backend/hidpp20/Device.h"
|
||||||
#include "features/DeviceFeature.h"
|
#include "features/DeviceFeature.h"
|
||||||
@ -32,6 +34,19 @@ namespace logid
|
|||||||
class Receiver;
|
class Receiver;
|
||||||
class InputDevice;
|
class InputDevice;
|
||||||
|
|
||||||
|
class DeviceNickname {
|
||||||
|
public:
|
||||||
|
explicit DeviceNickname(const std::shared_ptr<DeviceManager>& manager);
|
||||||
|
DeviceNickname() = delete;
|
||||||
|
DeviceNickname(const DeviceNickname&) = delete;
|
||||||
|
~DeviceNickname();
|
||||||
|
|
||||||
|
operator std::string() const;
|
||||||
|
private:
|
||||||
|
const int _nickname;
|
||||||
|
const std::weak_ptr<DeviceManager> _manager;
|
||||||
|
};
|
||||||
|
|
||||||
class DeviceConfig
|
class DeviceConfig
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -48,23 +63,28 @@ namespace logid
|
|||||||
* Currently, the logid::Device class has a hardcoded requirement
|
* Currently, the logid::Device class has a hardcoded requirement
|
||||||
* for an HID++ 2.0 device.
|
* for an HID++ 2.0 device.
|
||||||
*/
|
*/
|
||||||
class Device
|
class Device : public ipcgull::object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Device(std::string path, backend::hidpp::DeviceIndex index,
|
|
||||||
const std::shared_ptr<DeviceManager>& manager);
|
|
||||||
Device(const std::shared_ptr<backend::raw::RawDevice>& raw_device,
|
|
||||||
backend::hidpp::DeviceIndex index,
|
|
||||||
const std::shared_ptr<DeviceManager>& manager);
|
|
||||||
Device(Receiver* receiver, backend::hidpp::DeviceIndex index,
|
|
||||||
const std::shared_ptr<DeviceManager>& manager);
|
|
||||||
|
|
||||||
std::string name();
|
std::string name();
|
||||||
uint16_t pid();
|
uint16_t pid();
|
||||||
|
|
||||||
DeviceConfig& config();
|
DeviceConfig& config();
|
||||||
backend::hidpp20::Device& hidpp20();
|
backend::hidpp20::Device& hidpp20();
|
||||||
|
|
||||||
|
static std::shared_ptr<Device> make(
|
||||||
|
std::string path,
|
||||||
|
backend::hidpp::DeviceIndex index,
|
||||||
|
std::shared_ptr<DeviceManager> manager);
|
||||||
|
static std::shared_ptr<Device> make(
|
||||||
|
std::shared_ptr<backend::raw::RawDevice> raw_device,
|
||||||
|
backend::hidpp::DeviceIndex index,
|
||||||
|
std::shared_ptr<DeviceManager> manager);
|
||||||
|
static std::shared_ptr<Device> make(
|
||||||
|
Receiver* receiver,
|
||||||
|
backend::hidpp::DeviceIndex index,
|
||||||
|
std::shared_ptr<DeviceManager> manager);
|
||||||
|
|
||||||
void wakeup();
|
void wakeup();
|
||||||
void sleep();
|
void sleep();
|
||||||
|
|
||||||
@ -89,6 +109,15 @@ namespace logid
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class _Device;
|
||||||
|
Device(std::string path, backend::hidpp::DeviceIndex index,
|
||||||
|
std::shared_ptr<DeviceManager> manager);
|
||||||
|
Device(std::shared_ptr<backend::raw::RawDevice> raw_device,
|
||||||
|
backend::hidpp::DeviceIndex index,
|
||||||
|
std::shared_ptr<DeviceManager> manager);
|
||||||
|
Device(Receiver* receiver, backend::hidpp::DeviceIndex index,
|
||||||
|
std::shared_ptr<DeviceManager> manager);
|
||||||
|
|
||||||
void _init();
|
void _init();
|
||||||
|
|
||||||
/* Adds a feature without calling an error if unsupported */
|
/* Adds a feature without calling an error if unsupported */
|
||||||
@ -113,6 +142,18 @@ namespace logid
|
|||||||
|
|
||||||
void _makeResetMechanism();
|
void _makeResetMechanism();
|
||||||
std::unique_ptr<std::function<void()>> _reset_mechanism;
|
std::unique_ptr<std::function<void()>> _reset_mechanism;
|
||||||
|
|
||||||
|
const DeviceNickname _nickname;
|
||||||
|
std::shared_ptr<ipcgull::node> _ipc_node;
|
||||||
|
|
||||||
|
class DeviceIPC : public ipcgull::interface {
|
||||||
|
public:
|
||||||
|
DeviceIPC(Device* device);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<ipcgull::interface> _ipc_interface;
|
||||||
|
|
||||||
|
std::weak_ptr<Device> _self;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,18 +41,28 @@ namespace logid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DeviceManager::DeviceManager(std::shared_ptr<Configuration> config,
|
DeviceManager::DeviceManager(std::shared_ptr<Configuration> config,
|
||||||
std::shared_ptr<InputDevice> virtual_input) :
|
std::shared_ptr<InputDevice> virtual_input,
|
||||||
|
std::shared_ptr<ipcgull::server> server) :
|
||||||
backend::raw::DeviceMonitor(config->workerCount()),
|
backend::raw::DeviceMonitor(config->workerCount()),
|
||||||
_config (std::move(config)),
|
_server (std::move(server)), _config (std::move(config)),
|
||||||
_virtual_input (std::move(virtual_input))
|
_virtual_input (std::move(virtual_input)),
|
||||||
|
_root_node (ipcgull::node::make_root("")),
|
||||||
|
_device_node (ipcgull::node::make_root("devices")),
|
||||||
|
_receiver_node (ipcgull::node::make_root("receivers"))
|
||||||
{
|
{
|
||||||
|
_ipc_devices = _root_node->make_interface<DevicesIPC>();
|
||||||
|
_ipc_receivers = _root_node->make_interface<ReceiversIPC>();
|
||||||
|
_device_node->add_server(_server);
|
||||||
|
_receiver_node->add_server(_server);
|
||||||
|
_root_node->add_server(_server);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<DeviceManager> DeviceManager::make(
|
std::shared_ptr<DeviceManager> DeviceManager::make(
|
||||||
const std::shared_ptr<Configuration>& config,
|
const std::shared_ptr<Configuration>& config,
|
||||||
const std::shared_ptr<InputDevice>& virtual_input)
|
const std::shared_ptr<InputDevice>& virtual_input,
|
||||||
|
const std::shared_ptr<ipcgull::server>& server)
|
||||||
{
|
{
|
||||||
auto ret = std::make_shared<_DeviceManager>(config, virtual_input);
|
auto ret = std::make_shared<_DeviceManager>(config, virtual_input, server);
|
||||||
ret->_self = ret;
|
ret->_self = ret;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -67,6 +77,16 @@ std::shared_ptr<InputDevice> DeviceManager::virtualInput() const
|
|||||||
return _virtual_input;
|
return _virtual_input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const ipcgull::node> DeviceManager::devicesNode() const
|
||||||
|
{
|
||||||
|
return _device_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const ipcgull::node> DeviceManager::receiversNode() const
|
||||||
|
{
|
||||||
|
return _receiver_node;
|
||||||
|
}
|
||||||
|
|
||||||
void DeviceManager::addDevice(std::string path)
|
void DeviceManager::addDevice(std::string path)
|
||||||
{
|
{
|
||||||
bool defaultExists = true;
|
bool defaultExists = true;
|
||||||
@ -102,21 +122,24 @@ void DeviceManager::addDevice(std::string path)
|
|||||||
|
|
||||||
if(isReceiver) {
|
if(isReceiver) {
|
||||||
logPrintf(INFO, "Detected receiver at %s", path.c_str());
|
logPrintf(INFO, "Detected receiver at %s", path.c_str());
|
||||||
auto receiver = std::make_shared<Receiver>(path, _self.lock());
|
auto receiver = Receiver::make(path, _self.lock());
|
||||||
receiver->run();
|
receiver->run();
|
||||||
_receivers.emplace(path, receiver);
|
_receivers.emplace(path, receiver);
|
||||||
|
_ipc_receivers->receiverAdded(receiver);
|
||||||
} else {
|
} else {
|
||||||
/* TODO: Can non-receivers only contain 1 device?
|
/* TODO: Can non-receivers only contain 1 device?
|
||||||
* If the device exists, it is guaranteed to be an HID++ 2.0 device */
|
* If the device exists, it is guaranteed to be an HID++ 2.0 device */
|
||||||
if(defaultExists) {
|
if(defaultExists) {
|
||||||
auto device = std::make_shared<Device>(path, hidpp::DefaultDevice,
|
auto device = Device::make(path, hidpp::DefaultDevice,
|
||||||
_self.lock());
|
_self.lock());
|
||||||
_devices.emplace(path, device);
|
_devices.emplace(path, device);
|
||||||
|
_ipc_devices->deviceAdded(device);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
auto device = std::make_shared<Device>(path,
|
auto device = Device::make(path,
|
||||||
hidpp::CordedDevice, _self.lock());
|
hidpp::CordedDevice, _self.lock());
|
||||||
_devices.emplace(path, device);
|
_devices.emplace(path, device);
|
||||||
|
_ipc_devices->deviceAdded(device);
|
||||||
} catch(hidpp10::Error &e) {
|
} catch(hidpp10::Error &e) {
|
||||||
if(e.code() != hidpp10::Error::UnknownDevice)
|
if(e.code() != hidpp10::Error::UnknownDevice)
|
||||||
throw;
|
throw;
|
||||||
@ -134,18 +157,152 @@ void DeviceManager::addDevice(std::string path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeviceManager::addExternalDevice(const std::shared_ptr<Device> &d)
|
||||||
|
{
|
||||||
|
_ipc_devices->deviceAdded(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceManager::removeExternalDevice(const std::shared_ptr<Device> &d)
|
||||||
|
{
|
||||||
|
_ipc_devices->deviceRemoved(d);
|
||||||
|
}
|
||||||
|
|
||||||
void DeviceManager::removeDevice(std::string path)
|
void DeviceManager::removeDevice(std::string path)
|
||||||
{
|
{
|
||||||
auto receiver = _receivers.find(path);
|
auto receiver = _receivers.find(path);
|
||||||
|
|
||||||
if(receiver != _receivers.end()) {
|
if(receiver != _receivers.end()) {
|
||||||
|
_ipc_receivers->receiverRemoved(receiver->second);
|
||||||
_receivers.erase(receiver);
|
_receivers.erase(receiver);
|
||||||
logPrintf(INFO, "Receiver on %s disconnected", path.c_str());
|
logPrintf(INFO, "Receiver on %s disconnected", path.c_str());
|
||||||
} else {
|
} else {
|
||||||
auto device = _devices.find(path);
|
auto device = _devices.find(path);
|
||||||
if(device != _devices.end()) {
|
if(device != _devices.end()) {
|
||||||
|
_ipc_devices->deviceRemoved(device->second);
|
||||||
_devices.erase(device);
|
_devices.erase(device);
|
||||||
logPrintf(INFO, "Device on %s disconnected", path.c_str());
|
logPrintf(INFO, "Device on %s disconnected", path.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeviceManager::DevicesIPC::DevicesIPC() : ipcgull::interface(
|
||||||
|
"pizza.pixl.LogiOps.Devices",
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
{"deviceAdded",
|
||||||
|
ipcgull::make_signal<std::shared_ptr<Device>>(
|
||||||
|
{"device"})},
|
||||||
|
{"deviceRemoved",
|
||||||
|
ipcgull::make_signal<std::shared_ptr<Device>>(
|
||||||
|
{"device"})}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceManager::DevicesIPC::deviceAdded(
|
||||||
|
const std::shared_ptr<Device>& d) {
|
||||||
|
emit_signal("deviceAdded", d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceManager::DevicesIPC::deviceRemoved(
|
||||||
|
const std::shared_ptr<Device>& d) {
|
||||||
|
emit_signal("deviceRemoved", d);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceManager::ReceiversIPC::ReceiversIPC() : ipcgull::interface(
|
||||||
|
"pizza.pixl.LogiOps.Receivers",
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
{"receiverAdded",
|
||||||
|
ipcgull::make_signal<std::shared_ptr<Receiver>>(
|
||||||
|
{"device"})},
|
||||||
|
{"receiverRemoved",
|
||||||
|
ipcgull::make_signal<std::shared_ptr<Receiver>>(
|
||||||
|
{"device"})}
|
||||||
|
})
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceManager::ReceiversIPC::receiverAdded(
|
||||||
|
const std::shared_ptr<Receiver>& r) {
|
||||||
|
emit_signal("receiverAdded", r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceManager::ReceiversIPC::receiverRemoved(
|
||||||
|
const std::shared_ptr<Receiver>& r) {
|
||||||
|
emit_signal("receiverRemoved", r);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DeviceManager::newDeviceNickname()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(_nick_lock);
|
||||||
|
|
||||||
|
auto begin = _device_nicknames.begin();
|
||||||
|
if(begin != _device_nicknames.end()) {
|
||||||
|
if(*begin != 0) {
|
||||||
|
_device_nicknames.insert(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto i = std::adjacent_find(_device_nicknames.begin(),
|
||||||
|
_device_nicknames.end(),
|
||||||
|
[](int l, int r) { return l + 1 < r; });
|
||||||
|
|
||||||
|
|
||||||
|
if(i == _device_nicknames.end()) {
|
||||||
|
auto end = _device_nicknames.rbegin();
|
||||||
|
if(end != _device_nicknames.rend()) {
|
||||||
|
auto ret = *end + 1;
|
||||||
|
assert(ret > 0);
|
||||||
|
_device_nicknames.insert(ret);
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
_device_nicknames.insert(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ret = *i + 1;
|
||||||
|
assert(ret > 0);
|
||||||
|
_device_nicknames.insert(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DeviceManager::newReceiverNickname()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(_nick_lock);
|
||||||
|
|
||||||
|
auto begin = _receiver_nicknames.begin();
|
||||||
|
if(begin != _receiver_nicknames.end()) {
|
||||||
|
if(*begin != 0) {
|
||||||
|
_receiver_nicknames.insert(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto i = std::adjacent_find(_receiver_nicknames.begin(),
|
||||||
|
_receiver_nicknames.end(),
|
||||||
|
[](int l, int r) { return l + 1 < r; });
|
||||||
|
|
||||||
|
if(i == _receiver_nicknames.end()) {
|
||||||
|
auto end = _receiver_nicknames.rbegin();
|
||||||
|
if(end != _receiver_nicknames.rend()) {
|
||||||
|
auto ret = *end + 1;
|
||||||
|
assert(ret > 0);
|
||||||
|
_receiver_nicknames.insert(ret);
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
_receiver_nicknames.insert(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ret = *i + 1;
|
||||||
|
assert(ret > 0);
|
||||||
|
_receiver_nicknames.insert(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <ipcgull/node.h>
|
||||||
|
#include <ipcgull/interface.h>
|
||||||
|
|
||||||
#include "backend/raw/DeviceMonitor.h"
|
#include "backend/raw/DeviceMonitor.h"
|
||||||
#include "backend/hidpp/Device.h"
|
#include "backend/hidpp/Device.h"
|
||||||
@ -38,21 +40,64 @@ namespace logid
|
|||||||
public:
|
public:
|
||||||
static std::shared_ptr<DeviceManager> make(
|
static std::shared_ptr<DeviceManager> make(
|
||||||
const std::shared_ptr<Configuration>& config,
|
const std::shared_ptr<Configuration>& config,
|
||||||
const std::shared_ptr<InputDevice>& virtual_input);
|
const std::shared_ptr<InputDevice>& virtual_input,
|
||||||
|
const std::shared_ptr<ipcgull::server>& server);
|
||||||
[[nodiscard]] std::shared_ptr<Configuration> config() const;
|
[[nodiscard]] std::shared_ptr<Configuration> config() const;
|
||||||
[[nodiscard]] std::shared_ptr<InputDevice> virtualInput() const;
|
[[nodiscard]] std::shared_ptr<InputDevice> virtualInput() const;
|
||||||
|
[[nodiscard]] std::shared_ptr<const ipcgull::node> devicesNode() const;
|
||||||
|
[[nodiscard]] std::shared_ptr<const ipcgull::node>
|
||||||
|
receiversNode() const;
|
||||||
|
|
||||||
|
void addExternalDevice(const std::shared_ptr<Device>& d);
|
||||||
|
void removeExternalDevice(const std::shared_ptr<Device>& d);
|
||||||
protected:
|
protected:
|
||||||
void addDevice(std::string path) final;
|
void addDevice(std::string path) final;
|
||||||
void removeDevice(std::string path) final;
|
void removeDevice(std::string path) final;
|
||||||
private:
|
private:
|
||||||
|
class DevicesIPC : public ipcgull::interface {
|
||||||
|
public:
|
||||||
|
DevicesIPC();
|
||||||
|
void deviceAdded(const std::shared_ptr<Device>& d);
|
||||||
|
void deviceRemoved(const std::shared_ptr<Device>& d);
|
||||||
|
};
|
||||||
|
|
||||||
|
class ReceiversIPC : public ipcgull::interface {
|
||||||
|
public:
|
||||||
|
ReceiversIPC();
|
||||||
|
void receiverAdded(const std::shared_ptr<Receiver>& r);
|
||||||
|
void receiverRemoved(const std::shared_ptr<Receiver>& r);
|
||||||
|
};
|
||||||
|
|
||||||
friend class _DeviceManager;
|
friend class _DeviceManager;
|
||||||
DeviceManager(std::shared_ptr<Configuration> config,
|
DeviceManager(std::shared_ptr<Configuration> config,
|
||||||
std::shared_ptr<InputDevice> virtual_input);
|
std::shared_ptr<InputDevice> virtual_input,
|
||||||
|
std::shared_ptr<ipcgull::server> server);
|
||||||
|
|
||||||
std::weak_ptr<DeviceManager> _self;
|
std::weak_ptr<DeviceManager> _self;
|
||||||
|
std::shared_ptr<ipcgull::server> _server;
|
||||||
std::shared_ptr<Configuration> _config;
|
std::shared_ptr<Configuration> _config;
|
||||||
std::shared_ptr<InputDevice> _virtual_input;
|
std::shared_ptr<InputDevice> _virtual_input;
|
||||||
|
|
||||||
|
std::shared_ptr<ipcgull::node> _root_node;
|
||||||
|
|
||||||
|
std::shared_ptr<ipcgull::node> _device_node;
|
||||||
|
std::shared_ptr<ipcgull::node> _receiver_node;
|
||||||
|
|
||||||
|
std::shared_ptr<DevicesIPC> _ipc_devices;
|
||||||
|
std::shared_ptr<ReceiversIPC> _ipc_receivers;
|
||||||
|
|
||||||
std::map<std::string, std::shared_ptr<Device>> _devices;
|
std::map<std::string, std::shared_ptr<Device>> _devices;
|
||||||
std::map<std::string, std::shared_ptr<Receiver>> _receivers;
|
std::map<std::string, std::shared_ptr<Receiver>> _receivers;
|
||||||
|
|
||||||
|
friend class DeviceNickname;
|
||||||
|
friend class ReceiverNickname;
|
||||||
|
|
||||||
|
[[nodiscard]] int newDeviceNickname();
|
||||||
|
[[nodiscard]] int newReceiverNickname();
|
||||||
|
|
||||||
|
std::mutex _nick_lock;
|
||||||
|
std::set<int> _device_nicknames;
|
||||||
|
std::set<int> _receiver_nicknames;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,9 @@ InputDevice::InputDevice(const char* name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < REL_CNT; i++)
|
||||||
|
registered_axis[i] = false;
|
||||||
|
|
||||||
libevdev_enable_event_type(device, EV_REL);
|
libevdev_enable_event_type(device, EV_REL);
|
||||||
|
|
||||||
int err = libevdev_uinput_create_from_device(device,
|
int err = libevdev_uinput_create_from_device(device,
|
||||||
@ -76,7 +79,7 @@ InputDevice::~InputDevice()
|
|||||||
void InputDevice::registerKey(uint code)
|
void InputDevice::registerKey(uint code)
|
||||||
{
|
{
|
||||||
// TODO: Maybe print error message, if wrong code is passed?
|
// TODO: Maybe print error message, if wrong code is passed?
|
||||||
if(registered_keys[code] || code > KEY_CNT) {
|
if(code >= KEY_CNT || registered_keys[code]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +91,7 @@ void InputDevice::registerKey(uint code)
|
|||||||
void InputDevice::registerAxis(uint axis)
|
void InputDevice::registerAxis(uint axis)
|
||||||
{
|
{
|
||||||
// TODO: Maybe print error message, if wrong code is passed?
|
// TODO: Maybe print error message, if wrong code is passed?
|
||||||
if(registered_axis[axis] || axis > REL_CNT) {
|
if(axis >= REL_CNT || registered_axis[axis]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,15 +26,61 @@
|
|||||||
using namespace logid;
|
using namespace logid;
|
||||||
using namespace logid::backend;
|
using namespace logid::backend;
|
||||||
|
|
||||||
|
ReceiverNickname::ReceiverNickname(
|
||||||
|
const std::shared_ptr<DeviceManager>& manager) :
|
||||||
|
_nickname (manager->newReceiverNickname()), _manager (manager)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ReceiverNickname::operator std::string() const {
|
||||||
|
return std::to_string(_nickname);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReceiverNickname::~ReceiverNickname()
|
||||||
|
{
|
||||||
|
if(auto manager = _manager.lock()) {
|
||||||
|
std::lock_guard<std::mutex> lock(manager->_nick_lock);
|
||||||
|
manager->_receiver_nicknames.erase(_nickname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace logid {
|
||||||
|
class _Receiver : public Receiver {
|
||||||
|
public:
|
||||||
|
template <typename... Args>
|
||||||
|
_Receiver(Args... args) : Receiver(std::forward<Args>(args)...) { }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Receiver> Receiver::make(
|
||||||
|
const std::string &path,
|
||||||
|
const std::shared_ptr<DeviceManager> &manager) {
|
||||||
|
auto ret = std::make_shared<_Receiver>(path, manager);
|
||||||
|
ret->_self = ret;
|
||||||
|
ret->_ipc_node->manage(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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,
|
dj::ReceiverMonitor(path,
|
||||||
manager->config()->ioTimeout(),
|
manager->config()->ioTimeout(),
|
||||||
manager->workQueue()),
|
manager->workQueue()),
|
||||||
_path (path), _manager (manager)
|
_path (path), _manager (manager), _nickname (manager),
|
||||||
|
_ipc_node (manager->receiversNode()->make_child(_nickname)),
|
||||||
|
_ipc_interface (_ipc_node->make_interface<ReceiverIPC>(this))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Receiver::~Receiver()
|
||||||
|
{
|
||||||
|
if(auto manager = _manager.lock()) {
|
||||||
|
for(auto& d : _devices)
|
||||||
|
manager->removeExternalDevice(d.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Receiver::addDevice(hidpp::DeviceConnectionEvent event)
|
void Receiver::addDevice(hidpp::DeviceConnectionEvent event)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(_devices_change);
|
std::unique_lock<std::mutex> lock(_devices_change);
|
||||||
@ -77,10 +123,9 @@ void Receiver::addDevice(hidpp::DeviceConnectionEvent event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Device> device = std::make_shared<Device>(this,
|
auto device = Device::make(this, event.index, manager);
|
||||||
event.index, manager);
|
|
||||||
|
|
||||||
_devices.emplace(event.index, device);
|
_devices.emplace(event.index, device);
|
||||||
|
manager->addExternalDevice(device);
|
||||||
|
|
||||||
} catch(hidpp10::Error &e) {
|
} catch(hidpp10::Error &e) {
|
||||||
logPrintf(ERROR,
|
logPrintf(ERROR,
|
||||||
@ -100,7 +145,12 @@ void Receiver::addDevice(hidpp::DeviceConnectionEvent event)
|
|||||||
void Receiver::removeDevice(hidpp::DeviceIndex index)
|
void Receiver::removeDevice(hidpp::DeviceIndex index)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(_devices_change);
|
std::unique_lock<std::mutex> lock(_devices_change);
|
||||||
_devices.erase(index);
|
auto device = _devices.find(index);
|
||||||
|
if(device != _devices.end()) {
|
||||||
|
if(auto manager = _manager.lock())
|
||||||
|
manager->removeExternalDevice(device->second);
|
||||||
|
_devices.erase(device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& Receiver::path() const
|
const std::string& Receiver::path() const
|
||||||
@ -112,3 +162,8 @@ std::shared_ptr<dj::Receiver> Receiver::rawReceiver()
|
|||||||
{
|
{
|
||||||
return receiver();
|
return receiver();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Receiver::ReceiverIPC::ReceiverIPC(Receiver *receiver) :
|
||||||
|
ipcgull::interface("pizza.pixl.LogiOps.Receiver", {}, {}, {})
|
||||||
|
{
|
||||||
|
}
|
||||||
|
@ -25,21 +25,55 @@
|
|||||||
|
|
||||||
namespace logid
|
namespace logid
|
||||||
{
|
{
|
||||||
class Receiver : public backend::dj::ReceiverMonitor
|
class ReceiverNickname {
|
||||||
|
public:
|
||||||
|
explicit ReceiverNickname(const std::shared_ptr<DeviceManager>& manager);
|
||||||
|
ReceiverNickname() = delete;
|
||||||
|
ReceiverNickname(const ReceiverNickname&) = delete;
|
||||||
|
~ReceiverNickname();
|
||||||
|
|
||||||
|
operator std::string() const;
|
||||||
|
private:
|
||||||
|
const int _nickname;
|
||||||
|
const std::weak_ptr<DeviceManager> _manager;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Receiver : public backend::dj::ReceiverMonitor,
|
||||||
|
public ipcgull::object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Receiver(const std::string& path,
|
~Receiver();
|
||||||
const std::shared_ptr<DeviceManager>& manager);
|
|
||||||
|
static std::shared_ptr<Receiver> make(
|
||||||
|
const std::string& path,
|
||||||
|
const std::shared_ptr<DeviceManager>& manager);
|
||||||
const std::string& path() const;
|
const std::string& path() const;
|
||||||
std::shared_ptr<backend::dj::Receiver> rawReceiver();
|
std::shared_ptr<backend::dj::Receiver> rawReceiver();
|
||||||
protected:
|
protected:
|
||||||
void addDevice(backend::hidpp::DeviceConnectionEvent event) override;
|
void addDevice(backend::hidpp::DeviceConnectionEvent event) override;
|
||||||
void removeDevice(backend::hidpp::DeviceIndex index) override;
|
void removeDevice(backend::hidpp::DeviceIndex index) override;
|
||||||
private:
|
private:
|
||||||
|
friend class _Receiver;
|
||||||
|
|
||||||
|
Receiver(const std::string& path,
|
||||||
|
const std::shared_ptr<DeviceManager>& manager);
|
||||||
|
|
||||||
std::mutex _devices_change;
|
std::mutex _devices_change;
|
||||||
std::map<backend::hidpp::DeviceIndex, std::shared_ptr<Device>> _devices;
|
std::map<backend::hidpp::DeviceIndex, std::shared_ptr<Device>> _devices;
|
||||||
std::string _path;
|
std::string _path;
|
||||||
std::weak_ptr<DeviceManager> _manager;
|
std::weak_ptr<DeviceManager> _manager;
|
||||||
|
|
||||||
|
const ReceiverNickname _nickname;
|
||||||
|
std::shared_ptr<ipcgull::node> _ipc_node;
|
||||||
|
|
||||||
|
class ReceiverIPC : public ipcgull::interface {
|
||||||
|
public:
|
||||||
|
ReceiverIPC(Receiver* receiver);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<ipcgull::interface> _ipc_interface;
|
||||||
|
|
||||||
|
std::weak_ptr<Receiver> _self;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <ipcgull/exception.h>
|
||||||
|
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
#include "DeviceManager.h"
|
#include "DeviceManager.h"
|
||||||
@ -157,6 +158,19 @@ int main(int argc, char** argv)
|
|||||||
std::shared_ptr<Configuration> config;
|
std::shared_ptr<Configuration> config;
|
||||||
std::shared_ptr<InputDevice> virtual_input;
|
std::shared_ptr<InputDevice> virtual_input;
|
||||||
|
|
||||||
|
auto server = ipcgull::make_server("pizza.pixl.LogiOps",
|
||||||
|
"/pizza/pixl/logiops",
|
||||||
|
ipcgull::IPCGULL_USER);
|
||||||
|
|
||||||
|
std::thread( [server]() {
|
||||||
|
try {
|
||||||
|
server->start();
|
||||||
|
} catch(ipcgull::connection_failed& e) {
|
||||||
|
logPrintf(ERROR, "Lost IPC connection, terminating.");
|
||||||
|
std::terminate();
|
||||||
|
}
|
||||||
|
} ).detach();
|
||||||
|
|
||||||
// Read config
|
// Read config
|
||||||
try {
|
try {
|
||||||
config = std::make_shared<Configuration>(options.config_file);
|
config = std::make_shared<Configuration>(options.config_file);
|
||||||
@ -174,9 +188,11 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Scan devices, create listeners, handlers, etc.
|
// Scan devices, create listeners, handlers, etc.
|
||||||
auto device_manager = DeviceManager::make(config, virtual_input);
|
auto device_manager = DeviceManager::make(config, virtual_input, server);
|
||||||
|
|
||||||
device_manager->run();
|
device_manager->run();
|
||||||
|
|
||||||
|
server->stop_sync();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user