Rémi Bernon : winebus.sys: Introduce new HID report descriptor helpers.

Alexandre Julliard julliard at winehq.org
Thu Aug 12 16:35:19 CDT 2021


Module: wine
Branch: master
Commit: 2ea19ff3578c16392a01fcb8a4ab9b372143b39c
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=2ea19ff3578c16392a01fcb8a4ab9b372143b39c

Author: Rémi Bernon <rbernon at codeweavers.com>
Date:   Thu Aug 12 10:26:56 2021 +0200

winebus.sys: Introduce new HID report descriptor helpers.

And use them for mouse and keyboard.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/winebus.sys/Makefile.in  |  1 +
 dlls/winebus.sys/controller.h | 20 ++++++++++
 dlls/winebus.sys/hid.c        | 91 +++++++++++++++++++++++++++++++++++++++++++
 dlls/winebus.sys/main.c       | 41 ++++++++++---------
 4 files changed, 134 insertions(+), 19 deletions(-)

diff --git a/dlls/winebus.sys/Makefile.in b/dlls/winebus.sys/Makefile.in
index 9011bbb6075..8cde3c7b422 100644
--- a/dlls/winebus.sys/Makefile.in
+++ b/dlls/winebus.sys/Makefile.in
@@ -8,6 +8,7 @@ C_SRCS = \
 	bus_iohid.c \
 	bus_sdl.c \
 	bus_udev.c \
+	hid.c \
 	main.c
 
 RC_SRCS = winebus.rc
diff --git a/dlls/winebus.sys/controller.h b/dlls/winebus.sys/controller.h
index 2f4a72a94cd..aa838129ce2 100644
--- a/dlls/winebus.sys/controller.h
+++ b/dlls/winebus.sys/controller.h
@@ -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"
diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c
new file mode 100644
index 00000000000..052037ec19e
--- /dev/null
+++ b/dlls/winebus.sys/hid.c
@@ -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"
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c
index 6ceccd21442..84885bdcce9 100644
--- a/dlls/winebus.sys/main.c
+++ b/dlls/winebus.sys/main.c
@@ -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);
 }




More information about the wine-cvs mailing list