Support getting version of HID++ 1.0 devices

This commit is contained in:
pixl 2020-06-18 04:47:04 -04:00
parent 7571be1f54
commit ecc5062e0f
No known key found for this signature in database
GPG Key ID: 1866C148CD593B6E
8 changed files with 165 additions and 10 deletions

View File

@ -17,6 +17,7 @@ add_executable(logid
backend/raw/RawDevice.cpp backend/raw/RawDevice.cpp
backend/hidpp/Device.cpp backend/hidpp/Device.cpp
backend/hidpp/Report.cpp backend/hidpp/Report.cpp
backend/hidpp10/Error.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

View File

@ -3,6 +3,7 @@
#include "DeviceMonitor.h" #include "DeviceMonitor.h"
#include "util.h" #include "util.h"
#include "backend/hidpp10/Error.h"
#define NON_WIRELESS_DEV(index) (index) == HIDPP::DefaultDevice ? "default" : "corded" #define NON_WIRELESS_DEV(index) (index) == HIDPP::DefaultDevice ? "default" : "corded"
@ -128,7 +129,13 @@ void DeviceMonitor::addDevice(std::string path)
std::thread([device]() { device->listen(); }).detach(); std::thread([device]() { device->listen(); }).detach();
} }
catch(backend::hidpp::Device::InvalidDevice &e) catch(hidpp10::Error &e)
{
if(e.code() == hidpp10::Error::UnknownDevice) {}
else
throw;
}
catch(hidpp::Device::InvalidDevice &e)
{ {
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());
} }

View File

@ -2,6 +2,8 @@
#include "Device.h" #include "Device.h"
#include "Report.h" #include "Report.h"
#include "../hidpp20/features/Root.h" #include "../hidpp20/features/Root.h"
#include "../hidpp20/Error.h"
#include "../hidpp10/Error.h"
using namespace logid::backend; using namespace logid::backend;
using namespace logid::backend::hidpp; using namespace logid::backend::hidpp;
@ -30,13 +32,24 @@ Device::Device(const std::string& path, DeviceIndex index):
if(!supported_reports) if(!supported_reports)
throw InvalidDevice(InvalidDevice::NoHIDPPReport); throw InvalidDevice(InvalidDevice::NoHIDPPReport);
Report versionRequest(Report::Type::Short, index, hidpp20::FeatureID::ROOT, try
hidpp20::Root::Ping, LOGID_HIDPP_SOFTWARE_ID); {
Report versionRequest(Report::Type::Short, index, hidpp20::FeatureID::ROOT,
hidpp20::Root::Ping, LOGID_HIDPP_SOFTWARE_ID);
///TODO: Catch error auto versionResponse = sendReport(versionRequest);
auto versionResponse = sendReport(versionRequest); auto versionResponse_params = versionResponse.paramBegin();
auto versionResponse_params = versionResponse.paramBegin(); _version = std::make_tuple(versionResponse_params[0], versionResponse_params[1]);
_version = std::make_tuple(versionResponse_params[0], versionResponse_params[1]); }
catch(hidpp10::Error &e)
{
// Valid HID++ 1.0 devices should send an InvalidSubID error
if(e.code() != hidpp10::Error::InvalidSubID)
throw;
// HID++ 2.0 is not supported, assume HID++ 1.0
_version = std::make_tuple(1, 0);
}
// Pass all HID++ events with device index to this device. // Pass all HID++ events with device index to this device.
RawEventHandler rawEventHandler; RawEventHandler rawEventHandler;
@ -88,7 +101,18 @@ Report Device::sendReport(Report& report)
} }
auto raw_response = raw_device->sendReport(report.rawReport()); auto raw_response = raw_device->sendReport(report.rawReport());
return Report(raw_response);
Report response(raw_response);
Report::hidpp10_error hidpp10Error{};
if(response.isError10(&hidpp10Error))
throw hidpp10::Error(hidpp10Error.error_code);
Report::hidpp20_error hidpp20Error{};
if(response.isError20(&hidpp20Error))
throw hidpp10::Error(hidpp20Error.error_code);
return response;
} }
void Device::listen() void Device::listen()

View File

