mirror of
https://github.com/nefarius/ViGEmBus.git
synced 2025-08-10 00:52:17 +00:00
No comment
This commit is contained in:
48
src/Internal.h
Normal file
48
src/Internal.h
Normal 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;
|
||||
79
src/NotificationRequestPool.cpp
Normal file
79
src/NotificationRequestPool.cpp
Normal 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;
|
||||
}
|
||||
34
src/NotificationRequestPool.h
Normal file
34
src/NotificationRequestPool.h
Normal 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();
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user