mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-04-29 14:59:26 -04:00
192 lines
4.2 KiB
C++
192 lines
4.2 KiB
C++
#pragma once
|
|
|
|
#include <list>
|
|
#include <memory>
|
|
#include <mutex>
|
|
|
|
#include "Common/precompiled.h"
|
|
|
|
namespace nsyshid
|
|
{
|
|
typedef struct
|
|
{
|
|
/* +0x00 */ uint32be handle;
|
|
/* +0x04 */ uint32 ukn04;
|
|
/* +0x08 */ uint16 vendorId; // little-endian ?
|
|
/* +0x0A */ uint16 productId; // little-endian ?
|
|
/* +0x0C */ uint8 ifIndex;
|
|
/* +0x0D */ uint8 subClass;
|
|
/* +0x0E */ uint8 protocol;
|
|
/* +0x0F */ uint8 paddingGuessed0F;
|
|
/* +0x10 */ uint16be maxPacketSizeRX;
|
|
/* +0x12 */ uint16be maxPacketSizeTX;
|
|
} HID_t;
|
|
|
|
struct TransferCommand
|
|
{
|
|
uint8* data;
|
|
uint32 length;
|
|
|
|
TransferCommand(uint8* data, uint32 length)
|
|
: data(data), length(length)
|
|
{
|
|
}
|
|
virtual ~TransferCommand() = default;
|
|
};
|
|
|
|
struct ReadMessage final : TransferCommand
|
|
{
|
|
sint32 bytesRead;
|
|
|
|
ReadMessage(uint8* data, uint32 length, sint32 bytesRead)
|
|
: bytesRead(bytesRead), TransferCommand(data, length)
|
|
{
|
|
}
|
|
using TransferCommand::TransferCommand;
|
|
};
|
|
|
|
struct WriteMessage final : TransferCommand
|
|
{
|
|
sint32 bytesWritten;
|
|
|
|
WriteMessage(uint8* data, uint32 length, sint32 bytesWritten)
|
|
: bytesWritten(bytesWritten), TransferCommand(data, length)
|
|
{
|
|
}
|
|
using TransferCommand::TransferCommand;
|
|
};
|
|
|
|
struct ReportMessage final : TransferCommand
|
|
{
|
|
uint8 reportType;
|
|
uint8 reportId;
|
|
|
|
ReportMessage(uint8 reportType, uint8 reportId, uint8* data, uint32 length)
|
|
: reportType(reportType), reportId(reportId), TransferCommand(data, length)
|
|
{
|
|
}
|
|
using TransferCommand::TransferCommand;
|
|
};
|
|
|
|
static_assert(offsetof(HID_t, vendorId) == 0x8, "");
|
|
static_assert(offsetof(HID_t, productId) == 0xA, "");
|
|
static_assert(offsetof(HID_t, ifIndex) == 0xC, "");
|
|
static_assert(offsetof(HID_t, protocol) == 0xE, "");
|
|
|
|
class Device
|
|
{
|
|
public:
|
|
Device() = delete;
|
|
|
|
Device(uint16 vendorId,
|
|
uint16 productId,
|
|
uint8 interfaceIndex,
|
|
uint8 interfaceSubClass,
|
|
uint8 protocol);
|
|
|
|
Device(const Device& device) = delete;
|
|
|
|
Device& operator=(const Device& device) = delete;
|
|
|
|
virtual ~Device() = default;
|
|
|
|
HID_t* m_hid; // this info is passed to applications and must remain intact
|
|
|
|
uint16 m_vendorId;
|
|
uint16 m_productId;
|
|
uint8 m_interfaceIndex;
|
|
uint8 m_interfaceSubClass;
|
|
uint8 m_protocol;
|
|
uint16 m_maxPacketSizeRX;
|
|
uint16 m_maxPacketSizeTX;
|
|
|
|
virtual void AssignHID(HID_t* hid);
|
|
|
|
virtual bool Open() = 0;
|
|
|
|
virtual void Close() = 0;
|
|
|
|
virtual bool IsOpened() = 0;
|
|
|
|
enum class ReadResult
|
|
{
|
|
Success,
|
|
Error,
|
|
ErrorTimeout,
|
|
};
|
|
|
|
virtual ReadResult Read(ReadMessage* message) = 0;
|
|
|
|
enum class WriteResult
|
|
{
|
|
Success,
|
|
Error,
|
|
ErrorTimeout,
|
|
};
|
|
|
|
virtual WriteResult Write(WriteMessage* message) = 0;
|
|
|
|
virtual bool GetDescriptor(uint8 descType,
|
|
uint8 descIndex,
|
|
uint16 lang,
|
|
uint8* output,
|
|
uint32 outputMaxLength) = 0;
|
|
|
|
virtual bool SetIdle(uint8 ifIndex,
|
|
uint8 reportId,
|
|
uint8 duration) = 0;
|
|
|
|
virtual bool SetProtocol(uint8 ifIndex, uint8 protocol) = 0;
|
|
|
|
virtual bool SetReport(ReportMessage* message) = 0;
|
|
};
|
|
|
|
class Backend
|
|
{
|
|
public:
|
|
Backend();
|
|
|
|
Backend(const Backend& backend) = delete;
|
|
|
|
Backend& operator=(const Backend& backend) = delete;
|
|
|
|
virtual ~Backend() = default;
|
|
|
|
void DetachAllDevices();
|
|
|
|
// called from nsyshid when this backend is attached - do not call this yourself!
|
|
void OnAttach();
|
|
|
|
// called from nsyshid when this backend is detached - do not call this yourself!
|
|
void OnDetach();
|
|
|
|
bool IsBackendAttached();
|
|
|
|
virtual bool IsInitialisedOk() = 0;
|
|
|
|
protected:
|
|
// try to attach a device - only works if this backend is attached
|
|
bool AttachDevice(const std::shared_ptr<Device>& device);
|
|
|
|
void DetachDevice(const std::shared_ptr<Device>& device);
|
|
|
|
std::shared_ptr<Device> FindDevice(std::function<bool(const std::shared_ptr<Device>&)> isWantedDevice);
|
|
|
|
bool FindDeviceById(uint16 vendorId, uint16 productId);
|
|
|
|
bool IsDeviceWhitelisted(uint16 vendorId, uint16 productId);
|
|
|
|
// called from OnAttach() - attach devices that your backend can see here
|
|
virtual void AttachVisibleDevices() = 0;
|
|
|
|
private:
|
|
std::list<std::shared_ptr<Device>> m_devices;
|
|
std::recursive_mutex m_devicesMutex;
|
|
bool m_isAttached;
|
|
};
|
|
|
|
namespace backend
|
|
{
|
|
void AttachDefaultBackends();
|
|
}
|
|
} // namespace nsyshid
|