[PATCH 4/5] winebus.sys: Use HID descriptor helpers in bus_udev.c.
Rémi Bernon
rbernon at codeweavers.com
Thu Aug 12 03:26:57 CDT 2021
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/winebus.sys/bus_udev.c | 147 +++++++++-------------------------
dlls/winebus.sys/controller.h | 5 ++
dlls/winebus.sys/hid.c | 121 ++++++++++++++++++++++++++++
3 files changed, 162 insertions(+), 111 deletions(-)
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c
index 261d24d011b..f9469399202 100644
--- a/dlls/winebus.sys/bus_udev.c
+++ b/dlls/winebus.sys/bus_udev.c
@@ -112,25 +112,6 @@ static inline struct platform_private *impl_from_DEVICE_OBJECT(DEVICE_OBJECT *de
#ifdef HAS_PROPER_INPUT_HEADER
-#include "psh_hid_macros.h"
-
-static const BYTE REPORT_ABS_AXIS_TAIL[] = {
- LOGICAL_MINIMUM(4, /* placeholder */ 0x00000000),
- LOGICAL_MAXIMUM(4, /* placeholder */ 0x000000ff),
- PHYSICAL_MINIMUM(4, /* placeholder */ 0x00000000),
- PHYSICAL_MAXIMUM(4, /* placeholder */ 0x000000ff),
- REPORT_SIZE(1, 32),
- REPORT_COUNT(1, /* placeholder */ 0),
- INPUT(1, Data|Var|Abs),
-};
-#define IDX_ABS_LOG_MINIMUM 1
-#define IDX_ABS_LOG_MAXIMUM 6
-#define IDX_ABS_PHY_MINIMUM 11
-#define IDX_ABS_PHY_MAXIMUM 16
-#define IDX_ABS_AXIS_COUNT 23
-
-#include "pop_hid_macros.h"
-
static const BYTE ABS_TO_HID_MAP[][2] = {
{HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_X}, /*ABS_X*/
{HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_Y}, /*ABS_Y*/
@@ -199,8 +180,7 @@ struct wine_input_private {
BYTE *current_report_buffer;
enum { FIRST, NORMAL, DROPPED } report_state;
- int report_descriptor_size;
- BYTE *report_descriptor;
+ struct hid_descriptor desc;
int button_start;
BYTE button_map[KEY_MAX];
@@ -212,40 +192,6 @@ struct wine_input_private {
#define test_bit(arr,bit) (((BYTE*)(arr))[(bit)>>3]&(1<<((bit)&7)))
-static BYTE *add_axis_block(BYTE *report_ptr, BYTE count, BYTE page, BYTE *usages, BOOL absolute, const struct wine_input_absinfo *absinfo)
-{
- int i;
- memcpy(report_ptr, REPORT_AXIS_HEADER, sizeof(REPORT_AXIS_HEADER));
- report_ptr[IDX_AXIS_PAGE] = page;
- report_ptr += sizeof(REPORT_AXIS_HEADER);
- for (i = 0; i < count; i++)
- {
- memcpy(report_ptr, REPORT_AXIS_USAGE, sizeof(REPORT_AXIS_USAGE));
- report_ptr[IDX_AXIS_USAGE] = usages[i];
- report_ptr += sizeof(REPORT_AXIS_USAGE);
- }
- if (absolute)
- {
- memcpy(report_ptr, REPORT_ABS_AXIS_TAIL, sizeof(REPORT_ABS_AXIS_TAIL));
- if (absinfo)
- {
- *((int*)&report_ptr[IDX_ABS_LOG_MINIMUM]) = LE_DWORD(absinfo->info.minimum);
- *((int*)&report_ptr[IDX_ABS_LOG_MAXIMUM]) = LE_DWORD(absinfo->info.maximum);
- *((int*)&report_ptr[IDX_ABS_PHY_MINIMUM]) = LE_DWORD(absinfo->info.minimum);
- *((int*)&report_ptr[IDX_ABS_PHY_MAXIMUM]) = LE_DWORD(absinfo->info.maximum);
- }
- report_ptr[IDX_ABS_AXIS_COUNT] = count;
- report_ptr += sizeof(REPORT_ABS_AXIS_TAIL);
- }
- else
- {
- memcpy(report_ptr, REPORT_REL_AXIS_TAIL, sizeof(REPORT_REL_AXIS_TAIL));
- report_ptr[IDX_REL_AXIS_COUNT] = count;
- report_ptr += sizeof(REPORT_REL_AXIS_TAIL);
- }
- return report_ptr;
-}
-
static const BYTE* what_am_I(struct udev_device *dev)
{
static const BYTE Unknown[2] = {HID_USAGE_PAGE_GENERIC, 0};
@@ -408,8 +354,7 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
int rel_pages[TOP_REL_PAGE][HID_REL_MAX+1];
BYTE absbits[(ABS_MAX+7)/8];
BYTE relbits[(REL_MAX+7)/8];
- BYTE *report_ptr;
- INT i, descript_size;
+ INT i;
INT report_size;
INT button_count, abs_count, rel_count, hat_count;
const BYTE *device_usage = what_am_I(dev);
@@ -425,7 +370,6 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
return FALSE;
}
- descript_size = sizeof(REPORT_HEADER) + sizeof(REPORT_TAIL);
report_size = 0;
abs_count = 0;
@@ -443,7 +387,6 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
if (abs_pages[i][0] > 0)
{
int j;
- descript_size += sizeof(REPORT_AXIS_USAGE) * abs_pages[i][0];
for (j = 1; j <= abs_pages[i][0]; j++)
{
ext->abs_map[abs_pages[i][j]].report_index = report_size;
@@ -451,8 +394,6 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
}
abs_count++;
}
- descript_size += sizeof(REPORT_AXIS_HEADER) * abs_count;
- descript_size += sizeof(REPORT_ABS_AXIS_TAIL) * abs_count;
rel_count = 0;
memset(rel_pages, 0, sizeof(rel_pages));
@@ -467,7 +408,6 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
if (rel_pages[i][0] > 0)
{
int j;
- descript_size += sizeof(REPORT_AXIS_USAGE) * rel_pages[i][0];
for (j = 1; j <= rel_pages[i][0]; j++)
{
ext->rel_map[rel_pages[i][j]] = report_size;
@@ -475,17 +415,12 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
}
rel_count++;
}
- descript_size += sizeof(REPORT_AXIS_HEADER) * rel_count;
- descript_size += sizeof(REPORT_REL_AXIS_TAIL) * rel_count;
/* For now lump all buttons just into incremental usages, Ignore Keys */
ext->button_start = report_size;
button_count = count_buttons(ext->base.device_fd, ext->button_map);
if (button_count)
{
- descript_size += sizeof(REPORT_BUTTONS);
- if (button_count % 8)
- descript_size += sizeof(REPORT_PADDING);
report_size += (button_count + 7) / 8;
}
@@ -499,35 +434,26 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
report_size++;
hat_count++;
}
- if (hat_count > 0)
- descript_size += sizeof(REPORT_HATSWITCH);
- TRACE("Report Descriptor will be %i bytes\n", descript_size);
TRACE("Report will be %i bytes\n", report_size);
- ext->report_descriptor = HeapAlloc(GetProcessHeap(), 0, descript_size);
- if (!ext->report_descriptor)
- {
- ERR("Failed to alloc report descriptor\n");
+ if (!hid_descriptor_begin(&ext->desc, device_usage[0], device_usage[1]))
return FALSE;
- }
- report_ptr = ext->report_descriptor;
- memcpy(report_ptr, REPORT_HEADER, sizeof(REPORT_HEADER));
- report_ptr[IDX_HEADER_PAGE] = device_usage[0];
- report_ptr[IDX_HEADER_USAGE] = device_usage[1];
- report_ptr += sizeof(REPORT_HEADER);
if (abs_count)
{
for (i = 1; i < TOP_ABS_PAGE; i++)
{
if (abs_pages[i][0])
{
- BYTE usages[HID_ABS_MAX];
+ USAGE usages[HID_ABS_MAX];
int j;
for (j = 0; j < abs_pages[i][0]; j++)
usages[j] = ABS_TO_HID_MAP[abs_pages[i][j+1]][1];
- report_ptr = add_axis_block(report_ptr, abs_pages[i][0], i, usages, TRUE, &ext->abs_map[abs_pages[i][1]]);
+ if (!hid_descriptor_add_axes(&ext->desc, abs_pages[i][0], i, usages, FALSE, 32,
+ LE_DWORD(ext->abs_map[abs_pages[i][1]].info.minimum),
+ LE_DWORD(ext->abs_map[abs_pages[i][1]].info.maximum)))
+ return FALSE;
}
}
}
@@ -537,45 +463,41 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
{
if (rel_pages[i][0])
{
- BYTE usages[HID_REL_MAX];
+ USAGE usages[HID_REL_MAX];
int j;
for (j = 0; j < rel_pages[i][0]; j++)
usages[j] = REL_TO_HID_MAP[rel_pages[i][j+1]][1];
- report_ptr = add_axis_block(report_ptr, rel_pages[i][0], i, usages, FALSE, NULL);
+ if (!hid_descriptor_add_axes(&ext->desc, rel_pages[i][0], i, usages, TRUE, 8, 0x81, 0x7f))
+ return FALSE;
}
}
}
if (button_count)
{
- report_ptr = add_button_block(report_ptr, 1, button_count);
+ if (!hid_descriptor_add_buttons(&ext->desc, HID_USAGE_PAGE_BUTTON, 1, button_count))
+ return FALSE;
+
if (button_count % 8)
{
BYTE padding = 8 - (button_count % 8);
- report_ptr = add_padding_block(report_ptr, padding);
+ if (!hid_descriptor_add_padding(&ext->desc, padding))
+ return FALSE;
}
}
if (hat_count)
- report_ptr = add_hatswitch(report_ptr, hat_count);
-
- memcpy(report_ptr, REPORT_TAIL, sizeof(REPORT_TAIL));
-
- ext->report_descriptor_size = descript_size;
- ext->buffer_length = report_size;
- ext->current_report_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, report_size);
- if (ext->current_report_buffer == NULL)
{
- ERR("Failed to alloc report buffer\n");
- HeapFree(GetProcessHeap(), 0, ext->report_descriptor);
- return FALSE;
+ if (!hid_descriptor_add_hatswitch(&ext->desc, hat_count))
+ return FALSE;
}
- ext->last_report_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, report_size);
- if (ext->last_report_buffer == NULL)
- {
- ERR("Failed to alloc report buffer\n");
- HeapFree(GetProcessHeap(), 0, ext->report_descriptor);
- HeapFree(GetProcessHeap(), 0, ext->current_report_buffer);
+
+ if (!hid_descriptor_end(&ext->desc))
return FALSE;
- }
+
+ ext->buffer_length = report_size;
+ if (!(ext->current_report_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, report_size)))
+ goto failed;
+ if (!(ext->last_report_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, report_size)))
+ goto failed;
ext->report_state = FIRST;
/* Initialize axis in the report */
@@ -584,6 +506,12 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
set_abs_axis_value(ext, i, ext->abs_map[i].info.value);
return TRUE;
+
+failed:
+ HeapFree(GetProcessHeap(), 0, ext->current_report_buffer);
+ HeapFree(GetProcessHeap(), 0, ext->last_report_buffer);
+ hid_descriptor_free(&ext->desc);
+ return FALSE;
}
static BOOL set_report_from_event(struct wine_input_private *ext, struct input_event *ie)
@@ -972,7 +900,7 @@ static void lnxev_free_device(DEVICE_OBJECT *device)
HeapFree(GetProcessHeap(), 0, ext->current_report_buffer);
HeapFree(GetProcessHeap(), 0, ext->last_report_buffer);
- HeapFree(GetProcessHeap(), 0, ext->report_descriptor);
+ hid_descriptor_free(&ext->desc);
close(ext->base.device_fd);
udev_device_unref(ext->base.udev_device);
@@ -982,13 +910,10 @@ static NTSTATUS lnxev_get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer,
{
struct wine_input_private *ext = input_impl_from_DEVICE_OBJECT(device);
- *out_length = ext->report_descriptor_size;
-
- if (length < ext->report_descriptor_size)
- return STATUS_BUFFER_TOO_SMALL;
-
- memcpy(buffer, ext->report_descriptor, ext->report_descriptor_size);
+ *out_length = ext->desc.size;
+ if (length < ext->desc.size) return STATUS_BUFFER_TOO_SMALL;
+ memcpy(buffer, ext->desc.data, ext->desc.size);
return STATUS_SUCCESS;
}
diff --git a/dlls/winebus.sys/controller.h b/dlls/winebus.sys/controller.h
index aa838129ce2..b03338841e8 100644
--- a/dlls/winebus.sys/controller.h
+++ b/dlls/winebus.sys/controller.h
@@ -34,9 +34,14 @@ struct hid_descriptor
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 void hid_descriptor_free(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;
+extern BOOL hid_descriptor_add_padding(struct hid_descriptor *desc, BYTE bitcount) DECLSPEC_HIDDEN;
+extern BOOL hid_descriptor_add_hatswitch(struct hid_descriptor *desc, INT count) DECLSPEC_HIDDEN;
+extern BOOL hid_descriptor_add_axes(struct hid_descriptor *desc, BYTE count, USAGE usage_page,
+ const USAGE *usages, BOOL rel, INT size, LONG min, LONG max) DECLSPEC_HIDDEN;
/* Blocks of data for building HID device descriptions */
diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c
index 052037ec19e..86c27d3eded 100644
--- a/dlls/winebus.sys/hid.c
+++ b/dlls/winebus.sys/hid.c
@@ -44,6 +44,16 @@ BOOL hid_descriptor_append(struct hid_descriptor *desc, const BYTE *buffer, SIZE
#include "psh_hid_macros.h"
+static BOOL hid_descriptor_append_usage(struct hid_descriptor *desc, USAGE usage)
+{
+ const BYTE template[] =
+ {
+ USAGE(2, usage),
+ };
+
+ return hid_descriptor_append(desc, template, sizeof(template));
+}
+
BOOL hid_descriptor_begin(struct hid_descriptor *desc, USAGE usage_page, USAGE usage)
{
const BYTE template[] =
@@ -68,6 +78,11 @@ BOOL hid_descriptor_end(struct hid_descriptor *desc)
return hid_descriptor_append(desc, template, sizeof(template));
}
+void hid_descriptor_free(struct hid_descriptor *desc)
+{
+ HeapFree(GetProcessHeap(), 0, desc->data);
+}
+
BOOL hid_descriptor_add_buttons(struct hid_descriptor *desc, USAGE usage_page,
USAGE usage_min, USAGE usage_max)
{
@@ -88,4 +103,110 @@ BOOL hid_descriptor_add_buttons(struct hid_descriptor *desc, USAGE usage_page,
return hid_descriptor_append(desc, template, sizeof(template));
}
+BOOL hid_descriptor_add_padding(struct hid_descriptor *desc, BYTE bitcount)
+{
+ const BYTE template[] =
+ {
+ REPORT_COUNT(1, bitcount),
+ REPORT_SIZE(1, 1),
+ INPUT(1, Cnst|Var|Abs),
+ };
+
+ return hid_descriptor_append(desc, template, sizeof(template));
+}
+
+BOOL hid_descriptor_add_hatswitch(struct hid_descriptor *desc, INT count)
+{
+ const BYTE template[] =
+ {
+ USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
+ USAGE(1, HID_USAGE_GENERIC_HATSWITCH),
+ LOGICAL_MINIMUM(1, 1),
+ LOGICAL_MAXIMUM(1, 8),
+ PHYSICAL_MINIMUM(1, 0),
+ PHYSICAL_MAXIMUM(2, 8),
+ REPORT_SIZE(1, 4),
+ REPORT_COUNT(4, count),
+ UNIT(1, 0x0e /* none */),
+ INPUT(1, Data|Var|Abs|Null),
+ };
+
+ return hid_descriptor_append(desc, template, sizeof(template));
+}
+
+BOOL hid_descriptor_add_axes(struct hid_descriptor *desc, BYTE count, USAGE usage_page,
+ const USAGE *usages, BOOL rel, INT size, LONG min, LONG max)
+{
+ const BYTE template_begin[] =
+ {
+ USAGE_PAGE(1, usage_page),
+ COLLECTION(1, Physical),
+ };
+ const BYTE template_end[] =
+ {
+ END_COLLECTION,
+ };
+ const BYTE template_1[] =
+ {
+ LOGICAL_MINIMUM(1, min),
+ LOGICAL_MAXIMUM(1, max),
+ PHYSICAL_MINIMUM(1, min),
+ PHYSICAL_MAXIMUM(1, max),
+ REPORT_SIZE(1, size),
+ REPORT_COUNT(1, count),
+ INPUT(1, Data|Var|(rel ? Rel : Abs)),
+ };
+ const BYTE template_2[] =
+ {
+ LOGICAL_MINIMUM(2, min),
+ LOGICAL_MAXIMUM(2, max),
+ PHYSICAL_MINIMUM(2, min),
+ PHYSICAL_MAXIMUM(2, max),
+ REPORT_SIZE(1, size),
+ REPORT_COUNT(1, count),
+ INPUT(1, Data|Var|(rel ? Rel : Abs)),
+ };
+ const BYTE template_4[] =
+ {
+ LOGICAL_MINIMUM(4, min),
+ LOGICAL_MAXIMUM(4, max),
+ PHYSICAL_MINIMUM(4, min),
+ PHYSICAL_MAXIMUM(4, max),
+ REPORT_SIZE(1, size),
+ REPORT_COUNT(1, count),
+ INPUT(1, Data|Var|(rel ? Rel : Abs)),
+ };
+ int i;
+
+ if (!hid_descriptor_append(desc, template_begin, sizeof(template_begin)))
+ return FALSE;
+
+ for (i = 0; i < count; i++)
+ {
+ if (!hid_descriptor_append_usage(desc, usages[i]))
+ return FALSE;
+ }
+
+ if (size >= 16)
+ {
+ if (!hid_descriptor_append(desc, template_4, sizeof(template_4)))
+ return FALSE;
+ }
+ else if (size >= 8)
+ {
+ if (!hid_descriptor_append(desc, template_2, sizeof(template_2)))
+ return FALSE;
+ }
+ else
+ {
+ if (!hid_descriptor_append(desc, template_1, sizeof(template_1)))
+ return FALSE;
+ }
+
+ if (!hid_descriptor_append(desc, template_end, sizeof(template_end)))
+ return FALSE;
+
+ return TRUE;
+}
+
#include "pop_hid_macros.h"
--
2.32.0
More information about the wine-devel
mailing list