mirror of
https://gitea.tendokyu.moe/TeamTofuShop/taitools.git
synced 2026-09-27 01:00:00 +03:00
add winusb hook and usbio board skeletons
This commit is contained in:
@@ -8,3 +8,10 @@ DEFINE_GUID(
|
||||
0xF16F,
|
||||
0x11CF,
|
||||
0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30);
|
||||
|
||||
DEFINE_GUID(
|
||||
usbio_guid,
|
||||
0x46C3136FL,
|
||||
0x0FD5,
|
||||
0x4973,
|
||||
0xBC, 0x5A, 0xF4, 0xA9, 0xF3, 0x52, 0x81, 0x39);
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include "util/dprintf.h"
|
||||
#include "util/dump.h"
|
||||
|
||||
// JVS card reader
|
||||
|
||||
static const uint8_t j9100628a_ident[] = "taito;JVS-Reader;Ver1.00;JPN,Multipurpose";
|
||||
|
||||
static uint8_t j9100628a_features[] = {
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <devioctl.h>
|
||||
#include <hidclass.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "board/guid.h"
|
||||
#include "board/j9100647a.h"
|
||||
|
||||
#include "hook/iobuf.h"
|
||||
#include "hook/iohook.h"
|
||||
|
||||
#include "hooklib/setupapi.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
// USB IO
|
||||
|
||||
static HRESULT usbio_handle_irp(struct irp *irp);
|
||||
|
||||
static const wchar_t usbio_path[] = L"$usbio";
|
||||
|
||||
static HANDLE usbio_fd;
|
||||
static void *usbio_ops_ctx;
|
||||
|
||||
HRESULT usbio_hook_init()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
hr = iohook_open_nul_fd(&usbio_fd);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
iohook_push_handler(usbio_handle_irp);
|
||||
|
||||
hr = setupapi_add_phantom_dev(&usbio_guid, usbio_path);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT usbio_handle_irp(struct irp *irp)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include <windows.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#pragma pack(push,1)
|
||||
|
||||
// needs to handle digital and analog reads and writes, coin stuff, and
|
||||
// having an ad-on device (usually a card reader) and maybe an SD card??
|
||||
|
||||
// Mayhaps move this to a seperate thing in the event a second USB IO
|
||||
// providor is needed?
|
||||
struct usbio_dev {
|
||||
// TODO: populate with handler functions for various commands that
|
||||
// come in via winusb
|
||||
// It might also just do a mass bulk update, in which case we need
|
||||
// a struct that encompases all the digital and analog I/O pins and
|
||||
// their states.
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
HRESULT usbio_hook_init();
|
||||
@@ -7,6 +7,7 @@ board_lib = static_library(
|
||||
],
|
||||
link_with : [
|
||||
iccard_lib,
|
||||
hooklib_lib,
|
||||
],
|
||||
sources : [
|
||||
'config.c',
|
||||
@@ -17,6 +18,8 @@ board_lib = static_library(
|
||||
'io3.h',
|
||||
'j9100628a.c',
|
||||
'j9100628a.h',
|
||||
'j9100647a.c',
|
||||
'j9100647a.h',
|
||||
'io4.c',
|
||||
'io4.h',
|
||||
'sg-cmd.c',
|
||||
|
||||
@@ -4,6 +4,7 @@ hooklib_lib = static_library(
|
||||
implicit_include_directories : false,
|
||||
dependencies : [
|
||||
capnhook.get_variable('hook_dep'),
|
||||
winusb_lib,
|
||||
],
|
||||
sources : [
|
||||
'cursor.c',
|
||||
@@ -28,5 +29,7 @@ hooklib_lib = static_library(
|
||||
'setupapi.h',
|
||||
'spike.c',
|
||||
'spike.h',
|
||||
'winusb.c',
|
||||
'winusb.h',
|
||||
],
|
||||
)
|
||||
|
||||
@@ -23,6 +23,12 @@ static void setupapi_hook_init(void);
|
||||
|
||||
/* API hooks */
|
||||
|
||||
static HDEVINFO WINAPI my_SetupDiGetClassDevsA(
|
||||
const GUID *ClassGuid,
|
||||
char *Enumerator,
|
||||
HWND hwndParent,
|
||||
DWORD Flags);
|
||||
|
||||
static HDEVINFO WINAPI my_SetupDiGetClassDevsW(
|
||||
const GUID *ClassGuid,
|
||||
wchar_t *Enumerator,
|
||||
@@ -44,10 +50,24 @@ static BOOL WINAPI my_SetupDiGetDeviceInterfaceDetailW(
|
||||
DWORD *RequiredSize,
|
||||
SP_DEVINFO_DATA *DeviceInfoData);
|
||||
|
||||
static BOOL WINAPI my_SetupDiGetDeviceInterfaceDetailA(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
SP_DEVICE_INTERFACE_DATA *DeviceInterfaceData,
|
||||
SP_DEVICE_INTERFACE_DETAIL_DATA_A *DeviceInterfaceDetailData,
|
||||
DWORD DeviceInterfaceDetailDataSize,
|
||||
DWORD *RequiredSize,
|
||||
SP_DEVINFO_DATA *DeviceInfoData);
|
||||
|
||||
static BOOL WINAPI my_SetupDiDestroyDeviceInfoList(HDEVINFO DeviceInfoSet);
|
||||
|
||||
/* Links */
|
||||
|
||||
static HDEVINFO (WINAPI *next_SetupDiGetClassDevsA)(
|
||||
const GUID *ClassGuid,
|
||||
char *Enumerator,
|
||||
HWND hwndParent,
|
||||
DWORD Flags);
|
||||
|
||||
static HDEVINFO (WINAPI *next_SetupDiGetClassDevsW)(
|
||||
const GUID *ClassGuid,
|
||||
wchar_t *Enumerator,
|
||||
@@ -69,12 +89,24 @@ static BOOL (WINAPI *next_SetupDiGetDeviceInterfaceDetailW)(
|
||||
DWORD *RequiredSize,
|
||||
SP_DEVINFO_DATA *DeviceInfoData);
|
||||
|
||||
static BOOL (WINAPI *next_SetupDiGetDeviceInterfaceDetailA)(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
SP_DEVICE_INTERFACE_DATA *DeviceInterfaceData,
|
||||
SP_DEVICE_INTERFACE_DETAIL_DATA_A *DeviceInterfaceDetailData,
|
||||
DWORD DeviceInterfaceDetailDataSize,
|
||||
DWORD *RequiredSize,
|
||||
SP_DEVINFO_DATA *DeviceInfoData);
|
||||
|
||||
static BOOL (WINAPI *next_SetupDiDestroyDeviceInfoList)(HDEVINFO DeviceInfoSet);
|
||||
|
||||
/* Hook tbl */
|
||||
|
||||
static const struct hook_symbol setupapi_syms[] = {
|
||||
{
|
||||
.name = "SetupDiGetClassDevsA",
|
||||
.patch = my_SetupDiGetClassDevsA,
|
||||
.link = (void *) &next_SetupDiGetClassDevsA,
|
||||
}, {
|
||||
.name = "SetupDiGetClassDevsW",
|
||||
.patch = my_SetupDiGetClassDevsW,
|
||||
.link = (void *) &next_SetupDiGetClassDevsW,
|
||||
@@ -86,6 +118,10 @@ static const struct hook_symbol setupapi_syms[] = {
|
||||
.name = "SetupDiGetDeviceInterfaceDetailW",
|
||||
.patch = my_SetupDiGetDeviceInterfaceDetailW,
|
||||
.link = (void *) &next_SetupDiGetDeviceInterfaceDetailW,
|
||||
}, {
|
||||
.name = "SetupDiGetDeviceInterfaceDetailA",
|
||||
.patch = my_SetupDiGetDeviceInterfaceDetailA,
|
||||
.link = (void *) &next_SetupDiGetDeviceInterfaceDetailA,
|
||||
}, {
|
||||
.name = "SetupDiDestroyDeviceInfoList",
|
||||
.patch = my_SetupDiDestroyDeviceInfoList,
|
||||
@@ -155,6 +191,40 @@ void setupapi_hook_insert_hooks(HMODULE target)
|
||||
_countof(setupapi_syms));
|
||||
}
|
||||
|
||||
static HDEVINFO WINAPI my_SetupDiGetClassDevsA(
|
||||
const GUID *ClassGuid,
|
||||
char *Enumerator,
|
||||
HWND hwndParent,
|
||||
DWORD Flags)
|
||||
{
|
||||
struct setupapi_class *class_;
|
||||
HDEVINFO result;
|
||||
size_t i;
|
||||
|
||||
result = next_SetupDiGetClassDevsA(
|
||||
ClassGuid,
|
||||
Enumerator,
|
||||
hwndParent,
|
||||
Flags);
|
||||
|
||||
if (result == INVALID_HANDLE_VALUE || ClassGuid == NULL) {
|
||||
return result;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&setupapi_lock);
|
||||
|
||||
for (i = 0 ; i < setupapi_nclasses ; i++) {
|
||||
class_ = &setupapi_classes[i];
|
||||
if (memcmp(ClassGuid, class_->guid, sizeof(*ClassGuid)) == 0) {
|
||||
class_->cur_handle = result;
|
||||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&setupapi_lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static HDEVINFO WINAPI my_SetupDiGetClassDevsW(
|
||||
const GUID *ClassGuid,
|
||||
wchar_t *Enumerator,
|
||||
@@ -322,6 +392,82 @@ pass:
|
||||
DeviceInfoData);
|
||||
}
|
||||
|
||||
static BOOL WINAPI my_SetupDiGetDeviceInterfaceDetailA(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
SP_DEVICE_INTERFACE_DATA *DeviceInterfaceData,
|
||||
SP_DEVICE_INTERFACE_DETAIL_DATA_A *DeviceInterfaceDetailData,
|
||||
DWORD DeviceInterfaceDetailDataSize,
|
||||
DWORD *RequiredSize,
|
||||
SP_DEVINFO_DATA *DeviceInfoData)
|
||||
{
|
||||
const wchar_t *wstr;
|
||||
char path_ch[MAX_PATH];
|
||||
size_t nbytes_wstr;
|
||||
size_t nbytes_str;
|
||||
size_t nbytes_total;
|
||||
size_t i;
|
||||
bool match;
|
||||
|
||||
if (DeviceInfoSet == INVALID_HANDLE_VALUE || DeviceInterfaceData == NULL) {
|
||||
goto pass;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&setupapi_lock);
|
||||
|
||||
for ( i = 0, match = false ;
|
||||
i < setupapi_nclasses && !match ;
|
||||
i++) {
|
||||
if ( DeviceInfoSet == setupapi_classes[i].cur_handle &&
|
||||
DeviceInterfaceData->Reserved == (ULONG_PTR) setupapi_classes[i].path) {
|
||||
match = true;
|
||||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&setupapi_lock);
|
||||
|
||||
if (!match) {
|
||||
goto pass;
|
||||
}
|
||||
|
||||
wstr = (const wchar_t *) DeviceInterfaceData->Reserved;
|
||||
nbytes_wstr = (wcslen(wstr) + 1) * sizeof(wchar_t);
|
||||
|
||||
wcstombs_s(&nbytes_str, path_ch, MAX_PATH, (wchar_t *) DeviceInterfaceData->Reserved, MAX_PATH);
|
||||
nbytes_total = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath);
|
||||
nbytes_total += nbytes_str;
|
||||
|
||||
if (RequiredSize != NULL) {
|
||||
*RequiredSize = (DWORD) nbytes_total;
|
||||
}
|
||||
|
||||
if ( DeviceInterfaceDetailData == NULL &&
|
||||
DeviceInterfaceDetailDataSize < nbytes_total) {
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (DeviceInterfaceDetailData->cbSize!=sizeof(*DeviceInterfaceDetailData)) {
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memcpy(DeviceInterfaceDetailData->DevicePath, path_ch, nbytes_str);
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
|
||||
return TRUE;
|
||||
|
||||
pass:
|
||||
return next_SetupDiGetDeviceInterfaceDetailA(
|
||||
DeviceInfoSet,
|
||||
DeviceInterfaceData,
|
||||
DeviceInterfaceDetailData,
|
||||
DeviceInterfaceDetailDataSize,
|
||||
RequiredSize,
|
||||
DeviceInfoData);
|
||||
}
|
||||
|
||||
static BOOL WINAPI my_SetupDiDestroyDeviceInfoList(HDEVINFO DeviceInfoSet)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
#include <windows.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "hooklib/winusb.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static bool winusb_initted;
|
||||
static CRITICAL_SECTION winusb_lock;
|
||||
static struct winusb_dev *winusb_classes;
|
||||
static size_t winusb_nclasses;
|
||||
|
||||
static void winusb_hook_init();
|
||||
|
||||
BOOL my_WinUsb_QueryPipe(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR AlternateInterfaceNumber,
|
||||
UCHAR PipeIndex,
|
||||
PWINUSB_PIPE_INFORMATION PipeInformation
|
||||
);
|
||||
|
||||
BOOL my_WinUsb_QueryInterfaceSettings(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR AlternateInterfaceNumber,
|
||||
PUSB_INTERFACE_DESCRIPTOR UsbAltInterfaceDescriptor
|
||||
);
|
||||
|
||||
BOOL my_WinUsb_GetDescriptor(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR DescriptorType,
|
||||
UCHAR Index,
|
||||
USHORT LanguageID,
|
||||
PUCHAR Buffer,
|
||||
ULONG BufferLength,
|
||||
PULONG LengthTransferred
|
||||
);
|
||||
|
||||
BOOL my_WinUsb_WritePipe(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR PipeID,
|
||||
PUCHAR Buffer,
|
||||
ULONG BufferLength,
|
||||
PULONG LengthTransferred,
|
||||
LPOVERLAPPED Overlapped
|
||||
);
|
||||
|
||||
BOOL my_WinUsb_QueryDeviceInformation(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
ULONG InformationType,
|
||||
PULONG BufferLength,
|
||||
PVOID Buffer
|
||||
);
|
||||
|
||||
BOOL my_WinUsb_ReadPipe(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR PipeID,
|
||||
PUCHAR Buffer,
|
||||
ULONG BufferLength,
|
||||
PULONG LengthTransferred,
|
||||
LPOVERLAPPED Overlapped
|
||||
);
|
||||
|
||||
BOOL my_WinUsb_Initialize(
|
||||
HANDLE DeviceHandle,
|
||||
PWINUSB_INTERFACE_HANDLE InterfaceHandle
|
||||
);
|
||||
|
||||
BOOL my_WinUsb_Free(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle
|
||||
);
|
||||
|
||||
BOOL (*next_WinUsb_QueryPipe)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR AlternateInterfaceNumber,
|
||||
UCHAR PipeIndex,
|
||||
PWINUSB_PIPE_INFORMATION PipeInformation
|
||||
);
|
||||
|
||||
BOOL (*next_WinUsb_QueryInterfaceSettings)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR AlternateInterfaceNumber,
|
||||
PUSB_INTERFACE_DESCRIPTOR UsbAltInterfaceDescriptor
|
||||
);
|
||||
|
||||
BOOL (*next_WinUsb_GetDescriptor)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR DescriptorType,
|
||||
UCHAR Index,
|
||||
USHORT LanguageID,
|
||||
PUCHAR Buffer,
|
||||
ULONG BufferLength,
|
||||
PULONG LengthTransferred
|
||||
);
|
||||
|
||||
BOOL (*next_WinUsb_WritePipe)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR PipeID,
|
||||
PUCHAR Buffer,
|
||||
ULONG BufferLength,
|
||||
PULONG LengthTransferred,
|
||||
LPOVERLAPPED Overlapped
|
||||
);
|
||||
|
||||
BOOL (*next_WinUsb_QueryDeviceInformation)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
ULONG InformationType,
|
||||
PULONG BufferLength,
|
||||
PVOID Buffer
|
||||
);
|
||||
|
||||
BOOL (*next_WinUsb_ReadPipe)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR PipeID,
|
||||
PUCHAR Buffer,
|
||||
ULONG BufferLength,
|
||||
PULONG LengthTransferred,
|
||||
LPOVERLAPPED Overlapped
|
||||
);
|
||||
|
||||
BOOL (*next_WinUsb_Initialize)(
|
||||
HANDLE DeviceHandle,
|
||||
PWINUSB_INTERFACE_HANDLE InterfaceHandle
|
||||
);
|
||||
|
||||
BOOL (*next_WinUsb_Free)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle
|
||||
);
|
||||
|
||||
static const struct hook_symbol winusb_syms[] = {
|
||||
{
|
||||
.name = "WinUsb_QueryPipe",
|
||||
.patch = my_WinUsb_QueryPipe,
|
||||
.link = (void *) &next_WinUsb_QueryPipe,
|
||||
}, {
|
||||
.name = "WinUsb_QueryInterfaceSettings",
|
||||
.patch = my_WinUsb_QueryInterfaceSettings,
|
||||
.link = (void *) &next_WinUsb_QueryInterfaceSettings,
|
||||
}, {
|
||||
.name = "WinUsb_GetDescriptor",
|
||||
.patch = my_WinUsb_GetDescriptor,
|
||||
.link = (void *) &next_WinUsb_GetDescriptor,
|
||||
}, {
|
||||
.name = "WinUsb_WritePipe",
|
||||
.patch = my_WinUsb_WritePipe,
|
||||
.link = (void *) &next_WinUsb_WritePipe,
|
||||
}, {
|
||||
.name = "WinUsb_QueryDeviceInformation",
|
||||
.patch = my_WinUsb_QueryDeviceInformation,
|
||||
.link = (void *) &next_WinUsb_QueryDeviceInformation,
|
||||
}, {
|
||||
.name = "WinUsb_ReadPipe",
|
||||
.patch = my_WinUsb_ReadPipe,
|
||||
.link = (void *) &next_WinUsb_ReadPipe,
|
||||
}, {
|
||||
.name = "WinUsb_Initialize",
|
||||
.patch = my_WinUsb_Initialize,
|
||||
.link = (void *) &next_WinUsb_Initialize,
|
||||
}, {
|
||||
.name = "WinUsb_Free",
|
||||
.patch = my_WinUsb_Free,
|
||||
.link = (void *) &next_WinUsb_Free,
|
||||
}
|
||||
};
|
||||
|
||||
HRESULT winusb_add_phantom_dev(const struct winusb_dev *dev)
|
||||
{
|
||||
struct winusb_dev *class_;
|
||||
struct winusb_dev *new_array;
|
||||
HRESULT hr;
|
||||
|
||||
assert(dev != NULL);
|
||||
|
||||
winusb_hook_init();
|
||||
|
||||
EnterCriticalSection(&winusb_lock);
|
||||
|
||||
new_array = realloc(
|
||||
winusb_classes,
|
||||
(winusb_nclasses + 1) * sizeof(struct winusb_dev));
|
||||
|
||||
if (new_array == NULL) {
|
||||
hr = E_OUTOFMEMORY;
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
winusb_classes = new_array;
|
||||
|
||||
// TODO: Copy the dev class to the new slot in the array
|
||||
class_ = &winusb_classes[winusb_nclasses++];
|
||||
hr = S_OK;
|
||||
|
||||
end:
|
||||
LeaveCriticalSection(&winusb_lock);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static void winusb_hook_init()
|
||||
{
|
||||
if (winusb_initted) {
|
||||
return;
|
||||
}
|
||||
|
||||
winusb_hook_insert_hooks(NULL);
|
||||
|
||||
InitializeCriticalSection(&winusb_lock);
|
||||
winusb_initted = true;
|
||||
}
|
||||
|
||||
void winusb_hook_insert_hooks(HMODULE target)
|
||||
{
|
||||
hook_table_apply(
|
||||
target,
|
||||
"winusb.dll",
|
||||
winusb_syms,
|
||||
_countof(winusb_syms));
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include <windows.h>
|
||||
#include <stdint.h>
|
||||
#include <winusb.h>
|
||||
|
||||
#pragma pack(push,1)
|
||||
|
||||
// winusb - hooks for winusb ident, read and write passed to device
|
||||
// usio - providor for winusb, passes along read/write
|
||||
// ll3io - gives usio the data to write
|
||||
|
||||
struct winusb_dev {
|
||||
HANDLE fd;
|
||||
GUID class_guid;
|
||||
const wchar_t *path;
|
||||
//uint8_t read_pipe_id; // duno if this ever needs to change?
|
||||
//uint8_t write_pipe_id;
|
||||
struct _USB_DEVICE_DESCRIPTOR descriptor;
|
||||
void (*read_pipe)(void *ctx, uint8_t pipe_id, uint8_t *bfr, uint32_t bfr_len);
|
||||
void (*write_pipe)(void *ctx, uint8_t pipe_id, uint8_t *bfr, uint32_t bfr_len);
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
HRESULT winusb_add_phantom_dev(const struct winusb_dev *dev);
|
||||
void winusb_hook_insert_hooks(HMODULE target);
|
||||
+16
-2
@@ -37,6 +37,7 @@ HRESULT fastio_hook_init(fastio_provider_t main, fastio_provider_t sub)
|
||||
void fastio_match_board_number(uint8_t board_no, struct fastio_node root, struct fastio_node *board)
|
||||
{
|
||||
assert(&root != NULL);
|
||||
// FIXME
|
||||
|
||||
board = &root;
|
||||
while (board->next != NULL && board->next->board_no != board_no) {
|
||||
@@ -51,13 +52,26 @@ void fastio_match_board_number(uint8_t board_no, struct fastio_node root, struct
|
||||
}
|
||||
|
||||
void fastio_digital_read(void* ctx, uint8_t board_no, uint32_t *out)
|
||||
{
|
||||
//struct fastio_node *req_board = NULL;
|
||||
//fastio_match_board_number(board_no, fio_main, req_board);
|
||||
|
||||
// If we fail to find, or the board we found doesn't have the handler we need,
|
||||
// quietly return with out unmodified
|
||||
//if (req_board != NULL && req_board->digital_in != NULL) {
|
||||
if (fio_main.digital_in != NULL) {
|
||||
fio_main.digital_in(ctx, out);
|
||||
}
|
||||
}
|
||||
|
||||
void fastio_coins_in(void* ctx, uint8_t board_no, uint8_t slot_no, uint32_t *out)
|
||||
{
|
||||
struct fastio_node *req_board = NULL;
|
||||
fastio_match_board_number(board_no, fio_main, req_board);
|
||||
|
||||
// If we fail to find, or the board we found doesn't have the handler we need,
|
||||
// quietly return with out unmodified
|
||||
if (req_board != NULL && req_board->digital_in != NULL) {
|
||||
fio_main.digital_in(ctx, out);
|
||||
if (req_board != NULL && req_board->coins_in != NULL) {
|
||||
fio_main.coins_in(ctx, slot_no, out);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,3 +22,4 @@ typedef HRESULT (*fastio_provider_t)(struct fastio_node *root);
|
||||
|
||||
HRESULT fastio_hook_init(fastio_provider_t main, fastio_provider_t sub);
|
||||
void fastio_digital_read(void* ctx, uint8_t board_no, uint32_t *out);
|
||||
void fastio_coins_in(void* ctx, uint8_t board_no, uint8_t slot_no, uint32_t *out);
|
||||
|
||||
+6
-5
@@ -316,9 +316,6 @@ static int hook_iDmacDrvRegisterRead(HANDLE a1, DWORD register_id, DWORD* regist
|
||||
case 0x4004: *register_val = -2; break; // Status
|
||||
|
||||
case 0x4120: // JVS Buttons
|
||||
/*if (GetAsyncKeyState(VK_DELETE) & 0x8000) {
|
||||
*register_val = 0x40; // Test
|
||||
}*/
|
||||
fastio_digital_read(NULL, 0, (uint32_t *)register_val);
|
||||
break;
|
||||
|
||||
@@ -326,8 +323,12 @@ static int hook_iDmacDrvRegisterRead(HANDLE a1, DWORD register_id, DWORD* regist
|
||||
case 0x4128: break; // Analog 2
|
||||
case 0x412C: break; // Analog 3
|
||||
|
||||
case 0x4140: break; // Coin slot 1
|
||||
case 0x4144: break; // Coin slot 2
|
||||
case 0x4140:
|
||||
fastio_coins_in(NULL, 0, 1, (uint32_t *)register_val);
|
||||
break; // Coin slot 1
|
||||
case 0x4144:
|
||||
fastio_coins_in(NULL, 0, 2, (uint32_t *)register_val);
|
||||
break; // Coin slot 2
|
||||
|
||||
case 0x41A0: break;
|
||||
case 0x41A4: break;
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ uint16_t ll3_io_get_api_version(void)
|
||||
HRESULT ll3_io_init(void)
|
||||
{
|
||||
dprintf("ll3 IO: Init\n");
|
||||
ll3_io_config_load(&cfg, L".\\bananatools.ini");
|
||||
ll3_io_config_load(&cfg, L".\\taitools.ini");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -41,13 +41,16 @@ dxguid_lib = cc.find_library('dxguid')
|
||||
xinput_lib = cc.find_library('xinput')
|
||||
crypt_lib = cc.find_library('crypt32')
|
||||
winhttp_lib = cc.find_library('winhttp')
|
||||
hid_lib = cc.find_library('hid')
|
||||
winusb_lib = cc.find_library('winusb')
|
||||
|
||||
inc = include_directories('.')
|
||||
capnhook = subproject('capnhook')
|
||||
|
||||
subdir('ri')
|
||||
subdir('iccard')
|
||||
subdir('board')
|
||||
subdir('hooklib')
|
||||
subdir('board')
|
||||
subdir('jvs')
|
||||
subdir('platform')
|
||||
subdir('util')
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
ri_lib = static_library(
|
||||
'ri',
|
||||
include_directories : inc,
|
||||
implicit_include_directories : false,
|
||||
dependencies : [
|
||||
capnhook.get_variable('hook_dep'),
|
||||
capnhook.get_variable('hooklib_dep'),
|
||||
hid_lib,
|
||||
],
|
||||
sources : [
|
||||
'ri.c',
|
||||
'ri.h',
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,168 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <hidsdi.h>
|
||||
#include <process.h>
|
||||
|
||||
#include "hook/iohook.h"
|
||||
#include "util/dprintf.h"
|
||||
|
||||
#include "ri/ri.h"
|
||||
|
||||
static HWND ri_hwnd;
|
||||
static WNDCLASSEX ri_wndclass;
|
||||
static HANDLE selected_ri_dev = (HANDLE)-1;
|
||||
static uintptr_t ri_thread;
|
||||
|
||||
LRESULT CALLBACK ri_win_proc(HWND hWnd, UINT msg, WPARAM wparam, LPARAM lParam);
|
||||
static unsigned int __stdcall ri_thread_proc(void *ctx);
|
||||
|
||||
HRESULT ri_init(uint8_t dev_num)
|
||||
{
|
||||
wchar_t ri_dev_name[MAX_PATH] = L"\0";
|
||||
wchar_t hid_prod_name[MAX_PATH] = L"\0";
|
||||
UINT num_ri_devs = 0;
|
||||
UINT len_ri_dev_name = 0;
|
||||
DWORD err = 0;
|
||||
PRAWINPUTDEVICELIST ri_devs = NULL;
|
||||
|
||||
if (GetRawInputDeviceList(NULL, &num_ri_devs, sizeof(RAWINPUTDEVICELIST)) != 0) {
|
||||
err = GetLastError();
|
||||
dprintf("RawInput: GetRawInputDeviceList failed to get number of devices %08lX\n", err);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
ri_devs = malloc(sizeof(RAWINPUTDEVICELIST) * num_ri_devs);
|
||||
GetRawInputDeviceList(ri_devs, &num_ri_devs, sizeof(RAWINPUTDEVICELIST));
|
||||
|
||||
if (num_ri_devs <= 0) {
|
||||
err = GetLastError();
|
||||
dprintf("RawInput: GetRawInputDeviceList failed to get devices info %08lX\n", err);
|
||||
free(ri_devs);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
dprintf("RawInput: Raw Input device list (%d devices):\n", num_ri_devs);
|
||||
for (int i = 0; i < num_ri_devs; i++) {
|
||||
len_ri_dev_name = 0;
|
||||
if (GetRawInputDeviceInfoW(ri_devs[i].hDevice, RIDI_DEVICENAME, NULL, &len_ri_dev_name) != 0) {
|
||||
dprintf("RawInput: GetRawInputDeviceInfoW #%d failed to get name size\n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
if (len_ri_dev_name <= 0) {
|
||||
dprintf("RawInput: GetRawInputDeviceInfoW #%d len_ri_dev_name <= 0\n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
if (len_ri_dev_name >= MAX_PATH) {
|
||||
dprintf("\tDev #%d - (name too long, %d characters)\n", i, len_ri_dev_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GetRawInputDeviceInfoW(ri_devs[i].hDevice, RIDI_DEVICENAME, ri_dev_name, &len_ri_dev_name) <= 0) {
|
||||
dprintf("RawInput: GetRawInputDeviceInfoW #%d failed to get name\n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
HANDLE hiddev = CreateFileW(ri_dev_name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (hiddev == NULL) {
|
||||
dprintf("RawInput: CreateFileW failed on dev #%d for device %ls\n", i, ri_dev_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!HidD_GetProductString(hiddev, hid_prod_name, MAX_PATH)) {
|
||||
//dprintf("RawInput: HidD_GetProductString failed on dev #%d for device %ls\n", i, ri_dev_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
dprintf("\tDev #%d - %ls\n", i, hid_prod_name);
|
||||
}
|
||||
|
||||
selected_ri_dev = ri_devs[dev_num].hDevice;
|
||||
|
||||
free(ri_devs);
|
||||
|
||||
ri_wndclass.cbSize = sizeof(WNDCLASSEX);
|
||||
ri_wndclass.hInstance = GetModuleHandle(NULL);
|
||||
ri_wndclass.lpfnWndProc = ri_win_proc;
|
||||
ri_wndclass.lpszClassName = "Taitools Input";
|
||||
|
||||
RegisterClassEx(&ri_wndclass);
|
||||
|
||||
ri_thread = _beginthreadex(
|
||||
NULL,
|
||||
0,
|
||||
ri_thread_proc,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void ri_exit()
|
||||
{
|
||||
if (ri_hwnd) {
|
||||
PostMessage(ri_hwnd, WM_CLOSE, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int __stdcall ri_thread_proc(void *ctx)
|
||||
{
|
||||
dprintf("RawInput: ri_thread_proc begin\n");
|
||||
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
|
||||
|
||||
ri_hwnd = CreateWindowExA(0, ri_wndclass.lpszClassName, "Taitools Input", 0, 0, 0, 0, 0, NULL, NULL, ri_wndclass.hInstance, NULL);
|
||||
|
||||
RAWINPUTDEVICE Rid[4];
|
||||
Rid[0].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC
|
||||
Rid[0].usUsage = 0x02; // HID_USAGE_GENERIC_MOUSE
|
||||
Rid[0].dwFlags = RIDEV_NOLEGACY; // adds mouse and also ignores legacy mouse messages
|
||||
Rid[0].hwndTarget = ri_hwnd;
|
||||
|
||||
Rid[1].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC
|
||||
Rid[1].usUsage = 0x06; // HID_USAGE_GENERIC_KEYBOARD
|
||||
Rid[1].dwFlags = RIDEV_NOLEGACY; // adds keyboard and also ignores legacy keyboard messages
|
||||
Rid[1].hwndTarget = ri_hwnd;
|
||||
|
||||
Rid[2].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC
|
||||
Rid[2].usUsage = 0x05; // HID_USAGE_GENERIC_GAMEPAD
|
||||
Rid[2].dwFlags = 0; // adds game pad
|
||||
Rid[2].hwndTarget = ri_hwnd;
|
||||
|
||||
Rid[3].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC
|
||||
Rid[3].usUsage = 0x04; // HID_USAGE_GENERIC_JOYSTICK
|
||||
Rid[3].dwFlags = 0; // adds joystick
|
||||
Rid[3].hwndTarget = ri_hwnd;
|
||||
|
||||
if (!RegisterRawInputDevices(Rid, 4, sizeof(Rid[0]))) {
|
||||
dprintf("RawInput: Failed to register RI devices\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
MSG msg;
|
||||
while (GetMessage(&msg, ri_hwnd, 0, 0) > 0) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
DestroyWindow(ri_hwnd);
|
||||
ri_hwnd = NULL;
|
||||
UnregisterClass(ri_wndclass.lpszClassName, ri_wndclass.hInstance);
|
||||
dprintf("RawInput: ri_thread_proc end\n");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK ri_win_proc(HWND hWnd, UINT msg, WPARAM wparam, LPARAM lParam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_INPUT:
|
||||
//dprintf("RawInput: Got input\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc(hWnd, msg, wparam, lParam);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include <windows.h>
|
||||
#include <stdint.h>
|
||||
|
||||
HRESULT ri_init(uint8_t dev_num);
|
||||
void ri_exit();
|
||||
+36
-11
@@ -10,11 +10,11 @@
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static uint16_t coins;
|
||||
static uint16_t services;
|
||||
|
||||
static void siva_fastio_digital_read(void *ctx, uint32_t *out);
|
||||
static void siva_fastio_coin_read(
|
||||
void *ctx,
|
||||
uint8_t slot_no,
|
||||
uint32_t *out);
|
||||
static void siva_fastio_coin_read(void *ctx, uint8_t slot_no, uint32_t *out);
|
||||
|
||||
HRESULT siva_fastio_init(struct fastio_node *out)
|
||||
{
|
||||
@@ -22,6 +22,7 @@ HRESULT siva_fastio_init(struct fastio_node *out)
|
||||
|
||||
assert(out != NULL);
|
||||
|
||||
out->next = NULL;
|
||||
out->digital_in = siva_fastio_digital_read;
|
||||
out->coins_in = siva_fastio_coin_read;
|
||||
|
||||
@@ -34,13 +35,37 @@ HRESULT siva_fastio_init(struct fastio_node *out)
|
||||
|
||||
static void siva_fastio_digital_read(void *ctx, uint32_t *out)
|
||||
{
|
||||
|
||||
uint8_t btn = 0;
|
||||
uint8_t stick = 0;
|
||||
*out = 0;
|
||||
|
||||
assert(siva_dll.get_btns != NULL);
|
||||
|
||||
siva_dll.get_btns(&btn, &stick);
|
||||
|
||||
if (btn & BTN_TEST) {
|
||||
*out |= SIVA_SWITCH_SYS_TEST;
|
||||
}
|
||||
|
||||
if (btn & BTN_SERVICE) {
|
||||
*out |= SIVA_SWITCH_SYS_SERVICE;
|
||||
}
|
||||
}
|
||||
|
||||
static void siva_fastio_coin_read(
|
||||
void *ctx,
|
||||
uint8_t slot_no,
|
||||
uint32_t *out)
|
||||
static void siva_fastio_coin_read(void *ctx, uint8_t slot_no, uint32_t *out)
|
||||
{
|
||||
|
||||
}
|
||||
uint16_t coin = 0;
|
||||
uint16_t service = 0;
|
||||
|
||||
assert(siva_dll.get_btns != NULL);
|
||||
|
||||
if (slot_no != 1) {
|
||||
*out = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
siva_dll.read_coin_counter(&coin, &service);
|
||||
|
||||
*out += coin;
|
||||
*out += service;
|
||||
}
|
||||
|
||||
+16
-16
@@ -4,22 +4,22 @@
|
||||
#include "jvs/jvs-bus.h"
|
||||
#include "idmac/fastio.h"
|
||||
|
||||
enum SIVA_SWITCH {
|
||||
RIGHT_BUTTON = 0x000080,
|
||||
RIGHT_UP = 0x010000,
|
||||
RIGHT_DOWN = 0x040000,
|
||||
RIGHT_LEFT = 0x100000,
|
||||
RIGHT_RIGHT = 0x400000,
|
||||
LEFT_BUTTON = 0x000020,
|
||||
LEFT_UP = 0x000100,
|
||||
LEFT_DOWN = 0x000400,
|
||||
LEFT_LEFT = 0x001000,
|
||||
LEFT_RIGHT = 0x004000,
|
||||
SYS_SERVICE = 0x000004,
|
||||
SYS_TEST = 0x000040,
|
||||
SYS_SELECT = 0x000008,
|
||||
SYS_ENTER = 0x000010,
|
||||
SYS_COIN = 0x000001,
|
||||
enum {
|
||||
SIVA_SWITCH_RIGHT_BUTTON = 0x000080,
|
||||
SIVA_SWITCH_RIGHT_UP = 0x010000,
|
||||
SIVA_SWITCH_RIGHT_DOWN = 0x040000,
|
||||
SIVA_SWITCH_RIGHT_LEFT = 0x100000,
|
||||
SIVA_SWITCH_RIGHT_RIGHT = 0x400000,
|
||||
SIVA_SWITCH_LEFT_BUTTON = 0x000020,
|
||||
SIVA_SWITCH_LEFT_UP = 0x000100,
|
||||
SIVA_SWITCH_LEFT_DOWN = 0x000400,
|
||||
SIVA_SWITCH_LEFT_LEFT = 0x001000,
|
||||
SIVA_SWITCH_LEFT_RIGHT = 0x004000,
|
||||
SIVA_SWITCH_SYS_SERVICE = 0x000004,
|
||||
SIVA_SWITCH_SYS_TEST = 0x000040,
|
||||
SIVA_SWITCH_SYS_SELECT = 0x000008,
|
||||
SIVA_SWITCH_SYS_ENTER = 0x000010,
|
||||
SIVA_SWITCH_SYS_COIN = 0x000001,
|
||||
};
|
||||
|
||||
HRESULT siva_fastio_init(struct fastio_node *out);
|
||||
|
||||
+5
-5
@@ -8,12 +8,12 @@
|
||||
|
||||
void siva_io_config_load(struct siva_input_config *cfg, const wchar_t *filename)
|
||||
{
|
||||
cfg->test = GetPrivateProfileIntW(L"jvs", L"test", VK_HOME, filename);
|
||||
cfg->service = GetPrivateProfileIntW(L"jvs", L"service", VK_DELETE, filename);
|
||||
cfg->coin = GetPrivateProfileIntW(L"jvs", L"coin", VK_INSERT, filename);
|
||||
cfg->test = GetPrivateProfileIntW(L"jvs", L"test", VK_HOME, filename);
|
||||
cfg->service = GetPrivateProfileIntW(L"jvs", L"service", VK_DELETE, filename);
|
||||
cfg->coin = GetPrivateProfileIntW(L"jvs", L"coin", VK_INSERT, filename);
|
||||
|
||||
cfg->is_xinput = GetPrivateProfileIntW(L"deck", L"controller_type", 0, filename);
|
||||
cfg->xinput_player = GetPrivateProfileIntW(L"deck", L"controller_num", 0, filename);
|
||||
cfg->is_ri = GetPrivateProfileIntW(L"deck", L"input_type", 0, filename); // 0 for KB, 1 for RI
|
||||
cfg->device_num = GetPrivateProfileIntW(L"deck", L"device_num", 1, filename);
|
||||
|
||||
cfg->btn_l = GetPrivateProfileIntW(L"deck", L"left_button", 'C', filename);
|
||||
cfg->btn_r = GetPrivateProfileIntW(L"deck", L"right_button", 'N', filename);
|
||||
|
||||
+2
-2
@@ -5,8 +5,8 @@
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct siva_input_config {
|
||||
uint8_t is_xinput;
|
||||
uint8_t xinput_player;
|
||||
uint8_t is_ri;
|
||||
uint8_t device_num;
|
||||
|
||||
uint8_t test;
|
||||
uint8_t service;
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@ sivaio_lib = static_library(
|
||||
name_prefix : '',
|
||||
include_directories : inc,
|
||||
implicit_include_directories : false,
|
||||
dependencies : [
|
||||
xinput_lib,
|
||||
link_with : [
|
||||
ri_lib,
|
||||
],
|
||||
sources : [
|
||||
'sivaio.c',
|
||||
|
||||
+12
-52
@@ -1,5 +1,4 @@
|
||||
#include <windows.h>
|
||||
#include <xinput.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
@@ -8,6 +7,7 @@
|
||||
|
||||
#include "sivaio/sivaio.h"
|
||||
#include "sivaio/config.h"
|
||||
#include "ri/ri.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
@@ -16,7 +16,6 @@ static bool siva_io_service = false;
|
||||
static uint16_t siva_coin_ct = 0;
|
||||
static uint16_t siva_service_ct = 0;
|
||||
static struct siva_input_config cfg;
|
||||
static HANDLE selected_ri_dev = (HANDLE)-1;
|
||||
|
||||
uint16_t siva_io_get_api_version(void)
|
||||
{
|
||||
@@ -24,64 +23,24 @@ uint16_t siva_io_get_api_version(void)
|
||||
}
|
||||
|
||||
HRESULT siva_io_init(void)
|
||||
{
|
||||
wchar_t ri_dev_name[MAX_PATH] = L"\0";
|
||||
UINT num_ri_devs = 0;
|
||||
UINT len_ri_dev_name = 0;
|
||||
DWORD err = 0;
|
||||
PRAWINPUTDEVICELIST ri_devs = NULL;
|
||||
|
||||
{
|
||||
dprintf("Siva IO: Init\n");
|
||||
siva_io_config_load(&cfg, L".\\bananatools.ini");
|
||||
siva_io_config_load(&cfg, L".\\taitools.ini");
|
||||
|
||||
if (GetRawInputDeviceList(NULL, &num_ri_devs, sizeof(RAWINPUTDEVICELIST)) != 0) {
|
||||
err = GetLastError();
|
||||
dprintf("Siva IO: GetRawInputDeviceList failed to get number of devices %08lX\n", err);
|
||||
return E_FAIL;
|
||||
if (cfg.is_ri) {
|
||||
return ri_init(cfg.device_num);
|
||||
}
|
||||
|
||||
ri_devs = malloc(sizeof(RAWINPUTDEVICELIST) * num_ri_devs);
|
||||
GetRawInputDeviceList(ri_devs, &num_ri_devs, sizeof(RAWINPUTDEVICELIST));
|
||||
|
||||
if (num_ri_devs <= 0) {
|
||||
err = GetLastError();
|
||||
dprintf("Siva IO: GetRawInputDeviceList failed to get devices info %08lX\n", err);
|
||||
free(ri_devs);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
dprintf("Siva IO: Raw Input device list (%d devices):\n", num_ri_devs);
|
||||
for (int i = 0; i < num_ri_devs; i++) {
|
||||
len_ri_dev_name = 0;
|
||||
if (GetRawInputDeviceInfoW(ri_devs[i].hDevice, RIDI_DEVICENAME, NULL, &len_ri_dev_name) != 0) {
|
||||
dprintf("Siva IO: GetRawInputDeviceInfoW #%d failed to get name size\n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
if (len_ri_dev_name <= 0) {
|
||||
dprintf("Siva IO: GetRawInputDeviceInfoW #%d len_ri_dev_name <= 0\n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
if (len_ri_dev_name >= MAX_PATH) {
|
||||
dprintf("\tDev #%d - (name too long, %d characters)\n", i, len_ri_dev_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GetRawInputDeviceInfoW(ri_devs[i].hDevice, RIDI_DEVICENAME, ri_dev_name, &len_ri_dev_name) <= 0) {
|
||||
dprintf("Siva IO: GetRawInputDeviceInfoW #%d failed to get name\n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf("\tDev #%d - %ls\n", i, ri_dev_name);
|
||||
}
|
||||
|
||||
free(ri_devs);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void siva_io_get_btns(uint8_t *btn, uint8_t *stick)
|
||||
{
|
||||
|
||||
if (GetAsyncKeyState(VK_MENU) && GetAsyncKeyState(VK_F4)) {
|
||||
ri_exit();
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(cfg.test) & 0x8000) {
|
||||
*btn |= BTN_TEST;
|
||||
}
|
||||
@@ -89,6 +48,7 @@ void siva_io_get_btns(uint8_t *btn, uint8_t *stick)
|
||||
if (GetAsyncKeyState(cfg.service) & 0x8000) {
|
||||
*btn |= BTN_SERVICE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void siva_io_read_coin_counter(uint16_t *coins, uint16_t *services)
|
||||
|
||||
Reference in New Issue
Block a user