Commit e3431a02 authored by Arkadiusz Hiler's avatar Arkadiusz Hiler Committed by Alexandre Julliard

winebus.sys: Use 4 bits for hat switches.

Declaring them as 8 bits crashes game due to how Unity's native hid support parses the data.
parent 94a7b32a
......@@ -209,13 +209,14 @@ static BOOL hid_device_add_hatswitch_count(struct unix_device *iface, BYTE count
ERR("hatswitches should be added before buttons!\n");
else if ((iface->hid_device_state.bit_size % 8))
ERR("hatswitches should be byte aligned, missing padding!\n");
else if (iface->hid_device_state.bit_size + 8 * count > 0x80000)
else if (iface->hid_device_state.bit_size + 4 * (count + 1) > 0x80000)
ERR("report size overflow, too many elements!\n");
else
{
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;
if (count % 2) iface->hid_device_state.bit_size += 4;
return TRUE;
}
......@@ -231,16 +232,28 @@ 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[] =
{
REPORT_COUNT(1, 4),
REPORT_SIZE(1, 1),
INPUT(1, Cnst|Ary|Abs),
};
if (!hid_device_add_hatswitch_count(iface, count))
return FALSE;
return hid_report_descriptor_append(desc, template, sizeof(template));
if (!hid_report_descriptor_append(desc, template, sizeof(template)))
return FALSE;
if ((count % 2) && !hid_report_descriptor_append(desc, template_pad, sizeof(template_pad)))
return FALSE;
return TRUE;
}
static BOOL hid_device_add_axis_count(struct unix_device *iface, BOOL rel, BYTE count,
......@@ -1409,8 +1422,9 @@ BOOL hid_device_set_button(struct unix_device *iface, ULONG index, BOOL is_set)
* +1 | 6 5 4
* v
*/
static void hatswitch_decompose(BYTE value, LONG *x, LONG *y)
static void hatswitch_decompose(BYTE value, ULONG index, LONG *x, LONG *y)
{
value = (index % 2) ? (value >> 4) : (value & 0x0f);
*x = *y = 0;
if (value == 8 || value == 1 || value == 2) *y = -1;
if (value == 6 || value == 5 || value == 4) *y = +1;
......@@ -1418,49 +1432,61 @@ static void hatswitch_decompose(BYTE value, LONG *x, LONG *y)
if (value == 2 || value == 3 || value == 4) *x = +1;
}
static void hatswitch_compose(LONG x, LONG y, BYTE *value)
static void hatswitch_compose(LONG x, LONG y, BYTE *value, ULONG index)
{
if (x == 0 && y == 0) *value = 0;
else if (x == 0 && y < 0) *value = 1;
else if (x > 0 && y < 0) *value = 2;
else if (x > 0 && y == 0) *value = 3;
else if (x > 0 && y > 0) *value = 4;
else if (x == 0 && y > 0) *value = 5;
else if (x < 0 && y > 0) *value = 6;
else if (x < 0 && y == 0) *value = 7;
else if (x < 0 && y < 0) *value = 8;
BYTE new_value = 0;
if (x == 0 && y == 0) new_value = 0;
else if (x == 0 && y < 0) new_value = 1;
else if (x > 0 && y < 0) new_value = 2;
else if (x > 0 && y == 0) new_value = 3;
else if (x > 0 && y > 0) new_value = 4;
else if (x == 0 && y > 0) new_value = 5;
else if (x < 0 && y > 0) new_value = 6;
else if (x < 0 && y == 0) new_value = 7;
else if (x < 0 && y < 0) new_value = 8;
if (index % 2)
{
*value &= 0xf;
*value |= new_value << 4;
}
else
{
*value &= 0xf0;
*value |= 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;
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]);
hatswitch_decompose(state->report_buf[offset], index, &x, &y);
hatswitch_compose(new_x, y, &state->report_buf[offset], index);
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;
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]);
hatswitch_decompose(state->report_buf[offset], index, &x, &y);
hatswitch_compose(x, new_y, &state->report_buf[offset], index);
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;
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]);
hatswitch_decompose(state->report_buf[offset], index, &old_x, &old_y);
hatswitch_compose(old_x + x, old_y + y, &state->report_buf[offset], index);
return TRUE;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment