-
Notifications
You must be signed in to change notification settings - Fork 603
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
nsyshid: Add backends for cross platform USB passthrough support (#950)
- Loading branch information
1 parent
2a735f1
commit 98b5a87
Showing
17 changed files
with
2,285 additions
and
511 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# SPDX-FileCopyrightText: 2022 Andrea Pappacoda <[email protected]> | ||
# SPDX-License-Identifier: ISC | ||
|
||
find_package(libusb CONFIG) | ||
if (NOT libusb_FOUND) | ||
find_package(PkgConfig) | ||
if (PKG_CONFIG_FOUND) | ||
pkg_search_module(libusb IMPORTED_TARGET GLOBAL libusb-1.0 libusb) | ||
if (libusb_FOUND) | ||
add_library(libusb::libusb ALIAS PkgConfig::libusb) | ||
endif () | ||
endif () | ||
endif () | ||
|
||
find_package_handle_standard_args(libusb | ||
REQUIRED_VARS | ||
libusb_LINK_LIBRARIES | ||
libusb_FOUND | ||
VERSION_VAR libusb_VERSION | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#include "nsyshid.h" | ||
#include "Backend.h" | ||
|
||
#if NSYSHID_ENABLE_BACKEND_LIBUSB | ||
|
||
#include "BackendLibusb.h" | ||
|
||
#endif | ||
|
||
#if NSYSHID_ENABLE_BACKEND_WINDOWS_HID | ||
|
||
#include "BackendWindowsHID.h" | ||
|
||
#endif | ||
|
||
namespace nsyshid::backend | ||
{ | ||
void AttachDefaultBackends() | ||
{ | ||
#if NSYSHID_ENABLE_BACKEND_LIBUSB | ||
// add libusb backend | ||
{ | ||
auto backendLibusb = std::make_shared<backend::libusb::BackendLibusb>(); | ||
if (backendLibusb->IsInitialisedOk()) | ||
{ | ||
AttachBackend(backendLibusb); | ||
} | ||
} | ||
#endif // NSYSHID_ENABLE_BACKEND_LIBUSB | ||
#if NSYSHID_ENABLE_BACKEND_WINDOWS_HID | ||
// add windows hid backend | ||
{ | ||
auto backendWindowsHID = std::make_shared<backend::windows::BackendWindowsHID>(); | ||
if (backendWindowsHID->IsInitialisedOk()) | ||
{ | ||
AttachBackend(backendWindowsHID); | ||
} | ||
} | ||
#endif // NSYSHID_ENABLE_BACKEND_WINDOWS_HID | ||
} | ||
} // namespace nsyshid::backend |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
#ifndef CEMU_NSYSHID_BACKEND_H | ||
#define CEMU_NSYSHID_BACKEND_H | ||
|
||
#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; | ||
|
||
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(uint8* data, sint32 length, sint32& bytesRead) = 0; | ||
|
||
enum class WriteResult | ||
{ | ||
Success, | ||
Error, | ||
ErrorTimeout, | ||
}; | ||
|
||
virtual WriteResult Write(uint8* data, sint32 length, sint32& bytesWritten) = 0; | ||
|
||
virtual bool GetDescriptor(uint8 descType, | ||
uint8 descIndex, | ||
uint8 lang, | ||
uint8* output, | ||
uint32 outputMaxLength) = 0; | ||
|
||
virtual bool SetProtocol(uint32 ifIndef, uint32 protocol) = 0; | ||
|
||
virtual bool SetReport(uint8* reportData, sint32 length, uint8* originalData, sint32 originalLength) = 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 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 | ||
|
||
#endif // CEMU_NSYSHID_BACKEND_H |
Oops, something went wrong.