winebus.sys: Introduce new HID report descriptor helpers.
And use them for mouse and keyboard. Signed-off-by: Rémi Bernon <rbernon@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
5b9c1e9163
commit
2ea19ff357
|
@ -8,6 +8,7 @@ C_SRCS = \
|
|||
bus_iohid.c \
|
||||
bus_sdl.c \
|
||||
bus_udev.c \
|
||||
hid.c \
|
||||
main.c
|
||||
|
||||
RC_SRCS = winebus.rc
|
||||
|
|
|
@ -18,6 +18,26 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <hidusage.h>
|
||||
|
||||
struct hid_descriptor
|
||||
{
|
||||
BYTE *data;
|
||||
SIZE_T size;
|
||||
SIZE_T max_size;
|
||||
};
|
||||
|
||||
extern BOOL hid_descriptor_append(struct hid_descriptor *desc, const BYTE *buffer, SIZE_T size) DECLSPEC_HIDDEN;
|
||||
extern BOOL hid_descriptor_begin(struct hid_descriptor *desc, USAGE usage_page, USAGE usage) DECLSPEC_HIDDEN;
|
||||
extern BOOL hid_descriptor_end(struct hid_descriptor *desc) DECLSPEC_HIDDEN;
|
||||
|
||||
extern BOOL hid_descriptor_add_buttons(struct hid_descriptor *desc, USAGE usage_page,
|
||||
USAGE usage_min, USAGE usage_max) DECLSPEC_HIDDEN;
|
||||
|
||||
/* Blocks of data for building HID device descriptions */
|
||||
|
||||
#include "psh_hid_macros.h"
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Common HID report descriptor helpers
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "controller.h"
|
||||
|
||||
BOOL hid_descriptor_append(struct hid_descriptor *desc, const BYTE *buffer, SIZE_T size)
|
||||
{
|
||||
BYTE *tmp = desc->data;
|
||||
|
||||
if (desc->size + size > desc->max_size)
|
||||
{
|
||||
desc->max_size = max(desc->max_size * 3 / 2, desc->size + size);
|
||||
if (!desc->data) desc->data = HeapAlloc(GetProcessHeap(), 0, desc->max_size);
|
||||
else desc->data = HeapReAlloc(GetProcessHeap(), 0, tmp, desc->max_size);
|
||||
}
|
||||
|
||||
if (!desc->data)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, tmp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memcpy(desc->data + desc->size, buffer, size);
|
||||
desc->size += size;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#include "psh_hid_macros.h"
|
||||
|
||||
BOOL hid_descriptor_begin(struct hid_descriptor *desc, USAGE usage_page, USAGE usage)
|
||||
{
|
||||
const BYTE template[] =
|
||||
{
|
||||
USAGE_PAGE(2, usage_page),
|
||||
USAGE(2, usage),
|
||||
COLLECTION(1, Application),
|
||||
USAGE(1, 0),
|
||||
};
|
||||
|
||||
memset(desc, 0, sizeof(*desc));
|
||||
return hid_descriptor_append(desc, template, sizeof(template));
|
||||
}
|
||||
|
||||
BOOL hid_descriptor_end(struct hid_descriptor *desc)
|
||||
{
|
||||
static const BYTE template[] =
|
||||
{
|
||||
END_COLLECTION,
|
||||
};
|
||||
|
||||
return hid_descriptor_append(desc, template, sizeof(template));
|
||||
}
|
||||
|
||||
BOOL hid_descriptor_add_buttons(struct hid_descriptor *desc, USAGE usage_page,
|
||||
USAGE usage_min, USAGE usage_max)
|
||||
{
|
||||
const BYTE template[] =
|
||||
{
|
||||
USAGE_PAGE(2, usage_page),
|
||||
USAGE_MINIMUM(2, usage_min),
|
||||
USAGE_MAXIMUM(2, usage_max),
|
||||
LOGICAL_MINIMUM(1, 0),
|
||||
LOGICAL_MAXIMUM(1, 1),
|
||||
PHYSICAL_MINIMUM(1, 0),
|
||||
PHYSICAL_MAXIMUM(1, 1),
|
||||
REPORT_COUNT(2, usage_max - usage_min + 1),
|
||||
REPORT_SIZE(1, 1),
|
||||
INPUT(1, Data|Var|Abs),
|
||||
};
|
||||
|
||||
return hid_descriptor_append(desc, template, sizeof(template));
|
||||
}
|
||||
|
||||
#include "pop_hid_macros.h"
|
|
@ -94,7 +94,9 @@ static const struct product_desc XBOX_CONTROLLERS[] = {
|
|||
static DRIVER_OBJECT *driver_obj;
|
||||
|
||||
static DEVICE_OBJECT *mouse_obj;
|
||||
static struct hid_descriptor mouse_desc;
|
||||
static DEVICE_OBJECT *keyboard_obj;
|
||||
static struct hid_descriptor keyboard_desc;
|
||||
|
||||
/* The root-enumerated device stack. */
|
||||
DEVICE_OBJECT *bus_pdo;
|
||||
|
@ -483,16 +485,10 @@ static NTSTATUS mouse_get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer,
|
|||
{
|
||||
TRACE("buffer %p, length %u.\n", buffer, length);
|
||||
|
||||
*ret_length = sizeof(REPORT_HEADER) + sizeof(REPORT_BUTTONS) + sizeof(REPORT_TAIL);
|
||||
if (length < sizeof(REPORT_HEADER) + sizeof(REPORT_BUTTONS) + sizeof(REPORT_TAIL))
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
memcpy(buffer, REPORT_HEADER, sizeof(REPORT_HEADER));
|
||||
add_button_block(buffer + sizeof(REPORT_HEADER), 1, 3);
|
||||
memcpy(buffer + sizeof(REPORT_HEADER) + sizeof(REPORT_BUTTONS), REPORT_TAIL, sizeof(REPORT_TAIL));
|
||||
buffer[IDX_HEADER_PAGE] = HID_USAGE_PAGE_GENERIC;
|
||||
buffer[IDX_HEADER_USAGE] = HID_USAGE_GENERIC_MOUSE;
|
||||
*ret_length = mouse_desc.size;
|
||||
if (length < mouse_desc.size) return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
memcpy(buffer, mouse_desc.data, mouse_desc.size);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -545,6 +541,13 @@ static void mouse_device_create(void)
|
|||
{
|
||||
static const WCHAR busidW[] = {'W','I','N','E','M','O','U','S','E',0};
|
||||
|
||||
if (!hid_descriptor_begin(&mouse_desc, HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_MOUSE))
|
||||
return;
|
||||
if (!hid_descriptor_add_buttons(&mouse_desc, HID_USAGE_PAGE_BUTTON, 1, 3))
|
||||
return;
|
||||
if (!hid_descriptor_end(&mouse_desc))
|
||||
return;
|
||||
|
||||
mouse_obj = bus_create_hid_device(busidW, 0, 0, -1, 0, 0, busidW, FALSE, &mouse_vtbl, 0);
|
||||
IoInvalidateDeviceRelations(bus_pdo, BusRelations);
|
||||
}
|
||||
|
@ -557,17 +560,10 @@ static NTSTATUS keyboard_get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffe
|
|||
{
|
||||
TRACE("buffer %p, length %u.\n", buffer, length);
|
||||
|
||||
*ret_length = sizeof(REPORT_HEADER) + sizeof(REPORT_BUTTONS) + sizeof(REPORT_TAIL);
|
||||
if (length < sizeof(REPORT_HEADER) + sizeof(REPORT_BUTTONS) + sizeof(REPORT_TAIL))
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
memcpy(buffer, REPORT_HEADER, sizeof(REPORT_HEADER));
|
||||
add_button_block(buffer + sizeof(REPORT_HEADER), 0, 101);
|
||||
buffer[sizeof(REPORT_HEADER) + IDX_BUTTON_USAGE_PAGE] = HID_USAGE_PAGE_KEYBOARD;
|
||||
memcpy(buffer + sizeof(REPORT_HEADER) + sizeof(REPORT_BUTTONS), REPORT_TAIL, sizeof(REPORT_TAIL));
|
||||
buffer[IDX_HEADER_PAGE] = HID_USAGE_PAGE_GENERIC;
|
||||
buffer[IDX_HEADER_USAGE] = HID_USAGE_GENERIC_KEYBOARD;
|
||||
*ret_length = keyboard_desc.size;
|
||||
if (length < keyboard_desc.size) return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
memcpy(buffer, keyboard_desc.data, keyboard_desc.size);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -620,6 +616,13 @@ static void keyboard_device_create(void)
|
|||
{
|
||||
static const WCHAR busidW[] = {'W','I','N','E','K','E','Y','B','O','A','R','D',0};
|
||||
|
||||
if (!hid_descriptor_begin(&keyboard_desc, HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_KEYBOARD))
|
||||
return;
|
||||
if (!hid_descriptor_add_buttons(&keyboard_desc, HID_USAGE_PAGE_KEYBOARD, 0, 101))
|
||||
return;
|
||||
if (!hid_descriptor_end(&keyboard_desc))
|
||||
return;
|
||||
|
||||
keyboard_obj = bus_create_hid_device(busidW, 0, 0, -1, 0, 0, busidW, FALSE, &keyboard_vtbl, 0);
|
||||
IoInvalidateDeviceRelations(bus_pdo, BusRelations);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue