From: Aric Stewart Subject: [PATCH v4 4/7] winebus.sys: Process SDL device reports Message-Id: Date: Wed, 21 Feb 2018 06:56:46 -0600 v3: dynamic loading of the SDL library v4: Dynamically use Joystick Vendor and Product ID if available Signed-off-by: Aric Stewart --- dlls/winebus.sys/bus_sdl.c | 120 ++++++++++++++++++++++++++++++++++++++++++ dlls/winebus.sys/bus_udev.c | 19 +------ dlls/winebus.sys/controller.c | 17 ++++++ dlls/winebus.sys/controller.h | 1 + 4 files changed, 139 insertions(+), 18 deletions(-) diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 5f422a501e..964b465fd8 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -85,6 +85,8 @@ MAKE_FUNCPTR(SDL_WaitEvent); MAKE_FUNCPTR(SDL_JoystickNumButtons); MAKE_FUNCPTR(SDL_JoystickNumBalls); MAKE_FUNCPTR(SDL_JoystickNumHats); +MAKE_FUNCPTR(SDL_JoystickGetAxis); +MAKE_FUNCPTR(SDL_JoystickGetHat); #endif static Uint16 (*pSDL_JoystickGetProduct)(SDL_Joystick * joystick); static Uint16 (*pSDL_JoystickGetProductVersion)(SDL_Joystick * joystick); @@ -101,6 +103,9 @@ struct platform_private int report_descriptor_size; BYTE *report_descriptor; + + int buffer_length; + BYTE *report_buffer; }; static inline struct platform_private *impl_from_DEVICE_OBJECT(DEVICE_OBJECT *device) @@ -146,6 +151,43 @@ static BYTE *add_axis_block(BYTE *report_ptr, BYTE count, BYTE page, const BYTE return report_ptr; } +static void set_axis_value(struct platform_private *ext, int index, short value) +{ + int offset; + offset = ext->axis_start + index * 2; + *((WORD*)&ext->report_buffer[offset]) = LE_WORD(value); +} + +static void set_ball_value(struct platform_private *ext, int index, int value1, int value2) +{ + int offset; + offset = ext->ball_start + (index * 2); + if (value1 > 127) value1 = 127; + if (value1 < -127) value1 = -127; + if (value2 > 127) value2 = 127; + if (value2 < -127) value2 = -127; + ext->report_buffer[offset] = value1; + ext->report_buffer[offset + 1] = value2; +} + +static void set_hat_value(struct platform_private *ext, int index, int value) +{ + int offset; + offset = ext->hat_start + index; + switch (value) + { + case SDL_HAT_CENTERED: ext->report_buffer[offset] = 8; break; + case SDL_HAT_UP: ext->report_buffer[offset] = 0; break; + case SDL_HAT_RIGHTUP: ext->report_buffer[offset] = 1; break; + case SDL_HAT_RIGHT: ext->report_buffer[offset] = 2; break; + case SDL_HAT_RIGHTDOWN: ext->report_buffer[offset] = 3; break; + case SDL_HAT_DOWN: ext->report_buffer[offset] = 4; break; + case SDL_HAT_LEFTDOWN: ext->report_buffer[offset] = 5; break; + case SDL_HAT_LEFT: ext->report_buffer[offset] = 6; break; + case SDL_HAT_LEFTUP: ext->report_buffer[offset] = 7; break; + } +} + static BOOL build_report_descriptor(struct platform_private *ext) { BYTE *report_ptr; @@ -269,6 +311,20 @@ static BOOL build_report_descriptor(struct platform_private *ext) memcpy(report_ptr, REPORT_TAIL, sizeof(REPORT_TAIL)); ext->report_descriptor_size = descript_size; + ext->buffer_length = report_size; + ext->report_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, report_size); + if (ext->report_buffer == NULL) + { + ERR("Failed to alloc report buffer\n"); + HeapFree(GetProcessHeap(), 0, ext->report_descriptor); + return FALSE; + } + + /* Initialize axis in the report */ + for (i = 0; i < axis_count; i++) + set_axis_value(ext, i, pSDL_JoystickGetAxis(ext->sdl_joystick, i)); + for (i = 0; i < hat_count; i++) + set_hat_value(ext, i, pSDL_JoystickGetHat(ext->sdl_joystick, i)); return TRUE; } @@ -356,6 +412,66 @@ static const platform_vtbl sdl_vtbl = set_feature_report, }; +static BOOL set_report_from_event(SDL_Event *event) +{ + DEVICE_OBJECT *device; + struct platform_private *private; + /* All the events coming in will have 'which' as a 3rd field */ + SDL_JoystickID index = ((SDL_JoyButtonEvent*)event)->which; + + device = bus_find_hid_device(&sdl_vtbl, (void*)index); + if (!device) + { + ERR("Failed to find device at index %i\n",index); + return FALSE; + } + private = impl_from_DEVICE_OBJECT(device); + + switch(event->type) + { + case SDL_JOYBUTTONDOWN: + case SDL_JOYBUTTONUP: + { + SDL_JoyButtonEvent *ie = &event->jbutton; + + set_button_value(ie->button, ie->state, private->report_buffer); + + process_hid_report(device, private->report_buffer, private->buffer_length); + break; + } + case SDL_JOYAXISMOTION: + { + SDL_JoyAxisEvent *ie = &event->jaxis; + + if (ie->axis < 6) + { + set_axis_value(private, ie->axis, ie->value); + process_hid_report(device, private->report_buffer, private->buffer_length); + } + break; + } + case SDL_JOYBALLMOTION: + { + SDL_JoyBallEvent *ie = &event->jball; + + set_ball_value(private, ie->ball, ie->xrel, ie->yrel); + process_hid_report(device, private->report_buffer, private->buffer_length); + break; + } + case SDL_JOYHATMOTION: + { + SDL_JoyHatEvent *ie = &event->jhat; + + set_hat_value(private, ie->hat, ie->value); + process_hid_report(device, private->report_buffer, private->buffer_length); + break; + } + default: + ERR("TODO: Process Report (%x)\n",event->type); + } + return FALSE; +} + static void try_remove_device(SDL_JoystickID index) { DEVICE_OBJECT *device = NULL; @@ -441,6 +557,8 @@ static void process_device_event(SDL_Event *event) try_add_device(((SDL_JoyDeviceEvent*)event)->which); else if (event->type == SDL_JOYDEVICEREMOVED) try_remove_device(((SDL_JoyDeviceEvent*)event)->which); + else if (event->type >= SDL_JOYAXISMOTION && event->type <= SDL_JOYBUTTONUP) + set_report_from_event(event); } static DWORD CALLBACK deviceloop_thread(void *args) @@ -494,6 +612,8 @@ NTSTATUS WINAPI sdl_driver_init(DRIVER_OBJECT *driver, UNICODE_STRING *registry_ LOAD_FUNCPTR(SDL_JoystickNumButtons); LOAD_FUNCPTR(SDL_JoystickNumBalls); LOAD_FUNCPTR(SDL_JoystickNumHats); + LOAD_FUNCPTR(SDL_JoystickGetAxis); + LOAD_FUNCPTR(SDL_JoystickGetHat); #undef LOAD_FUNCPTR pSDL_JoystickGetProduct = wine_dlsym(sdl_handle, "SDL_JoystickGetProduct", NULL, 0); pSDL_JoystickGetProductVersion = wine_dlsym(sdl_handle, "SDL_JoystickGetProductVersion", NULL, 0); diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 9d78f1905b..417573f13a 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -271,23 +271,6 @@ static const BYTE* what_am_I(struct udev_device *dev) return Unknown; } -static void set_button_value(struct wine_input_private *ext, int code, int value) -{ - int index = ext->button_map[code]; - int bindex = index / 8; - int b = index % 8; - BYTE mask; - - mask = 1<current_report_buffer[bindex] = ext->current_report_buffer[bindex] | mask; - else - { - mask = ~mask; - ext->current_report_buffer[bindex] = ext->current_report_buffer[bindex] & mask; - } -} - static void set_abs_axis_value(struct wine_input_private *ext, int code, int value) { int index; @@ -608,7 +591,7 @@ static BOOL set_report_from_event(struct wine_input_private *ext, struct input_e return FALSE; #endif case EV_KEY: - set_button_value(ext, ie->code, ie->value); + set_button_value(ext->button_map[ie->code], ie->value, ext->current_report_buffer); return FALSE; case EV_ABS: set_abs_axis_value(ext, ie->code, ie->value); diff --git a/dlls/winebus.sys/controller.c b/dlls/winebus.sys/controller.c index 6c707a741b..d58fbf317a 100644 --- a/dlls/winebus.sys/controller.c +++ b/dlls/winebus.sys/controller.c @@ -46,3 +46,20 @@ BYTE *add_hatswitch(BYTE *report_ptr, INT count) report_ptr[IDX_HATSWITCH_COUNT] = count; return report_ptr + sizeof(REPORT_HATSWITCH); } + + +void set_button_value(int index, int value, BYTE* buffer) +{ + int bindex = index / 8; + int b = index % 8; + BYTE mask; + + mask = 1<