Add ChangeHost hidpp20 feature

This commit is contained in:
pixl 2020-07-15 15:18:28 -04:00
parent f51ba0f681
commit d59daf86e2
No known key found for this signature in database
GPG Key ID: 1866C148CD593B6E
9 changed files with 191 additions and 1 deletions

View File

@ -55,6 +55,7 @@ add_executable(logid
backend/hidpp20/features/SmartShift.cpp backend/hidpp20/features/SmartShift.cpp
backend/hidpp20/features/ReprogControls.cpp backend/hidpp20/features/ReprogControls.cpp
backend/hidpp20/features/HiresScroll.cpp backend/hidpp20/features/HiresScroll.cpp
backend/hidpp20/features/ChangeHost.cpp
backend/dj/Report.cpp backend/dj/Report.cpp
util/mutex_queue.h util/mutex_queue.h
util/workqueue.cpp util/workqueue.cpp

View File

@ -189,6 +189,22 @@ Report Device::sendReport(Report& report)
return response; return response;
} }
void Device::sendReportNoResponse(Report &report)
{
switch(report.type())
{
case Report::Type::Short:
if(!(_supported_reports & HIDPP_REPORT_SHORT_SUPPORTED))
report.setType(Report::Type::Long);
break;
case Report::Type::Long:
/* Report can be truncated, but that isn't a good idea. */
assert(_supported_reports & HIDPP_REPORT_LONG_SUPPORTED);
}
_raw_device->sendReportNoResponse(report.rawReport());
}
std::string Device::name() const std::string Device::name() const
{ {
return _name; return _name;

View File

@ -85,6 +85,7 @@ namespace hidpp
eventHandlers(); eventHandlers();
Report sendReport(Report& report); Report sendReport(Report& report);
void sendReportNoResponse(Report& report);
void handleEvent(Report& report); void handleEvent(Report& report);
private: private:

View File

@ -54,4 +54,24 @@ std::vector<uint8_t> Device::callFunction(uint8_t feature_index,
auto response = this->sendReport(request); auto response = this->sendReport(request);
return std::vector<uint8_t>(response.paramBegin(), response.paramEnd()); return std::vector<uint8_t>(response.paramBegin(), response.paramEnd());
}
void Device::callFunctionNoResponse(uint8_t feature_index, uint8_t function,
std::vector<uint8_t> &params)
{
hidpp::Report::Type type;
assert(params.size() <= hidpp::LongParamLength);
if(params.size() <= hidpp::ShortParamLength)
type = hidpp::Report::Type::Short;
else if(params.size() <= hidpp::LongParamLength)
type = hidpp::Report::Type::Long;
else
throw hidpp::Report::InvalidReportID();
hidpp::Report request(type, deviceIndex(), feature_index, function,
LOGID_HIDPP_SOFTWARE_ID);
std::copy(params.begin(), params.end(), request.paramBegin());
this->sendReportNoResponse(request);
} }

View File

@ -34,6 +34,10 @@ namespace hidpp20 {
std::vector<uint8_t> callFunction(uint8_t feature_index, std::vector<uint8_t> callFunction(uint8_t feature_index,
uint8_t function, uint8_t function,
std::vector<uint8_t>& params); std::vector<uint8_t>& params);
void callFunctionNoResponse(uint8_t feature_index,
uint8_t function,
std::vector<uint8_t>& params);
}; };
}}} }}}

View File

@ -33,11 +33,18 @@ uint16_t UnsupportedFeature::code() const noexcept
return _f_id; return _f_id;
} }
std::vector<uint8_t> Feature::callFunction(uint8_t function_id, std::vector<uint8_t>& params) std::vector<uint8_t> Feature::callFunction(uint8_t function_id,
std::vector<uint8_t>& params)
{ {
return _device->callFunction(_index, function_id, params); return _device->callFunction(_index, function_id, params);
} }
void Feature::callFunctionNoResponse(uint8_t function_id,
std::vector<uint8_t>& params)
{
_device->callFunctionNoResponse(_index, function_id, params);
}
Feature::Feature(Device* dev, uint16_t _id) : _device (dev) Feature::Feature(Device* dev, uint16_t _id) : _device (dev)
{ {
_index = hidpp20::FeatureID::ROOT; _index = hidpp20::FeatureID::ROOT;

View File

@ -45,6 +45,8 @@ namespace hidpp20 {
explicit Feature(Device* dev, uint16_t _id); explicit Feature(Device* dev, uint16_t _id);
std::vector<uint8_t> callFunction(uint8_t function_id, std::vector<uint8_t> callFunction(uint8_t function_id,
std::vector<uint8_t>& params); std::vector<uint8_t>& params);
void callFunctionNoResponse(uint8_t function_id,
std::vector<uint8_t>& params);
private: private:
Device* _device; Device* _device;
uint8_t _index; uint8_t _index;

View File

@ -0,0 +1,78 @@
/*
* Copyright 2019-2020 PixlOne
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ChangeHost.h"
#include "../Error.h"
using namespace logid::backend::hidpp20;
ChangeHost::ChangeHost(Device *dev) : Feature(dev, ID), _host_count (0)
{
}
ChangeHost::HostInfo ChangeHost::getHostInfo()
{
std::vector<uint8_t> params(0);
auto response = callFunction(GetHostInfo, params);
HostInfo info{};
info.hostCount = response[0];
info.currentHost = response[1];
info.enhancedHostSwitch = response[2] & 1;
if(!_host_count)
_host_count = info.hostCount;
return info;
}
void ChangeHost::setHost(uint8_t host)
{
/* Expect connection to be severed here, send without response
*
* Since there is no response, we have to emulate any kind of
* error that may be returned (i.e. InvalidArgument as per the docs)
*/
if(!_host_count)
getHostInfo();
if(host >= _host_count)
throw hidpp20::Error(hidpp20::Error::InvalidArgument);
std::vector<uint8_t> params = {host};
callFunctionNoResponse(SetCurrentHost, params);
}
std::vector<uint8_t> ChangeHost::getCookies()
{
if(!_host_count)
getHostInfo();
std::vector<uint8_t> params(0);
auto response = callFunction(GetCookies, params);
response.resize(_host_count);
return response;
}
void ChangeHost::setCookie(uint8_t host, uint8_t cookie)
{
std::vector<uint8_t> params = {host, cookie};
callFunction(SetCookie, params);
}

View File

@ -0,0 +1,61 @@
/*
* Copyright 2019-2020 PixlOne
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef LOGID_BACKEND_HIDPP20_FEATURE_CHANGEHOST_H
#define LOGID_BACKEND_HIDPP20_FEATURE_CHANGEHOST_H
#include "../feature_defs.h"
#include "../Feature.h"
namespace logid {
namespace backend {
namespace hidpp20
{
class ChangeHost : public Feature
{
public:
static const uint16_t ID = FeatureID::CHANGE_HOST;
virtual uint16_t getID() { return ID; }
ChangeHost(Device* dev);
enum Function {
GetHostInfo = 0,
SetCurrentHost = 1,
GetCookies = 2,
SetCookie = 3
};
struct HostInfo
{
uint8_t hostCount;
uint8_t currentHost;
bool enhancedHostSwitch;
};
HostInfo getHostInfo();
void setHost(uint8_t host);
std::vector<uint8_t> getCookies();
void setCookie(uint8_t host, uint8_t cookie);
private:
uint8_t _host_count;
};
}}}
#endif //LOGID_BACKEND_HIDPP20_FEATURE_CHANGEHOST_H