| | |
| | | /* This is the joystick API for Simple DirectMedia Layer */ |
| | | |
| | | #include "SDL.h" |
| | | #include "SDL_atomic.h" |
| | | #include "SDL_events.h" |
| | | #include "SDL_sysjoystick.h" |
| | | #include "SDL_assert.h" |
| | |
| | | #endif |
| | | #include "../video/SDL_sysvideo.h" |
| | | |
| | | /* This is included in only one place because it has a large static list of controllers */ |
| | | #include "controller_type.h" |
| | | |
| | | #ifdef __WIN32__ |
| | | /* Needed for checking for input remapping programs */ |
| | | #include "../core/windows/SDL_windows.h" |
| | | |
| | | #undef UNICODE /* We want ASCII functions */ |
| | | #include <tlhelp32.h> |
| | | #endif |
| | | |
| | | static SDL_JoystickDriver *SDL_joystick_drivers[] = { |
| | | #if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT) |
| | | &SDL_WINDOWS_JoystickDriver, |
| | | #endif |
| | | #ifdef SDL_JOYSTICK_LINUX |
| | | &SDL_LINUX_JoystickDriver, |
| | | #endif |
| | | #ifdef SDL_JOYSTICK_IOKIT |
| | | &SDL_DARWIN_JoystickDriver, |
| | | #endif |
| | | #if defined(__IPHONEOS__) || defined(__TVOS__) |
| | | &SDL_IOS_JoystickDriver, |
| | | #endif |
| | | #ifdef SDL_JOYSTICK_ANDROID |
| | | &SDL_ANDROID_JoystickDriver, |
| | | #endif |
| | | #ifdef SDL_JOYSTICK_EMSCRIPTEN |
| | | &SDL_EMSCRIPTEN_JoystickDriver, |
| | | #endif |
| | | #ifdef SDL_JOYSTICK_HAIKU |
| | | &SDL_HAIKU_JoystickDriver, |
| | | #endif |
| | | #ifdef SDL_JOYSTICK_USBHID /* !!! FIXME: "USBHID" is a generic name, and doubly-confusing with HIDAPI next to it. This is the *BSD interface, rename this. */ |
| | | &SDL_BSD_JoystickDriver, |
| | | #endif |
| | | #ifdef SDL_JOYSTICK_HIDAPI |
| | | &SDL_HIDAPI_JoystickDriver, |
| | | #endif |
| | | #if defined(SDL_JOYSTICK_DUMMY) || defined(SDL_JOYSTICK_DISABLED) |
| | | &SDL_DUMMY_JoystickDriver |
| | | #endif |
| | | }; |
| | | static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE; |
| | | static SDL_Joystick *SDL_joysticks = NULL; |
| | | static SDL_bool SDL_updating_joystick = SDL_FALSE; |
| | | static SDL_mutex *SDL_joystick_lock = NULL; /* This needs to support recursive locks */ |
| | | static SDL_atomic_t SDL_next_joystick_instance_id; |
| | | |
| | | void |
| | | SDL_LockJoysticks(void) |
| | |
| | | int |
| | | SDL_JoystickInit(void) |
| | | { |
| | | int status; |
| | | int i, status; |
| | | |
| | | SDL_GameControllerInitMappings(); |
| | | |
| | |
| | | } |
| | | #endif /* !SDL_EVENTS_DISABLED */ |
| | | |
| | | status = SDL_SYS_JoystickInit(); |
| | | if (status >= 0) { |
| | | status = 0; |
| | | status = -1; |
| | | for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) { |
| | | if (SDL_joystick_drivers[i]->Init() >= 0) { |
| | | status = 0; |
| | | } |
| | | } |
| | | return (status); |
| | | return status; |
| | | } |
| | | |
| | | /* |
| | |
| | | int |
| | | SDL_NumJoysticks(void) |
| | | { |
| | | return SDL_SYS_NumJoysticks(); |
| | | int i, total_joysticks = 0; |
| | | SDL_LockJoysticks(); |
| | | for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) { |
| | | total_joysticks += SDL_joystick_drivers[i]->GetCount(); |
| | | } |
| | | SDL_UnlockJoysticks(); |
| | | return total_joysticks; |
| | | } |
| | | |
| | | /* |
| | | * Return the next available joystick instance ID |
| | | * This may be called by drivers from multiple threads, unprotected by any locks |
| | | */ |
| | | SDL_JoystickID SDL_GetNextJoystickInstanceID() |
| | | { |
| | | return SDL_AtomicIncRef(&SDL_next_joystick_instance_id); |
| | | } |
| | | |
| | | /* |
| | | * Get the driver and device index for an API device index |
| | | * This should be called while the joystick lock is held, to prevent another thread from updating the list |
| | | */ |
| | | SDL_bool |
| | | SDL_GetDriverAndJoystickIndex(int device_index, SDL_JoystickDriver **driver, int *driver_index) |
| | | { |
| | | int i, num_joysticks, total_joysticks = 0; |
| | | |
| | | if (device_index >= 0) { |
| | | for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) { |
| | | num_joysticks = SDL_joystick_drivers[i]->GetCount(); |
| | | if (device_index < num_joysticks) { |
| | | *driver = SDL_joystick_drivers[i]; |
| | | *driver_index = device_index; |
| | | return SDL_TRUE; |
| | | } |
| | | device_index -= num_joysticks; |
| | | total_joysticks += num_joysticks; |
| | | } |
| | | } |
| | | |
| | | SDL_SetError("There are %d joysticks available", total_joysticks); |
| | | return SDL_FALSE; |
| | | } |
| | | |
| | | /* |
| | | * Perform any needed fixups for joystick names |
| | | */ |
| | | static const char * |
| | | SDL_FixupJoystickName(const char *name) |
| | | { |
| | | if (name) { |
| | | const char *skip_prefix = "NVIDIA Corporation "; |
| | | |
| | | if (SDL_strncmp(name, skip_prefix, SDL_strlen(skip_prefix)) == 0) { |
| | | name += SDL_strlen(skip_prefix); |
| | | } |
| | | } |
| | | return name; |
| | | } |
| | | |
| | | |
| | | /* |
| | | * Get the implementation dependent name of a joystick |
| | |
| | | const char * |
| | | SDL_JoystickNameForIndex(int device_index) |
| | | { |
| | | if (device_index < 0 || device_index >= SDL_NumJoysticks()) { |
| | | SDL_SetError("There are %d joysticks available", SDL_NumJoysticks()); |
| | | return (NULL); |
| | | SDL_JoystickDriver *driver; |
| | | const char *name = NULL; |
| | | |
| | | SDL_LockJoysticks(); |
| | | if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) { |
| | | name = SDL_FixupJoystickName(driver->GetDeviceName(device_index)); |
| | | } |
| | | return (SDL_SYS_JoystickNameForDeviceIndex(device_index)); |
| | | SDL_UnlockJoysticks(); |
| | | |
| | | /* FIXME: Really we should reference count this name so it doesn't go away after unlock */ |
| | | return name; |
| | | } |
| | | |
| | | int |
| | | SDL_JoystickGetDevicePlayerIndex(int device_index) |
| | | { |
| | | SDL_JoystickDriver *driver; |
| | | int player_index = -1; |
| | | |
| | | SDL_LockJoysticks(); |
| | | if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) { |
| | | player_index = driver->GetDevicePlayerIndex(device_index); |
| | | } |
| | | SDL_UnlockJoysticks(); |
| | | |
| | | return player_index; |
| | | } |
| | | |
| | | /* |
| | |
| | | SDL_Joystick * |
| | | SDL_JoystickOpen(int device_index) |
| | | { |
| | | SDL_JoystickDriver *driver; |
| | | SDL_JoystickID instance_id; |
| | | SDL_Joystick *joystick; |
| | | SDL_Joystick *joysticklist; |
| | | const char *joystickname = NULL; |
| | | |
| | | if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) { |
| | | SDL_SetError("There are %d joysticks available", SDL_NumJoysticks()); |
| | | return (NULL); |
| | | } |
| | | |
| | | SDL_LockJoysticks(); |
| | | |
| | | if (!SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) { |
| | | SDL_UnlockJoysticks(); |
| | | return NULL; |
| | | } |
| | | |
| | | joysticklist = SDL_joysticks; |
| | | /* If the joystick is already open, return it |
| | | * it is important that we have a single joystick * for each instance id |
| | | */ |
| | | instance_id = driver->GetDeviceInstanceID(device_index); |
| | | while (joysticklist) { |
| | | if (SDL_JoystickGetDeviceInstanceID(device_index) == joysticklist->instance_id) { |
| | | if (instance_id == joysticklist->instance_id) { |
| | | joystick = joysticklist; |
| | | ++joystick->ref_count; |
| | | SDL_UnlockJoysticks(); |
| | | return (joystick); |
| | | return joystick; |
| | | } |
| | | joysticklist = joysticklist->next; |
| | | } |
| | |
| | | SDL_UnlockJoysticks(); |
| | | return NULL; |
| | | } |
| | | joystick->driver = driver; |
| | | joystick->instance_id = instance_id; |
| | | joystick->attached = SDL_TRUE; |
| | | joystick->player_index = -1; |
| | | |
| | | if (SDL_SYS_JoystickOpen(joystick, device_index) < 0) { |
| | | if (driver->Open(joystick, device_index) < 0) { |
| | | SDL_free(joystick); |
| | | SDL_UnlockJoysticks(); |
| | | return NULL; |
| | | } |
| | | |
| | | joystickname = SDL_SYS_JoystickNameForDeviceIndex(device_index); |
| | | if (joystickname) |
| | | joystickname = driver->GetDeviceName(device_index); |
| | | if (joystickname) { |
| | | joystick->name = SDL_strdup(joystickname); |
| | | else |
| | | } else { |
| | | joystick->name = NULL; |
| | | } |
| | | |
| | | joystick->guid = driver->GetDeviceGUID(device_index); |
| | | |
| | | if (joystick->naxes > 0) { |
| | | joystick->axes = (SDL_JoystickAxisInfo *) SDL_calloc(joystick->naxes, sizeof(SDL_JoystickAxisInfo)); |
| | |
| | | |
| | | SDL_UnlockJoysticks(); |
| | | |
| | | SDL_SYS_JoystickUpdate(joystick); |
| | | driver->Update(joystick); |
| | | |
| | | return (joystick); |
| | | return joystick; |
| | | } |
| | | |
| | | |
| | |
| | | SDL_JoystickNumAxes(SDL_Joystick * joystick) |
| | | { |
| | | if (!SDL_PrivateJoystickValid(joystick)) { |
| | | return (-1); |
| | | return -1; |
| | | } |
| | | return (joystick->naxes); |
| | | return joystick->naxes; |
| | | } |
| | | |
| | | /* |
| | |
| | | SDL_JoystickNumHats(SDL_Joystick * joystick) |
| | | { |
| | | if (!SDL_PrivateJoystickValid(joystick)) { |
| | | return (-1); |
| | | return -1; |
| | | } |
| | | return (joystick->nhats); |
| | | return joystick->nhats; |
| | | } |
| | | |
| | | /* |
| | |
| | | SDL_JoystickNumBalls(SDL_Joystick * joystick) |
| | | { |
| | | if (!SDL_PrivateJoystickValid(joystick)) { |
| | | return (-1); |
| | | return -1; |
| | | } |
| | | return (joystick->nballs); |
| | | return joystick->nballs; |
| | | } |
| | | |
| | | /* |
| | |
| | | SDL_JoystickNumButtons(SDL_Joystick * joystick) |
| | | { |
| | | if (!SDL_PrivateJoystickValid(joystick)) { |
| | | return (-1); |
| | | return -1; |
| | | } |
| | | return (joystick->nbuttons); |
| | | return joystick->nbuttons; |
| | | } |
| | | |
| | | /* |
| | |
| | | Sint16 state; |
| | | |
| | | if (!SDL_PrivateJoystickValid(joystick)) { |
| | | return (0); |
| | | return 0; |
| | | } |
| | | if (axis < joystick->naxes) { |
| | | state = joystick->axes[axis].value; |
| | |
| | | SDL_SetError("Joystick only has %d axes", joystick->naxes); |
| | | state = 0; |
| | | } |
| | | return (state); |
| | | return state; |
| | | } |
| | | |
| | | /* |
| | |
| | | Uint8 state; |
| | | |
| | | if (!SDL_PrivateJoystickValid(joystick)) { |
| | | return (0); |
| | | return 0; |
| | | } |
| | | if (hat < joystick->nhats) { |
| | | state = joystick->hats[hat]; |
| | |
| | | SDL_SetError("Joystick only has %d hats", joystick->nhats); |
| | | state = 0; |
| | | } |
| | | return (state); |
| | | return state; |
| | | } |
| | | |
| | | /* |
| | |
| | | int retval; |
| | | |
| | | if (!SDL_PrivateJoystickValid(joystick)) { |
| | | return (-1); |
| | | return -1; |
| | | } |
| | | |
| | | retval = 0; |
| | |
| | | } else { |
| | | return SDL_SetError("Joystick only has %d balls", joystick->nballs); |
| | | } |
| | | return (retval); |
| | | return retval; |
| | | } |
| | | |
| | | /* |
| | |
| | | Uint8 state; |
| | | |
| | | if (!SDL_PrivateJoystickValid(joystick)) { |
| | | return (0); |
| | | return 0; |
| | | } |
| | | if (button < joystick->nbuttons) { |
| | | state = joystick->buttons[button]; |
| | |
| | | SDL_SetError("Joystick only has %d buttons", joystick->nbuttons); |
| | | state = 0; |
| | | } |
| | | return (state); |
| | | return state; |
| | | } |
| | | |
| | | /* |
| | |
| | | return SDL_FALSE; |
| | | } |
| | | |
| | | return SDL_SYS_JoystickAttached(joystick); |
| | | return joystick->attached; |
| | | } |
| | | |
| | | /* |
| | |
| | | SDL_JoystickInstanceID(SDL_Joystick * joystick) |
| | | { |
| | | if (!SDL_PrivateJoystickValid(joystick)) { |
| | | return (-1); |
| | | return -1; |
| | | } |
| | | |
| | | return (joystick->instance_id); |
| | | return joystick->instance_id; |
| | | } |
| | | |
| | | /* |
| | |
| | | SDL_LockJoysticks(); |
| | | for (joystick = SDL_joysticks; joystick; joystick = joystick->next) { |
| | | if (joystick->instance_id == joyid) { |
| | | SDL_UnlockJoysticks(); |
| | | return joystick; |
| | | break; |
| | | } |
| | | } |
| | | SDL_UnlockJoysticks(); |
| | | return NULL; |
| | | return joystick; |
| | | } |
| | | |
| | | /* |
| | |
| | | SDL_JoystickName(SDL_Joystick * joystick) |
| | | { |
| | | if (!SDL_PrivateJoystickValid(joystick)) { |
| | | return (NULL); |
| | | return NULL; |
| | | } |
| | | |
| | | return (joystick->name); |
| | | return SDL_FixupJoystickName(joystick->name); |
| | | } |
| | | |
| | | int |
| | | SDL_JoystickGetPlayerIndex(SDL_Joystick * joystick) |
| | | { |
| | | if (!SDL_PrivateJoystickValid(joystick)) { |
| | | return -1; |
| | | } |
| | | return joystick->player_index; |
| | | } |
| | | |
| | | int |
| | | SDL_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms) |
| | | { |
| | | if (!SDL_PrivateJoystickValid(joystick)) { |
| | | return -1; |
| | | } |
| | | return joystick->driver->Rumble(joystick, low_frequency_rumble, high_frequency_rumble, duration_ms); |
| | | } |
| | | |
| | | /* |
| | |
| | | SDL_Joystick *joysticklist; |
| | | SDL_Joystick *joysticklistprev; |
| | | |
| | | if (!joystick) { |
| | | if (!SDL_PrivateJoystickValid(joystick)) { |
| | | return; |
| | | } |
| | | |
| | |
| | | return; |
| | | } |
| | | |
| | | SDL_SYS_JoystickClose(joystick); |
| | | joystick->driver->Close(joystick); |
| | | joystick->hwdata = NULL; |
| | | |
| | | joysticklist = SDL_joysticks; |
| | |
| | | void |
| | | SDL_JoystickQuit(void) |
| | | { |
| | | int i; |
| | | |
| | | /* Make sure we're not getting called in the middle of updating joysticks */ |
| | | SDL_assert(!SDL_updating_joystick); |
| | | |
| | |
| | | } |
| | | |
| | | /* Quit the joystick setup */ |
| | | SDL_SYS_JoystickQuit(); |
| | | for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) { |
| | | SDL_joystick_drivers[i]->Quit(); |
| | | } |
| | | |
| | | SDL_UnlockJoysticks(); |
| | | |
| | |
| | | |
| | | /* These are global for SDL_sysjoystick.c and SDL_events.c */ |
| | | |
| | | void SDL_PrivateJoystickAdded(int device_index) |
| | | void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance) |
| | | { |
| | | #if !SDL_EVENTS_DISABLED |
| | | SDL_Event event; |
| | | int device_index; |
| | | |
| | | device_index = SDL_JoystickGetDeviceIndexFromInstanceID(device_instance); |
| | | if (device_index < 0) { |
| | | return; |
| | | } |
| | | |
| | | event.type = SDL_JOYDEVICEADDED; |
| | | |
| | |
| | | |
| | | void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance) |
| | | { |
| | | SDL_Joystick *joystick; |
| | | |
| | | #if !SDL_EVENTS_DISABLED |
| | | SDL_Event event; |
| | | |
| | |
| | | |
| | | UpdateEventsForDeviceRemoval(); |
| | | #endif /* !SDL_EVENTS_DISABLED */ |
| | | |
| | | /* Mark this joystick as no longer attached */ |
| | | for (joystick = SDL_joysticks; joystick; joystick = joystick->next) { |
| | | if (joystick->instance_id == device_instance) { |
| | | joystick->attached = SDL_FALSE; |
| | | joystick->force_recentering = SDL_TRUE; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | int |
| | |
| | | posted = SDL_PushEvent(&event) == 1; |
| | | } |
| | | #endif /* !SDL_EVENTS_DISABLED */ |
| | | return (posted); |
| | | return posted; |
| | | } |
| | | |
| | | int |
| | |
| | | posted = SDL_PushEvent(&event) == 1; |
| | | } |
| | | #endif /* !SDL_EVENTS_DISABLED */ |
| | | return (posted); |
| | | return posted; |
| | | } |
| | | |
| | | int |
| | |
| | | posted = SDL_PushEvent(&event) == 1; |
| | | } |
| | | #endif /* !SDL_EVENTS_DISABLED */ |
| | | return (posted); |
| | | return posted; |
| | | } |
| | | |
| | | int |
| | |
| | | break; |
| | | default: |
| | | /* Invalid state -- bail */ |
| | | return (0); |
| | | return 0; |
| | | } |
| | | #endif /* !SDL_EVENTS_DISABLED */ |
| | | |
| | |
| | | posted = SDL_PushEvent(&event) == 1; |
| | | } |
| | | #endif /* !SDL_EVENTS_DISABLED */ |
| | | return (posted); |
| | | return posted; |
| | | } |
| | | |
| | | void |
| | | SDL_JoystickUpdate(void) |
| | | { |
| | | int i; |
| | | SDL_Joystick *joystick; |
| | | |
| | | SDL_LockJoysticks(); |
| | |
| | | SDL_UnlockJoysticks(); |
| | | |
| | | for (joystick = SDL_joysticks; joystick; joystick = joystick->next) { |
| | | SDL_SYS_JoystickUpdate(joystick); |
| | | if (joystick->attached) { |
| | | joystick->driver->Update(joystick); |
| | | |
| | | if (joystick->delayed_guide_button) { |
| | | SDL_GameControllerHandleDelayedGuideButton(joystick); |
| | | } |
| | | } |
| | | |
| | | if (joystick->force_recentering) { |
| | | int i; |
| | | |
| | | /* Tell the app that everything is centered/unpressed... */ |
| | | for (i = 0; i < joystick->naxes; i++) { |
| | | if (joystick->axes[i].has_initial_value) { |
| | |
| | | /* this needs to happen AFTER walking the joystick list above, so that any |
| | | dangling hardware data from removed devices can be free'd |
| | | */ |
| | | SDL_SYS_JoystickDetect(); |
| | | for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) { |
| | | SDL_joystick_drivers[i]->Detect(); |
| | | } |
| | | |
| | | SDL_UnlockJoysticks(); |
| | | } |
| | |
| | | } |
| | | break; |
| | | } |
| | | return (state); |
| | | return state; |
| | | #endif /* SDL_EVENTS_DISABLED */ |
| | | } |
| | | |
| | |
| | | /* guid16[4] is product ID */ |
| | | guid16[5] == 0x0000 |
| | | /* guid16[6] is product version */ |
| | | ) { |
| | | ) { |
| | | if (vendor) { |
| | | *vendor = guid16[2]; |
| | | } |
| | |
| | | *version = 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | SDL_bool |
| | | SDL_IsJoystickPS4(Uint16 vendor, Uint16 product) |
| | | { |
| | | return (GuessControllerType(vendor, product) == k_eControllerType_PS4Controller); |
| | | } |
| | | |
| | | SDL_bool |
| | | SDL_IsJoystickNintendoSwitchPro(Uint16 vendor, Uint16 product) |
| | | { |
| | | return (GuessControllerType(vendor, product) == k_eControllerType_SwitchProController); |
| | | } |
| | | |
| | | SDL_bool |
| | | SDL_IsJoystickSteamController(Uint16 vendor, Uint16 product) |
| | | { |
| | | return BIsSteamController(GuessControllerType(vendor, product)); |
| | | } |
| | | |
| | | SDL_bool |
| | | SDL_IsJoystickXbox360(Uint16 vendor, Uint16 product) |
| | | { |
| | | /* Filter out some bogus values here */ |
| | | if (vendor == 0x0000 && product == 0x0000) { |
| | | return SDL_FALSE; |
| | | } |
| | | if (vendor == 0x0001 && product == 0x0001) { |
| | | return SDL_FALSE; |
| | | } |
| | | return (GuessControllerType(vendor, product) == k_eControllerType_XBox360Controller); |
| | | } |
| | | |
| | | SDL_bool |
| | | SDL_IsJoystickXboxOne(Uint16 vendor, Uint16 product) |
| | | { |
| | | return (GuessControllerType(vendor, product) == k_eControllerType_XBoxOneController); |
| | | } |
| | | |
| | | SDL_bool |
| | | SDL_IsJoystickXInput(SDL_JoystickGUID guid) |
| | | { |
| | | return (guid.data[14] == 'x') ? SDL_TRUE : SDL_FALSE; |
| | | } |
| | | |
| | | SDL_bool |
| | | SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid) |
| | | { |
| | | return (guid.data[14] == 'h') ? SDL_TRUE : SDL_FALSE; |
| | | } |
| | | |
| | | static SDL_bool SDL_IsJoystickProductWheel(Uint32 vidpid) |
| | |
| | | Uint16 product; |
| | | Uint32 vidpid; |
| | | |
| | | if (guid.data[14] == 'x') { |
| | | if (SDL_IsJoystickXInput(guid)) { |
| | | /* XInput GUID, get the type based on the XInput device subtype */ |
| | | switch (guid.data[15]) { |
| | | case 0x01: /* XINPUT_DEVSUBTYPE_GAMEPAD */ |
| | |
| | | return SDL_JOYSTICK_TYPE_THROTTLE; |
| | | } |
| | | |
| | | if (GuessControllerType(vendor, product) != k_eControllerType_UnknownNonSteamController) { |
| | | return SDL_JOYSTICK_TYPE_GAMECONTROLLER; |
| | | } |
| | | |
| | | return SDL_JOYSTICK_TYPE_UNKNOWN; |
| | | } |
| | | |
| | | static SDL_bool SDL_IsPS4RemapperRunning(void) |
| | | { |
| | | #ifdef __WIN32__ |
| | | const char *mapper_processes[] = { |
| | | "DS4Windows.exe", |
| | | "InputMapper.exe", |
| | | }; |
| | | int i; |
| | | PROCESSENTRY32 pe32; |
| | | SDL_bool found = SDL_FALSE; |
| | | |
| | | /* Take a snapshot of all processes in the system */ |
| | | HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); |
| | | if (hProcessSnap != INVALID_HANDLE_VALUE) { |
| | | pe32.dwSize = sizeof(PROCESSENTRY32); |
| | | if (Process32First(hProcessSnap, &pe32)) { |
| | | do |
| | | { |
| | | for (i = 0; i < SDL_arraysize(mapper_processes); ++i) { |
| | | if (SDL_strcasecmp(pe32.szExeFile, mapper_processes[i]) == 0) { |
| | | found = SDL_TRUE; |
| | | } |
| | | } |
| | | } while (Process32Next(hProcessSnap, &pe32) && !found); |
| | | } |
| | | CloseHandle(hProcessSnap); |
| | | } |
| | | return found; |
| | | #else |
| | | return SDL_FALSE; |
| | | #endif |
| | | } |
| | | |
| | | SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid) |
| | | { |
| | | Uint16 vendor; |
| | | Uint16 product; |
| | | |
| | | SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL); |
| | | |
| | | if (SDL_IsJoystickPS4(vendor, product) && SDL_IsPS4RemapperRunning()) { |
| | | return SDL_TRUE; |
| | | } |
| | | |
| | | if (SDL_IsGameControllerNameAndGUID(name, guid) && |
| | | SDL_ShouldIgnoreGameController(name, guid)) { |
| | | return SDL_TRUE; |
| | | } |
| | | |
| | | return SDL_FALSE; |
| | | } |
| | | |
| | | /* return the guid for this index */ |
| | | SDL_JoystickGUID SDL_JoystickGetDeviceGUID(int device_index) |
| | | { |
| | | if (device_index < 0 || device_index >= SDL_NumJoysticks()) { |
| | | SDL_JoystickGUID emptyGUID; |
| | | SDL_SetError("There are %d joysticks available", SDL_NumJoysticks()); |
| | | SDL_zero(emptyGUID); |
| | | return emptyGUID; |
| | | SDL_JoystickDriver *driver; |
| | | SDL_JoystickGUID guid; |
| | | |
| | | SDL_LockJoysticks(); |
| | | if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) { |
| | | guid = driver->GetDeviceGUID(device_index); |
| | | } else { |
| | | SDL_zero(guid); |
| | | } |
| | | return SDL_SYS_JoystickGetDeviceGUID(device_index); |
| | | SDL_UnlockJoysticks(); |
| | | |
| | | return guid; |
| | | } |
| | | |
| | | Uint16 SDL_JoystickGetDeviceVendor(int device_index) |
| | |
| | | |
| | | SDL_JoystickID SDL_JoystickGetDeviceInstanceID(int device_index) |
| | | { |
| | | if (device_index < 0 || device_index >= SDL_NumJoysticks()) { |
| | | SDL_SetError("There are %d joysticks available", SDL_NumJoysticks()); |
| | | return -1; |
| | | SDL_JoystickDriver *driver; |
| | | SDL_JoystickID instance_id = -1; |
| | | |
| | | SDL_LockJoysticks(); |
| | | if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) { |
| | | instance_id = driver->GetDeviceInstanceID(device_index); |
| | | } |
| | | return SDL_SYS_GetInstanceIdOfDeviceIndex(device_index); |
| | | SDL_UnlockJoysticks(); |
| | | |
| | | return instance_id; |
| | | } |
| | | |
| | | int SDL_JoystickGetDeviceIndexFromInstanceID(SDL_JoystickID instance_id) |
| | | { |
| | | int i, num_joysticks, device_index = -1; |
| | | |
| | | SDL_LockJoysticks(); |
| | | num_joysticks = SDL_NumJoysticks(); |
| | | for (i = 0; i < num_joysticks; ++i) { |
| | | if (SDL_JoystickGetDeviceInstanceID(i) == instance_id) { |
| | | device_index = i; |
| | | break; |
| | | } |
| | | } |
| | | SDL_UnlockJoysticks(); |
| | | |
| | | return device_index; |
| | | } |
| | | |
| | | SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick * joystick) |
| | |
| | | SDL_zero(emptyGUID); |
| | | return emptyGUID; |
| | | } |
| | | return SDL_SYS_JoystickGetGUID(joystick); |
| | | return joystick->guid; |
| | | } |
| | | |
| | | Uint16 SDL_JoystickGetVendor(SDL_Joystick * joystick) |
| | |
| | | *pszGUID = '\0'; |
| | | } |
| | | |
| | | |
| | | /*----------------------------------------------------------------------------- |
| | | * Purpose: Returns the 4 bit nibble for a hex character |
| | | * Input : c - |
| | |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | /* convert the string version of a joystick guid to the struct */ |
| | | SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID) |
| | | { |
| | |
| | | return guid; |
| | | } |
| | | |
| | | |
| | | /* update the power level for this joystick */ |
| | | void SDL_PrivateJoystickBatteryLevel(SDL_Joystick * joystick, SDL_JoystickPowerLevel ePowerLevel) |
| | | { |
| | | joystick->epowerlevel = ePowerLevel; |
| | | } |
| | | |
| | | |
| | | /* return its power level */ |
| | | SDL_JoystickPowerLevel SDL_JoystickCurrentPowerLevel(SDL_Joystick * joystick) |
| | | { |
| | | if (!SDL_PrivateJoystickValid(joystick)) { |
| | | return (SDL_JOYSTICK_POWER_UNKNOWN); |
| | | return SDL_JOYSTICK_POWER_UNKNOWN; |
| | | } |
| | | return joystick->epowerlevel; |
| | | } |