From: Arkadiusz Hiler ahiler@codeweavers.com
Declaring them as 8 bits crashes game due to how Unity's native hid support parses the data. --- dlls/winebus.sys/hid.c | 66 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 12 deletions(-)
diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index 733f9a51f96..7e661953639 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -215,7 +215,7 @@ static BOOL hid_device_add_hatswitch_count(struct unix_device *iface, BYTE count { if (!iface->hid_device_state.hatswitch_count) iface->hid_device_state.hatswitch_start = offset; iface->hid_device_state.hatswitch_count += count; - iface->hid_device_state.bit_size += 8 * count; + iface->hid_device_state.bit_size += 4 * count; return TRUE; }
@@ -224,6 +224,7 @@ static BOOL hid_device_add_hatswitch_count(struct unix_device *iface, BYTE count
BOOL hid_device_add_hatswitch(struct unix_device *iface, INT count) { + BOOL ret; struct hid_report_descriptor *desc = &iface->hid_report_descriptor; const BYTE template[] = { @@ -231,16 +232,27 @@ BOOL hid_device_add_hatswitch(struct unix_device *iface, INT count) USAGE(1, HID_USAGE_GENERIC_HATSWITCH), LOGICAL_MINIMUM(1, 1), LOGICAL_MAXIMUM(1, 8), - REPORT_SIZE(1, 8), + REPORT_SIZE(1, 4), REPORT_COUNT(4, count), UNIT(1, 0x0), /* None */ INPUT(1, Data|Var|Abs|Null), }; + const BYTE template_pad[] = + { + INPUT(1, Cnst|Ary|Abs), + };
if (!hid_device_add_hatswitch_count(iface, count)) return FALSE;
- return hid_report_descriptor_append(desc, template, sizeof(template)); + ret = hid_report_descriptor_append(desc, template, sizeof(template)); + + if (ret && count % 2) { + ret = hid_report_descriptor_append(desc, template_pad, sizeof(template_pad)); + iface->hid_device_state.bit_size += 4; + } + + return ret; }
static BOOL hid_device_add_axis_count(struct unix_device *iface, BOOL rel, BYTE count, @@ -1431,36 +1443,66 @@ static void hatswitch_compose(LONG x, LONG y, BYTE *value) else if (x < 0 && y < 0) *value = 8; }
+static BYTE hatswitch_get(BYTE report_byte, LONG which) +{ + if (which) + return report_byte >> 4; + else + return report_byte & 0x0f; +} + +static void hatswitch_set(BYTE *report_byte, BYTE which, BYTE new_value) +{ + if (which) + { + new_value <<= 4; + *report_byte &= 0xf; + } + else + *report_byte &= 0xf0; + + *report_byte |= new_value; +} + BOOL hid_device_set_hatswitch_x(struct unix_device *iface, ULONG index, LONG new_x) { struct hid_device_state *state = &iface->hid_device_state; - ULONG offset = state->hatswitch_start + index; + ULONG offset = state->hatswitch_start + index / 2; + BYTE value; LONG x, y; if (index > state->hatswitch_count) return FALSE; - hatswitch_decompose(state->report_buf[offset], &x, &y); - hatswitch_compose(new_x, y, &state->report_buf[offset]); + value = hatswitch_get(state->report_buf[offset], index % 2); + hatswitch_decompose(value, &x, &y); + hatswitch_compose(new_x, y, &value); + hatswitch_set(&state->report_buf[offset], index % 2, value); return TRUE; }
BOOL hid_device_set_hatswitch_y(struct unix_device *iface, ULONG index, LONG new_y) { struct hid_device_state *state = &iface->hid_device_state; - ULONG offset = state->hatswitch_start + index; + ULONG offset = state->hatswitch_start + index / 2; + BYTE value; LONG x, y; if (index > state->hatswitch_count) return FALSE; - hatswitch_decompose(state->report_buf[offset], &x, &y); - hatswitch_compose(x, new_y, &state->report_buf[offset]); + value = hatswitch_get(state->report_buf[offset], index % 2); + hatswitch_decompose(value, &x, &y); + hatswitch_compose(x, new_y, &value); + hatswitch_set(&state->report_buf[offset], index % 2, value); return TRUE; }
BOOL hid_device_move_hatswitch(struct unix_device *iface, ULONG index, LONG x, LONG y) { struct hid_device_state *state = &iface->hid_device_state; - ULONG offset = state->hatswitch_start + index; + ULONG offset = state->hatswitch_start + index / 2; + BYTE value; LONG old_x, old_y; if (index > state->hatswitch_count) return FALSE; - hatswitch_decompose(state->report_buf[offset], &old_x, &old_y); - hatswitch_compose(old_x + x, old_y + y, &state->report_buf[offset]); + value = hatswitch_get(state->report_buf[offset], index % 2); + hatswitch_decompose(value, &old_x, &old_y); + hatswitch_compose(old_x + x, old_y + y, &value); + hatswitch_set(&state->report_buf[offset], index % 2, value); return TRUE; }