Skip to content

Commit

Permalink
nsyshid: Add backends for cross platform USB passthrough support (#950)
Browse files Browse the repository at this point in the history
  • Loading branch information
ssievert42 committed Sep 18, 2023
1 parent 2a735f1 commit 98b5a87
Show file tree
Hide file tree
Showing 17 changed files with 2,285 additions and 511 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ jobs:
- name: "Install system dependencies"
run: |
brew update
brew install llvm@15 ninja nasm molten-vk
brew install llvm@15 ninja nasm molten-vk automake libtool
- name: "Bootstrap vcpkg"
run: |
Expand Down
2 changes: 1 addition & 1 deletion BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ You can skip this section if you have an Intel Mac. Every time you compile, you

### Installing dependencies

`brew install boost git cmake llvm ninja nasm molten-vk`
`brew install boost git cmake llvm ninja nasm molten-vk automake libtool`

### Build Cemu using cmake and clang
1. `git clone --recursive https://github.com/cemu-project/Cemu`
Expand Down
17 changes: 17 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,23 @@ if (WIN32)
endif()
option(ENABLE_CUBEB "Enabled cubeb backend" ON)

# usb hid backends
if (WIN32)
option(ENABLE_NSYSHID_WINDOWS_HID "Enables the native Windows HID backend for nsyshid" ON)
endif ()
# libusb and windows hid backends shouldn't be active at the same time; otherwise we'd see all devices twice!
if (NOT ENABLE_NSYSHID_WINDOWS_HID)
option(ENABLE_NSYSHID_LIBUSB "Enables the libusb backend for nsyshid" ON)
else ()
set(ENABLE_NSYSHID_LIBUSB OFF CACHE BOOL "" FORCE)
endif ()
if (ENABLE_NSYSHID_WINDOWS_HID)
add_compile_definitions(NSYSHID_ENABLE_BACKEND_WINDOWS_HID)
endif ()
if (ENABLE_NSYSHID_LIBUSB)
add_compile_definitions(NSYSHID_ENABLE_BACKEND_LIBUSB)
endif ()

option(ENABLE_WXWIDGETS "Build with wxWidgets UI (Currently required)" ON)

set(THREADS_PREFER_PTHREAD_FLAG true)
Expand Down
20 changes: 20 additions & 0 deletions cmake/Findlibusb.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# SPDX-FileCopyrightText: 2022 Andrea Pappacoda <andrea@pappacoda.it>
# 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
)
19 changes: 19 additions & 0 deletions src/Cafe/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,14 @@ add_library(CemuCafe
OS/libs/nn_uds/nn_uds.h
OS/libs/nsyshid/nsyshid.cpp
OS/libs/nsyshid/nsyshid.h
OS/libs/nsyshid/Backend.h
OS/libs/nsyshid/AttachDefaultBackends.cpp
OS/libs/nsyshid/Whitelist.cpp
OS/libs/nsyshid/Whitelist.h
OS/libs/nsyshid/BackendLibusb.cpp
OS/libs/nsyshid/BackendLibusb.h
OS/libs/nsyshid/BackendWindowsHID.cpp
OS/libs/nsyshid/BackendWindowsHID.h
OS/libs/nsyskbd/nsyskbd.cpp
OS/libs/nsyskbd/nsyskbd.h
OS/libs/nsysnet/nsysnet.cpp
Expand Down Expand Up @@ -524,6 +532,17 @@ if (ENABLE_WAYLAND)
target_link_libraries(CemuCafe PUBLIC Wayland::Client)
endif()

if (ENABLE_NSYSHID_LIBUSB)
if (ENABLE_VCPKG)
find_package(libusb CONFIG REQUIRED)
target_include_directories(CemuCafe PRIVATE ${LIBUSB_INCLUDE_DIRS})
target_link_libraries(CemuCafe PRIVATE ${LIBUSB_LIBRARIES})
else ()
find_package(libusb MODULE REQUIRED)
target_link_libraries(CemuCafe PRIVATE libusb::libusb)
endif ()
endif ()

if (ENABLE_WXWIDGETS)
target_link_libraries(CemuCafe PRIVATE wx::base wx::core)
endif()
Expand Down
41 changes: 41 additions & 0 deletions src/Cafe/OS/libs/nsyshid/AttachDefaultBackends.cpp
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
141 changes: 141 additions & 0 deletions src/Cafe/OS/libs/nsyshid/Backend.h
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

0 comments on commit 98b5a87

Please sign in to comment.