winebus.sys: Use the computed element offsets to create reports.

Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Rémi Bernon 2021-09-22 10:30:44 +02:00 committed by Alexandre Julliard
parent de050c974b
commit 9d5e9b5f42
4 changed files with 67 additions and 99 deletions

View File

@ -123,11 +123,6 @@ struct sdl_device
SDL_GameController *sdl_controller;
SDL_JoystickID id;
int button_start;
int axis_start;
int ball_start;
int hat_start;
int buffer_length;
BYTE *report_buffer;
@ -152,40 +147,44 @@ static struct sdl_device *find_device_from_id(SDL_JoystickID id)
static void set_button_value(struct sdl_device *impl, int index, int value)
{
int byte_index = impl->button_start + index / 8;
struct hid_device_state *state = &impl->unix_device.hid_device_state;
USHORT offset = state->button_start;
int byte_index = offset + index / 8;
int bit_index = index % 8;
BYTE mask = 1 << bit_index;
if (value)
{
impl->report_buffer[byte_index] = impl->report_buffer[byte_index] | mask;
}
else
{
mask = ~mask;
impl->report_buffer[byte_index] = impl->report_buffer[byte_index] & mask;
}
if (index >= state->button_count) return;
if (value) impl->report_buffer[byte_index] |= mask;
else impl->report_buffer[byte_index] &= ~mask;
}
static void set_axis_value(struct sdl_device *impl, int index, short value)
{
DWORD *report = (DWORD *)(impl->report_buffer + impl->axis_start);
report[index] = LE_DWORD(value);
struct hid_device_state *state = &impl->unix_device.hid_device_state;
USHORT offset = state->abs_axis_start;
if (index >= state->abs_axis_count) return;
offset += index * sizeof(DWORD);
*(DWORD *)&impl->report_buffer[offset] = LE_DWORD(value);
}
static void set_ball_value(struct sdl_device *impl, int index, int value1, int value2)
{
int offset;
offset = impl->ball_start + (index * sizeof(DWORD));
struct hid_device_state *state = &impl->unix_device.hid_device_state;
USHORT offset = state->rel_axis_start;
if (index >= state->rel_axis_count) return;
offset += index * sizeof(DWORD);
*(DWORD *)&impl->report_buffer[offset] = LE_DWORD(value1);
*(DWORD *)&impl->report_buffer[offset + sizeof(DWORD)] = LE_DWORD(value2);
}
static void set_hat_value(struct sdl_device *impl, int index, int value)
{
int byte = impl->hat_start + index;
struct hid_device_state *state = &impl->unix_device.hid_device_state;
USHORT offset = state->hatswitch_start;
unsigned char val;
if (index >= state->hatswitch_count) return;
offset += index;
switch (value)
{
/* 8 1 2
@ -203,7 +202,7 @@ static void set_hat_value(struct sdl_device *impl, int index, int value)
default: return;
}
impl->report_buffer[byte] = val;
impl->report_buffer[offset] = val;
}
static BOOL descriptor_add_haptic(struct sdl_device *impl)
@ -246,8 +245,7 @@ static NTSTATUS build_joystick_report_descriptor(struct unix_device *iface)
HID_USAGE_GENERIC_WHEEL
};
struct sdl_device *impl = impl_from_unix_device(iface);
int i, report_size = 1;
int button_count, axis_count, ball_count, hat_count;
int i, button_count, axis_count, ball_count, hat_count;
axis_count = pSDL_JoystickNumAxes(impl->sdl_joystick);
if (axis_count > 6)
@ -255,8 +253,6 @@ static NTSTATUS build_joystick_report_descriptor(struct unix_device *iface)
FIXME("Clamping joystick to 6 axis\n");
axis_count = 6;
}
impl->axis_start = report_size;
report_size += (sizeof(DWORD) * axis_count);
ball_count = pSDL_JoystickNumBalls(impl->sdl_joystick);
if (axis_count + ball_count * 2 > ARRAY_SIZE(joystick_usages))
@ -264,19 +260,9 @@ static NTSTATUS build_joystick_report_descriptor(struct unix_device *iface)
FIXME("Capping ball + axis at 9\n");
ball_count = (ARRAY_SIZE(joystick_usages) - axis_count) / 2;
}
impl->ball_start = report_size;
report_size += (sizeof(DWORD) * 2 * ball_count);
hat_count = pSDL_JoystickNumHats(impl->sdl_joystick);
impl->hat_start = report_size;
report_size += hat_count;
/* For now lump all buttons just into incremental usages, Ignore Keys */
button_count = pSDL_JoystickNumButtons(impl->sdl_joystick);
impl->button_start = report_size;
report_size += (button_count + 7) / 8;
TRACE("Report will be %i bytes\n", report_size);
if (!hid_device_begin_report_descriptor(iface, HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_JOYSTICK))
return STATUS_NO_MEMORY;
@ -301,8 +287,8 @@ static NTSTATUS build_joystick_report_descriptor(struct unix_device *iface)
if (!hid_device_end_report_descriptor(iface))
return STATUS_NO_MEMORY;
impl->buffer_length = report_size;
if (!(impl->report_buffer = calloc(1, report_size))) goto failed;
impl->buffer_length = iface->hid_device_state.report_len;
if (!(impl->report_buffer = calloc(1, impl->buffer_length))) goto failed;
/* Initialize axis in the report */
for (i = 0; i < axis_count; i++)
@ -353,13 +339,6 @@ static NTSTATUS build_controller_report_descriptor(struct unix_device *iface)
ULONG i, button_count = SDL_CONTROLLER_BUTTON_MAX - 1;
C_ASSERT(SDL_CONTROLLER_AXIS_MAX == 6);
impl->axis_start = 0;
impl->hat_start = SDL_CONTROLLER_AXIS_MAX * sizeof(DWORD);
impl->button_start = impl->hat_start + 1;
impl->buffer_length = impl->button_start + (button_count + 7) / 8;
TRACE("Report will be %i bytes\n", impl->buffer_length);
if (!hid_device_begin_report_descriptor(iface, HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_GAMEPAD))
return STATUS_NO_MEMORY;
@ -387,6 +366,7 @@ static NTSTATUS build_controller_report_descriptor(struct unix_device *iface)
if (!hid_device_end_report_descriptor(iface))
return STATUS_NO_MEMORY;
impl->buffer_length = impl->unix_device.hid_device_state.report_len;
if (!(impl->report_buffer = calloc(1, impl->buffer_length))) goto failed;
/* Initialize axis in the report */

View File

@ -127,12 +127,11 @@ struct lnxev_device
BYTE *current_report_buffer;
enum { FIRST, NORMAL, DROPPED } report_state;
int button_start;
BYTE button_map[KEY_MAX];
BYTE abs_map[HID_ABS_MAX];
BYTE rel_map[HID_REL_MAX];
BYTE hat_map[8];
BYTE button_map[KEY_MAX];
int hat_values[8];
int abs_map[HID_ABS_MAX];
};
static inline struct base_device *impl_from_unix_device(struct unix_device *iface)
@ -331,25 +330,22 @@ static const BYTE* what_am_I(struct udev_device *dev)
return Unknown;
}
static void set_button_value(int index, int value, BYTE* buffer)
static void set_button_value(struct lnxev_device *impl, int index, int value)
{
int bindex = index / 8;
int b = index % 8;
BYTE mask;
mask = 1<<b;
if (value)
buffer[bindex] = buffer[bindex] | mask;
else
{
mask = ~mask;
buffer[bindex] = buffer[bindex] & mask;
}
struct hid_device_state *state = &impl->base.unix_device.hid_device_state;
USHORT offset = state->button_start;
int byte_index = offset + index / 8;
int bit_index = index % 8;
BYTE mask = 1 << bit_index;
if (index >= state->button_count) return;
if (value) impl->current_report_buffer[byte_index] |= mask;
else impl->current_report_buffer[byte_index] &= ~mask;
}
static void set_abs_axis_value(struct lnxev_device *impl, int code, int value)
{
int index;
struct hid_device_state *state = &impl->base.unix_device.hid_device_state;
USHORT offset, index;
/* check for hatswitches */
if (code <= ABS_HAT3Y && code >= ABS_HAT0X)
{
@ -387,22 +383,33 @@ static void set_abs_axis_value(struct lnxev_device *impl, int code, int value)
else
value = 6;
}
impl->current_report_buffer[impl->hat_map[index]] = value;
index = impl->hat_map[index];
offset = state->hatswitch_start;
if (index >= state->hatswitch_count) return;
offset += index;
impl->current_report_buffer[offset] = value;
}
else if (code < HID_ABS_MAX && ABS_TO_HID_MAP[code][0] != 0)
{
index = impl->abs_map[code];
*((DWORD*)&impl->current_report_buffer[index]) = LE_DWORD(value);
offset = state->abs_axis_start;
if (index >= state->abs_axis_count) return;
offset += index * sizeof(DWORD);
*(DWORD *)&impl->current_report_buffer[offset] = LE_DWORD(value);
}
}
static void set_rel_axis_value(struct lnxev_device *impl, int code, int value)
{
int index;
struct hid_device_state *state = &impl->base.unix_device.hid_device_state;
USHORT offset, index;
if (code < HID_REL_MAX && REL_TO_HID_MAP[code][0] != 0)
{
index = impl->rel_map[code];
*(DWORD *)&impl->current_report_buffer[index] = LE_DWORD(value);
offset = state->rel_axis_start;
if (index >= state->rel_axis_count) return;
offset += index * sizeof(DWORD);
*(DWORD *)&impl->current_report_buffer[offset] = LE_DWORD(value);
}
}
@ -455,9 +462,7 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d
BYTE absbits[(ABS_MAX+7)/8];
BYTE relbits[(REL_MAX+7)/8];
USAGE_AND_PAGE usage;
INT i;
INT report_size;
INT button_count, abs_count, rel_count, hat_count;
INT i, button_count, abs_count, rel_count, hat_count;
const BYTE *device_usage = what_am_I(dev);
struct lnxev_device *impl = lnxev_impl_from_unix_device(iface);
@ -472,8 +477,6 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d
memset(absbits, 0, sizeof(absbits));
}
report_size = 0;
if (!hid_device_begin_report_descriptor(iface, device_usage[0], device_usage[1]))
return STATUS_NO_MEMORY;
@ -490,9 +493,7 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d
LE_DWORD(abs_info[i].minimum), LE_DWORD(abs_info[i].maximum)))
return STATUS_NO_MEMORY;
impl->abs_map[i] = report_size;
report_size += 4;
abs_count++;
impl->abs_map[i] = abs_count++;
}
rel_count = 0;
@ -506,47 +507,32 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d
INT32_MIN, INT32_MAX))
return STATUS_NO_MEMORY;
impl->rel_map[i] = report_size;
report_size += 4;
rel_count++;
impl->rel_map[i] = rel_count++;
}
hat_count = 0;
for (i = ABS_HAT0X; i <=ABS_HAT3X; i+=2)
{
if (!test_bit(absbits, i)) continue;
impl->hat_map[i - ABS_HAT0X] = report_size;
impl->hat_map[i - ABS_HAT0X] = hat_count++;
impl->hat_values[i - ABS_HAT0X] = 0;
impl->hat_values[i - ABS_HAT0X + 1] = 0;
report_size++;
hat_count++;
}
if (hat_count)
{
if (!hid_device_add_hatswitch(iface, hat_count))
return STATUS_NO_MEMORY;
}
if (hat_count && !hid_device_add_hatswitch(iface, hat_count))
return STATUS_NO_MEMORY;
/* For now lump all buttons just into incremental usages, Ignore Keys */
impl->button_start = report_size;
button_count = count_buttons(impl->base.device_fd, impl->button_map);
if (button_count)
{
if (!hid_device_add_buttons(iface, HID_USAGE_PAGE_BUTTON, 1, button_count))
return STATUS_NO_MEMORY;
report_size += (button_count + 7) / 8;
}
if (button_count && !hid_device_add_buttons(iface, HID_USAGE_PAGE_BUTTON, 1, button_count))
return STATUS_NO_MEMORY;
if (!hid_device_end_report_descriptor(iface))
return STATUS_NO_MEMORY;
TRACE("Report will be %i bytes\n", report_size);
impl->buffer_length = report_size;
if (!(impl->current_report_buffer = calloc(1, report_size))) goto failed;
if (!(impl->last_report_buffer = calloc(1, report_size))) goto failed;
impl->buffer_length = iface->hid_device_state.report_len;
if (!(impl->current_report_buffer = calloc(1, impl->buffer_length))) goto failed;
if (!(impl->last_report_buffer = calloc(1, impl->buffer_length))) goto failed;
impl->report_state = FIRST;
/* Initialize axis in the report */
@ -594,7 +580,7 @@ static BOOL set_report_from_event(struct lnxev_device *impl, struct input_event
return FALSE;
#endif
case EV_KEY:
set_button_value(impl->button_start * 8 + impl->button_map[ie->code], ie->value, impl->current_report_buffer);
set_button_value(impl, impl->button_map[ie->code], ie->value);
return FALSE;
case EV_ABS:
set_abs_axis_value(impl, ie->code, ie->value);

View File

@ -94,6 +94,7 @@ BOOL hid_device_end_report_descriptor(struct unix_device *iface)
END_COLLECTION,
};
iface->hid_device_state.report_len = (iface->hid_device_state.bit_size + 7) / 8;
return hid_report_descriptor_append(desc, template, sizeof(template));
}

View File

@ -68,6 +68,7 @@ struct hid_device_state
USHORT hatswitch_count;
USHORT button_start;
USHORT button_count;
USHORT report_len;
};
struct unix_device