Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
Not completely sure if there was a reason for it not to be there while there's a mouse device, but I want to cleanup user32 rawinput code, and get rid of the hardcoded devices if possible. This will make the keyboard device available too.
dlls/winebus.sys/main.c | 70 ++++++++++++++++++++++++++++++++++++ dlls/winehid.sys/winehid.inf | 1 + 2 files changed, 71 insertions(+)
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index acd166758e7..99f834d2f40 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -97,6 +97,7 @@ static const struct product_desc XBOX_CONTROLLERS[] = { static DRIVER_OBJECT *driver_obj;
static DEVICE_OBJECT *mouse_obj; +static DEVICE_OBJECT *keyboard_obj;
/* The root-enumerated device stack. */ DEVICE_OBJECT *bus_pdo; @@ -540,6 +541,74 @@ static void mouse_device_create(void) IoInvalidateDeviceRelations(bus_pdo, BusRelations); }
+static NTSTATUS keyboard_get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *ret_length) +{ + TRACE("buffer %p, length %u.\n", buffer, length); + + *ret_length = sizeof(REPORT_HEADER) + sizeof(REPORT_TAIL); + if (length < sizeof(REPORT_HEADER) + sizeof(REPORT_TAIL)) + return STATUS_BUFFER_TOO_SMALL; + + memcpy(buffer, REPORT_HEADER, sizeof(REPORT_HEADER)); + memcpy(buffer + sizeof(REPORT_HEADER), REPORT_TAIL, sizeof(REPORT_TAIL)); + buffer[IDX_HEADER_PAGE] = HID_USAGE_PAGE_GENERIC; + buffer[IDX_HEADER_USAGE] = HID_USAGE_GENERIC_KEYBOARD; + + return STATUS_SUCCESS; +} + +static NTSTATUS keyboard_get_string(DEVICE_OBJECT *device, DWORD index, WCHAR *buffer, DWORD length) +{ + static const WCHAR nameW[] = {'W','i','n','e',' ','H','I','D',' ','k','e','y','b','o','a','r','d',0}; + if (index != HID_STRING_ID_IPRODUCT) + return STATUS_NOT_IMPLEMENTED; + if (length < ARRAY_SIZE(nameW)) + return STATUS_BUFFER_TOO_SMALL; + strcpyW(buffer, nameW); + return STATUS_SUCCESS; +} + +static NTSTATUS keyboard_begin_report_processing(DEVICE_OBJECT *device) +{ + return STATUS_SUCCESS; +} + +static NTSTATUS keyboard_set_output_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report, DWORD length, ULONG_PTR *ret_length) +{ + FIXME("id %u, stub!\n", id); + return STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS keyboard_get_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report, DWORD length, ULONG_PTR *ret_length) +{ + FIXME("id %u, stub!\n", id); + return STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS keyboard_set_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report, DWORD length, ULONG_PTR *ret_length) +{ + FIXME("id %u, stub!\n", id); + return STATUS_NOT_IMPLEMENTED; +} + +static const platform_vtbl keyboard_vtbl = +{ + .get_reportdescriptor = keyboard_get_reportdescriptor, + .get_string = keyboard_get_string, + .begin_report_processing = keyboard_begin_report_processing, + .set_output_report = keyboard_set_output_report, + .get_feature_report = keyboard_get_feature_report, + .set_feature_report = keyboard_set_feature_report, +}; + +static void keyboard_device_create(void) +{ + static const WCHAR busidW[] = {'W','I','N','E','K','E','Y','B','O','A','R','D',0}; + + keyboard_obj = bus_create_hid_device(busidW, 0, 0, -1, 0, 0, busidW, FALSE, &keyboard_vtbl, 0); + IoInvalidateDeviceRelations(bus_pdo, BusRelations); +} + static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) { static const WCHAR SDL_enabledW[] = {'E','n','a','b','l','e',' ','S','D','L',0}; @@ -554,6 +623,7 @@ static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) break; case IRP_MN_START_DEVICE: mouse_device_create(); + keyboard_device_create();
if (check_bus_option(&SDL_enabled, 1)) { diff --git a/dlls/winehid.sys/winehid.inf b/dlls/winehid.sys/winehid.inf index 566448e4a51..f9ed4091217 100644 --- a/dlls/winehid.sys/winehid.inf +++ b/dlls/winehid.sys/winehid.inf @@ -12,6 +12,7 @@ Wine IOHID device=device_section,IOHID Wine libevent device=device_section,LNXEV Wine SDL HID device=device_section,SDLJOY Wine mouse device=device_section,WINEMOUSE +Wine keyboard device=device_section,WINEKEYBOARD
[device_section.Services] AddService = winehid,0x2,svc_section
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- include/Makefile.in | 1 + include/ntddkbd.h | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 include/ntddkbd.h
diff --git a/include/Makefile.in b/include/Makefile.in index 8e40b90a3da..0d9db037ca7 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -529,6 +529,7 @@ SOURCES = \ nserror.h \ nspapi.h \ ntddcdrm.h \ + ntddkbd.h \ ntddmou.h \ ntddndis.h \ ntddscsi.h \ diff --git a/include/ntddkbd.h b/include/ntddkbd.h new file mode 100644 index 00000000000..fab28a024c9 --- /dev/null +++ b/include/ntddkbd.h @@ -0,0 +1,24 @@ +/* + * Copyright 2021 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef _NTDDKBD_ +#define _NTDDKBD_ + +DEFINE_GUID(GUID_DEVINTERFACE_KEYBOARD,0x884b96c3,0x56ef,0x11d1,0xbc,0x8c,0x00,0xa0,0xc9,0x14,0x05,0xdd); + +#endif
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/device.c | 1 + dlls/hidclass.sys/hid.h | 2 ++ dlls/hidclass.sys/pnp.c | 11 +++++++++++ 3 files changed, 14 insertions(+)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index 35cc40c01ea..a7825080deb 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -32,6 +32,7 @@ #include "ddk/wdm.h" #include "devguid.h" #include "ntddmou.h" +#include "ntddkbd.h"
WINE_DEFAULT_DEBUG_CHANNEL(hid); WINE_DECLARE_DEBUG_CHANNEL(hid_report); diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h index 9e829332bdc..5a502840691 100644 --- a/dlls/hidclass.sys/hid.h +++ b/dlls/hidclass.sys/hid.h @@ -69,6 +69,8 @@ typedef struct _BASE_DEVICE_EXTENSION
BOOL is_mouse; UNICODE_STRING mouse_link_name; + BOOL is_keyboard; + UNICODE_STRING keyboard_link_name; } pdo; } u;
diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c index de6f409a16b..3d81c16356e 100644 --- a/dlls/hidclass.sys/pnp.c +++ b/dlls/hidclass.sys/pnp.c @@ -23,6 +23,7 @@ #include <stdarg.h> #include "hid.h" #include "ntddmou.h" +#include "ntddkbd.h" #include "ddk/hidtypes.h" #include "ddk/wdm.h" #include "regstr.h" @@ -399,10 +400,18 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device, IRP *irp) if (!IoRegisterDeviceInterface(device, &GUID_DEVINTERFACE_MOUSE, NULL, &ext->u.pdo.mouse_link_name)) ext->u.pdo.is_mouse = TRUE; } + if (ext->u.pdo.preparsed_data->caps.UsagePage == HID_USAGE_PAGE_GENERIC + && ext->u.pdo.preparsed_data->caps.Usage == HID_USAGE_GENERIC_KEYBOARD) + { + if (!IoRegisterDeviceInterface(device, &GUID_DEVINTERFACE_KEYBOARD, NULL, &ext->u.pdo.keyboard_link_name)) + ext->u.pdo.is_keyboard = TRUE; + }
IoSetDeviceInterfaceState(&ext->u.pdo.link_name, TRUE); if (ext->u.pdo.is_mouse) IoSetDeviceInterfaceState(&ext->u.pdo.mouse_link_name, TRUE); + if (ext->u.pdo.is_keyboard) + IoSetDeviceInterfaceState(&ext->u.pdo.keyboard_link_name, TRUE); status = STATUS_SUCCESS; break;
@@ -413,6 +422,8 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device, IRP *irp) IoSetDeviceInterfaceState(&ext->u.pdo.link_name, FALSE); if (ext->u.pdo.is_mouse) IoSetDeviceInterfaceState(&ext->u.pdo.mouse_link_name, FALSE); + if (ext->u.pdo.is_keyboard) + IoSetDeviceInterfaceState(&ext->u.pdo.keyboard_link_name, TRUE);
if (ext->u.pdo.thread) {
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/rawinput.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index 7796a65641e..129c1933c36 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -39,6 +39,7 @@
#include "initguid.h" #include "ntddmou.h" +#include "ntddkbd.h"
WINE_DEFAULT_DEBUG_CHANNEL(rawinput);
@@ -211,6 +212,21 @@ static void find_devices(void)
SetupDiDestroyDeviceInfoList(set);
+ set = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_KEYBOARD, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); + + for (idx = 0; SetupDiEnumDeviceInterfaces(set, NULL, &GUID_DEVINTERFACE_KEYBOARD, idx, &iface); ++idx) + { + static const RID_DEVICE_INFO_KEYBOARD keyboard_info = {0, 0, 1, 12, 3, 101}; + + if (!(device = add_device(set, &iface))) + continue; + + device->info.dwType = RIM_TYPEKEYBOARD; + device->info.u.keyboard = keyboard_info; + } + + SetupDiDestroyDeviceInfoList(set); + LeaveCriticalSection(&rawinput_devices_cs); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=89230
Your paranoid android.
=== debiant2 (64 bit WoW report) ===
user32: win.c:10096: Test failed: Expected foreground window 0, got 0000000000EE0050 win.c:10102: Test failed: Expected foreground window 00000000000E0120, got 0000000000EE0050
On 4/22/21 2:26 PM, Rémi Bernon wrote:
Signed-off-by: Rémi Bernon rbernon@codeweavers.com
Not completely sure if there was a reason for it not to be there while there's a mouse device, but I want to cleanup user32 rawinput code, and get rid of the hardcoded devices if possible. This will make the keyboard device available too.
Yeah, the mouse device was added when I found an application that needed it. It did seem like a good idea to use it instead of the fake WINE_MOUSE device, and ditto for keyboards, but it wasn't immediately clear to me how to do that, so I left it alone...
(Admittedly it's still not immediately clear, but I'm also missing some understanding/context behind how we deal with input.)