summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2022-03-11 04:12:44 +1100
committer Vas Crabb <vas@vastheman.com>2022-03-11 04:12:44 +1100
commita0732c321661af4c2577bbf6ab9699025cf868bc (patch)
treef00e3961d770a14ac9de07f78d6ca2902f2bbdf8 /src/osd
parent76a3bb2ec848ed9c8836cc7b4fee047078b70233 (diff)
osd/modules/input/input_rawinput.cpp: Allow re-plugging mouse/keyboard.
Diffstat (limited to 'src/osd')
-rw-r--r--src/osd/modules/input/input_common.h6
-rw-r--r--src/osd/modules/input/input_rawinput.cpp269
-rw-r--r--src/osd/modules/input/input_windows.cpp22
-rw-r--r--src/osd/modules/input/input_xinput.cpp12
-rw-r--r--src/osd/windows/window.cpp18
-rw-r--r--src/osd/windows/winmain.h2
6 files changed, 203 insertions, 126 deletions
diff --git a/src/osd/modules/input/input_common.h b/src/osd/modules/input/input_common.h
index 49c4e768dcf..45661fe957c 100644
--- a/src/osd/modules/input/input_common.h
+++ b/src/osd/modules/input/input_common.h
@@ -295,7 +295,8 @@ private:
std::vector<std::unique_ptr<device_info>> m_list;
public:
- size_t size() const { return m_list.size(); }
+ auto size() const { return m_list.size(); }
+ auto empty() const { return m_list.empty(); }
auto begin() { return m_list.begin(); }
auto end() { return m_list.end(); }
@@ -318,7 +319,8 @@ public:
m_list.erase(std::remove_if(std::begin(m_list), std::end(m_list), device_matches), m_list.end());
}
- void for_each_device(std::function<void (device_info*)> action)
+ template <typename T>
+ void for_each_device(T &&action)
{
for (auto &device: m_list)
action(device.get());
diff --git a/src/osd/modules/input/input_rawinput.cpp b/src/osd/modules/input/input_rawinput.cpp
index 248b7bb48ab..10b47a60e31 100644
--- a/src/osd/modules/input/input_rawinput.cpp
+++ b/src/osd/modules/input/input_rawinput.cpp
@@ -19,6 +19,7 @@
#include <algorithm>
#include <functional>
#include <mutex>
+#include <new>
// MAME headers
#include "emu.h"
@@ -35,12 +36,6 @@
namespace {
-// Typedefs for dynamically loaded functions
-typedef UINT (WINAPI *get_rawinput_device_list_ptr)(PRAWINPUTDEVICELIST, PUINT, UINT);
-typedef UINT (WINAPI *get_rawinput_data_ptr)( HRAWINPUT, UINT, LPVOID, PUINT, UINT);
-typedef UINT (WINAPI *get_rawinput_device_info_ptr)(HANDLE, UINT, LPVOID, PUINT);
-typedef BOOL (WINAPI *register_rawinput_devices_ptr)(PCRAWINPUTDEVICE, UINT, UINT);
-
class safe_regkey
{
private:
@@ -294,7 +289,7 @@ public:
rawinput_keyboard_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) :
rawinput_device(machine, std::move(name), std::move(id), DEVICE_CLASS_KEYBOARD, module),
- keyboard({{0}})
+ keyboard({ { 0 } })
{
}
@@ -326,7 +321,7 @@ class rawinput_mouse_device : public rawinput_device
private:
std::mutex m_device_lock;
public:
- mouse_state mouse;
+ mouse_state mouse;
rawinput_mouse_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) :
rawinput_device(machine, std::move(name), std::move(id), DEVICE_CLASS_MOUSE, module),
@@ -442,12 +437,7 @@ public:
class rawinput_module : public wininput_module
{
private:
- osd::dynamic_module::ptr m_user32_dll;
- get_rawinput_device_list_ptr get_rawinput_device_list = nullptr;
- get_rawinput_data_ptr get_rawinput_data = nullptr;
- get_rawinput_device_info_ptr get_rawinput_device_info = nullptr;
- register_rawinput_devices_ptr register_rawinput_devices = nullptr;
- std::mutex m_module_lock;
+ std::mutex m_module_lock;
public:
rawinput_module(const char *type, const char *name) : wininput_module(type, name)
@@ -456,163 +446,234 @@ public:
bool probe() override
{
- m_user32_dll = osd::dynamic_module::open({ "user32.dll" });
-
- get_rawinput_device_list = m_user32_dll->bind<get_rawinput_device_list_ptr>("GetRawInputDeviceList");
- get_rawinput_data = m_user32_dll->bind<get_rawinput_data_ptr>("GetRawInputData");
- get_rawinput_device_info = m_user32_dll->bind<get_rawinput_device_info_ptr>("GetRawInputDeviceInfoW");
- register_rawinput_devices = m_user32_dll->bind<register_rawinput_devices_ptr>("RegisterRawInputDevices");
-
- return get_rawinput_device_list && get_rawinput_data && get_rawinput_device_info && register_rawinput_devices;
+ return true;
}
void input_init(running_machine &machine) override
{
- // get the number of devices, allocate a device list, and fetch it
+ // get initial number of devices
UINT device_count = 0;
- if ((*get_rawinput_device_list)(nullptr, &device_count, sizeof(RAWINPUTDEVICELIST)) != 0)
+ if (GetRawInputDeviceList(nullptr, &device_count, sizeof(RAWINPUTDEVICELIST)) != 0)
+ {
+ osd_printf_error("Error getting initial number of RawInput devices.\n");
return;
-
- if (device_count == 0)
+ }
+ if (!device_count)
return;
- auto rawinput_devices = std::make_unique<RAWINPUTDEVICELIST[]>(device_count);
- if ((*get_rawinput_device_list)(rawinput_devices.get(), &device_count, sizeof(RAWINPUTDEVICELIST)) == UINT(-1))
+ std::unique_ptr<RAWINPUTDEVICELIST []> rawinput_devices;
+ UINT retrieved;
+ do
+ {
+ rawinput_devices.reset(new (std::nothrow) RAWINPUTDEVICELIST [device_count]);
+ if (!rawinput_devices)
+ {
+ osd_printf_error("Error allocating buffer for RawInput device list.\n");
+ return;
+ }
+ retrieved = GetRawInputDeviceList(rawinput_devices.get(), &device_count, sizeof(RAWINPUTDEVICELIST));
+ }
+ while ((UINT(-1) == retrieved) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER));
+ if (UINT(-1) == retrieved)
+ {
+ osd_printf_error("Error listing RawInput devices.\n");
return;
+ }
// iterate backwards through devices; new devices are added at the head
- for (int devnum = device_count - 1; devnum >= 0; devnum--)
- {
- RAWINPUTDEVICELIST *device = &rawinput_devices[devnum];
- add_rawinput_device(machine, device);
- }
+ for (int devnum = retrieved - 1; devnum >= 0; devnum--)
+ add_rawinput_device(machine, rawinput_devices[devnum]);
// don't enable global inputs when debugging
if (!machine.options().debug())
- {
m_global_inputs_enabled = downcast<windows_options &>(machine.options()).global_inputs();
- }
// If we added no devices, no need to register for notifications
- if (devicelist()->size() == 0)
+ if (devicelist()->empty())
return;
// finally, register to receive raw input WM_INPUT messages if we found devices
RAWINPUTDEVICE registration;
registration.usUsagePage = usagepage();
registration.usUsage = usage();
- registration.dwFlags = m_global_inputs_enabled ? 0x00000100 : 0;
+ registration.dwFlags = RIDEV_DEVNOTIFY;
+ if (m_global_inputs_enabled)
+ registration.dwFlags |= RIDEV_INPUTSINK;
registration.hwndTarget = std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window();
// register the device
- (*register_rawinput_devices)(&registration, 1, sizeof(registration));
+ RegisterRawInputDevices(&registration, 1, sizeof(registration));
}
protected:
- virtual void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST *device) = 0;
+ virtual void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST const &device) = 0;
virtual USHORT usagepage() = 0;
virtual USHORT usage() = 0;
int init_internal() override
{
- if (!get_rawinput_device_list || !get_rawinput_data ||
- !get_rawinput_device_info || !register_rawinput_devices )
- {
- return 1;
- }
-
- osd_printf_verbose("RawInput: APIs detected\n");
return 0;
}
template<class TDevice>
- TDevice *create_rawinput_device(running_machine &machine, PRAWINPUTDEVICELIST rawinputdevice)
+ TDevice *create_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST const &rawinputdevice)
{
// determine the length of the device name, allocate it, and fetch it if not nameless
UINT name_length = 0;
- if ((*get_rawinput_device_info)(rawinputdevice->hDevice, RIDI_DEVICENAME, nullptr, &name_length) != 0)
+ if (GetRawInputDeviceInfoW(rawinputdevice.hDevice, RIDI_DEVICENAME, nullptr, &name_length) != 0)
return nullptr;
std::unique_ptr<WCHAR []> tname = std::make_unique<WCHAR []>(name_length + 1);
- if (name_length > 1 && (*get_rawinput_device_info)(rawinputdevice->hDevice, RIDI_DEVICENAME, tname.get(), &name_length) == UINT(-1))
+ if (name_length > 1 && GetRawInputDeviceInfoW(rawinputdevice.hDevice, RIDI_DEVICENAME, tname.get(), &name_length) == UINT(-1))
return nullptr;
// if this is an RDP name, skip it
- if (_tcsstr(tname.get(), TEXT("Root#RDP_")) != nullptr)
+ if (wcsstr(tname.get(), L"Root#RDP_") != nullptr)
return nullptr;
// improve the name and then allocate a device
- std::wstring name = rawinput_device_improve_name(tname.get());
-
- // convert name to utf8
- std::string utf8_name = osd::text::from_wstring(name);
+ std::string utf8_name = osd::text::from_wstring(rawinput_device_improve_name(tname.get()));
- // set device id to raw input name
+ // set device ID to raw input name
std::string utf8_id = osd::text::from_wstring(tname.get());
+ tname.reset();
+
TDevice &devinfo = devicelist()->create_device<TDevice>(machine, std::move(utf8_name), std::move(utf8_id), *this);
// Add the handle
- devinfo.set_handle(rawinputdevice->hDevice);
+ devinfo.set_handle(rawinputdevice.hDevice);
return &devinfo;
}
bool handle_input_event(input_event eventid, void *eventdata) override
{
- // Only handle raw input data
- if (!input_enabled() || eventid != INPUT_EVENT_RAWINPUT)
- return false;
-
- HRAWINPUT rawinputdevice = *static_cast<HRAWINPUT*>(eventdata);
-
- BYTE small_buffer[4096];
- std::unique_ptr<BYTE[]> larger_buffer;
- LPBYTE data = small_buffer;
- UINT size;
+ switch (eventid)
+ {
+ // handle raw input data
+ case INPUT_EVENT_RAWINPUT:
+ {
+ // ignore if not enabled
+ if (!input_enabled())
+ return false;
+
+ HRAWINPUT rawinputdevice = *static_cast<HRAWINPUT *>(eventdata);
+
+ BYTE small_buffer[4096];
+ std::unique_ptr<BYTE []> larger_buffer;
+ LPBYTE data = small_buffer;
+ UINT size;
+
+ // determine the size of data buffer we need
+ if (GetRawInputData(rawinputdevice, RID_INPUT, nullptr, &size, sizeof(RAWINPUTHEADER)) != 0)
+ return false;
+
+ // if necessary, allocate a temporary buffer and fetch the data
+ if (size > sizeof(small_buffer))
+ {
+ larger_buffer.reset(new (std::nothrow) BYTE [size]);
+ data = larger_buffer.get();
+ if (!data)
+ return false;
+ }
+
+ // fetch the data and process the appropriate message types
+ UINT result = GetRawInputData(rawinputdevice, RID_INPUT, data, &size, sizeof(RAWINPUTHEADER));
+ if (UINT(-1) == result)
+ {
+ return false;
+ }
+ else if (result)
+ {
+ std::lock_guard<std::mutex> scope_lock(m_module_lock);
+
+ auto *input = reinterpret_cast<RAWINPUT *>(data);
+ if (!input->header.hDevice)
+ return false;
+
+ // find the device in the list and update
+ auto target_device = std::find_if(
+ devicelist()->begin(),
+ devicelist()->end(),
+ [input] (auto const &device)
+ {
+ auto devinfo = dynamic_cast<rawinput_device *>(device.get());
+ return devinfo && (input->header.hDevice == devinfo->device_handle());
+ });
+ if (devicelist()->end() == target_device)
+ return false;
+
+ static_cast<rawinput_device *>(target_device->get())->queue_events(input, 1);
+ return true;
+ }
+ }
+ break;
- // ignore if not enabled
- if (!input_enabled())
- return false;
+ case INPUT_EVENT_ARRIVAL:
+ {
+ HRAWINPUT rawinputdevice = *static_cast<HRAWINPUT *>(eventdata);
+
+ // determine the length of the device name, allocate it, and fetch it if not nameless
+ UINT name_length = 0;
+ if (GetRawInputDeviceInfoW(rawinputdevice, RIDI_DEVICENAME, nullptr, &name_length) != 0)
+ return false;
+
+ std::unique_ptr<WCHAR []> tname = std::make_unique<WCHAR []>(name_length + 1);
+ if (name_length > 1 && GetRawInputDeviceInfoW(rawinputdevice, RIDI_DEVICENAME, tname.get(), &name_length) == UINT(-1))
+ return false;
+ std::string utf8_id = osd::text::from_wstring(tname.get());
+ tname.reset();
+
+ std::lock_guard<std::mutex> scope_lock(m_module_lock);
+
+ // find the device in the list and update
+ auto target_device = std::find_if(
+ devicelist()->begin(),
+ devicelist()->end(),
+ [&utf8_id] (auto const &device)
+ {
+ auto devinfo = dynamic_cast<rawinput_device *>(device.get());
+ return devinfo && !devinfo->device_handle() && (devinfo->id() == utf8_id);
+ });
+ if (devicelist()->end() == target_device)
+ return false;
- // determine the size of databuffer we need
- if ((*get_rawinput_data)(rawinputdevice, RID_INPUT, nullptr, &size, sizeof(RAWINPUTHEADER)) != 0)
- return false;
+ static_cast<rawinput_device *>(target_device->get())->set_handle(rawinputdevice);
+ return true;
+ }
+ break;
- // if necessary, allocate a temporary buffer and fetch the data
- if (size > sizeof(small_buffer))
- {
- larger_buffer = std::make_unique<BYTE[]>(size);
- data = larger_buffer.get();
- if (data == nullptr)
- return false;
- }
+ case INPUT_EVENT_REMOVAL:
+ {
+ HRAWINPUT rawinputdevice = *static_cast<HRAWINPUT *>(eventdata);
- // fetch the data and process the appropriate message types
- bool result = (*get_rawinput_data)(static_cast<HRAWINPUT>(rawinputdevice), RID_INPUT, data, &size, sizeof(RAWINPUTHEADER));
- if (result)
- {
- std::lock_guard<std::mutex> scope_lock(m_module_lock);
+ std::lock_guard<std::mutex> scope_lock(m_module_lock);
- auto *input = reinterpret_cast<RAWINPUT*>(data);
+ // find the device in the list and update
+ auto target_device = std::find_if(
+ devicelist()->begin(),
+ devicelist()->end(),
+ [rawinputdevice] (auto const &device)
+ {
+ auto devinfo = dynamic_cast<rawinput_device *>(device.get());
+ return devinfo && (rawinputdevice == devinfo->device_handle());
+ });
- // find the device in the list and update
- auto target_device = std::find_if(
- devicelist()->begin(),
- devicelist()->end(),
- [input] (auto const &device)
- {
- auto devinfo = dynamic_cast<rawinput_device *>(device.get());
- return devinfo && (input->header.hDevice == devinfo->device_handle());
- });
+ if (devicelist()->end() == target_device)
+ return false;
- if (target_device != devicelist()->end())
- {
- static_cast<rawinput_device *>((*target_device).get())->queue_events(input, 1);
+ (*target_device)->reset();
+ static_cast<rawinput_device *>(target_device->get())->set_handle(nullptr);
return true;
}
+ break;
+
+ default:
+ break;
}
+ // must have been unhandled
return false;
}
};
@@ -633,10 +694,10 @@ protected:
USHORT usagepage() override { return 1; }
USHORT usage() override { return 6; }
- void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST *device) override
+ void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST const &device) override
{
// make sure this is a keyboard
- if (device->dwType != RIM_TYPEKEYBOARD)
+ if (device.dwType != RIM_TYPEKEYBOARD)
return;
// allocate and link in a new device
@@ -679,10 +740,10 @@ protected:
USHORT usagepage() override { return 1; }
USHORT usage() override { return 2; }
- void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST *device) override
+ void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST const &device) override
{
// make sure this is a mouse
- if (device->dwType != RIM_TYPEMOUSE)
+ if (device.dwType != RIM_TYPEMOUSE)
return;
// allocate and link in a new device
@@ -728,11 +789,11 @@ protected:
USHORT usagepage() override { return 1; }
USHORT usage() override { return 2; }
- void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST *device) override
+ void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST const &device) override
{
// make sure this is a mouse
- if (device->dwType != RIM_TYPEMOUSE)
+ if (device.dwType != RIM_TYPEMOUSE)
return;
// allocate and link in a new device
diff --git a/src/osd/modules/input/input_windows.cpp b/src/osd/modules/input/input_windows.cpp
index bbe109eb53a..4415e71f3a4 100644
--- a/src/osd/modules/input/input_windows.cpp
+++ b/src/osd/modules/input/input_windows.cpp
@@ -27,39 +27,39 @@
bool windows_osd_interface::should_hide_mouse() const
{
bool hidemouse = false;
- wininput_module* mod;
+ wininput_module *mod;
- mod = dynamic_cast<wininput_module*>(m_keyboard_input);
+ mod = dynamic_cast<wininput_module *>(m_keyboard_input);
if (mod) hidemouse |= mod->should_hide_mouse();
- mod = dynamic_cast<wininput_module*>(m_mouse_input);
+ mod = dynamic_cast<wininput_module *>(m_mouse_input);
if (mod) hidemouse |= mod->should_hide_mouse();
- mod = dynamic_cast<wininput_module*>(m_lightgun_input);
+ mod = dynamic_cast<wininput_module *>(m_lightgun_input);
if (mod) hidemouse |= mod->should_hide_mouse();
- mod = dynamic_cast<wininput_module*>(m_joystick_input);
+ mod = dynamic_cast<wininput_module *>(m_joystick_input);
if (mod) hidemouse |= mod->should_hide_mouse();
return hidemouse;
}
-bool windows_osd_interface::handle_input_event(input_event eventid, void* eventdata) const
+bool windows_osd_interface::handle_input_event(input_event eventid, void *eventdata) const
{
bool handled = false;
- wininput_module* mod;
+ wininput_module *mod;
- mod = dynamic_cast<wininput_module*>(m_keyboard_input);
+ mod = dynamic_cast<wininput_module *>(m_keyboard_input);
if (mod) handled |= mod->handle_input_event(eventid, eventdata);
- mod = dynamic_cast<wininput_module*>(m_mouse_input);
+ mod = dynamic_cast<wininput_module *>(m_mouse_input);
if (mod) handled |= mod->handle_input_event(eventid, eventdata);
- mod = dynamic_cast<wininput_module*>(m_lightgun_input);
+ mod = dynamic_cast<wininput_module *>(m_lightgun_input);
if (mod) handled |= mod->handle_input_event(eventid, eventdata);
- mod = dynamic_cast<wininput_module*>(m_joystick_input);
+ mod = dynamic_cast<wininput_module *>(m_joystick_input);
if (mod) handled |= mod->handle_input_event(eventid, eventdata);
return handled;
diff --git a/src/osd/modules/input/input_xinput.cpp b/src/osd/modules/input/input_xinput.cpp
index dd4c418aacd..8c75240abf7 100644
--- a/src/osd/modules/input/input_xinput.cpp
+++ b/src/osd/modules/input/input_xinput.cpp
@@ -201,12 +201,12 @@ xinput_joystick_device * xinput_api_helper::create_xinput_device(running_machine
// xinput_joystick_device
//============================================================
-xinput_joystick_device::xinput_joystick_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module, std::shared_ptr<xinput_api_helper> helper)
- : device_info(machine, std::string(name), std::string(id), DEVICE_CLASS_JOYSTICK, module),
- gamepad({{0}}),
- xinput_state({0}),
- m_xinput_helper(helper),
- m_configured(false)
+xinput_joystick_device::xinput_joystick_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module, std::shared_ptr<xinput_api_helper> helper) :
+ device_info(machine, std::string(name), std::string(id), DEVICE_CLASS_JOYSTICK, module),
+ gamepad({ { 0 } }),
+ xinput_state({ 0 }),
+ m_xinput_helper(helper),
+ m_configured(false)
{
}
diff --git a/src/osd/windows/window.cpp b/src/osd/windows/window.cpp
index 6627be003a8..bcf89fc0267 100644
--- a/src/osd/windows/window.cpp
+++ b/src/osd/windows/window.cpp
@@ -8,9 +8,6 @@
#define LOG_TEMP_PAUSE 0
-// Needed for RAW Input
-#define WM_INPUT 0x00FF
-
// standard C headers
#include <process.h>
@@ -1112,6 +1109,21 @@ LRESULT CALLBACK win_window_info::video_window_proc(HWND wnd, UINT message, WPAR
return DefWindowProc(wnd, message, wparam, lparam);
break;
+ // input device change: handle RawInput device connection/disconnection
+ case WM_INPUT_DEVICE_CHANGE:
+ switch (wparam)
+ {
+ case GIDC_ARRIVAL:
+ downcast<windows_osd_interface&>(window->machine().osd()).handle_input_event(INPUT_EVENT_ARRIVAL, &lparam);
+ break;
+ case GIDC_REMOVAL:
+ downcast<windows_osd_interface&>(window->machine().osd()).handle_input_event(INPUT_EVENT_REMOVAL, &lparam);
+ break;
+ default:
+ return DefWindowProc(wnd, message, wparam, lparam);
+ }
+ break;
+
// input: handle the raw input
case WM_INPUT:
downcast<windows_osd_interface&>(window->machine().osd()).handle_input_event(INPUT_EVENT_RAWINPUT, &lparam);
diff --git a/src/osd/windows/winmain.h b/src/osd/windows/winmain.h
index ef1cd1aff4f..7c1689cff9f 100644
--- a/src/osd/windows/winmain.h
+++ b/src/osd/windows/winmain.h
@@ -243,6 +243,8 @@ enum input_event
INPUT_EVENT_KEYDOWN,
INPUT_EVENT_KEYUP,
INPUT_EVENT_RAWINPUT,
+ INPUT_EVENT_ARRIVAL,
+ INPUT_EVENT_REMOVAL,
INPUT_EVENT_MOUSE_BUTTON
};