You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

213 lines
6.1 KiB

/*
* 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_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
{
struct EventHandler
{
std::function<bool(Report&)> condition;
std::function<void(Report&)> callback;
};
class InvalidReceiver : public std::exception
{
public:
enum Reason
{
NoDJReports
};
explicit InvalidReceiver(Reason reason);
const char* what() const noexcept override;
Reason code() const noexcept;
private:
Reason _reason;
};
class Receiver final
{
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 enumerateDj();
struct ConnectionStatusEvent
{
hidpp::DeviceIndex index;
bool linkLost;
};
ConnectionStatusEvent connectionStatusEvent(dj::Report& report);
/* 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 NotificationFlags
{
bool deviceBatteryStatus;
bool receiverWirelessNotifications;
bool receiverSoftwarePresent;
};
NotificationFlags getHidppNotifications();
void enableHidppNotifications(NotificationFlags flags);
void enumerateHidpp();
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 PairingInfo
{
uint8_t destinationId;
uint8_t reportInterval;
uint16_t pid;
DeviceType::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);
void listen();
void stopListening();
void addDjEventHandler(const std::string& nickname,
const std::shared_ptr<EventHandler>& handler);
void removeDjEventHandler(const std::string& nickname);
const std::map<std::string, std::shared_ptr<EventHandler>>&
djEventHandlers();
void addHidppEventHandler(const std::string& nickname,
const std::shared_ptr<hidpp::EventHandler>& handler);
void removeHidppEventHandler(const std::string& nickname);
const std::map<std::string, std::shared_ptr<hidpp::EventHandler>>&
hidppEventHandlers();
std::shared_ptr<raw::RawDevice> rawDevice() const;
private:
void _sendDjRequest(hidpp::DeviceIndex index, uint8_t function,
const std::vector<uint8_t>&& params);
void _handleDjEvent(dj::Report& report);
void _handleHidppEvent(hidpp::Report& report);
std::map<std::string, std::shared_ptr<EventHandler>>
_dj_event_handlers;
std::map<std::string, std::shared_ptr<hidpp::EventHandler>>
_hidpp_event_handlers;
std::shared_ptr<raw::RawDevice> _raw_device;
hidpp10::Device _hidpp10_device;
};
}
namespace hidpp
{
struct DeviceConnectionEvent
{
hidpp::DeviceIndex index;
uint16_t pid;
dj::DeviceType::DeviceType deviceType;
bool unifying;
bool softwarePresent;
bool encrypted;
bool linkEstablished;
bool withPayload;
bool fromTimeoutCheck = false; // Fake field
};
}}}
#endif //LOGID_BACKEND_DJ_RECEIVER_H