src/joystick/SDL_joystick.c
author David Ludwig
Thu, 31 Dec 2015 01:54:11 -0500
changeset 9993 e05d46c27ce3
parent 9916 9429bc102632
child 9998 f67cf37e9cd4
permissions -rw-r--r--
WinRT: minor code-comment cleanups
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "../SDL_internal.h"
    22 
    23 /* This is the joystick API for Simple DirectMedia Layer */
    24 
    25 #include "SDL.h"
    26 #include "SDL_events.h"
    27 #include "SDL_sysjoystick.h"
    28 #include "SDL_assert.h"
    29 #include "SDL_hints.h"
    30 
    31 #if !SDL_EVENTS_DISABLED
    32 #include "../events/SDL_events_c.h"
    33 #endif
    34 
    35 static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE;
    36 static SDL_Joystick *SDL_joysticks = NULL;
    37 static SDL_Joystick *SDL_updating_joystick = NULL;
    38 
    39 static void
    40 SDL_JoystickAllowBackgroundEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
    41 {
    42     if (hint && *hint == '1') {
    43         SDL_joystick_allows_background_events = SDL_TRUE;
    44     } else {
    45         SDL_joystick_allows_background_events = SDL_FALSE;
    46     }
    47 }
    48 
    49 int
    50 SDL_JoystickInit(void)
    51 {
    52     int status;
    53 
    54     /* See if we should allow joystick events while in the background */
    55     SDL_AddHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
    56                         SDL_JoystickAllowBackgroundEventsChanged, NULL);
    57 
    58 #if !SDL_EVENTS_DISABLED
    59     if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0) {
    60         return -1;
    61     }
    62 #endif /* !SDL_EVENTS_DISABLED */
    63 
    64     status = SDL_SYS_JoystickInit();
    65     if (status >= 0) {
    66         status = 0;
    67     }
    68     return (status);
    69 }
    70 
    71 /*
    72  * Count the number of joysticks attached to the system
    73  */
    74 int
    75 SDL_NumJoysticks(void)
    76 {
    77     return SDL_SYS_NumJoysticks();
    78 }
    79 
    80 /*
    81  * Get the implementation dependent name of a joystick
    82  */
    83 const char *
    84 SDL_JoystickNameForIndex(int device_index)
    85 {
    86     if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
    87         SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
    88         return (NULL);
    89     }
    90     return (SDL_SYS_JoystickNameForDeviceIndex(device_index));
    91 }
    92 
    93 /*
    94  * Open a joystick for use - the index passed as an argument refers to
    95  * the N'th joystick on the system.  This index is the value which will
    96  * identify this joystick in future joystick events.
    97  *
    98  * This function returns a joystick identifier, or NULL if an error occurred.
    99  */
   100 SDL_Joystick *
   101 SDL_JoystickOpen(int device_index)
   102 {
   103     SDL_Joystick *joystick;
   104     SDL_Joystick *joysticklist;
   105     const char *joystickname = NULL;
   106 
   107     if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
   108         SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
   109         return (NULL);
   110     }
   111 
   112     joysticklist = SDL_joysticks;
   113     /* If the joystick is already open, return it
   114     * it is important that we have a single joystick * for each instance id
   115     */
   116     while (joysticklist) {
   117         if (SDL_SYS_GetInstanceIdOfDeviceIndex(device_index) == joysticklist->instance_id) {
   118                 joystick = joysticklist;
   119                 ++joystick->ref_count;
   120                 return (joystick);
   121         }
   122         joysticklist = joysticklist->next;
   123     }
   124 
   125     /* Create and initialize the joystick */
   126     joystick = (SDL_Joystick *) SDL_malloc((sizeof *joystick));
   127     if (joystick == NULL) {
   128         SDL_OutOfMemory();
   129         return NULL;
   130     }
   131 
   132     SDL_memset(joystick, 0, (sizeof *joystick));
   133     if (SDL_SYS_JoystickOpen(joystick, device_index) < 0) {
   134         SDL_free(joystick);
   135         return NULL;
   136     }
   137 
   138     joystickname = SDL_SYS_JoystickNameForDeviceIndex(device_index);
   139     if (joystickname)
   140         joystick->name = SDL_strdup(joystickname);
   141     else
   142         joystick->name = NULL;
   143 
   144     if (joystick->naxes > 0) {
   145         joystick->axes = (Sint16 *) SDL_malloc
   146             (joystick->naxes * sizeof(Sint16));
   147     }
   148     if (joystick->nhats > 0) {
   149         joystick->hats = (Uint8 *) SDL_malloc
   150             (joystick->nhats * sizeof(Uint8));
   151     }
   152     if (joystick->nballs > 0) {
   153         joystick->balls = (struct balldelta *) SDL_malloc
   154             (joystick->nballs * sizeof(*joystick->balls));
   155     }
   156     if (joystick->nbuttons > 0) {
   157         joystick->buttons = (Uint8 *) SDL_malloc
   158             (joystick->nbuttons * sizeof(Uint8));
   159     }
   160     if (((joystick->naxes > 0) && !joystick->axes)
   161         || ((joystick->nhats > 0) && !joystick->hats)
   162         || ((joystick->nballs > 0) && !joystick->balls)
   163         || ((joystick->nbuttons > 0) && !joystick->buttons)) {
   164         SDL_OutOfMemory();
   165         SDL_JoystickClose(joystick);
   166         return NULL;
   167     }
   168     if (joystick->axes) {
   169         SDL_memset(joystick->axes, 0, joystick->naxes * sizeof(Sint16));
   170     }
   171     if (joystick->hats) {
   172         SDL_memset(joystick->hats, 0, joystick->nhats * sizeof(Uint8));
   173     }
   174     if (joystick->balls) {
   175         SDL_memset(joystick->balls, 0,
   176             joystick->nballs * sizeof(*joystick->balls));
   177     }
   178     if (joystick->buttons) {
   179         SDL_memset(joystick->buttons, 0, joystick->nbuttons * sizeof(Uint8));
   180     }
   181     joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;
   182 
   183     /* Add joystick to list */
   184     ++joystick->ref_count;
   185     /* Link the joystick in the list */
   186     joystick->next = SDL_joysticks;
   187     SDL_joysticks = joystick;
   188 
   189     SDL_SYS_JoystickUpdate(joystick);
   190 
   191     return (joystick);
   192 }
   193 
   194 
   195 /*
   196  * Checks to make sure the joystick is valid.
   197  */
   198 int
   199 SDL_PrivateJoystickValid(SDL_Joystick * joystick)
   200 {
   201     int valid;
   202 
   203     if (joystick == NULL) {
   204         SDL_SetError("Joystick hasn't been opened yet");
   205         valid = 0;
   206     } else {
   207         valid = 1;
   208     }
   209 
   210     return valid;
   211 }
   212 
   213 /*
   214  * Get the number of multi-dimensional axis controls on a joystick
   215  */
   216 int
   217 SDL_JoystickNumAxes(SDL_Joystick * joystick)
   218 {
   219     if (!SDL_PrivateJoystickValid(joystick)) {
   220         return (-1);
   221     }
   222     return (joystick->naxes);
   223 }
   224 
   225 /*
   226  * Get the number of hats on a joystick
   227  */
   228 int
   229 SDL_JoystickNumHats(SDL_Joystick * joystick)
   230 {
   231     if (!SDL_PrivateJoystickValid(joystick)) {
   232         return (-1);
   233     }
   234     return (joystick->nhats);
   235 }
   236 
   237 /*
   238  * Get the number of trackballs on a joystick
   239  */
   240 int
   241 SDL_JoystickNumBalls(SDL_Joystick * joystick)
   242 {
   243     if (!SDL_PrivateJoystickValid(joystick)) {
   244         return (-1);
   245     }
   246     return (joystick->nballs);
   247 }
   248 
   249 /*
   250  * Get the number of buttons on a joystick
   251  */
   252 int
   253 SDL_JoystickNumButtons(SDL_Joystick * joystick)
   254 {
   255     if (!SDL_PrivateJoystickValid(joystick)) {
   256         return (-1);
   257     }
   258     return (joystick->nbuttons);
   259 }
   260 
   261 /*
   262  * Get the current state of an axis control on a joystick
   263  */
   264 Sint16
   265 SDL_JoystickGetAxis(SDL_Joystick * joystick, int axis)
   266 {
   267     Sint16 state;
   268 
   269     if (!SDL_PrivateJoystickValid(joystick)) {
   270         return (0);
   271     }
   272     if (axis < joystick->naxes) {
   273         state = joystick->axes[axis];
   274     } else {
   275         SDL_SetError("Joystick only has %d axes", joystick->naxes);
   276         state = 0;
   277     }
   278     return (state);
   279 }
   280 
   281 /*
   282  * Get the current state of a hat on a joystick
   283  */
   284 Uint8
   285 SDL_JoystickGetHat(SDL_Joystick * joystick, int hat)
   286 {
   287     Uint8 state;
   288 
   289     if (!SDL_PrivateJoystickValid(joystick)) {
   290         return (0);
   291     }
   292     if (hat < joystick->nhats) {
   293         state = joystick->hats[hat];
   294     } else {
   295         SDL_SetError("Joystick only has %d hats", joystick->nhats);
   296         state = 0;
   297     }
   298     return (state);
   299 }
   300 
   301 /*
   302  * Get the ball axis change since the last poll
   303  */
   304 int
   305 SDL_JoystickGetBall(SDL_Joystick * joystick, int ball, int *dx, int *dy)
   306 {
   307     int retval;
   308 
   309     if (!SDL_PrivateJoystickValid(joystick)) {
   310         return (-1);
   311     }
   312 
   313     retval = 0;
   314     if (ball < joystick->nballs) {
   315         if (dx) {
   316             *dx = joystick->balls[ball].dx;
   317         }
   318         if (dy) {
   319             *dy = joystick->balls[ball].dy;
   320         }
   321         joystick->balls[ball].dx = 0;
   322         joystick->balls[ball].dy = 0;
   323     } else {
   324         return SDL_SetError("Joystick only has %d balls", joystick->nballs);
   325     }
   326     return (retval);
   327 }
   328 
   329 /*
   330  * Get the current state of a button on a joystick
   331  */
   332 Uint8
   333 SDL_JoystickGetButton(SDL_Joystick * joystick, int button)
   334 {
   335     Uint8 state;
   336 
   337     if (!SDL_PrivateJoystickValid(joystick)) {
   338         return (0);
   339     }
   340     if (button < joystick->nbuttons) {
   341         state = joystick->buttons[button];
   342     } else {
   343         SDL_SetError("Joystick only has %d buttons", joystick->nbuttons);
   344         state = 0;
   345     }
   346     return (state);
   347 }
   348 
   349 /*
   350  * Return if the joystick in question is currently attached to the system,
   351  *  \return SDL_FALSE if not plugged in, SDL_TRUE if still present.
   352  */
   353 SDL_bool
   354 SDL_JoystickGetAttached(SDL_Joystick * joystick)
   355 {
   356     if (!SDL_PrivateJoystickValid(joystick)) {
   357         return SDL_FALSE;
   358     }
   359 
   360     return SDL_SYS_JoystickAttached(joystick);
   361 }
   362 
   363 /*
   364  * Get the instance id for this opened joystick
   365  */
   366 SDL_JoystickID
   367 SDL_JoystickInstanceID(SDL_Joystick * joystick)
   368 {
   369     if (!SDL_PrivateJoystickValid(joystick)) {
   370         return (-1);
   371     }
   372 
   373     return (joystick->instance_id);
   374 }
   375 
   376 /*
   377  * Find the SDL_Joystick that owns this instance id
   378  */
   379 SDL_Joystick *
   380 SDL_JoystickFromInstanceID(SDL_JoystickID joyid)
   381 {
   382     SDL_Joystick *joystick = SDL_joysticks;
   383     while (joystick) {
   384         if (joystick->instance_id == joyid) {
   385             return joystick;
   386         }
   387         joystick = joystick->next;
   388     }
   389 
   390     return NULL;
   391 }
   392 
   393 /*
   394  * Get the friendly name of this joystick
   395  */
   396 const char *
   397 SDL_JoystickName(SDL_Joystick * joystick)
   398 {
   399     if (!SDL_PrivateJoystickValid(joystick)) {
   400         return (NULL);
   401     }
   402 
   403     return (joystick->name);
   404 }
   405 
   406 /*
   407  * Close a joystick previously opened with SDL_JoystickOpen()
   408  */
   409 void
   410 SDL_JoystickClose(SDL_Joystick * joystick)
   411 {
   412     SDL_Joystick *joysticklist;
   413     SDL_Joystick *joysticklistprev;
   414 
   415     if (!joystick) {
   416         return;
   417     }
   418 
   419     /* First decrement ref count */
   420     if (--joystick->ref_count > 0) {
   421         return;
   422     }
   423 
   424     if (joystick == SDL_updating_joystick) {
   425         return;
   426     }
   427 
   428     SDL_SYS_JoystickClose(joystick);
   429     joystick->hwdata = NULL;
   430 
   431     joysticklist = SDL_joysticks;
   432     joysticklistprev = NULL;
   433     while (joysticklist) {
   434         if (joystick == joysticklist) {
   435             if (joysticklistprev) {
   436                 /* unlink this entry */
   437                 joysticklistprev->next = joysticklist->next;
   438             } else {
   439                 SDL_joysticks = joystick->next;
   440             }
   441             break;
   442         }
   443         joysticklistprev = joysticklist;
   444         joysticklist = joysticklist->next;
   445     }
   446 
   447     SDL_free(joystick->name);
   448 
   449     /* Free the data associated with this joystick */
   450     SDL_free(joystick->axes);
   451     SDL_free(joystick->hats);
   452     SDL_free(joystick->balls);
   453     SDL_free(joystick->buttons);
   454     SDL_free(joystick);
   455 }
   456 
   457 void
   458 SDL_JoystickQuit(void)
   459 {
   460     /* Make sure we're not getting called in the middle of updating joysticks */
   461     SDL_assert(!SDL_updating_joystick);
   462 
   463     /* Stop the event polling */
   464     while (SDL_joysticks) {
   465         SDL_joysticks->ref_count = 1;
   466         SDL_JoystickClose(SDL_joysticks);
   467     }
   468 
   469     /* Quit the joystick setup */
   470     SDL_SYS_JoystickQuit();
   471 
   472 #if !SDL_EVENTS_DISABLED
   473     SDL_QuitSubSystem(SDL_INIT_EVENTS);
   474 #endif
   475 }
   476 
   477 
   478 static SDL_bool
   479 SDL_PrivateJoystickShouldIgnoreEvent()
   480 {
   481     if (SDL_joystick_allows_background_events) {
   482         return SDL_FALSE;
   483     }
   484 
   485     if (SDL_WasInit(SDL_INIT_VIDEO)) {
   486         if (SDL_GetKeyboardFocus() == NULL) {
   487             /* Video is initialized and we don't have focus, ignore the event. */
   488             return SDL_TRUE;
   489         } else {
   490             return SDL_FALSE;
   491         }
   492     }
   493 
   494     /* Video subsystem wasn't initialized, always allow the event */
   495     return SDL_FALSE;
   496 }
   497 
   498 /* These are global for SDL_sysjoystick.c and SDL_events.c */
   499 
   500 int
   501 SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
   502 {
   503     int posted;
   504 
   505     /* Make sure we're not getting garbage or duplicate events */
   506     if (axis >= joystick->naxes) {
   507         return 0;
   508     }
   509     if (value == joystick->axes[axis]) {
   510         return 0;
   511     }
   512 
   513     /* We ignore events if we don't have keyboard focus, except for centering
   514      * events.
   515      */
   516     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
   517         if ((value > 0 && value >= joystick->axes[axis]) ||
   518             (value < 0 && value <= joystick->axes[axis])) {
   519             return 0;
   520         }
   521     }
   522 
   523     /* Update internal joystick state */
   524     joystick->axes[axis] = value;
   525 
   526     /* Post the event, if desired */
   527     posted = 0;
   528 #if !SDL_EVENTS_DISABLED
   529     if (SDL_GetEventState(SDL_JOYAXISMOTION) == SDL_ENABLE) {
   530         SDL_Event event;
   531         event.type = SDL_JOYAXISMOTION;
   532         event.jaxis.which = joystick->instance_id;
   533         event.jaxis.axis = axis;
   534         event.jaxis.value = value;
   535         posted = SDL_PushEvent(&event) == 1;
   536     }
   537 #endif /* !SDL_EVENTS_DISABLED */
   538     return (posted);
   539 }
   540 
   541 int
   542 SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value)
   543 {
   544     int posted;
   545 
   546     /* Make sure we're not getting garbage or duplicate events */
   547     if (hat >= joystick->nhats) {
   548         return 0;
   549     }
   550     if (value == joystick->hats[hat]) {
   551         return 0;
   552     }
   553 
   554     /* We ignore events if we don't have keyboard focus, except for centering
   555      * events.
   556      */
   557     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
   558         if (value != SDL_HAT_CENTERED) {
   559             return 0;
   560         }
   561     }
   562 
   563     /* Update internal joystick state */
   564     joystick->hats[hat] = value;
   565 
   566     /* Post the event, if desired */
   567     posted = 0;
   568 #if !SDL_EVENTS_DISABLED
   569     if (SDL_GetEventState(SDL_JOYHATMOTION) == SDL_ENABLE) {
   570         SDL_Event event;
   571         event.jhat.type = SDL_JOYHATMOTION;
   572         event.jhat.which = joystick->instance_id;
   573         event.jhat.hat = hat;
   574         event.jhat.value = value;
   575         posted = SDL_PushEvent(&event) == 1;
   576     }
   577 #endif /* !SDL_EVENTS_DISABLED */
   578     return (posted);
   579 }
   580 
   581 int
   582 SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball,
   583                         Sint16 xrel, Sint16 yrel)
   584 {
   585     int posted;
   586 
   587     /* Make sure we're not getting garbage events */
   588     if (ball >= joystick->nballs) {
   589         return 0;
   590     }
   591 
   592     /* We ignore events if we don't have keyboard focus. */
   593     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
   594         return 0;
   595     }
   596 
   597     /* Update internal mouse state */
   598     joystick->balls[ball].dx += xrel;
   599     joystick->balls[ball].dy += yrel;
   600 
   601     /* Post the event, if desired */
   602     posted = 0;
   603 #if !SDL_EVENTS_DISABLED
   604     if (SDL_GetEventState(SDL_JOYBALLMOTION) == SDL_ENABLE) {
   605         SDL_Event event;
   606         event.jball.type = SDL_JOYBALLMOTION;
   607         event.jball.which = joystick->instance_id;
   608         event.jball.ball = ball;
   609         event.jball.xrel = xrel;
   610         event.jball.yrel = yrel;
   611         posted = SDL_PushEvent(&event) == 1;
   612     }
   613 #endif /* !SDL_EVENTS_DISABLED */
   614     return (posted);
   615 }
   616 
   617 int
   618 SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state)
   619 {
   620     int posted;
   621 #if !SDL_EVENTS_DISABLED
   622     SDL_Event event;
   623 
   624     switch (state) {
   625     case SDL_PRESSED:
   626         event.type = SDL_JOYBUTTONDOWN;
   627         break;
   628     case SDL_RELEASED:
   629         event.type = SDL_JOYBUTTONUP;
   630         break;
   631     default:
   632         /* Invalid state -- bail */
   633         return (0);
   634     }
   635 #endif /* !SDL_EVENTS_DISABLED */
   636 
   637     /* Make sure we're not getting garbage or duplicate events */
   638     if (button >= joystick->nbuttons) {
   639         return 0;
   640     }
   641     if (state == joystick->buttons[button]) {
   642         return 0;
   643     }
   644 
   645     /* We ignore events if we don't have keyboard focus, except for button
   646      * release. */
   647     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
   648         if (state == SDL_PRESSED) {
   649             return 0;
   650         }
   651     }
   652 
   653     /* Update internal joystick state */
   654     joystick->buttons[button] = state;
   655 
   656     /* Post the event, if desired */
   657     posted = 0;
   658 #if !SDL_EVENTS_DISABLED
   659     if (SDL_GetEventState(event.type) == SDL_ENABLE) {
   660         event.jbutton.which = joystick->instance_id;
   661         event.jbutton.button = button;
   662         event.jbutton.state = state;
   663         posted = SDL_PushEvent(&event) == 1;
   664     }
   665 #endif /* !SDL_EVENTS_DISABLED */
   666     return (posted);
   667 }
   668 
   669 void
   670 SDL_JoystickUpdate(void)
   671 {
   672     SDL_Joystick *joystick;
   673 
   674     joystick = SDL_joysticks;
   675     while (joystick) {
   676         SDL_Joystick *joysticknext;
   677         /* save off the next pointer, the Update call may cause a joystick removed event
   678          * and cause our joystick pointer to be freed
   679          */
   680         joysticknext = joystick->next;
   681 
   682         SDL_updating_joystick = joystick;
   683 
   684         SDL_SYS_JoystickUpdate(joystick);
   685 
   686         if (joystick->force_recentering) {
   687             int i;
   688 
   689             /* Tell the app that everything is centered/unpressed...  */
   690             for (i = 0; i < joystick->naxes; i++) {
   691                 SDL_PrivateJoystickAxis(joystick, i, 0);
   692             }
   693 
   694             for (i = 0; i < joystick->nbuttons; i++) {
   695                 SDL_PrivateJoystickButton(joystick, i, 0);
   696             }
   697 
   698             for (i = 0; i < joystick->nhats; i++) {
   699                 SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
   700             }
   701 
   702             joystick->force_recentering = SDL_FALSE;
   703         }
   704 
   705         SDL_updating_joystick = NULL;
   706 
   707         /* If the joystick was closed while updating, free it here */
   708         if (joystick->ref_count <= 0) {
   709             SDL_JoystickClose(joystick);
   710         }
   711 
   712         joystick = joysticknext;
   713     }
   714 
   715     /* this needs to happen AFTER walking the joystick list above, so that any
   716        dangling hardware data from removed devices can be free'd
   717      */
   718     SDL_SYS_JoystickDetect();
   719 }
   720 
   721 int
   722 SDL_JoystickEventState(int state)
   723 {
   724 #if SDL_EVENTS_DISABLED
   725     return SDL_DISABLE;
   726 #else
   727     const Uint32 event_list[] = {
   728         SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION,
   729         SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED
   730     };
   731     unsigned int i;
   732 
   733     switch (state) {
   734     case SDL_QUERY:
   735         state = SDL_DISABLE;
   736         for (i = 0; i < SDL_arraysize(event_list); ++i) {
   737             state = SDL_EventState(event_list[i], SDL_QUERY);
   738             if (state == SDL_ENABLE) {
   739                 break;
   740             }
   741         }
   742         break;
   743     default:
   744         for (i = 0; i < SDL_arraysize(event_list); ++i) {
   745             SDL_EventState(event_list[i], state);
   746         }
   747         break;
   748     }
   749     return (state);
   750 #endif /* SDL_EVENTS_DISABLED */
   751 }
   752 
   753 /* return the guid for this index */
   754 SDL_JoystickGUID SDL_JoystickGetDeviceGUID(int device_index)
   755 {
   756     if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
   757         SDL_JoystickGUID emptyGUID;
   758         SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
   759         SDL_zero(emptyGUID);
   760         return emptyGUID;
   761     }
   762     return SDL_SYS_JoystickGetDeviceGUID(device_index);
   763 }
   764 
   765 /* return the guid for this opened device */
   766 SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick * joystick)
   767 {
   768     if (!SDL_PrivateJoystickValid(joystick)) {
   769         SDL_JoystickGUID emptyGUID;
   770         SDL_zero(emptyGUID);
   771         return emptyGUID;
   772     }
   773     return SDL_SYS_JoystickGetGUID(joystick);
   774 }
   775 
   776 /* convert the guid to a printable string */
   777 void SDL_JoystickGetGUIDString(SDL_JoystickGUID guid, char *pszGUID, int cbGUID)
   778 {
   779     static const char k_rgchHexToASCII[] = "0123456789abcdef";
   780     int i;
   781 
   782     if ((pszGUID == NULL) || (cbGUID <= 0)) {
   783         return;
   784     }
   785 
   786     for (i = 0; i < sizeof(guid.data) && i < (cbGUID-1)/2; i++) {
   787         /* each input byte writes 2 ascii chars, and might write a null byte. */
   788         /* If we don't have room for next input byte, stop */
   789         unsigned char c = guid.data[i];
   790 
   791         *pszGUID++ = k_rgchHexToASCII[c >> 4];
   792         *pszGUID++ = k_rgchHexToASCII[c & 0x0F];
   793     }
   794     *pszGUID = '\0';
   795 }
   796 
   797 
   798 /*-----------------------------------------------------------------------------
   799  * Purpose: Returns the 4 bit nibble for a hex character
   800  * Input  : c -
   801  * Output : unsigned char
   802  *-----------------------------------------------------------------------------*/
   803 static unsigned char nibble(char c)
   804 {
   805     if ((c >= '0') && (c <= '9')) {
   806         return (unsigned char)(c - '0');
   807     }
   808 
   809     if ((c >= 'A') && (c <= 'F')) {
   810         return (unsigned char)(c - 'A' + 0x0a);
   811     }
   812 
   813     if ((c >= 'a') && (c <= 'f')) {
   814         return (unsigned char)(c - 'a' + 0x0a);
   815     }
   816 
   817     /* received an invalid character, and no real way to return an error */
   818     /* AssertMsg1(false, "Q_nibble invalid hex character '%c' ", c); */
   819     return 0;
   820 }
   821 
   822 
   823 /* convert the string version of a joystick guid to the struct */
   824 SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID)
   825 {
   826     SDL_JoystickGUID guid;
   827     int maxoutputbytes= sizeof(guid);
   828     size_t len = SDL_strlen(pchGUID);
   829     Uint8 *p;
   830     size_t i;
   831 
   832     /* Make sure it's even */
   833     len = (len) & ~0x1;
   834 
   835     SDL_memset(&guid, 0x00, sizeof(guid));
   836 
   837     p = (Uint8 *)&guid;
   838     for (i = 0; (i < len) && ((p - (Uint8 *)&guid) < maxoutputbytes); i+=2, p++) {
   839         *p = (nibble(pchGUID[i]) << 4) | nibble(pchGUID[i+1]);
   840     }
   841 
   842     return guid;
   843 }
   844 
   845 
   846 /* update the power level for this joystick */
   847 void SDL_PrivateJoystickBatteryLevel(SDL_Joystick * joystick, SDL_JoystickPowerLevel ePowerLevel)
   848 {
   849     joystick->epowerlevel = ePowerLevel;
   850 }
   851 
   852 
   853 /* return its power level */
   854 SDL_JoystickPowerLevel SDL_JoystickCurrentPowerLevel(SDL_Joystick * joystick)
   855 {
   856     if (!SDL_PrivateJoystickValid(joystick)) {
   857         return (SDL_JOYSTICK_POWER_UNKNOWN);
   858     }
   859     return joystick->epowerlevel;
   860 }
   861 
   862 
   863 /* vi: set ts=4 sw=4 expandtab: */