/*
* Copyright 2019-2023 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 .
*
*/
#ifndef LOGID_BACKEND_DJ_RECEIVER_H
#define LOGID_BACKEND_DJ_RECEIVER_H
#include
#include
namespace logid::backend::hidpp {
enum DeviceType : uint8_t {
DeviceUnknown = 0x00,
DeviceKeyboard = 0x01,
DeviceMouse = 0x02,
DeviceNumpad = 0x03,
DevicePresenter = 0x04,
/* 0x05-0x07 is reserved */
DeviceTrackball = 0x08,
DeviceTouchpad = 0x09
};
struct DeviceConnectionEvent {
DeviceIndex index{};
uint16_t pid{};
DeviceType deviceType = DeviceUnknown;
bool unifying{};
bool softwarePresent{};
bool encrypted{};
bool linkEstablished{};
bool withPayload{};
bool fromTimeoutCheck = false; // Fake field
};
}
namespace logid::backend::hidpp10 {
struct DeviceDiscoveryEvent {
hidpp::DeviceType deviceType = hidpp::DeviceUnknown;
uint8_t seq_num{};
uint64_t address{};
uint16_t pid{};
uint8_t authentication{};
std::string name;
};
enum PairingError : uint8_t {
NoPairingError = 0x00,
Timeout = 0x01,
UnsupportedDevice = 0x02,
TooManyDevices = 0x03,
/* Errors 0x04-0x05 are reserved */
ConnectionSeqTimeout = 0x06,
};
struct PairStatusEvent {
bool pairing{};
PairingError error = NoPairingError;
};
struct BoltPairStatusEvent {
bool pairing{};
uint8_t error;
};
struct DiscoveryStatusEvent {
bool discovering{};
uint8_t error{}; // don't know the error codes
};
class InvalidReceiver : public std::exception {
public:
[[nodiscard]] const char* what() const noexcept override;
};
class Receiver : public Device {
public:
/* 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 Events : uint8_t {
// These events are identical to their DJ counterparts
DeviceDisconnection = 0x40,
DeviceConnection = 0x41,
PairStatus = 0x4a,
PasskeyRequest = 0x4d,
DeviceDiscovered = 0x4f,
DiscoveryStatus = 0x53,
BoltPairStatus = 0x54,
};
enum Registers : uint8_t {
EnableHidppNotifications = 0x00,
ConnectionState = 0x02,
DevicePairing = 0xb2,
DeviceActivity = 0xb3,
PairingInfo = 0xb5,
BoltDeviceDiscovery = 0xc0,
BoltDevicePairing = 0xc1,
};
struct NotificationFlags {
bool deviceBatteryStatus;
bool receiverWirelessNotifications;
bool receiverSoftwarePresent;
};
NotificationFlags getNotificationFlags();
void setNotifications(NotificationFlags flags);
void enumerate();
uint8_t getConnectionState(hidpp::DeviceIndex index);
void startPairing(uint8_t timeout = 0);
void startBoltPairing(const DeviceDiscoveryEvent& discovery);
void stopPairing();
void startDiscover(uint8_t timeout = 0);
void stopDiscover();
void disconnect(hidpp::DeviceIndex index);
std::map getDeviceActivity();
[[nodiscard]] bool bolt() const;
struct PairingInfo {
uint8_t destinationId;
uint8_t reportInterval;
uint16_t pid;
hidpp::DeviceType deviceType;
};
enum class PowerSwitchLocation : uint8_t {
Reserved = 0x0,
Base = 0x1,
TopCase = 0x2,
TopRightEdge = 0x3,
Other = 0x4,
TopLeft = 0x5,
BottomLeft = 0x6,
TopRight = 0x7,
BottomRight = 0x8,
TopEdge = 0x9,
RightEdge = 0xa,
LeftEdge = 0xb,
BottomEdge = 0xc
};
struct ExtendedPairingInfo {
uint32_t serialNumber;
uint8_t reportTypes[4];
PowerSwitchLocation powerSwitchLocation;
};
struct PairingInfo getPairingInfo(hidpp::DeviceIndex index);
struct ExtendedPairingInfo getExtendedPairingInfo(hidpp::DeviceIndex index);
std::string getDeviceName(hidpp::DeviceIndex index);
static hidpp::DeviceIndex deviceDisconnectionEvent(const hidpp::Report& report);
static hidpp::DeviceConnectionEvent deviceConnectionEvent(const hidpp::Report& report);
static PairStatusEvent pairStatusEvent(const hidpp::Report& report);
static BoltPairStatusEvent boltPairStatusEvent(const hidpp::Report& report);
static DiscoveryStatusEvent discoveryStatusEvent(const hidpp::Report& report);
static bool fillDeviceDiscoveryEvent(DeviceDiscoveryEvent& event,
const hidpp::Report& report);
static std::string passkeyEvent(const hidpp::Report& report);
protected:
Receiver(const std::string& path,
const std::shared_ptr& monitor,
double timeout);
private:
void _receiverCheck();
bool _is_bolt = false;
public:
template
static std::shared_ptr make(Args... args) {
auto receiver = makeDerived(std::forward(args)...);
receiver->_receiverCheck();
return receiver;
}
};
}
#endif //LOGID_BACKEND_DJ_RECEIVER_H