No comment

This commit is contained in:
Benjamin Höglinger-Stelzer
2019-04-22 12:13:45 +02:00
parent 9071d6c3af
commit 3f1286cbc9
8 changed files with 227 additions and 49 deletions

48
src/Internal.h Normal file
View File

@@ -0,0 +1,48 @@
#pragma once
#include "XusbNotificationRequest.h"
#include "NotificationRequestPool.h"
//
// Represents a driver connection object.
//
typedef struct _VIGEM_CLIENT_T
{
HANDLE hBusDevice;
} VIGEM_CLIENT;
//
// Represents the (connection) state of a target device object.
//
typedef enum _VIGEM_TARGET_STATE
{
VIGEM_TARGET_NEW,
VIGEM_TARGET_INITIALIZED,
VIGEM_TARGET_CONNECTED,
VIGEM_TARGET_DISCONNECTED
} VIGEM_TARGET_STATE, *PVIGEM_TARGET_STATE;
//
// Represents a virtual gamepad object.
//
typedef struct _VIGEM_TARGET_T
{
ULONG Size;
ULONG SerialNo;
VIGEM_TARGET_STATE State;
USHORT VendorId;
USHORT ProductId;
VIGEM_TARGET_TYPE Type;
DWORD_PTR Notification;
boost::shared_ptr<boost::asio::io_service> io_svc;
boost::shared_ptr<boost::asio::io_service::work> worker;
boost::shared_ptr<boost::thread_group> worker_threads;
boost::shared_ptr<boost::mutex> enqueue_lock;
std::shared_ptr<NotificationRequestPool> pool;
HANDLE WaitHandles[VIGEM_INVERTED_CALL_THREAD_COUNT];
std::vector<XusbNotificationRequest*> notify_req;
} VIGEM_TARGET;

View File

@@ -0,0 +1,79 @@
#include "NotificationRequestPool.h"
NotificationRequestPool::NotificationRequestPool(
HANDLE bus,
const ULONG serial,
PFN_VIGEM_X360_NOTIFICATION callback) :
callback_(callback),
stop_(false)
{
for (auto& wait_handle : wait_handles_)
{
wait_handle = CreateEvent(nullptr, FALSE, FALSE, nullptr);
XusbNotificationRequest req(bus, serial, wait_handle);
requests_.push_back(std::ref(req));
}
io_svc_.reset(new boost::asio::io_service());
worker_.reset(new boost::asio::io_service::work(*io_svc_));
worker_threads_.reset(new boost::thread_group());
thread_ = std::make_shared<boost::thread>(boost::ref(*this));
for (auto& request : requests_)
request.get().request_async();
}
NotificationRequestPool::~NotificationRequestPool()
{
for (auto& wait_handle : wait_handles_)
CloseHandle(wait_handle);
thread_->join();
}
void NotificationRequestPool::operator()()
{
boost::asio::io_service::strand strand(*io_svc_);
while (true)
{
const auto ret = WaitForMultipleObjects(
requests_.size(),
wait_handles_,
FALSE,
INFINITE
);
const auto index = ret - WAIT_OBJECT_0;
auto& req = requests_[index].get();
//const boost::function<void(
// PVIGEM_CLIENT,
// PVIGEM_TARGET,
// UCHAR,
// UCHAR,
// UCHAR
// )> pfn = callback_;
//strand.post(boost::bind(pfn,
// client,
// target,
// notify.LargeMotor,
// notify.SmallMotor,
// notify.LedNumber
//));
req.request_async();
boost::mutex::scoped_lock lock(m_);
if (stop_)
break;
}
}
void NotificationRequestPool::terminate()
{
boost::mutex::scoped_lock lock(m_);
stop_ = true;
}

View File

@@ -0,0 +1,34 @@
#pragma once
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <vector>
#include "XusbNotificationRequest.h"
#include "ViGEm/Client.h"
#define VIGEM_INVERTED_CALL_THREAD_COUNT 20
class NotificationRequestPool
{
HANDLE wait_handles_[VIGEM_INVERTED_CALL_THREAD_COUNT]{};
PFN_VIGEM_X360_NOTIFICATION callback_;
std::vector<std::reference_wrapper<XusbNotificationRequest>> requests_;
std::shared_ptr<boost::thread> thread_;
boost::mutex m_;
boost::condition_variable cv_;
bool stop_;
boost::shared_ptr<boost::asio::io_service> io_svc_;
boost::shared_ptr<boost::asio::io_service::work> worker_;
boost::shared_ptr<boost::thread_group> worker_threads_;
public:
NotificationRequestPool(HANDLE bus, ULONG serial, PFN_VIGEM_X360_NOTIFICATION callback);
~NotificationRequestPool();
void operator()();
void terminate();
};

View File

