Implement dj::Receiver class
Again, many things were done here.
This commit is contained in:
		@@ -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();
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user