| /* |
| Simple DirectMedia Layer |
| Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org> |
| |
| This software is provided 'as-is', without any express or implied |
| warranty. In no event will the authors be held liable for any damages |
| arising from the use of this software. |
| |
| Permission is granted to anyone to use this software for any purpose, |
| including commercial applications, and to alter it and redistribute it |
| freely, subject to the following restrictions: |
| |
| 1. The origin of this software must not be misrepresented; you must not |
| claim that you wrote the original software. If you use this software |
| in a product, an acknowledgment in the product documentation would be |
| appreciated but is not required. |
| 2. Altered source versions must be plainly marked as such, and must not be |
| misrepresented as being the original software. |
| 3. This notice may not be removed or altered from any source distribution. |
| */ |
| #include "../SDL_internal.h" |
| |
| /* This is the joystick API for Simple DirectMedia Layer */ |
| |
| #include "SDL.h" |
| #include "SDL_events.h" |
| #include "SDL_sysjoystick.h" |
| #include "SDL_assert.h" |
| #include "SDL_hints.h" |
| |
| #if !SDL_EVENTS_DISABLED |
| #include "../events/SDL_events_c.h" |
| #endif |
| |
| static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE; |
| static SDL_Joystick *SDL_joysticks = NULL; |
| static SDL_Joystick *SDL_updating_joystick = NULL; |
| |
| static void |
| SDL_JoystickAllowBackgroundEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint) |
| { |
| if (hint && *hint == '1') { |
| SDL_joystick_allows_background_events = SDL_TRUE; |
| } else { |
| SDL_joystick_allows_background_events = SDL_FALSE; |
| } |
| } |
| |
| int |
| SDL_JoystickInit(void) |
| { |
| int status; |
| |
| /* See if we should allow joystick events while in the background */ |
| SDL_AddHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, |
| SDL_JoystickAllowBackgroundEventsChanged, NULL); |
| |
| #if !SDL_EVENTS_DISABLED |
| if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0) { |
| return -1; |
| } |
| #endif /* !SDL_EVENTS_DISABLED */ |
| |
| status = SDL_SYS_JoystickInit(); |
| if (status >= 0) { |
| status = 0; |
| } |
| return (status); |
| } |
| |
| /* |
| * Count the number of joysticks attached to the system |
| */ |
| int |
| SDL_NumJoysticks(void) |
| { |
| return SDL_SYS_NumJoysticks(); |
| } |
| |
| /* |
| * 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); |
| } |
| return (SDL_SYS_JoystickNameForDeviceIndex(device_index)); |
| } |
| |
| /* |
| * Open a joystick for use - the index passed as an argument refers to |
| * the N'th joystick on the system. This index is the value which will |
| * identify this joystick in future joystick events. |
| * |
| * This function returns a joystick identifier, or NULL if an error occurred. |
| */ |
| SDL_Joystick * |
| SDL_JoystickOpen(int device_index) |
| { |
| 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); |
| } |
| |
| joysticklist = SDL_joysticks; |
| /* If the joystick is already open, return it |
| * it is important that we have a single joystick * for each instance id |
| */ |
| while (joysticklist) { |
| if (SDL_SYS_GetInstanceIdOfDeviceIndex(device_index) == joysticklist->instance_id) { |
| joystick = joysticklist; |
| ++joystick->ref_count; |
| return (joystick); |
| } |
| joysticklist = joysticklist->next; |
| } |
| |
| /* Create and initialize the joystick */ |
| joystick = (SDL_Joystick *) SDL_malloc((sizeof *joystick)); |
| if (joystick == NULL) { |
| SDL_OutOfMemory(); |
| return NULL; |
| } |
| |
| SDL_memset(joystick, 0, (sizeof *joystick)); |
| if (SDL_SYS_JoystickOpen(joystick, device_index) < 0) { |
| SDL_free(joystick); |
| return NULL; |
| } |
| |
| joystickname = SDL_SYS_JoystickNameForDeviceIndex(device_index); |
| if (joystickname) |
| joystick->name = SDL_strdup(joystickname); |
| else |
| joystick->name = NULL; |
| |
| if (joystick->naxes > 0) { |
| joystick->axes = (Sint16 *) SDL_malloc |
| (joystick->naxes * sizeof(Sint16)); |
| } |
| if (joystick->nhats > 0) { |
| joystick->hats = (Uint8 *) SDL_malloc |
| (joystick->nhats * sizeof(Uint8)); |
| } |
| if (joystick->nballs > 0) { |
| joystick->balls = (struct balldelta *) SDL_malloc |
| (joystick->nballs * sizeof(*joystick->balls)); |
| } |
| if (joystick->nbuttons > 0) { |
| joystick->buttons = (Uint8 *) SDL_malloc |
| (joystick->nbuttons * sizeof(Uint8)); |
| } |
| if (((joystick->naxes > 0) && !joystick->axes) |
| || ((joystick->nhats > 0) && !joystick->hats) |
| || ((joystick->nballs > 0) && !joystick->balls) |
| || ((joystick->nbuttons > 0) && !joystick->buttons)) { |
| SDL_OutOfMemory(); |
| SDL_JoystickClose(joystick); |
| return NULL; |
| } |
| if (joystick->axes) { |
| SDL_memset(joystick->axes, 0, joystick->naxes * sizeof(Sint16)); |
| } |
| if (joystick->hats) { |
| SDL_memset(joystick->hats, 0, joystick->nhats * sizeof(Uint8)); |
| } |
| if (joystick->balls) { |
| SDL_memset(joystick->balls, 0, |
| joystick->nballs * sizeof(*joystick->balls)); |
| } |
| if (joystick->buttons) { |
| SDL_memset(joystick->buttons, 0, joystick->nbuttons * sizeof(Uint8)); |
| } |
| joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN; |
| |
| /* Add joystick to list */ |
| ++joystick->ref_count; |
| /* Link the joystick in the list */ |
| joystick->next = SDL_joysticks; |
| SDL_joysticks = joystick; |
| |
| SDL_SYS_JoystickUpdate(joystick); |
| |
| return (joystick); |
| } |
| |
| |
| /* |
| * Checks to make sure the joystick is valid. |
| */ |
| int |
| SDL_PrivateJoystickValid(SDL_Joystick * joystick) |
| { |
| int valid; |
| |
| if (joystick == NULL) { |
| SDL_SetError("Joystick hasn't been opened yet"); |
| valid = 0; |
| } else { |
| valid = 1; |
| } |
| |
| return valid; |
| } |
| |
| /* |
| * Get the number of multi-dimensional axis controls on a joystick |
| */ |
| int |
| SDL_JoystickNumAxes(SDL_Joystick * joystick) |
| { |
| if (!SDL_PrivateJoystickValid(joystick)) { |
| return (-1); |
| } |
| return (joystick->naxes); |
| } |
| |
| /* |
| * Get the number of hats on a joystick |
| */ |
| int |
| SDL_JoystickNumHats(SDL_Joystick * joystick) |
| { |
| if (!SDL_PrivateJoystickValid(joystick)) { |
| return (-1); |
| } |
| return (joystick->nhats); |
| } |
| |
| /* |
| * Get the number of trackballs on a joystick |
| */ |
| int |
| SDL_JoystickNumBalls(SDL_Joystick * joystick) |
| { |
| if (!SDL_PrivateJoystickValid(joystick)) { |
| return (-1); |
| } |
| return (joystick->nballs); |
| } |
| |
| /* |
| * Get the number of buttons on a joystick |
| */ |
| int |
| SDL_JoystickNumButtons(SDL_Joystick * joystick) |
| { |
| if (!SDL_PrivateJoystickValid(joystick)) { |
| return (-1); |
| } |
| return (joystick->nbuttons); |
| } |
| |
| /* |
| * Get the current state of an axis control on a joystick |
| */ |
| Sint16 |
| SDL_JoystickGetAxis(SDL_Joystick * joystick, int axis) |
| { |
| Sint16 state; |
| |
| if (!SDL_PrivateJoystickValid(joystick)) { |
| return (0); |
| } |
| if (axis < joystick->naxes) { |
| state = joystick->axes[axis]; |
| } else { |
| SDL_SetError("Joystick only has %d axes", joystick->naxes); |
| state = 0; |
| } |
| return (state); |
| } |
| |
| /* |
| * Get the current state of a hat on a joystick |
| */ |
| Uint8 |
| SDL_JoystickGetHat(SDL_Joystick * joystick, int hat) |
| { |
| Uint8 state; |
| |
| if (!SDL_PrivateJoystickValid(joystick)) { |
| return (0); |
| } |
| if (hat < joystick->nhats) { |
| state = joystick->hats[hat]; |
| } else { |
| SDL_SetError("Joystick only has %d hats", joystick->nhats); |
| state = 0; |
| } |
| return (state); |
| } |
| |
| /* |
| * Get the ball axis change since the last poll |
| */ |
| int |
| SDL_JoystickGetBall(SDL_Joystick * joystick, int ball, int *dx, int *dy) |
| { |
| int retval; |
| |
| if (!SDL_PrivateJoystickValid(joystick)) { |
| return (-1); |
| } |
| |
| retval = 0; |
| if (ball < joystick->nballs) { |
| if (dx) { |
| *dx = joystick->balls[ball].dx; |
| } |
| if (dy) { |
| *dy = joystick->balls[ball].dy; |
| } |
| joystick->balls[ball].dx = 0; |
| joystick->balls[ball].dy = 0; |
| } else { |
| return SDL_SetError("Joystick only has %d balls", joystick->nballs); |
| } |
| return (retval); |
| } |
| |
| /* |
| * Get the current state of a button on a joystick |
| */ |
| Uint8 |
| SDL_JoystickGetButton(SDL_Joystick * joystick, int button) |
| { |
| Uint8 state; |
| |
| if (!SDL_PrivateJoystickValid(joystick)) { |
| return (0); |
| } |
| if (button < joystick->nbuttons) { |
| state = joystick->buttons[button]; |
| } else { |
| SDL_SetError("Joystick only has %d buttons", joystick->nbuttons); |
| state = 0; |
| } |
| return (state); |
| } |
| |
| /* |
| * Return if the joystick in question is currently attached to the system, |
| * \return SDL_FALSE if not plugged in, SDL_TRUE if still present. |
| */ |
| SDL_bool |
| SDL_JoystickGetAttached(SDL_Joystick * joystick) |
| { |
| if (!SDL_PrivateJoystickValid(joystick)) { |
| return SDL_FALSE; |
| } |
| |
| return SDL_SYS_JoystickAttached(joystick); |
| } |
| |
| /* |
| * Get the instance id for this opened joystick |
| */ |
| SDL_JoystickID |
| SDL_JoystickInstanceID(SDL_Joystick * joystick) |
| { |
| if (!SDL_PrivateJoystickValid(joystick)) { |
| return (-1); |
| } |
| |
| return (joystick->instance_id); |
| } |
| |
| /* |
| * Find the SDL_Joystick that owns this instance id |
| */ |
| SDL_Joystick * |
| SDL_JoystickFromInstanceID(SDL_JoystickID joyid) |
| { |
| SDL_Joystick *joystick = SDL_joysticks; |
| while (joystick) { |
| if (joystick->instance_id == joyid) { |
| return joystick; |
| } |
| joystick = joystick->next; |
| } |
| |
| return NULL; |
| } |
| |
| /* |
| * Get the friendly name of this joystick |
| */ |
| const char * |
| SDL_JoystickName(SDL_Joystick * joystick) |
| { |
| if (!SDL_PrivateJoystickValid(joystick)) { |
| return (NULL); |
| } |
| |
| return (joystick->name); |
| } |
| |
| /* |
| * Close a joystick previously opened with SDL_JoystickOpen() |
| */ |
| void |
| SDL_JoystickClose(SDL_Joystick * joystick) |
| { |
| SDL_Joystick *joysticklist; |
| SDL_Joystick *joysticklistprev; |
| |
| if (!joystick) { |
| return; |
| } |
| |
| /* First decrement ref count */ |
| if (--joystick->ref_count > 0) { |
| return; |
| } |
| |
| if (joystick == SDL_updating_joystick) { |
| return; |
| } |
| |
| SDL_SYS_JoystickClose(joystick); |
| joystick->hwdata = NULL; |
| |
| joysticklist = SDL_joysticks; |
| joysticklistprev = NULL; |
| while (joysticklist) { |
| if (joystick == joysticklist) { |
| if (joysticklistprev) { |
| /* unlink this entry */ |
| joysticklistprev->next = joysticklist->next; |
| } else { |
| SDL_joysticks = joystick->next; |
| } |
| break; |
| } |
| joysticklistprev = joysticklist; |
| joysticklist = joysticklist->next; |
| } |
| |
| SDL_free(joystick->name); |
| |
| /* Free the data associated with this joystick */ |
| SDL_free(joystick->axes); |
| SDL_free(joystick->hats); |
| SDL_free(joystick->balls); |
| SDL_free(joystick->buttons); |
| SDL_free(joystick); |
| } |
| |
| void |
| SDL_JoystickQuit(void) |
| { |
| /* Make sure we're not getting called in the middle of updating joysticks */ |
| SDL_assert(!SDL_updating_joystick); |
| |
| /* Stop the event polling */ |
| while (SDL_joysticks) { |
| SDL_joysticks->ref_count = 1; |
| SDL_JoystickClose(SDL_joysticks); |
| } |
| |
| /* Quit the joystick setup */ |
| SDL_SYS_JoystickQuit(); |
| |
| #if !SDL_EVENTS_DISABLED |
| SDL_QuitSubSystem(SDL_INIT_EVENTS); |
| #endif |
| } |
| |
| |
| static SDL_bool |
| SDL_PrivateJoystickShouldIgnoreEvent() |
| { |
| if (SDL_joystick_allows_background_events) { |
| return SDL_FALSE; |
| } |
| |
| if (SDL_WasInit(SDL_INIT_VIDEO)) { |
| if (SDL_GetKeyboardFocus() == NULL) { |
| /* Video is initialized and we don't have focus, ignore the event. */ |
| return SDL_TRUE; |
| } else { |
| return SDL_FALSE; |
| } |
| } |
| |
| /* Video subsystem wasn't initialized, always allow the event */ |
| return SDL_FALSE; |
| } |
| |
| /* These are global for SDL_sysjoystick.c and SDL_events.c */ |
| |
| void SDL_PrivateJoystickAdded(int device_index) |
| { |
| #if !SDL_EVENTS_DISABLED |
| SDL_Event event; |
| |
| event.type = SDL_JOYDEVICEADDED; |
| |
| if (SDL_GetEventState(event.type) == SDL_ENABLE) { |
| event.jdevice.which = device_index; |
| if ( (SDL_EventOK == NULL) || |
| (*SDL_EventOK) (SDL_EventOKParam, &event) ) { |
| SDL_PushEvent(&event); |
| } |
| } |
| #endif /* !SDL_EVENTS_DISABLED */ |
| } |
| |
| /* |
| * If there is an existing add event in the queue, it needs to be modified |
| * to have the right value for which, because the number of controllers in |
| * the system is now one less. |
| */ |
| static void UpdateEventsForDeviceRemoval() |
| { |
| int i, num_events; |
| SDL_Event *events; |
| |
| num_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED); |
| if (num_events <= 0) { |
| return; |
| } |
| |
| events = SDL_stack_alloc(SDL_Event, num_events); |
| if (!events) { |
| return; |
| } |
| |
| num_events = SDL_PeepEvents(events, num_events, SDL_GETEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED); |
| for (i = 0; i < num_events; ++i) { |
| --events[i].jdevice.which; |
| } |
| SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0); |
| |
| SDL_stack_free(events); |
| } |
| |
| void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance) |
| { |
| #if !SDL_EVENTS_DISABLED |
| SDL_Event event; |
| |
| event.type = SDL_JOYDEVICEREMOVED; |
| |
| if (SDL_GetEventState(event.type) == SDL_ENABLE) { |
| event.jdevice.which = device_instance; |
| if ( (SDL_EventOK == NULL) || |
| (*SDL_EventOK) (SDL_EventOKParam, &event) ) { |
| SDL_PushEvent(&event); |
| } |
| } |
| |
| UpdateEventsForDeviceRemoval(); |
| #endif /* !SDL_EVENTS_DISABLED */ |
| } |
| |
| int |
| SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value) |
| { |
| int posted; |
| |
| /* Make sure we're not getting garbage or duplicate events */ |
| if (axis >= joystick->naxes) { |
| return 0; |
| } |
| if (value == joystick->axes[axis]) { |
| return 0; |
| } |
| |
| /* We ignore events if we don't have keyboard focus, except for centering |
| * events. |
| */ |
| if (SDL_PrivateJoystickShouldIgnoreEvent()) { |
| if ((value > 0 && value >= joystick->axes[axis]) || |
| (value < 0 && value <= joystick->axes[axis])) { |
| return 0; |
| } |
| } |
| |
| /* Update internal joystick state */ |
| joystick->axes[axis] = value; |
| |
| /* Post the event, if desired */ |
| posted = 0; |
| #if !SDL_EVENTS_DISABLED |
| if (SDL_GetEventState(SDL_JOYAXISMOTION) == SDL_ENABLE) { |
| SDL_Event event; |
| event.type = SDL_JOYAXISMOTION; |
| event.jaxis.which = joystick->instance_id; |
| event.jaxis.axis = axis; |
| event.jaxis.value = value; |
| posted = SDL_PushEvent(&event) == 1; |
| } |
| #endif /* !SDL_EVENTS_DISABLED */ |
| return (posted); |
| } |
| |
| int |
| SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value) |
| { |
| int posted; |
| |
| /* Make sure we're not getting garbage or duplicate events */ |
| if (hat >= joystick->nhats) { |
| return 0; |
| } |
| if (value == joystick->hats[hat]) { |
| return 0; |
| } |
| |
| /* We ignore events if we don't have keyboard focus, except for centering |
| * events. |
| */ |
| if (SDL_PrivateJoystickShouldIgnoreEvent()) { |
| if (value != SDL_HAT_CENTERED) { |
| return 0; |
| } |
| } |
| |
| /* Update internal joystick state */ |
| joystick->hats[hat] = value; |
| |
| /* Post the event, if desired */ |
| posted = 0; |
| #if !SDL_EVENTS_DISABLED |
| if (SDL_GetEventState(SDL_JOYHATMOTION) == SDL_ENABLE) { |
| SDL_Event event; |
| event.jhat.type = SDL_JOYHATMOTION; |
| event.jhat.which = joystick->instance_id; |
| event.jhat.hat = hat; |
| event.jhat.value = value; |
| posted = SDL_PushEvent(&event) == 1; |
| } |
| #endif /* !SDL_EVENTS_DISABLED */ |
| return (posted); |
| } |
| |
| int |
| SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball, |
| Sint16 xrel, Sint16 yrel) |
| { |
| int posted; |
| |
| /* Make sure we're not getting garbage events */ |
| if (ball >= joystick->nballs) { |
| return 0; |
| } |
| |
| /* We ignore events if we don't have keyboard focus. */ |
| if (SDL_PrivateJoystickShouldIgnoreEvent()) { |
| return 0; |
| } |
| |
| /* Update internal mouse state */ |
| joystick->balls[ball].dx += xrel; |
| joystick->balls[ball].dy += yrel; |
| |
| /* Post the event, if desired */ |
| posted = 0; |
| #if !SDL_EVENTS_DISABLED |
| if (SDL_GetEventState(SDL_JOYBALLMOTION) == SDL_ENABLE) { |
| SDL_Event event; |
| event.jball.type = SDL_JOYBALLMOTION; |
| event.jball.which = joystick->instance_id; |
| event.jball.ball = ball; |
| event.jball.xrel = xrel; |
| event.jball.yrel = yrel; |
| posted = SDL_PushEvent(&event) == 1; |
| } |
| #endif /* !SDL_EVENTS_DISABLED */ |
| return (posted); |
| } |
| |
| int |
| SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state) |
| { |
| int posted; |
| #if !SDL_EVENTS_DISABLED |
| SDL_Event event; |
| |
| switch (state) { |
| case SDL_PRESSED: |
| event.type = SDL_JOYBUTTONDOWN; |
| break; |
| case SDL_RELEASED: |
| event.type = SDL_JOYBUTTONUP; |
| break; |
| default: |
| /* Invalid state -- bail */ |
| return (0); |
| } |
| #endif /* !SDL_EVENTS_DISABLED */ |
| |
| /* Make sure we're not getting garbage or duplicate events */ |
| if (button >= joystick->nbuttons) { |
| return 0; |
| } |
| if (state == joystick->buttons[button]) { |
| return 0; |
| } |
| |
| /* We ignore events if we don't have keyboard focus, except for button |
| * release. */ |
| if (SDL_PrivateJoystickShouldIgnoreEvent()) { |
| if (state == SDL_PRESSED) { |
| return 0; |
| } |
| } |
| |
| /* Update internal joystick state */ |
| joystick->buttons[button] = state; |
| |
| /* Post the event, if desired */ |
| posted = 0; |
| #if !SDL_EVENTS_DISABLED |
| if (SDL_GetEventState(event.type) == SDL_ENABLE) { |
| event.jbutton.which = joystick->instance_id; |
| event.jbutton.button = button; |
| event.jbutton.state = state; |
| posted = SDL_PushEvent(&event) == 1; |
| } |
| #endif /* !SDL_EVENTS_DISABLED */ |
| return (posted); |
| } |
| |
| void |
| SDL_JoystickUpdate(void) |
| { |
| SDL_Joystick *joystick; |
| |
| joystick = SDL_joysticks; |
| while (joystick) { |
| SDL_Joystick *joysticknext; |
| /* save off the next pointer, the Update call may cause a joystick removed event |
| * and cause our joystick pointer to be freed |
| */ |
| joysticknext = joystick->next; |
| |
| SDL_updating_joystick = joystick; |
| |
| SDL_SYS_JoystickUpdate(joystick); |
| |
| if (joystick->force_recentering) { |
| int i; |
| |
| /* Tell the app that everything is centered/unpressed... */ |
| for (i = 0; i < joystick->naxes; i++) { |
| SDL_PrivateJoystickAxis(joystick, i, 0); |
| } |
| |
| for (i = 0; i < joystick->nbuttons; i++) { |
| SDL_PrivateJoystickButton(joystick, i, 0); |
| } |
| |
| for (i = 0; i < joystick->nhats; i++) { |
| SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED); |
| } |
| |
| joystick->force_recentering = SDL_FALSE; |
| } |
| |
| SDL_updating_joystick = NULL; |
| |
| /* If the joystick was closed while updating, free it here */ |
| if (joystick->ref_count <= 0) { |
| SDL_JoystickClose(joystick); |
| } |
| |
| joystick = joysticknext; |
| } |
| |
| /* 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(); |
| } |
| |
| int |
| SDL_JoystickEventState(int state) |
| { |
| #if SDL_EVENTS_DISABLED |
| return SDL_DISABLE; |
| #else |
| const Uint32 event_list[] = { |
| SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION, |
| SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED |
| }; |
| unsigned int i; |
| |
| switch (state) { |
| case SDL_QUERY: |
| state = SDL_DISABLE; |
| for (i = 0; i < SDL_arraysize(event_list); ++i) { |
| state = SDL_EventState(event_list[i], SDL_QUERY); |
| if (state == SDL_ENABLE) { |
| break; |
| } |
| } |
| break; |
| default: |
| for (i = 0; i < SDL_arraysize(event_list); ++i) { |
| SDL_EventState(event_list[i], state); |
| } |
| break; |
| } |
| return (state); |
| #endif /* SDL_EVENTS_DISABLED */ |
| } |
| |
| /* 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; |
| } |
| return SDL_SYS_JoystickGetDeviceGUID(device_index); |
| } |
| |
| /* return the guid for this opened device */ |
| SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick * joystick) |
| { |
| if (!SDL_PrivateJoystickValid(joystick)) { |
| SDL_JoystickGUID emptyGUID; |
| SDL_zero(emptyGUID); |
| return emptyGUID; |
| } |
| return SDL_SYS_JoystickGetGUID(joystick); |
| } |
| |
| /* convert the guid to a printable string */ |
| void SDL_JoystickGetGUIDString(SDL_JoystickGUID guid, char *pszGUID, int cbGUID) |
| { |
| static const char k_rgchHexToASCII[] = "0123456789abcdef"; |
| int i; |
| |
| if ((pszGUID == NULL) || (cbGUID <= 0)) { |
| return; |
| } |
| |
| for (i = 0; i < sizeof(guid.data) && i < (cbGUID-1)/2; i++) { |
| /* each input byte writes 2 ascii chars, and might write a null byte. */ |
| /* If we don't have room for next input byte, stop */ |
| unsigned char c = guid.data[i]; |
| |
| *pszGUID++ = k_rgchHexToASCII[c >> 4]; |
| *pszGUID++ = k_rgchHexToASCII[c & 0x0F]; |
| } |
| *pszGUID = '\0'; |
| } |
| |
| |
| /*----------------------------------------------------------------------------- |
| * Purpose: Returns the 4 bit nibble for a hex character |
| * Input : c - |
| * Output : unsigned char |
| *-----------------------------------------------------------------------------*/ |
| static unsigned char nibble(char c) |
| { |
| if ((c >= '0') && (c <= '9')) { |
| return (unsigned char)(c - '0'); |
| } |
| |
| if ((c >= 'A') && (c <= 'F')) { |
| return (unsigned char)(c - 'A' + 0x0a); |
| } |
| |
| if ((c >= 'a') && (c <= 'f')) { |
| return (unsigned char)(c - 'a' + 0x0a); |
| } |
| |
| /* received an invalid character, and no real way to return an error */ |
| /* AssertMsg1(false, "Q_nibble invalid hex character '%c' ", c); */ |
| return 0; |
| } |
| |
| |
| /* convert the string version of a joystick guid to the struct */ |
| SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID) |
| { |
| SDL_JoystickGUID guid; |
| int maxoutputbytes= sizeof(guid); |
| size_t len = SDL_strlen(pchGUID); |
| Uint8 *p; |
| size_t i; |
| |
| /* Make sure it's even */ |
| len = (len) & ~0x1; |
| |
| SDL_memset(&guid, 0x00, sizeof(guid)); |
| |
| p = (Uint8 *)&guid; |
| for (i = 0; (i < len) && ((p - (Uint8 *)&guid) < maxoutputbytes); i+=2, p++) { |
| *p = (nibble(pchGUID[i]) << 4) | nibble(pchGUID[i+1]); |
| } |
| |
| 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 joystick->epowerlevel; |
| } |
| |
| |
| /* vi: set ts=4 sw=4 expandtab: */ |