src/joystick/SDL_joystick.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. SDL_Lock_EventThread
  2. SDL_Unlock_EventThread
  3. SDL_JoystickInit
  4. SDL_NumJoysticks
  5. SDL_JoystickName
  6. SDL_JoystickOpen
  7. SDL_JoystickOpened
  8. ValidJoystick
  9. SDL_JoystickIndex
  10. SDL_JoystickNumAxes
  11. SDL_JoystickNumHats
  12. SDL_JoystickNumBalls
  13. SDL_JoystickNumButtons
  14. SDL_JoystickGetAxis
  15. SDL_JoystickGetHat
  16. SDL_JoystickGetBall
  17. SDL_JoystickGetButton
  18. SDL_JoystickClose
  19. SDL_JoystickQuit
  20. SDL_PrivateJoystickAxis
  21. SDL_PrivateJoystickHat
  22. SDL_PrivateJoystickBall
  23. SDL_PrivateJoystickButton
  24. SDL_JoystickUpdate
  25. SDL_JoystickEventState

   1 /*
   2     SDL - Simple DirectMedia Layer
   3     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
   4 
   5     This library is free software; you can redistribute it and/or
   6     modify it under the terms of the GNU Library General Public
   7     License as published by the Free Software Foundation; either
   8     version 2 of the License, or (at your option) any later version.
   9 
  10     This library is distributed in the hope that it will be useful,
  11     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13     Library General Public License for more details.
  14 
  15     You should have received a copy of the GNU Library General Public
  16     License along with this library; if not, write to the Free
  17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 
  19     Sam Lantinga
  20     slouken@devolution.com
  21 */
  22 
  23 #ifdef SAVE_RCSID
  24 static char rcsid =
  25  "@(#) $Id: SDL_joystick.c,v 1.1.2.21 2001/02/10 07:20:04 hercules Exp $";
  26 #endif
  27 
  28 /* This is the joystick API for Simple DirectMedia Layer */
  29 
  30 #include <stdio.h>
  31 #include <stdlib.h>
  32 #include <string.h>
  33 
  34 #include "SDL_error.h"
  35 #include "SDL_events.h"
  36 #ifndef DISABLE_EVENTS
  37 #include "SDL_events_c.h"
  38 #endif
  39 #include "SDL_joystick_c.h"
  40 #include "SDL_sysjoystick.h"
  41 
  42 /* This is used for Quake III Arena */
  43 #ifdef DISABLE_EVENTS
  44 #define SDL_Lock_EventThread()
     /* [<][>][^][v][top][bottom][index][help] */
  45 #define SDL_Unlock_EventThread()
     /* [<][>][^][v][top][bottom][index][help] */
  46 #endif
  47 
  48 Uint8 SDL_numjoysticks = 0;
  49 SDL_Joystick **SDL_joysticks = NULL;
  50 static SDL_Joystick *default_joystick = NULL;
  51 
  52 int SDL_JoystickInit(void)
     /* [<][>][^][v][top][bottom][index][help] */
  53 {
  54         int arraylen;
  55         int status;
  56 
  57         SDL_numjoysticks = 0;
  58         status = SDL_SYS_JoystickInit();
  59         if ( status >= 0 ) {
  60                 arraylen = (status+1)*sizeof(*SDL_joysticks);
  61                 SDL_joysticks = (SDL_Joystick **)malloc(arraylen);
  62                 if ( SDL_joysticks == NULL ) {
  63                         SDL_numjoysticks = 0;
  64                 } else {
  65                         memset(SDL_joysticks, 0, arraylen);
  66                 }
  67                 SDL_numjoysticks = status;
  68                 status = 0;
  69         }
  70         default_joystick = NULL;
  71         return(status);
  72 }
  73 
  74 /*
  75  * Count the number of joysticks attached to the system
  76  */
  77 int SDL_NumJoysticks(void)
     /* [<][>][^][v][top][bottom][index][help] */
  78 {
  79         return SDL_numjoysticks;
  80 }
  81 
  82 /*
  83  * Get the implementation dependent name of a joystick
  84  */
  85 const char *SDL_JoystickName(int device_index)
     /* [<][>][^][v][top][bottom][index][help] */
  86 {
  87         if ( (device_index < 0) || (device_index >= SDL_numjoysticks) ) {
  88                 SDL_SetError("There are %d joysticks available",
  89                              SDL_numjoysticks);
  90                 return(NULL);
  91         }
  92         return(SDL_SYS_JoystickName(device_index));
  93 }
  94 
  95 /*
  96  * Open a joystick for use - the index passed as an argument refers to
  97  * the N'th joystick on the system.  This index is the value which will
  98  * identify this joystick in future joystick events.
  99  *
 100  * This function returns a joystick identifier, or NULL if an error occurred.
 101  */
 102 SDL_Joystick *SDL_JoystickOpen(int device_index)
     /* [<][>][^][v][top][bottom][index][help] */
 103 {
 104         int i;
 105         SDL_Joystick *joystick;
 106 
 107         if ( (device_index < 0) || (device_index >= SDL_numjoysticks) ) {
 108                 SDL_SetError("There are %d joysticks available",
 109                              SDL_numjoysticks);
 110                 return(NULL);
 111         }
 112 
 113         /* If the joystick is already open, return it */
 114         for ( i=0; SDL_joysticks[i]; ++i ) {
 115                 if ( device_index == SDL_joysticks[i]->index ) {
 116                         joystick = SDL_joysticks[i];
 117                         ++joystick->ref_count;
 118                         return(joystick);
 119                 }
 120         }
 121 
 122         /* Create and initialize the joystick */
 123         joystick = (SDL_Joystick *)malloc((sizeof *joystick));
 124         if ( joystick != NULL ) {
 125                 memset(joystick, 0, (sizeof *joystick));
 126                 joystick->index = device_index;
 127                 if ( SDL_SYS_JoystickOpen(joystick) < 0 ) {
 128                         free(joystick);
 129                         joystick = NULL;
 130                 } else {
 131                         if ( joystick->naxes > 0 ) {
 132                                 joystick->axes = (Sint16 *)malloc
 133                                         (joystick->naxes*sizeof(Sint16));
 134                         }
 135                         if ( joystick->nhats > 0 ) {
 136                                 joystick->hats = (Uint8 *)malloc
 137                                         (joystick->nhats*sizeof(Uint8));
 138                         }
 139                         if ( joystick->nballs > 0 ) {
 140                                 joystick->balls = (struct balldelta *)malloc
 141                                   (joystick->nballs*sizeof(*joystick->balls));
 142                         }
 143                         if ( joystick->nbuttons > 0 ) {
 144                                 joystick->buttons = (Uint8 *)malloc
 145                                         (joystick->nbuttons*sizeof(Uint8));
 146                         }
 147                         if ( ((joystick->naxes > 0) && !joystick->axes)
 148                           || ((joystick->nhats > 0) && !joystick->hats)
 149                           || ((joystick->nballs > 0) && !joystick->balls)
 150                           || ((joystick->nbuttons > 0) && !joystick->buttons)) {
 151                                 SDL_OutOfMemory();
 152                                 SDL_JoystickClose(joystick);
 153                                 joystick = NULL;
 154                         }
 155                         if ( joystick->axes ) {
 156                                 memset(joystick->axes, 0,
 157                                         joystick->naxes*sizeof(Sint16));
 158                         }
 159                         if ( joystick->hats ) {
 160                                 memset(joystick->hats, 0,
 161                                         joystick->nhats*sizeof(Uint8));
 162                         }
 163                         if ( joystick->balls ) {
 164                                 memset(joystick->balls, 0,
 165                                   joystick->nballs*sizeof(*joystick->balls));
 166                         }
 167                         if ( joystick->buttons ) {
 168                                 memset(joystick->buttons, 0,
 169                                         joystick->nbuttons*sizeof(Uint8));
 170                         }
 171                 }
 172         }
 173         if ( joystick ) {
 174                 /* Add joystick to list */
 175                 ++joystick->ref_count;
 176                 SDL_Lock_EventThread();
 177                 for ( i=0; SDL_joysticks[i]; ++i )
 178                         /* Skip to next joystick */;
 179                 SDL_joysticks[i] = joystick;
 180                 SDL_Unlock_EventThread();
 181         }
 182         return(joystick);
 183 }
 184 
 185 /*
 186  * Returns 1 if the joystick has been opened, or 0 if it has not.
 187  */
 188 int SDL_JoystickOpened(int device_index)
     /* [<][>][^][v][top][bottom][index][help] */
 189 {
 190         int i, opened;
 191 
 192         opened = 0;
 193         for ( i=0; SDL_joysticks[i]; ++i ) {
 194                 if ( SDL_joysticks[i]->index == (Uint8)device_index ) {
 195                         opened = 1;
 196                         break;
 197                 }
 198         }
 199         return(opened);
 200 }
 201 
 202 static int ValidJoystick(SDL_Joystick **joystick)
     /* [<][>][^][v][top][bottom][index][help] */
 203 {
 204         int valid;
 205 
 206         if ( *joystick == NULL ) {
 207                 *joystick = default_joystick;
 208         }
 209         if ( *joystick == NULL ) {
 210                 SDL_SetError("Joystick hasn't been opened yet");
 211                 valid = 0;
 212         } else {
 213                 valid = 1;
 214         }
 215         return valid;
 216 }
 217 
 218 /*
 219  * Get the device index of an opened joystick.
 220  */
 221 int SDL_JoystickIndex(SDL_Joystick *joystick)
     /* [<][>][^][v][top][bottom][index][help] */
 222 {
 223         if ( ! ValidJoystick(&joystick) ) {
 224                 return(-1);
 225         }
 226         return(joystick->index);
 227 }
 228 
 229 /*
 230  * Get the number of multi-dimensional axis controls on a joystick
 231  */
 232 int SDL_JoystickNumAxes(SDL_Joystick *joystick)
     /* [<][>][^][v][top][bottom][index][help] */
 233 {
 234         if ( ! ValidJoystick(&joystick) ) {
 235                 return(-1);
 236         }
 237         return(joystick->naxes);
 238 }
 239 
 240 /*
 241  * Get the number of hats on a joystick
 242  */
 243 int SDL_JoystickNumHats(SDL_Joystick *joystick)
     /* [<][>][^][v][top][bottom][index][help] */
 244 {
 245         if ( ! ValidJoystick(&joystick) ) {
 246                 return(-1);
 247         }
 248         return(joystick->nhats);
 249 }
 250 
 251 /*
 252  * Get the number of trackballs on a joystick
 253  */
 254 int SDL_JoystickNumBalls(SDL_Joystick *joystick)
     /* [<][>][^][v][top][bottom][index][help] */
 255 {
 256         if ( ! ValidJoystick(&joystick) ) {
 257                 return(-1);
 258         }
 259         return(joystick->nballs);
 260 }
 261 
 262 /*
 263  * Get the number of buttons on a joystick
 264  */
 265 int SDL_JoystickNumButtons(SDL_Joystick *joystick)
     /* [<][>][^][v][top][bottom][index][help] */
 266 {
 267         if ( ! ValidJoystick(&joystick) ) {
 268                 return(-1);
 269         }
 270         return(joystick->nbuttons);
 271 }
 272 
 273 /*
 274  * Get the current state of an axis control on a joystick
 275  */
 276 Sint16 SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis)
     /* [<][>][^][v][top][bottom][index][help] */
 277 {
 278         Sint16 state;
 279 
 280         if ( ! ValidJoystick(&joystick) ) {
 281                 return(0);
 282         }
 283         if ( axis < joystick->naxes ) {
 284                 state = joystick->axes[axis];
 285         } else {
 286                 SDL_SetError("Joystick only has %d axes", joystick->naxes);
 287                 state = 0;
 288         }
 289         return(state);
 290 }
 291 
 292 /*
 293  * Get the current state of a hat on a joystick
 294  */
 295 Uint8 SDL_JoystickGetHat(SDL_Joystick *joystick, int hat)
     /* [<][>][^][v][top][bottom][index][help] */
 296 {
 297         Uint8 state;
 298 
 299         if ( ! ValidJoystick(&joystick) ) {
 300                 return(0);
 301         }
 302         if ( hat < joystick->nhats ) {
 303                 state = joystick->hats[hat];
 304         } else {
 305                 SDL_SetError("Joystick only has %d hats", joystick->nhats);
 306                 state = 0;
 307         }
 308         return(state);
 309 }
 310 
 311 /*
 312  * Get the ball axis change since the last poll
 313  */
 314 int SDL_JoystickGetBall(SDL_Joystick *joystick, int ball, int *dx, int *dy)
     /* [<][>][^][v][top][bottom][index][help] */
 315 {
 316         int retval;
 317 
 318         if ( ! ValidJoystick(&joystick) ) {
 319                 return(-1);
 320         }
 321 
 322         retval = 0;
 323         if ( ball < joystick->nballs ) {
 324                 if ( dx ) {
 325                         *dx = joystick->balls[ball].dx;
 326                 }
 327                 if ( dy ) {
 328                         *dy = joystick->balls[ball].dy;
 329                 }
 330                 joystick->balls[ball].dx = 0;
 331                 joystick->balls[ball].dy = 0;
 332         } else {
 333                 SDL_SetError("Joystick only has %d balls", joystick->nballs);
 334                 retval = -1;
 335         }
 336         return(retval);
 337 }
 338 
 339 /*
 340  * Get the current state of a button on a joystick
 341  */
 342 Uint8 SDL_JoystickGetButton(SDL_Joystick *joystick, int button)
     /* [<][>][^][v][top][bottom][index][help] */
 343 {
 344         Uint8 state;
 345 
 346         if ( ! ValidJoystick(&joystick) ) {
 347                 return(0);
 348         }
 349         if ( button < joystick->nbuttons ) {
 350                 state = joystick->buttons[button];
 351         } else {
 352                 SDL_SetError("Joystick only has %d buttons",joystick->nbuttons);
 353                 state = 0;
 354         }
 355         return(state);
 356 }
 357 
 358 /*
 359  * Close a joystick previously opened with SDL_JoystickOpen()
 360  */
 361 void SDL_JoystickClose(SDL_Joystick *joystick)
     /* [<][>][^][v][top][bottom][index][help] */
 362 {
 363         int i;
 364 
 365         if ( ! ValidJoystick(&joystick) ) {
 366                 return;
 367         }
 368 
 369         /* First decrement ref count */
 370         if ( --joystick->ref_count > 0 ) {
 371                 return;
 372         }
 373 
 374         /* Lock the event queue - prevent joystick polling */
 375         SDL_Lock_EventThread();
 376 
 377         if ( joystick == default_joystick ) {
 378                 default_joystick = NULL;
 379         }
 380         SDL_SYS_JoystickClose(joystick);
 381 
 382         /* Remove joystick from list */
 383         for ( i=0; SDL_joysticks[i]; ++i ) {
 384                 if ( joystick == SDL_joysticks[i] ) {
 385                         memcpy(&SDL_joysticks[i], &SDL_joysticks[i+1],
 386                                (SDL_numjoysticks-i)*sizeof(joystick));
 387                         break;
 388                 }
 389         }
 390 
 391         /* Let the event thread keep running */
 392         SDL_Unlock_EventThread();
 393 
 394         /* Free the data associated with this joystick */
 395         if ( joystick->axes ) {
 396                 free(joystick->axes);
 397         }
 398         if ( joystick->hats ) {
 399                 free(joystick->hats);
 400         }
 401         if ( joystick->balls ) {
 402                 free(joystick->balls);
 403         }
 404         if ( joystick->buttons ) {
 405                 free(joystick->buttons);
 406         }
 407         free(joystick);
 408 }
 409 
 410 void SDL_JoystickQuit(void)
     /* [<][>][^][v][top][bottom][index][help] */
 411 {
 412         /* Stop the event polling */
 413         SDL_Lock_EventThread();
 414         SDL_numjoysticks = 0;
 415         SDL_Unlock_EventThread();
 416 
 417         /* Quit the joystick setup */
 418         SDL_SYS_JoystickQuit();
 419         if ( SDL_joysticks ) {
 420                 free(SDL_joysticks);
 421                 SDL_joysticks = NULL;
 422         }
 423 }
 424 
 425 
 426 /* These are global for SDL_sysjoystick.c and SDL_events.c */
 427 
 428 int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
     /* [<][>][^][v][top][bottom][index][help] */
 429 {
 430         int posted;
 431 
 432         /* Update internal joystick state */
 433         joystick->axes[axis] = value;
 434 
 435         /* Post the event, if desired */
 436         posted = 0;
 437 #ifndef DISABLE_EVENTS
 438         if ( SDL_ProcessEvents[SDL_JOYAXISMOTION] == SDL_ENABLE ) {
 439                 SDL_Event event;
 440                 event.type = SDL_JOYAXISMOTION;
 441                 event.jaxis.which = joystick->index;
 442                 event.jaxis.axis = axis;
 443                 event.jaxis.value = value;
 444                 if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) {
 445                         posted = 1;
 446                         SDL_PushEvent(&event);
 447                 }
 448         }
 449 #endif /* !DISABLE_EVENTS */
 450         return(posted);
 451 }
 452 
 453 int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
     /* [<][>][^][v][top][bottom][index][help] */
 454 {
 455         int posted;
 456 
 457         /* Update internal joystick state */
 458         joystick->hats[hat] = value;
 459 
 460         /* Post the event, if desired */
 461         posted = 0;
 462 #ifndef DISABLE_EVENTS
 463         if ( SDL_ProcessEvents[SDL_JOYHATMOTION] == SDL_ENABLE ) {
 464                 SDL_Event event;
 465                 event.jhat.type = SDL_JOYHATMOTION;
 466                 event.jhat.which = joystick->index;
 467                 event.jhat.hat = hat;
 468                 event.jhat.value = value;
 469                 if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) {
 470                         posted = 1;
 471                         SDL_PushEvent(&event);
 472                 }
 473         }
 474 #endif /* !DISABLE_EVENTS */
 475         return(posted);
 476 }
 477 
 478 int SDL_PrivateJoystickBall(SDL_Joystick *joystick, Uint8 ball,
     /* [<][>][^][v][top][bottom][index][help] */
 479                                         Sint16 xrel, Sint16 yrel)
 480 {
 481         int posted;
 482 
 483         /* Update internal mouse state */
 484         joystick->balls[ball].dx += xrel;
 485         joystick->balls[ball].dy += yrel;
 486 
 487         /* Post the event, if desired */
 488         posted = 0;
 489 #ifndef DISABLE_EVENTS
 490         if ( SDL_ProcessEvents[SDL_JOYBALLMOTION] == SDL_ENABLE ) {
 491                 SDL_Event event;
 492                 event.jball.type = SDL_JOYBALLMOTION;
 493                 event.jball.which = joystick->index;
 494                 event.jball.ball = ball;
 495                 event.jball.xrel = xrel;
 496                 event.jball.yrel = yrel;
 497                 if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) {
 498                         posted = 1;
 499                         SDL_PushEvent(&event);
 500                 }
 501         }
 502 #endif /* !DISABLE_EVENTS */
 503         return(posted);
 504 }
 505 
 506 int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
     /* [<][>][^][v][top][bottom][index][help] */
 507 {
 508         int posted;
 509 #ifndef DISABLE_EVENTS
 510         SDL_Event event;
 511 
 512         switch ( state ) {
 513                 case SDL_PRESSED:
 514                         event.type = SDL_JOYBUTTONDOWN;
 515                         break;
 516                 case SDL_RELEASED:
 517                         event.type = SDL_JOYBUTTONUP;
 518                         break;
 519                 default:
 520                         /* Invalid state -- bail */
 521                         return(0);
 522         }
 523 #endif /* !DISABLE_EVENTS */
 524 
 525         /* Update internal joystick state */
 526         joystick->buttons[button] = state;
 527 
 528         /* Post the event, if desired */
 529         posted = 0;
 530 #ifndef DISABLE_EVENTS
 531         if ( SDL_ProcessEvents[event.type] == SDL_ENABLE ) {
 532                 event.jbutton.which = joystick->index;
 533                 event.jbutton.button = button;
 534                 event.jbutton.state = state;
 535                 if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) {
 536                         posted = 1;
 537                         SDL_PushEvent(&event);
 538                 }
 539         }
 540 #endif /* !DISABLE_EVENTS */
 541         return(posted);
 542 }
 543 
 544 void SDL_JoystickUpdate(void)
     /* [<][>][^][v][top][bottom][index][help] */
 545 {
 546         int i;
 547 
 548         for ( i=0; SDL_joysticks[i]; ++i ) {
 549                 SDL_SYS_JoystickUpdate(SDL_joysticks[i]);
 550         }
 551 }
 552 
 553 int SDL_JoystickEventState(int state)
     /* [<][>][^][v][top][bottom][index][help] */
 554 {
 555 #ifdef DISABLE_EVENTS
 556         return SDL_IGNORE;
 557 #else
 558         const Uint8 event_list[] = {
 559                 SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION,
 560                 SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP,
 561         };
 562         int i;
 563 
 564         switch (state) {
 565                 case SDL_QUERY:
 566                         state = SDL_IGNORE;
 567                         for ( i=0; i<SDL_TABLESIZE(event_list); ++i ) {
 568                                 state = SDL_EventState(event_list[i],SDL_QUERY);
 569                                 if ( state == SDL_ENABLE ) {
 570                                         break;
 571                                 }
 572                         }
 573                         break;
 574                 default:
 575                         for ( i=0; i<SDL_TABLESIZE(event_list); ++i ) {
 576                                 SDL_EventState(event_list[i], state);
 577                         }
 578                         break;
 579         }
 580         return(state);
 581 #endif /* DISABLE_EVENTS */
 582 }

/* [<][>][^][v][top][bottom][index][help] */