Implement dj::Receiver class
Again, many things were done here.
This commit is contained in:
parent
47db60fad8
commit
b41649b0de
|
@ -15,9 +15,12 @@ add_executable(logid
|
||||||
backend/Error.cpp
|
backend/Error.cpp
|
||||||
backend/raw/DeviceMonitor.cpp
|
backend/raw/DeviceMonitor.cpp
|
||||||
backend/raw/RawDevice.cpp
|
backend/raw/RawDevice.cpp
|
||||||
|
backend/dj/Receiver.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
|
||||||
|
backend/hidpp10/Device.cpp
|
||||||
backend/hidpp20/Device.cpp
|
backend/hidpp20/Device.cpp
|
||||||
backend/hidpp20/Error.cpp
|
backend/hidpp20/Error.cpp
|
||||||
backend/hidpp20/Feature.cpp
|
backend/hidpp20/Feature.cpp
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "DeviceMonitor.h"
|
#include "DeviceMonitor.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "backend/hidpp10/Error.h"
|
#include "backend/hidpp10/Error.h"
|
||||||
|
#include "backend/dj/Receiver.h"
|
||||||
|
|
||||||
#define NON_WIRELESS_DEV(index) (index) == HIDPP::DefaultDevice ? "default" : "corded"
|
#define NON_WIRELESS_DEV(index) (index) == HIDPP::DefaultDevice ? "default" : "corded"
|
||||||
|
|
||||||
|
@ -103,12 +104,26 @@ void DeviceMonitor::stopAndDeleteDevice (const std::string &path, HIDPP::DeviceI
|
||||||
void DeviceMonitor::addDevice(std::string path)
|
void DeviceMonitor::addDevice(std::string path)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
auto device = std::make_shared<backend::hidpp::Device>(path, hidpp::DeviceIndex::WirelessDevice1);
|
std::tuple<uint8_t, uint8_t> version;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
hidpp::Device device(path, hidpp::DefaultDevice);
|
||||||
|
|
||||||
log_printf(DEBUG, "Detected HID++ device at %s", path.c_str());
|
log_printf(DEBUG, "Detected HID++ device at %s", path.c_str());
|
||||||
|
|
||||||
auto version = device->version();
|
version = device.version();
|
||||||
log_printf(DEBUG, "HID++ version: %d.%d", std::get<0>(version), std::get<1>(version));
|
log_printf(DEBUG, "HID++ version: %d.%d", std::get<0>(version), std::get<1>(version));
|
||||||
|
} catch(std::system_error &e) { }
|
||||||
|
|
||||||
|
if(version == std::make_tuple(1, 0))
|
||||||
|
{
|
||||||
|
// This is a receiver
|
||||||
|
dj::Receiver receiver(path);
|
||||||
|
receiver.enumerate();
|
||||||
|
receiver.listen();
|
||||||
|
while(true) {}
|
||||||
|
}
|
||||||
|
/*
|
||||||
auto eventHandler = std::make_shared<backend::hidpp::EventHandler>();
|
auto eventHandler = std::make_shared<backend::hidpp::EventHandler>();
|
||||||
eventHandler->condition = [device](backend::hidpp::Report& report)->bool
|
eventHandler->condition = [device](backend::hidpp::Report& report)->bool
|
||||||
{
|
{
|
||||||
|
@ -125,9 +140,9 @@ void DeviceMonitor::addDevice(std::string path)
|
||||||
|
|
||||||
device->addEventHandler("MONITOR_ALL", eventHandler);
|
device->addEventHandler("MONITOR_ALL", eventHandler);
|
||||||
|
|
||||||
devices.push_back(device);
|
devices.push_back(device);*/
|
||||||
|
|
||||||
std::thread([device]() { device->listen(); }).detach();
|
//std::thread([device]() { device->listen(); }).detach();
|
||||||
}
|
}
|
||||||
catch(hidpp10::Error &e)
|
catch(hidpp10::Error &e)
|
||||||
{
|
{
|
||||||
|
@ -139,10 +154,11 @@ void DeviceMonitor::addDevice(std::string path)
|
||||||
{
|
{
|
||||||
log_printf(DEBUG, "Detected device at %s but %s", path.c_str(), e.what());
|
log_printf(DEBUG, "Detected device at %s but %s", path.c_str(), e.what());
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
catch(std::system_error &e)
|
catch(std::system_error &e)
|
||||||
{
|
{
|
||||||
log_printf(WARN, "Failed to open %s: %s", path.c_str(), e.what());
|
log_printf(WARN, "Failed to open %s: %s", path.c_str(), e.what());
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceMonitor::removeDevice(std::string path)
|
void DeviceMonitor::removeDevice(std::string path)
|
||||||
|
|
21
src/logid/backend/dj/Error.cpp
Normal file
21
src/logid/backend/dj/Error.cpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#include "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 std::string("Reserved error code " + std::to_string(_code))
|
||||||
|
.c_str();
|
||||||
|
}
|
||||||
|
}
|
30
src/logid/backend/dj/Error.h
Normal file
30
src/logid/backend/dj/Error.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef LOGID_HIDPP_BACKEND_DJ_ERROR_H
|
||||||
|
#define LOGID_HIDPP_BACKEND_DJ_ERROR_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace logid {
|
||||||
|
namespace backend {
|
||||||
|
namespace dj
|
||||||
|
{
|
||||||
|
class Error : public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum ErrorCode : uint8_t
|
||||||
|
{
|
||||||
|
Unknown = 0x00,
|
||||||
|
KeepAliveTimeout = 0x01
|
||||||
|
};
|
||||||
|
|
||||||
|
Error(uint8_t code);
|
||||||
|
|
||||||
|
virtual const char* what() const noexcept;
|
||||||
|
uint8_t code() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t _code;
|
||||||
|
};
|
||||||
|
}}}
|
||||||
|
|
||||||
|
#endif //LOGID_HIDPP_BACKEND_DJ_ERROR_H
|
255
src/logid/backend/dj/Receiver.cpp
Normal file
255
src/logid/backend/dj/Receiver.cpp
Normal file
|
@ -0,0 +1,255 @@
|
||||||
|
#include <cassert>
|
||||||
|
#include "Report.h"
|
||||||
|
#include "Receiver.h"
|
||||||
|
#include "Error.h"
|
||||||
|
|
||||||
|
using namespace logid::backend::dj;
|
||||||
|
using namespace logid::backend;
|
||||||
|
|
||||||
|
InvalidReceiver::InvalidReceiver(Reason reason) : _reason (reason)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* InvalidReceiver::what() const noexcept
|
||||||
|
{
|
||||||
|
return "Invalid receiver";
|
||||||
|
}
|
||||||
|
|
||||||
|
InvalidReceiver::Reason InvalidReceiver::code() const noexcept
|
||||||
|
{
|
||||||
|
return _reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
Receiver::Receiver(std::string path) :
|
||||||
|
raw_device (std::make_shared<raw::RawDevice>(path)),
|
||||||
|
_hidpp10_device (raw_device, hidpp::DefaultDevice)
|
||||||
|
{
|
||||||
|
if(!supportsDjReports(raw_device->reportDescriptor()))
|
||||||
|
throw InvalidReceiver(InvalidReceiver::NoDJReports);
|
||||||
|
|
||||||
|
|
||||||
|
// Pass all HID++ events on DefaultDevice to handleHidppEvent
|
||||||
|
RawEventHandler hidppRawEventHandler;
|
||||||
|
hidppRawEventHandler.condition = [this](std::vector<uint8_t>& report)->bool
|
||||||
|
{
|
||||||
|
return (report[hidpp::Offset::Type] == hidpp::Report::Type::Short ||
|
||||||
|
report[hidpp::Offset::Type] == hidpp::Report::Type::Long) &&
|
||||||
|
(report[hidpp::Offset::DeviceIndex] == hidpp::DefaultDevice);
|
||||||
|
};
|
||||||
|
hidppRawEventHandler.callback = [this](std::vector<uint8_t>& report)->void
|
||||||
|
{
|
||||||
|
hidpp::Report _report(report);
|
||||||
|
this->handleHidppEvent(_report);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pass all DJ events with device index to handleHidppEvent
|
||||||
|
RawEventHandler djRawEventHandler;
|
||||||
|
djRawEventHandler.condition = [this](std::vector<uint8_t>& report)->bool
|
||||||
|
{
|
||||||
|
return (report[Offset::Type] == Report::Type::Short ||
|
||||||
|
report[Offset::Type] == Report::Type::Long);
|
||||||
|
};
|
||||||
|
djRawEventHandler.callback = [this](std::vector<uint8_t>& report)->void
|
||||||
|
{
|
||||||
|
Report _report(report);
|
||||||
|
this->handleDjEvent(_report);
|
||||||
|
};
|
||||||
|
|
||||||
|
raw_device->addEventHandler("RECV_HIDPP", hidppRawEventHandler);
|
||||||
|
raw_device->addEventHandler("RECV_DJ", djRawEventHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Receiver::enumerate()
|
||||||
|
{
|
||||||
|
sendDjRequest(hidpp::DefaultDevice, GetPairedDevices,{});
|
||||||
|
}
|
||||||
|
|
||||||
|
Receiver::notification_flags Receiver::getHidppNotifications()
|
||||||
|
{
|
||||||
|
auto response = _hidpp10_device.getRegister(EnableHidppNotifications, {});
|
||||||
|
|
||||||
|
notification_flags flags{};
|
||||||
|
|
||||||
|
flags.device_battery_status = response[0] & (1 << 4);
|
||||||
|
flags.receiver_wireless_notifications = response[1] & (1 << 0);
|
||||||
|
flags.receiver_software_present = response[1] & (1 << 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Receiver::enableHidppNotifications(notification_flags flags)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> request(3);
|
||||||
|
|
||||||
|
if(flags.device_battery_status)
|
||||||
|
request[0] |= (1 << 4);
|
||||||
|
if(flags.receiver_wireless_notifications)
|
||||||
|
request[1] |= (1 << 0);
|
||||||
|
if(flags.receiver_software_present)
|
||||||
|
request[1] |= (1 << 3);
|
||||||
|
|
||||||
|
_hidpp10_device.setRegister(EnableHidppNotifications, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
///TODO: Investigate usage
|
||||||
|
uint8_t Receiver::getConnectionState(hidpp::DeviceIndex index)
|
||||||
|
{
|
||||||
|
auto response = _hidpp10_device.setRegister(ConnectionState, {index});
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<hidpp::DeviceIndex, uint8_t> Receiver::getDeviceActivity()
|
||||||
|
{
|
||||||
|
auto response = _hidpp10_device.getRegister(DeviceActivity, {});
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Receiver::pairing_info Receiver::getPairingInfo(hidpp::DeviceIndex index)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> request(1);
|
||||||
|
request[0] = index;
|
||||||
|
request[0] += 0x19;
|
||||||
|
|
||||||
|
auto response = _hidpp10_device.getRegister(PairingInfo, request);
|
||||||
|
|
||||||
|
pairing_info info{};
|
||||||
|
info.destination_id = response[0];
|
||||||
|
info.report_interval = response[1];
|
||||||
|
info.pid = response[2];
|
||||||
|
info.pid |= (response[3] << 8);
|
||||||
|
info.device_type = response[6];
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
Receiver::extended_pairing_info
|
||||||
|
Receiver::getExtendedPairingInfo(hidpp::DeviceIndex index)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> request(1);
|
||||||
|
request[0] = index;
|
||||||
|
request[0] += 0x29;
|
||||||
|
|
||||||
|
auto response = _hidpp10_device.getRegister(PairingInfo, request);
|
||||||
|
|
||||||
|
extended_pairing_info info{};
|
||||||
|
|
||||||
|
info.serial_number = 0;
|
||||||
|
for(uint8_t i = 0; i < 4; i++)
|
||||||
|
info.serial_number |= (response[i] << 8*i);
|
||||||
|
|
||||||
|
for(uint8_t i = 0; i < 4; i++)
|
||||||
|
info.report_types[i] = response[i + 4];
|
||||||
|
|
||||||
|
info.power_switch_location = response[8] & 0xf;
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Receiver::getDeviceName(hidpp::DeviceIndex index)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> request(1);
|
||||||
|
request[0] = index;
|
||||||
|
request[0] += 0x39;
|
||||||
|
|
||||||
|
auto response = _hidpp10_device.getRegister(PairingInfo, request);
|
||||||
|
|
||||||
|
uint8_t size = response[0];
|
||||||
|
assert(size <= 14);
|
||||||
|
|
||||||
|
std::string name(size, ' ');
|
||||||
|
for(std::size_t i = 0; i < size; i++)
|
||||||
|
name[i] = response[i + 1];
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
hidpp::DeviceIndex Receiver::deviceConnectionEvent(hidpp::Report &report)
|
||||||
|
{
|
||||||
|
assert(report.subId() == DeviceConnection);
|
||||||
|
return report.deviceIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
hidpp::DeviceIndex Receiver::deviceDisconnectionEvent(hidpp::Report& report)
|
||||||
|
{
|
||||||
|
assert(report.subId() == DeviceDisconnection);
|
||||||
|
return report.deviceIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Receiver::handleDjEvent(Report& report)
|
||||||
|
{
|
||||||
|
if(report.feature() == DeviceConnection ||
|
||||||
|
report.feature() == DeviceDisconnection ||
|
||||||
|
report.feature() == ConnectionStatus)
|
||||||
|
{
|
||||||
|
printf("%s DJ IN: ", raw_device->hidrawPath().c_str());
|
||||||
|
for(auto &i: report.rawData())
|
||||||
|
printf("%02x ", i);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Receiver::handleHidppEvent(hidpp::Report &report)
|
||||||
|
{
|
||||||
|
printf("%s HID++ IN: ", raw_device->hidrawPath().c_str());
|
||||||
|
for(auto &i: report.rawReport())
|
||||||
|
printf("%02x ", i);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
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->sendReportNoResponse(request.rawData());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Receiver::listen()
|
||||||
|
{
|
||||||
|
std::thread{[=]() { raw_device->listen(); }}.detach();
|
||||||
|
}
|
125
src/logid/backend/dj/Receiver.h
Normal file
125
src/logid/backend/dj/Receiver.h
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
#ifndef LOGID_BACKEND_DJ_RECEIVER_H
|
||||||
|
#define LOGID_BACKEND_DJ_RECEIVER_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include "../raw/RawDevice.h"
|
||||||
|
#include "Report.h"
|
||||||
|
#include "../hidpp/Report.h"
|
||||||
|
#include "../hidpp10/Device.h"
|
||||||
|
|
||||||
|
namespace logid {
|
||||||
|
namespace backend {
|
||||||
|
namespace dj
|
||||||
|
{
|
||||||
|
class InvalidReceiver : public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Reason
|
||||||
|
{
|
||||||
|
NoDJReports
|
||||||
|
};
|
||||||
|
explicit InvalidReceiver(Reason reason);
|
||||||
|
virtual const char* what() const noexcept;
|
||||||
|
Reason code() const noexcept;
|
||||||
|
private:
|
||||||
|
Reason _reason;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Receiver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Receiver(std::string path);
|
||||||
|
|
||||||
|
enum DjEvents : uint8_t
|
||||||
|
{
|
||||||
|
DeviceDisconnection = 0x40,
|
||||||
|
DeviceConnection = 0x41,
|
||||||
|
ConnectionStatus = 0x42
|
||||||
|
};
|
||||||
|
|
||||||
|
enum DjCommands : uint8_t
|
||||||
|
{
|
||||||
|
SwitchAndKeepAlive = 0x80,
|
||||||
|
GetPairedDevices = 0x81
|
||||||
|
};
|
||||||
|
|
||||||
|
void enumerate();
|
||||||
|
|
||||||
|
/* The following functions deal with HID++ 1.0 features.
|
||||||
|
* While these are not technically DJ functions, it is redundant
|
||||||
|
* to have a separate hidpp10::Receiver class for these functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum HidppEvents : uint8_t
|
||||||
|
{
|
||||||
|
// These events are identical to their DJ counterparts
|
||||||
|
// DeviceDisconnection = 0x40,
|
||||||
|
// DeviceConnection = 0x41,
|
||||||
|
LockingChange = 0x4a
|
||||||
|
};
|
||||||
|
|
||||||
|
enum HidppRegisters : uint8_t
|
||||||
|
{
|
||||||
|
EnableHidppNotifications = 0x00,
|
||||||
|
ConnectionState = 0x02,
|
||||||
|
DevicePairing = 0xb2,
|
||||||
|
DeviceActivity = 0xb3,
|
||||||
|
PairingInfo = 0xb5
|
||||||
|
};
|
||||||
|
|
||||||
|
struct notification_flags
|
||||||
|
{
|
||||||
|
bool device_battery_status;
|
||||||
|
bool receiver_wireless_notifications;
|
||||||
|
bool receiver_software_present;
|
||||||
|
};
|
||||||
|
|
||||||
|
notification_flags getHidppNotifications();
|
||||||
|
void enableHidppNotifications(notification_flags flags);
|
||||||
|
|
||||||
|
///TODO: Understand output of this function
|
||||||
|
uint8_t getConnectionState(hidpp::DeviceIndex index);
|
||||||
|
|
||||||
|
void startPairing(uint8_t timeout = 0);
|
||||||
|
void stopPairing();
|
||||||
|
void disconnect(hidpp::DeviceIndex index);
|
||||||
|
|
||||||
|
std::map<hidpp::DeviceIndex, uint8_t> getDeviceActivity();
|
||||||
|
|
||||||
|
struct pairing_info
|
||||||
|
{
|
||||||
|
uint8_t destination_id;
|
||||||
|
uint8_t report_interval;
|
||||||
|
uint16_t pid;
|
||||||
|
uint8_t device_type; ///TODO: Create enum for DeviceType
|
||||||
|
};
|
||||||
|
|
||||||
|
struct extended_pairing_info
|
||||||
|
{
|
||||||
|
uint32_t serial_number;
|
||||||
|
uint8_t report_types[4];
|
||||||
|
uint8_t power_switch_location; ///TODO: Create enum
|
||||||
|
};
|
||||||
|
|
||||||
|
pairing_info getPairingInfo(hidpp::DeviceIndex index);
|
||||||
|
extended_pairing_info getExtendedPairingInfo(hidpp::DeviceIndex index);
|
||||||
|
|
||||||
|
std::string getDeviceName(hidpp::DeviceIndex index);
|
||||||
|
|
||||||
|
hidpp::DeviceIndex deviceConnectionEvent(hidpp::Report& report);
|
||||||
|
hidpp::DeviceIndex deviceDisconnectionEvent(hidpp::Report& report);
|
||||||
|
|
||||||
|
void handleDjEvent(dj::Report& report);
|
||||||
|
void handleHidppEvent(hidpp::Report& report);
|
||||||
|
|
||||||
|
void listen();
|
||||||
|
private:
|
||||||
|
void sendDjRequest(hidpp::DeviceIndex index, uint8_t function,
|
||||||
|
const std::vector<uint8_t>&& params);
|
||||||
|
|
||||||
|
std::shared_ptr<raw::RawDevice> raw_device;
|
||||||
|
hidpp10::Device _hidpp10_device;
|
||||||
|
};
|
||||||
|
}}}
|
||||||
|
|
||||||
|
#endif //LOGID_BACKEND_DJ_RECEIVER_H
|
|
@ -1,11 +1,12 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
#include "Report.h"
|
#include "Report.h"
|
||||||
|
|
||||||
using namespace logid::backend::dj;
|
using namespace logid::backend::dj;
|
||||||
using namespace logid::backend;
|
using namespace logid::backend;
|
||||||
|
|
||||||
static const std::array<uint8_t, 35> DJReportDesc = {
|
static const std::array<uint8_t, 34> DJReportDesc = {
|
||||||
0xA1, 0x01, // Collection (Application)
|
0xA1, 0x01, // Collection (Application)
|
||||||
0x85, 0x20, // Report ID (32)
|
0x85, 0x20, // Report ID (32)
|
||||||
0x95, 0x0E, // Report Count (14)
|
0x95, 0x0E, // Report Count (14)
|
||||||
|
@ -25,8 +26,68 @@ static const std::array<uint8_t, 35> DJReportDesc = {
|
||||||
0xC0 // End Collection
|
0xC0 // End Collection
|
||||||
};
|
};
|
||||||
|
|
||||||
bool dj::supportsDjReports(std::vector<uint8_t>& rdesc)
|
bool dj::supportsDjReports(std::vector<uint8_t>&& rdesc)
|
||||||
{
|
{
|
||||||
auto it = std::search(rdesc.begin(), rdesc.end(), DJReportDesc.begin(), DJReportDesc.end());
|
auto it = std::search(rdesc.begin(), rdesc.end(), DJReportDesc.begin(), DJReportDesc.end());
|
||||||
return it != rdesc.end();
|
return it != rdesc.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Report::Report(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> Report::rawData() const
|
||||||
|
{
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
|
@ -3,17 +3,35 @@
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "../raw/RawDevice.h"
|
#include "../raw/RawDevice.h"
|
||||||
|
#include "defs.h"
|
||||||
|
#include "../hidpp/defs.h"
|
||||||
|
|
||||||
namespace logid::backend::dj
|
namespace logid::backend::dj
|
||||||
{
|
{
|
||||||
bool supportsDjReports(std::vector<uint8_t>& rawDevice);
|
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(std::vector<uint8_t>&& rdesc);
|
||||||
class Report
|
class Report
|
||||||
{
|
{
|
||||||
enum Type: uint8_t
|
public:
|
||||||
{
|
typedef ReportType::ReportType Type;
|
||||||
Short = 0x20, // Short DJ reports use 12 byte parameters
|
|
||||||
Long = 0x21 // Long DJ reports use 29 byte parameters
|
explicit Report(std::vector<uint8_t>& data);
|
||||||
};
|
Report(Type type, hidpp::DeviceIndex index, uint8_t feature);
|
||||||
|
|
||||||
|
Type type() const;
|
||||||
|
hidpp::DeviceIndex index() const;
|
||||||
|
uint8_t feature() const;
|
||||||
|
std::vector<uint8_t>::iterator paramBegin();
|
||||||
|
std::vector<uint8_t> rawData() const;
|
||||||
|
private:
|
||||||
|
std::vector<uint8_t> _data;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,12 @@ namespace dj
|
||||||
Long = 0x21
|
Long = 0x21
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
#endif //LOGID_BACKEND_DJ_DEFS_H
|
|
@ -26,7 +26,19 @@ Device::InvalidDevice::Reason Device::InvalidDevice::code() const noexcept
|
||||||
|
|
||||||
/// TODO: Initialize a single RawDevice for each path.
|
/// TODO: Initialize a single RawDevice for each path.
|
||||||
Device::Device(const std::string& path, DeviceIndex index):
|
Device::Device(const std::string& path, DeviceIndex index):
|
||||||
raw_device (std::make_shared<raw::RawDevice>(path)), path (path), index (index)
|
raw_device (std::make_shared<raw::RawDevice>(path)), path (path),
|
||||||
|
_index (index)
|
||||||
|
{
|
||||||
|
_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
Device::Device(std::shared_ptr<raw::RawDevice> raw_device, DeviceIndex index) :
|
||||||
|
raw_device (raw_device), _index (index)
|
||||||
|
{
|
||||||
|
_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::_init()
|
||||||
{
|
{
|
||||||
supported_reports = getSupportedReports(raw_device->reportDescriptor());
|
supported_reports = getSupportedReports(raw_device->reportDescriptor());
|
||||||
if(!supported_reports)
|
if(!supported_reports)
|
||||||
|
@ -34,8 +46,9 @@ Device::Device(const std::string& path, DeviceIndex index):
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Report versionRequest(Report::Type::Short, index, hidpp20::FeatureID::ROOT,
|
Report versionRequest(Report::Type::Short, _index,
|
||||||
hidpp20::Root::Ping, LOGID_HIDPP_SOFTWARE_ID);
|
hidpp20::FeatureID::ROOT,hidpp20::Root::Ping,
|
||||||
|
LOGID_HIDPP_SOFTWARE_ID);
|
||||||
|
|
||||||
auto versionResponse = sendReport(versionRequest);
|
auto versionResponse = sendReport(versionRequest);
|
||||||
auto versionResponse_params = versionResponse.paramBegin();
|
auto versionResponse_params = versionResponse.paramBegin();
|
||||||
|
@ -53,10 +66,11 @@ Device::Device(const std::string& path, DeviceIndex index):
|
||||||
|
|
||||||
// Pass all HID++ events with device index to this device.
|
// Pass all HID++ events with device index to this device.
|
||||||
RawEventHandler rawEventHandler;
|
RawEventHandler rawEventHandler;
|
||||||
rawEventHandler.condition = [index](std::vector<uint8_t>& report)->bool
|
rawEventHandler.condition = [this](std::vector<uint8_t>& report)->bool
|
||||||
{
|
{
|
||||||
return (report[Offset::Type] == Report::Type::Short ||
|
return (report[Offset::Type] == Report::Type::Short ||
|
||||||
report[Offset::Type] == Report::Type::Long) && (report[Offset::DeviceIndex] == index);
|
report[Offset::Type] == Report::Type::Long) &&
|
||||||
|
(report[Offset::DeviceIndex] == this->_index);
|
||||||
};
|
};
|
||||||
rawEventHandler.callback = [this](std::vector<uint8_t>& report)->void
|
rawEventHandler.callback = [this](std::vector<uint8_t>& report)->void
|
||||||
{
|
{
|
||||||
|
@ -64,7 +78,15 @@ Device::Device(const std::string& path, DeviceIndex index):
|
||||||
this->handleEvent(_report);
|
this->handleEvent(_report);
|
||||||
};
|
};
|
||||||
|
|
||||||
raw_device->addEventHandler("DEV_" + std::to_string(index), rawEventHandler);
|
raw_device->addEventHandler("DEV_" + std::to_string(_index), rawEventHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
Device::~Device()
|
||||||
|
{
|
||||||
|
raw_device->removeEventHandler("DEV_" + std::to_string(_index));
|
||||||
|
///TODO: tmp
|
||||||
|
raw_device->stopListener();
|
||||||
|
raw_device.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::addEventHandler(const std::string& nickname, const std::shared_ptr<EventHandler>& handler)
|
void Device::addEventHandler(const std::string& nickname, const std::shared_ptr<EventHandler>& handler)
|
||||||
|
|
|
@ -37,9 +37,11 @@ namespace hidpp
|
||||||
};
|
};
|
||||||
|
|
||||||
Device(const std::string& path, DeviceIndex index);
|
Device(const std::string& path, DeviceIndex index);
|
||||||
|
Device(std::shared_ptr<raw::RawDevice> raw_device, DeviceIndex index);
|
||||||
|
~Device();
|
||||||
|
|
||||||
std::string devicePath() const { return path; }
|
std::string devicePath() const { return path; }
|
||||||
DeviceIndex deviceIndex() const { return index; }
|
DeviceIndex deviceIndex() const { return _index; }
|
||||||
std::tuple<uint8_t, uint8_t> version() const { return _version; }
|
std::tuple<uint8_t, uint8_t> version() const { return _version; }
|
||||||
|
|
||||||
void listen(); // Runs asynchronously
|
void listen(); // Runs asynchronously
|
||||||
|
@ -52,9 +54,11 @@ namespace hidpp
|
||||||
|
|
||||||
void handleEvent(Report& report);
|
void handleEvent(Report& report);
|
||||||
private:
|
private:
|
||||||
|
void _init();
|
||||||
|
|
||||||
std::shared_ptr<raw::RawDevice> raw_device;
|
std::shared_ptr<raw::RawDevice> raw_device;
|
||||||
std::string path;
|
std::string path;
|
||||||
DeviceIndex index;
|
DeviceIndex _index;
|
||||||
uint8_t supported_reports;
|
uint8_t supported_reports;
|
||||||
|
|
||||||
std::tuple<uint8_t, uint8_t> _version;
|
std::tuple<uint8_t, uint8_t> _version;
|
||||||
|
|
|
@ -95,6 +95,27 @@ const char *Report::InvalidReportLength::what() const noexcept
|
||||||
return "Invalid report length";
|
return "Invalid report length";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Report::Report(Report::Type type, DeviceIndex device_index,
|
||||||
|
uint8_t sub_id, uint8_t address)
|
||||||
|
{
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case Type::Short:
|
||||||
|
_data.resize(HeaderLength + ShortParamLength);
|
||||||
|
break;
|
||||||
|
case Type::Long:
|
||||||
|
_data.resize(HeaderLength + LongParamLength);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw InvalidReportID();
|
||||||
|
}
|
||||||
|
|
||||||
|
_data[Offset::Type] = type;
|
||||||
|
_data[Offset::DeviceIndex] = device_index;
|
||||||
|
_data[Offset::SubID] = sub_id;
|
||||||
|
_data[Offset::Address] = address;
|
||||||
|
}
|
||||||
|
|
||||||
Report::Report(Report::Type type, DeviceIndex device_index,
|
Report::Report(Report::Type type, DeviceIndex device_index,
|
||||||
uint8_t feature_index, uint8_t function, uint8_t sw_id)
|
uint8_t feature_index, uint8_t function, uint8_t sw_id)
|
||||||
{
|
{
|
||||||
|
@ -123,6 +144,7 @@ Report::Report(const std::vector<uint8_t>& data)
|
||||||
{
|
{
|
||||||
_data = data;
|
_data = data;
|
||||||
|
|
||||||
|
// Truncating data is entirely valid here.
|
||||||
switch(_data[Offset::Type])
|
switch(_data[Offset::Type])
|
||||||
{
|
{
|
||||||
case Type::Short:
|
case Type::Short:
|
||||||
|
@ -136,6 +158,11 @@ Report::Report(const std::vector<uint8_t>& data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Report::Type Report::type() const
|
||||||
|
{
|
||||||
|
return static_cast<Report::Type>(_data[Offset::Type]);
|
||||||
|
}
|
||||||
|
|
||||||
void Report::setType(Report::Type type)
|
void Report::setType(Report::Type type)
|
||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
|
@ -153,6 +180,58 @@ void Report::setType(Report::Type type)
|
||||||
_data[Offset::Type] = type;
|
_data[Offset::Type] = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t Report::feature() const
|
||||||
|
{
|
||||||
|
return _data[Offset::Feature];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Report::setFeature(uint8_t feature)
|
||||||
|
{
|
||||||
|
_data[Offset::Parameters] = feature;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Report::subId() const
|
||||||
|
{
|
||||||
|
return _data[Offset::SubID];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Report::setSubId(uint8_t sub_id)
|
||||||
|
{
|
||||||
|
_data[Offset::SubID] = sub_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Report::function() const
|
||||||
|
{
|
||||||
|
return (_data[Offset::Function] >> 4) & 0x0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Report::setFunction(uint8_t function)
|
||||||
|
{
|
||||||
|
_data[Offset::Function] &= 0x0f;
|
||||||
|
_data[Offset::Function] |= (function << 4) & 0x0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Report::swId() const
|
||||||
|
{
|
||||||
|
return _data[Offset::Function] & 0x0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Report::setSwId(uint8_t sub_id)
|
||||||
|
{
|
||||||
|
_data[Offset::Function] &= 0x0f;
|
||||||
|
_data[Offset::Function] |= sub_id & 0x0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Report::address() const
|
||||||
|
{
|
||||||
|
return _data[Offset::Address];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Report::setAddress(uint8_t address)
|
||||||
|
{
|
||||||
|
_data[Offset::Address] = address;
|
||||||
|
}
|
||||||
|
|
||||||
void Report::setParams(const std::vector<uint8_t>& _params)
|
void Report::setParams(const std::vector<uint8_t>& _params)
|
||||||
{
|
{
|
||||||
assert(_params.size() <= _data.size()-HeaderLength);
|
assert(_params.size() <= _data.size()-HeaderLength);
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace logid::backend::hidpp
|
||||||
static constexpr uint8_t DeviceIndex = 1;
|
static constexpr uint8_t DeviceIndex = 1;
|
||||||
static constexpr uint8_t SubID = 2;
|
static constexpr uint8_t SubID = 2;
|
||||||
static constexpr uint8_t Feature = 2;
|
static constexpr uint8_t Feature = 2;
|
||||||
|
static constexpr uint8_t Address = 3;
|
||||||
static constexpr uint8_t Function = 3;
|
static constexpr uint8_t Function = 3;
|
||||||
static constexpr uint8_t Parameters = 4;
|
static constexpr uint8_t Parameters = 4;
|
||||||
}
|
}
|
||||||
|
@ -47,16 +48,37 @@ namespace logid::backend::hidpp
|
||||||
static constexpr uint8_t swIdMask = 0x0f;
|
static constexpr uint8_t swIdMask = 0x0f;
|
||||||
static constexpr uint8_t functionMask = 0x0f;
|
static constexpr uint8_t functionMask = 0x0f;
|
||||||
|
|
||||||
|
Report(Report::Type type, DeviceIndex device_index,
|
||||||
|
uint8_t sub_id,
|
||||||
|
uint8_t address);
|
||||||
Report(Report::Type type, DeviceIndex device_index,
|
Report(Report::Type type, DeviceIndex device_index,
|
||||||
uint8_t feature_index,
|
uint8_t feature_index,
|
||||||
uint8_t function,
|
uint8_t function,
|
||||||
uint8_t sw_id);
|
uint8_t sw_id);
|
||||||
explicit Report(const std::vector<uint8_t>& data);
|
explicit Report(const std::vector<uint8_t>& data);
|
||||||
|
|
||||||
Report::Type type() const { return static_cast<Report::Type>(_data[Offset::Type]); };
|
Report::Type type() const;
|
||||||
void setType(Report::Type type);
|
void setType(Report::Type type);
|
||||||
|
|
||||||
std::vector<uint8_t>::iterator paramBegin() { return _data.begin() + Offset::Parameters; }
|
uint8_t feature() const;
|
||||||
|
void setFeature(uint8_t feature);
|
||||||
|
|
||||||
|
uint8_t subId() const;
|
||||||
|
void setSubId(uint8_t sub_id);
|
||||||
|
|
||||||
|
uint8_t function() const;
|
||||||
|
void setFunction(uint8_t function);
|
||||||
|
|
||||||
|
uint8_t swId() const;
|
||||||
|
void setSwId(uint8_t sw_id);
|
||||||
|
|
||||||
|
uint8_t address() const;
|
||||||
|
void setAddress(uint8_t address);
|
||||||
|
|
||||||
|
std::vector<uint8_t>::iterator paramBegin()
|
||||||
|
{
|
||||||
|
return _data.begin() + Offset::Parameters;
|
||||||
|
}
|
||||||
std::vector<uint8_t>::iterator paramEnd() { return _data.end(); }
|
std::vector<uint8_t>::iterator paramEnd() { return _data.end(); }
|
||||||
void setParams(const std::vector<uint8_t>& _params);
|
void setParams(const std::vector<uint8_t>& _params);
|
||||||
|
|
||||||
|
|
62
src/logid/backend/hidpp10/Device.cpp
Normal file
62
src/logid/backend/hidpp10/Device.cpp
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#include <cassert>
|
||||||
|
#include <utility>
|
||||||
|
#include "Device.h"
|
||||||
|
#include "defs.h"
|
||||||
|
|
||||||
|
using namespace logid::backend;
|
||||||
|
using namespace logid::backend::hidpp10;
|
||||||
|
|
||||||
|
Device::Device(const std::string &path, hidpp::DeviceIndex index) :
|
||||||
|
hidpp::Device(path, index)
|
||||||
|
{
|
||||||
|
assert(version() == std::make_tuple(1, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
Device::Device(std::shared_ptr<raw::RawDevice> raw_dev,
|
||||||
|
hidpp::DeviceIndex index) : hidpp::Device(std::move(raw_dev), index)
|
||||||
|
{
|
||||||
|
assert(version() == std::make_tuple(1, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> Device::getRegister(uint8_t address,
|
||||||
|
const std::vector<uint8_t>& params)
|
||||||
|
{
|
||||||
|
assert(params.size() <= hidpp::LongParamLength);
|
||||||
|
|
||||||
|
hidpp::Report::Type type = params.size() <= hidpp::ShortParamLength ?
|
||||||
|
hidpp::Report::Type::Short : hidpp::Report::Type::Long;
|
||||||
|
|
||||||
|
uint8_t sub_id = type == hidpp::Report::Type::Short ?
|
||||||
|
GetRegisterShort : GetRegisterLong;
|
||||||
|
|
||||||
|
return accessRegister(sub_id, address, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> Device::setRegister(uint8_t address,
|
||||||
|
const std::vector<uint8_t>& params)
|
||||||
|
{
|
||||||
|
assert(params.size() <= hidpp::LongParamLength);
|
||||||
|
|
||||||
|
hidpp::Report::Type type = params.size() <= hidpp::ShortParamLength ?
|
||||||
|
hidpp::Report::Type::Short : hidpp::Report::Type::Long;
|
||||||
|
|
||||||
|
uint8_t sub_id = type == hidpp::Report::Type::Short ?
|
||||||
|
SetRegisterShort : SetRegisterLong;
|
||||||
|
|
||||||
|
return accessRegister(sub_id, address, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> Device::accessRegister(uint8_t sub_id, uint8_t address, const std::vector<uint8_t> ¶ms)
|
||||||
|
{
|
||||||
|
hidpp::Report::Type type = params.size() <= hidpp::ShortParamLength ?
|
||||||
|
hidpp::Report::Type::Short : hidpp::Report::Type::Long;
|
||||||
|
|
||||||
|
hidpp::Report request(type, deviceIndex(), sub_id, address);
|
||||||
|
std::copy(params.begin(), params.end(), request.paramBegin());
|
||||||
|
|
||||||
|
auto response = sendReport(request);
|
||||||
|
return std::vector<uint8_t>(response.paramBegin(), response.paramEnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
28
src/logid/backend/hidpp10/Device.h
Normal file
28
src/logid/backend/hidpp10/Device.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef LOGID_BACKEND_HIDPP10_DEVICE_H
|
||||||
|
#define LOGID_BACKEND_HIDPP10_DEVICE_H
|
||||||
|
|
||||||
|
#include "../hidpp/Device.h"
|
||||||
|
|
||||||
|
namespace logid {
|
||||||
|
namespace backend {
|
||||||
|
namespace hidpp10
|
||||||
|
{
|
||||||
|
class Device : public hidpp::Device
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Device(const std::string& path, hidpp::DeviceIndex index);
|
||||||
|
Device(std::shared_ptr<raw::RawDevice> raw_dev,
|
||||||
|
hidpp::DeviceIndex index);
|
||||||
|
|
||||||
|
std::vector<uint8_t> getRegister(uint8_t address,
|
||||||
|
const std::vector<uint8_t>& params);
|
||||||
|
|
||||||
|
std::vector<uint8_t> setRegister(uint8_t address,
|
||||||
|
const std::vector<uint8_t>& params);
|
||||||
|
private:
|
||||||
|
std::vector<uint8_t> accessRegister(uint8_t sub_id,
|
||||||
|
uint8_t address, const std::vector<uint8_t>& params);
|
||||||
|
};
|
||||||
|
}}}
|
||||||
|
|
||||||
|
#endif //LOGID_BACKEND_HIDPP10_DEVICE_H
|
17
src/logid/backend/hidpp10/defs.h
Normal file
17
src/logid/backend/hidpp10/defs.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef LOGID_BACKEND_HIDPP10_DEFS_H
|
||||||
|
#define LOGID_BACKEND_HIDPP10_DEFS_H
|
||||||
|
|
||||||
|
namespace logid {
|
||||||
|
namespace backend {
|
||||||
|
namespace hidpp10
|
||||||
|
{
|
||||||
|
enum SubID: uint8_t
|
||||||
|
{
|
||||||
|
SetRegisterShort = 0x80,
|
||||||
|
GetRegisterShort = 0x81,
|
||||||
|
SetRegisterLong = 0x82,
|
||||||
|
GetRegisterLong = 0x83
|
||||||
|
};
|
||||||
|
}}}
|
||||||
|
|
||||||
|
#endif //LOGID_BACKEND_HIDPP10_DEFS_H
|
|
@ -75,6 +75,8 @@ RawDevice::RawDevice(std::string path) : path (path), continue_listen (false)
|
||||||
close(fd);
|
close(fd);
|
||||||
throw std::system_error(err, std::system_category(), "RawDevice pipe open failed");
|
throw std::system_error(err, std::system_category(), "RawDevice pipe open failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
continue_listen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RawDevice::~RawDevice()
|
RawDevice::~RawDevice()
|
||||||
|
@ -106,6 +108,27 @@ std::vector<uint8_t> RawDevice::sendReport(const std::vector<uint8_t>& report)
|
||||||
return _respondToReport(report);
|
return _respondToReport(report);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DJ commands are not systematically acknowledged, do not expect a result.
|
||||||
|
void RawDevice::sendReportNoResponse(const std::vector<uint8_t>& report)
|
||||||
|
{
|
||||||
|
assert(supportedReportID(report[0]));
|
||||||
|
|
||||||
|
/* If the listener will stop, handle I/O manually.
|
||||||
|
* Otherwise, push to queue and wait for result. */
|
||||||
|
if(continue_listen)
|
||||||
|
{
|
||||||
|
std::packaged_task<std::vector<uint8_t>()> task([this, report]() {
|
||||||
|
this->_sendReport(report);
|
||||||
|
return std::vector<uint8_t>();
|
||||||
|
});
|
||||||
|
auto f = task.get_future();
|
||||||
|
write_queue.push(&task);
|
||||||
|
f.get();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_sendReport(report);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> RawDevice::_respondToReport
|
std::vector<uint8_t> RawDevice::_respondToReport
|
||||||
(const std::vector<uint8_t>& request)
|
(const std::vector<uint8_t>& request)
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,6 +29,7 @@ namespace raw
|
||||||
std::vector<uint8_t> reportDescriptor() const { return rdesc; }
|
std::vector<uint8_t> reportDescriptor() const { return rdesc; }
|
||||||
|
|
||||||
std::vector<uint8_t> sendReport(const std::vector<uint8_t>& report);
|
std::vector<uint8_t> sendReport(const std::vector<uint8_t>& report);
|
||||||
|
void sendReportNoResponse(const std::vector<uint8_t>& report);
|
||||||
void interruptRead();
|
void interruptRead();
|
||||||
|
|
||||||
void listen();
|
void listen();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user