Skip to content

Commit

Permalink
Add ChangeHost hidpp20 feature
Browse files Browse the repository at this point in the history
  • Loading branch information
PixlOne committed Jul 15, 2020
1 parent f51ba0f commit d59daf8
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/logid/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ add_executable(logid
backend/hidpp20/features/SmartShift.cpp
backend/hidpp20/features/ReprogControls.cpp
backend/hidpp20/features/HiresScroll.cpp
backend/hidpp20/features/ChangeHost.cpp
backend/dj/Report.cpp
util/mutex_queue.h
util/workqueue.cpp
Expand Down
16 changes: 16 additions & 0 deletions src/logid/backend/hidpp/Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,22 @@ Report Device::sendReport(Report& report)
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
{
return _name;
Expand Down
1 change: 1 addition & 0 deletions src/logid/backend/hidpp/Device.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ namespace hidpp
eventHandlers();

Report sendReport(Report& report);
void sendReportNoResponse(Report& report);

void handleEvent(Report& report);
private:
Expand Down
20 changes: 20 additions & 0 deletions src/logid/backend/hidpp20/Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,24 @@ std::vector<uint8_t> Device::callFunction(uint8_t feature_index,

auto response = this->sendReport(request);
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);
}
4 changes: 4 additions & 0 deletions src/logid/backend/hidpp20/Device.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ namespace hidpp20 {
std::vector<uint8_t> callFunction(uint8_t feature_index,
uint8_t function,
std::vector<uint8_t>& params);

void callFunctionNoResponse(uint8_t feature_index,
uint8_t function,
std::vector<uint8_t>& params);
};
}}}

Expand Down
9 changes: 8 additions & 1 deletion src/logid/backend/hidpp20/Feature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,18 @@ uint16_t UnsupportedFeature::code() const noexcept
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);
}

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)
{
_index = hidpp20::FeatureID::ROOT;
Expand Down
2 changes: 2 additions & 0 deletions src/logid/backend/hidpp20/Feature.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ namespace hidpp20 {
explicit Feature(Device* dev, uint16_t _id);
std::vector<uint8_t> callFunction(uint8_t function_id,
std::vector<uint8_t>& params);
void callFunctionNoResponse(uint8_t function_id,
std::vector<uint8_t>& params);
private:
Device* _device;
uint8_t _index;
Expand Down
78 changes: 78 additions & 0 deletions src/logid/backend/hidpp20/features/ChangeHost.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
61 changes: 61 additions & 0 deletions src/logid/backend/hidpp20/features/ChangeHost.h
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit d59daf8

Please sign in to comment.