@ -2,6 +2,8 @@
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include "Report.h" #include "Report.h"
#include "../hidpp10/Error.h"
#include "../hidpp20/Error.h"
using namespace logid::backend::hidpp; using namespace logid::backend::hidpp;
using namespace logid::backend; using namespace logid::backend;
@ -159,9 +161,31 @@ void Report::setParams(const std::vector<uint8_t>& _params)
_data[Offset::Parameters + i] = _params[i]; _data[Offset::Parameters + i] = _params[i];
} }
bool Report::isError10(Report::hidpp10_error *error)
{
assert(error != nullptr);
if(_data[Offset::Type] != Type::Short ||
_data[Offset::SubID] != hidpp10::ErrorID)
return false;
error->sub_id = _data[3];
error->address = _data[4];
error->error_code = _data[5];
return true;
}
bool Report::isError20(Report::hidpp20_error* error) bool Report::isError20(Report::hidpp20_error* error)
{ {
if(_data[Offset::Type] != Type::Long || if(_data[Offset::Type] != Type::Long ||
_data[Offset::Feature] != 0xff) _data[Offset::Feature] != hidpp20::ErrorID)
return false; return false;
error->feature_index= _data[3];
error->function = (_data[4] >> 4) & 0x0f;
error->software_id = _data[4] & 0x0f;
error->error_code = _data[5];
return true;
} }

View File

@ -18,6 +18,7 @@ namespace logid::backend::hidpp
{ {
static constexpr uint8_t Type = 0; static constexpr uint8_t Type = 0;
static constexpr uint8_t DeviceIndex = 1; static constexpr uint8_t DeviceIndex = 1;
static constexpr uint8_t SubID = 2;
static constexpr uint8_t Feature = 2; static constexpr uint8_t Feature = 2;
static constexpr uint8_t Function = 3; static constexpr uint8_t Function = 3;
static constexpr uint8_t Parameters = 4; static constexpr uint8_t Parameters = 4;
@ -59,6 +60,13 @@ namespace logid::backend::hidpp
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);
struct hidpp10_error
{
uint8_t sub_id, address, error_code;
};
bool isError10(hidpp10_error* error);
struct hidpp20_error struct hidpp20_error
{ {
uint8_t feature_index, function, software_id, error_code; uint8_t feature_index, function, software_id, error_code;

View File

@ -1,7 +1,7 @@
#ifndef LOGID_HIDPP_DEFS_H #ifndef LOGID_HIDPP_DEFS_H
#define LOGID_HIDPP_DEFS_H #define LOGID_HIDPP_DEFS_H
#define LOGID_HIDPP_SOFTWARE_ID 1 #define LOGID_HIDPP_SOFTWARE_ID 0
namespace logid::backend::hidpp namespace logid::backend::hidpp
{ {

View File

@ -0,0 +1,50 @@
#include <cassert>
#include <string>
#include "Error.h"
using namespace logid::backend::hidpp10;
Error::Error(uint8_t code): _code(code)
{
assert(code != Success);
}
const char* Error::what() const noexcept
{
switch(_code)
{
case Success:
return "Success";
case InvalidSubID:
return "Invalid sub ID";
case InvalidAddress:
return "Invalid address";
case InvalidValue:
return "Invalid value";
case ConnectFail:
return "Connection failure";
case TooManyDevices:
return "Too many devices";
case AlreadyExists:
return "Already exists";
case Busy:
return "Busy";
case UnknownDevice:
return "Unknown device";
case ResourceError:
return "Resource error";
case RequestUnavailable:
return "Request unavailable";
case InvalidParameterValue:
return "Invalid parameter value";
case WrongPINCode:
return "Wrong PIN code";
default:
return std::string("Unknown error code " + std::to_string(_code)).c_str();
}
}
uint8_t Error::code() const noexcept
{
return _code;
}

View File

@ -0,0 +1,41 @@
#ifndef LOGID_BACKEND_HIDPP10_ERROR_H
#define LOGID_BACKEND_HIDPP10_ERROR_H
#include <cstdint>
namespace logid {
namespace backend {
namespace hidpp10 {
static constexpr uint8_t ErrorID = 0x8f;
class Error: public std::exception
{
public:
enum ErrorCode: uint8_t
{
Success = 0x00,
InvalidSubID = 0x01,
InvalidAddress = 0x02,
InvalidValue = 0x03,
ConnectFail = 0x04,
TooManyDevices = 0x05,
AlreadyExists = 0x06,
Busy = 0x07,
UnknownDevice = 0x08,
ResourceError = 0x09,
RequestUnavailable = 0x0A,
InvalidParameterValue = 0x0B,
WrongPINCode = 0x0C
};
Error(uint8_t code);
virtual const char* what() const noexcept;
uint8_t code() const noexcept;
private:
uint8_t _code;
};
}}}
#endif //LOGID_BACKEND_HIDPP10_ERROR_H