@@ -55,12 +55,15 @@ SOFTWARE.
#include <ratio>
#include <thread>
#include "Internal.h"
#include "NotificationRequestPool.h"
//
// TODO: this is... not optimal. Improve in the future.
//
#define VIGEM_TARGETS_MAX USHRT_MAX
#define VIGEM_INVERTED_CALL_THREAD_COUNT 20
typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)(
@@ -75,45 +78,7 @@ typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)(
LONG WINAPI vigem_internal_exception_handler(struct _EXCEPTION_POINTERS* apExceptionInfo);
//
// Represents a driver connection object.
//
typedef struct _VIGEM_CLIENT_T
{
HANDLE hBusDevice;
} VIGEM_CLIENT;
//
// Represents the (connection) state of a target device object.
//
typedef enum _VIGEM_TARGET_STATE
{
VIGEM_TARGET_NEW,
VIGEM_TARGET_INITIALIZED,
VIGEM_TARGET_CONNECTED,
VIGEM_TARGET_DISCONNECTED
} VIGEM_TARGET_STATE, *PVIGEM_TARGET_STATE;
//
// Represents a virtual gamepad object.
//
typedef struct _VIGEM_TARGET_T
{
ULONG Size;
ULONG SerialNo;
VIGEM_TARGET_STATE State;
USHORT VendorId;
USHORT ProductId;
VIGEM_TARGET_TYPE Type;
DWORD_PTR Notification;
boost::shared_ptr<boost::asio::io_service> io_svc;
boost::shared_ptr<boost::asio::io_service::work> worker;
boost::shared_ptr<boost::thread_group> worker_threads;
boost::shared_ptr<boost::mutex> enqueue_lock;
} VIGEM_TARGET;
//
// Initializes a virtual gamepad object.
@@ -138,6 +103,9 @@ PVIGEM_TARGET FORCEINLINE VIGEM_TARGET_ALLOC_INIT(
target->worker_threads.reset(new boost::thread_group());
target->enqueue_lock.reset(new boost::mutex());
for (auto& WaitHandle : target->WaitHandles)
WaitHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr);
return target;
}
@@ -625,8 +593,26 @@ VIGEM_ERROR vigem_target_x360_register_notification(
target->Notification = reinterpret_cast<DWORD_PTR>(notification);
for (int i = 1; i <= VIGEM_INVERTED_CALL_THREAD_COUNT; i++)
target->worker_threads->create_thread(boost::bind(&vigem_internal_x360_notification_worker, target, vigem));
//for (auto i = 0; i < /* VIGEM_INVERTED_CALL_THREAD_COUNT */ 1; i++)
//{
// auto req = new XusbNotificationRequest(
// vigem->hBusDevice,
// target->SerialNo,
// target->WaitHandles[i]
// );
// target->notify_req.emplace_back(req);
// //target->worker_threads->create_thread(*req);
//}
target->pool = std::make_shared<NotificationRequestPool>(
vigem->hBusDevice,
target->SerialNo,
PFN_VIGEM_X360_NOTIFICATION(target->Notification)
);
//for (int i = 1; i <= VIGEM_INVERTED_CALL_THREAD_COUNT; i++)
// target->worker_threads->create_thread(boost::bind(&vigem_internal_x360_notification_worker, target, vigem));
return VIGEM_ERROR_NONE;
}

View File

@@ -305,9 +305,12 @@
<ClInclude Include="$(SolutionDir)\include\ViGEm\Common.h" />
<ClInclude Include="$(SolutionDir)\include\ViGEm\Util.h" />
<ClInclude Include="$(SolutionDir)\include\ViGEm\km\BusShared.h" />
<ClInclude Include="Internal.h" />
<ClInclude Include="NotificationRequestPool.h" />
<ClInclude Include="XusbNotificationRequest.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="NotificationRequestPool.cpp" />
<ClCompile Include="ViGEmClient.cpp" />
<ClCompile Include="XusbNotificationRequest.cpp" />
</ItemGroup>

View File

@@ -36,6 +36,12 @@
<ClInclude Include="XusbNotificationRequest.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NotificationRequestPool.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Internal.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ViGEmClient.cpp">
@@ -44,5 +50,8 @@
<ClCompile Include="XusbNotificationRequest.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NotificationRequestPool.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -4,25 +4,42 @@
XusbNotificationRequest::XusbNotificationRequest(
HANDLE bus,
ULONG serial,
HANDLE wait
HANDLE notification
) : parent_bus(bus),
payload(), transferred(0),
overlapped()
{
overlapped.hEvent = wait;
overlapped.hEvent = notification;
XUSB_REQUEST_NOTIFICATION_INIT(&payload, serial);
}
void XusbNotificationRequest::requestAsync()
bool XusbNotificationRequest::request_async()
{
DeviceIoControl(
const auto ret = DeviceIoControl(
parent_bus,
IOCTL_XUSB_REQUEST_NOTIFICATION,
&payload,
payload.Size,
&payload,
payload.Size,
&transferred,
nullptr,
&overlapped
);
return (!ret && GetLastError() == ERROR_IO_PENDING);
}
UCHAR XusbNotificationRequest::get_led_number() const
{
return payload.LedNumber;
}
UCHAR XusbNotificationRequest::get_large_motor() const
{
return payload.LargeMotor;
}
UCHAR XusbNotificationRequest::get_small_motor() const
{
return payload.SmallMotor;
}

View File

@@ -5,14 +5,16 @@
class XusbNotificationRequest
{
private:
HANDLE parent_bus;
XUSB_REQUEST_NOTIFICATION payload;
DWORD transferred;
OVERLAPPED overlapped;
public:
XusbNotificationRequest(HANDLE bus, ULONG serial, HANDLE wait);
XusbNotificationRequest(HANDLE bus, ULONG serial, HANDLE notification);
bool request_async();
void requestAsync();
UCHAR get_led_number() const;
UCHAR get_large_motor() const;
UCHAR get_small_motor() const;
};