Added an API to get the type of a connected joystick
authorSam Lantinga <slouken@libsdl.org>
Fri, 27 Jan 2017 05:59:58 -0800
changeset 10855fc18eb831c08
parent 10854 ca523d8f1af2
child 10856 486aa38c6a88
Added an API to get the type of a connected joystick
include/SDL_joystick.h
src/dynapi/SDL_dynapi_overrides.h
src/dynapi/SDL_dynapi_procs.h
src/joystick/SDL_joystick.c
src/joystick/SDL_sysjoystick.h
     1.1 --- a/include/SDL_joystick.h	Wed Jan 25 22:24:54 2017 -0800
     1.2 +++ b/include/SDL_joystick.h	Fri Jan 27 05:59:58 2017 -0800
     1.3 @@ -75,6 +75,19 @@
     1.4  
     1.5  typedef enum
     1.6  {
     1.7 +    SDL_JOYSTICK_TYPE_UNKNOWN,
     1.8 +    SDL_JOYSTICK_TYPE_GAMECONTROLLER,
     1.9 +    SDL_JOYSTICK_TYPE_WHEEL,
    1.10 +    SDL_JOYSTICK_TYPE_ARCADE_STICK,
    1.11 +    SDL_JOYSTICK_TYPE_FLIGHT_STICK,
    1.12 +    SDL_JOYSTICK_TYPE_DANCE_PAD,
    1.13 +    SDL_JOYSTICK_TYPE_GUITAR,
    1.14 +    SDL_JOYSTICK_TYPE_DRUM_KIT,
    1.15 +    SDL_JOYSTICK_TYPE_ARCADE_PAD,
    1.16 +} SDL_JoystickType;
    1.17 +
    1.18 +typedef enum
    1.19 +{
    1.20      SDL_JOYSTICK_POWER_UNKNOWN = -1,
    1.21      SDL_JOYSTICK_POWER_EMPTY,
    1.22      SDL_JOYSTICK_POWER_LOW,
    1.23 @@ -125,6 +138,12 @@
    1.24  extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetDeviceProductVersion(int device_index);
    1.25  
    1.26  /**
    1.27 + *  Get the type of a joystick, if available.
    1.28 + *  This can be called before any joysticks are opened.
    1.29 + */
    1.30 +extern DECLSPEC SDL_JoystickType SDLCALL SDL_JoystickGetDeviceType(int device_index);
    1.31 +
    1.32 +/**
    1.33   *  Open a joystick for use.
    1.34   *  The index passed as an argument refers to the N'th joystick on the system.
    1.35   *  This index is not the value which will identify this joystick in future
    1.36 @@ -170,6 +189,11 @@
    1.37  extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetProductVersion(SDL_Joystick * joystick);
    1.38  
    1.39  /**
    1.40 + *  Get the type of an opened joystick.
    1.41 + */
    1.42 +extern DECLSPEC SDL_JoystickType SDLCALL SDL_JoystickGetType(SDL_Joystick * joystick);
    1.43 +
    1.44 +/**
    1.45   *  Return a string representation for this guid. pszGUID must point to at least 33 bytes
    1.46   *  (32 for the string plus a NULL terminator).
    1.47   */
     2.1 --- a/src/dynapi/SDL_dynapi_overrides.h	Wed Jan 25 22:24:54 2017 -0800
     2.2 +++ b/src/dynapi/SDL_dynapi_overrides.h	Fri Jan 27 05:59:58 2017 -0800
     2.3 @@ -625,3 +625,5 @@
     2.4  #define SDL_GameControllerNumMappings SDL_GameControllerNumMappings_REAL
     2.5  #define SDL_GameControllerMappingForIndex SDL_GameControllerMappingForIndex_REAL
     2.6  #define SDL_JoystickGetAxisInitialState SDL_JoystickGetAxisInitialState_REAL
     2.7 +#define SDL_JoystickGetDeviceType SDL_JoystickGetDeviceType_REAL
     2.8 +#define SDL_JoystickGetType SDL_JoystickGetType_REAL
     3.1 --- a/src/dynapi/SDL_dynapi_procs.h	Wed Jan 25 22:24:54 2017 -0800
     3.2 +++ b/src/dynapi/SDL_dynapi_procs.h	Fri Jan 27 05:59:58 2017 -0800
     3.3 @@ -657,3 +657,5 @@
     3.4  SDL_DYNAPI_PROC(int,SDL_GameControllerNumMappings,(void),(),return)
     3.5  SDL_DYNAPI_PROC(char*,SDL_GameControllerMappingForIndex,(int a),(a),return)
     3.6  SDL_DYNAPI_PROC(SDL_bool,SDL_JoystickGetAxisInitialState,(SDL_Joystick *a, int b, Sint16 *c),(a,b,c),return)
     3.7 +SDL_DYNAPI_PROC(SDL_JoystickType,SDL_JoystickGetDeviceType,(int a),(a),return)
     3.8 +SDL_DYNAPI_PROC(SDL_JoystickType,SDL_JoystickGetType,(SDL_Joystick *a),(a),return)
     4.1 --- a/src/joystick/SDL_joystick.c	Wed Jan 25 22:24:54 2017 -0800
     4.2 +++ b/src/joystick/SDL_joystick.c	Fri Jan 27 05:59:58 2017 -0800
     4.3 @@ -32,6 +32,8 @@
     4.4  #include "../events/SDL_events_c.h"
     4.5  #endif
     4.6  
     4.7 +#define MAKE_VIDPID(VID, PID)   (((Uint32)(VID))<<16|(PID))
     4.8 +
     4.9  static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE;
    4.10  static SDL_Joystick *SDL_joysticks = NULL;
    4.11  static SDL_bool SDL_updating_joystick = SDL_FALSE;
    4.12 @@ -121,17 +123,14 @@
    4.13  static SDL_bool
    4.14  SDL_JoystickAxesCenteredAtZero(SDL_Joystick *joystick)
    4.15  {
    4.16 -    struct {
    4.17 -        Uint16 vendor;
    4.18 -        Uint16 product;
    4.19 -    } zero_centered_joysticks[] = {
    4.20 -        { 0x0e8f, 0x3013 }, /* HuiJia SNES USB adapter */
    4.21 -        { 0x05a0, 0x3232 }, /* 8Bitdo Zero Gamepad */
    4.22 +    static Uint32 zero_centered_joysticks[] = {
    4.23 +        MAKE_VIDPID(0x0e8f, 0x3013),    /* HuiJia SNES USB adapter */
    4.24 +        MAKE_VIDPID(0x05a0, 0x3232),    /* 8Bitdo Zero Gamepad */
    4.25      };
    4.26  
    4.27      int i;
    4.28 -    Uint16 vendor = SDL_JoystickGetVendor(joystick);
    4.29 -    Uint16 product = SDL_JoystickGetProduct(joystick);
    4.30 +    Uint32 id = MAKE_VIDPID(SDL_JoystickGetVendor(joystick),
    4.31 +                            SDL_JoystickGetProduct(joystick));
    4.32  
    4.33  /*printf("JOYSTICK '%s' VID/PID 0x%.4x/0x%.4x AXES: %d\n", joystick->name, vendor, product, joystick->naxes);*/
    4.34  
    4.35 @@ -141,8 +140,7 @@
    4.36      }
    4.37  
    4.38      for (i = 0; i < SDL_arraysize(zero_centered_joysticks); ++i) {
    4.39 -        if (vendor == zero_centered_joysticks[i].vendor &&
    4.40 -            product == zero_centered_joysticks[i].product) {
    4.41 +        if (id == zero_centered_joysticks[i]) {
    4.42              return SDL_TRUE;
    4.43          }
    4.44      }
    4.45 @@ -185,14 +183,13 @@
    4.46      }
    4.47  
    4.48      /* Create and initialize the joystick */
    4.49 -    joystick = (SDL_Joystick *) SDL_malloc((sizeof *joystick));
    4.50 +    joystick = (SDL_Joystick *) SDL_calloc(sizeof(*joystick), 1);
    4.51      if (joystick == NULL) {
    4.52          SDL_OutOfMemory();
    4.53          SDL_UnlockJoystickList();
    4.54          return NULL;
    4.55      }
    4.56  
    4.57 -    SDL_memset(joystick, 0, (sizeof *joystick));
    4.58      if (SDL_SYS_JoystickOpen(joystick, device_index) < 0) {
    4.59          SDL_free(joystick);
    4.60          SDL_UnlockJoystickList();
    4.61 @@ -237,6 +234,8 @@
    4.62          }
    4.63      }
    4.64  
    4.65 +    joystick->is_game_controller = SDL_IsGameController(device_index);
    4.66 +
    4.67      /* Add joystick to list */
    4.68      ++joystick->ref_count;
    4.69      /* Link the joystick in the list */
    4.70 @@ -932,7 +931,7 @@
    4.71  #endif /* SDL_EVENTS_DISABLED */
    4.72  }
    4.73  
    4.74 -static void GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version)
    4.75 +static void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version)
    4.76  {
    4.77      Uint16 *guid16 = (Uint16 *)guid.data;
    4.78  
    4.79 @@ -967,6 +966,73 @@
    4.80      }
    4.81  }
    4.82  
    4.83 +static SDL_bool SDL_IsJoystickGUIDWheel(SDL_JoystickGUID guid)
    4.84 +{
    4.85 +    static Uint32 wheel_joysticks[] = {
    4.86 +        MAKE_VIDPID(0x046d, 0xc294),    /* Logitech generic wheel */
    4.87 +        MAKE_VIDPID(0x046d, 0xc295),    /* Logitech Momo Force */
    4.88 +        MAKE_VIDPID(0x046d, 0xc298),    /* Logitech Driving Force Pro */
    4.89 +        MAKE_VIDPID(0x046d, 0xc299),    /* Logitech G25 */
    4.90 +        MAKE_VIDPID(0x046d, 0xc29a),    /* Logitech Driving Force GT */
    4.91 +        MAKE_VIDPID(0x046d, 0xc29b),    /* Logitech G27 */
    4.92 +        MAKE_VIDPID(0x046d, 0xc261),    /* Logitech G920 (initial mode) */
    4.93 +        MAKE_VIDPID(0x046d, 0xc262),    /* Logitech G920 (active mode) */
    4.94 +        MAKE_VIDPID(0x044f, 0xb65d),    /* Thrustmaster Wheel FFB */
    4.95 +        MAKE_VIDPID(0x044f, 0xb677),    /* Thrustmaster T150 */
    4.96 +        MAKE_VIDPID(0x044f, 0xb664),    /* Thrustmaster TX (initial mode) */
    4.97 +        MAKE_VIDPID(0x044f, 0xb669),    /* Thrustmaster TX (active mode) */
    4.98 +    };
    4.99 +    Uint16 vendor;
   4.100 +    Uint16 product;
   4.101 +    Uint32 id;
   4.102 +    int i;
   4.103 +
   4.104 +    SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL);
   4.105 +    id = MAKE_VIDPID(vendor, product);
   4.106 +
   4.107 +    for (i = 0; i < SDL_arraysize(wheel_joysticks); ++i) {
   4.108 +        if (id == wheel_joysticks[i]) {
   4.109 +            return SDL_TRUE;
   4.110 +        }
   4.111 +    }
   4.112 +    return SDL_FALSE;
   4.113 +}
   4.114 +
   4.115 +static SDL_JoystickType SDL_GetJoystickGUIDType(SDL_JoystickGUID guid)
   4.116 +{
   4.117 +    if (guid.data[14] == 'x') {
   4.118 +        /* XInput GUID, get the type based on the XInput device subtype */
   4.119 +        switch (guid.data[15]) {
   4.120 +        case 0x01:  /* XINPUT_DEVSUBTYPE_GAMEPAD */
   4.121 +            return SDL_JOYSTICK_TYPE_GAMECONTROLLER;
   4.122 +        case 0x02:  /* XINPUT_DEVSUBTYPE_WHEEL */
   4.123 +            return SDL_JOYSTICK_TYPE_WHEEL;
   4.124 +        case 0x03:  /* XINPUT_DEVSUBTYPE_ARCADE_STICK */
   4.125 +            return SDL_JOYSTICK_TYPE_ARCADE_STICK;
   4.126 +        case 0x04:  /* XINPUT_DEVSUBTYPE_FLIGHT_STICK */
   4.127 +            return SDL_JOYSTICK_TYPE_FLIGHT_STICK;
   4.128 +        case 0x05:  /* XINPUT_DEVSUBTYPE_DANCE_PAD */
   4.129 +            return SDL_JOYSTICK_TYPE_DANCE_PAD;
   4.130 +        case 0x06:  /* XINPUT_DEVSUBTYPE_GUITAR */
   4.131 +        case 0x07:  /* XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE */
   4.132 +        case 0x0B:  /* XINPUT_DEVSUBTYPE_GUITAR_BASS */
   4.133 +            return SDL_JOYSTICK_TYPE_GUITAR;
   4.134 +        case 0x08:  /* XINPUT_DEVSUBTYPE_DRUM_KIT */
   4.135 +            return SDL_JOYSTICK_TYPE_DRUM_KIT;
   4.136 +        case 0x13:  /* XINPUT_DEVSUBTYPE_ARCADE_PAD */
   4.137 +            return SDL_JOYSTICK_TYPE_ARCADE_PAD;
   4.138 +        default:
   4.139 +            return SDL_JOYSTICK_TYPE_UNKNOWN;
   4.140 +        }
   4.141 +    }
   4.142 +
   4.143 +    if (SDL_IsJoystickGUIDWheel(guid)) {
   4.144 +        return SDL_JOYSTICK_TYPE_WHEEL;
   4.145 +    }
   4.146 +
   4.147 +    return SDL_JOYSTICK_TYPE_UNKNOWN;
   4.148 +}
   4.149 +
   4.150  /* return the guid for this index */
   4.151  SDL_JoystickGUID SDL_JoystickGetDeviceGUID(int device_index)
   4.152  {
   4.153 @@ -984,7 +1050,7 @@
   4.154      Uint16 vendor;
   4.155      SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
   4.156  
   4.157 -    GetJoystickGUIDInfo(guid, &vendor, NULL, NULL);
   4.158 +    SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL);
   4.159      return vendor;
   4.160  }
   4.161  
   4.162 @@ -993,7 +1059,7 @@
   4.163      Uint16 product;
   4.164      SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
   4.165  
   4.166 -    GetJoystickGUIDInfo(guid, NULL, &product, NULL);
   4.167 +    SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL);
   4.168      return product;
   4.169  }
   4.170  
   4.171 @@ -1002,10 +1068,24 @@
   4.172      Uint16 version;
   4.173      SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
   4.174  
   4.175 -    GetJoystickGUIDInfo(guid, NULL, NULL, &version);
   4.176 +    SDL_GetJoystickGUIDInfo(guid, NULL, NULL, &version);
   4.177      return version;
   4.178  }
   4.179  
   4.180 +SDL_JoystickType SDL_JoystickGetDeviceType(int device_index)
   4.181 +{
   4.182 +    SDL_JoystickType type;
   4.183 +    SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
   4.184 +
   4.185 +    type = SDL_GetJoystickGUIDType(guid);
   4.186 +    if (type == SDL_JOYSTICK_TYPE_UNKNOWN) {
   4.187 +        if (SDL_IsGameController(device_index)) {
   4.188 +            type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
   4.189 +        }
   4.190 +    }
   4.191 +    return type;
   4.192 +}
   4.193 +
   4.194  /* return the guid for this opened device */
   4.195  SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick * joystick)
   4.196  {
   4.197 @@ -1022,7 +1102,7 @@
   4.198      Uint16 vendor;
   4.199      SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
   4.200  
   4.201 -    GetJoystickGUIDInfo(guid, &vendor, NULL, NULL);
   4.202 +    SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL);
   4.203      return vendor;
   4.204  }
   4.205  
   4.206 @@ -1031,7 +1111,7 @@
   4.207      Uint16 product;
   4.208      SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
   4.209  
   4.210 -    GetJoystickGUIDInfo(guid, NULL, &product, NULL);
   4.211 +    SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL);
   4.212      return product;
   4.213  }
   4.214  
   4.215 @@ -1040,10 +1120,24 @@
   4.216      Uint16 version;
   4.217      SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
   4.218  
   4.219 -    GetJoystickGUIDInfo(guid, NULL, NULL, &version);
   4.220 +    SDL_GetJoystickGUIDInfo(guid, NULL, NULL, &version);
   4.221      return version;
   4.222  }
   4.223  
   4.224 +SDL_JoystickType SDL_JoystickGetType(SDL_Joystick * joystick)
   4.225 +{
   4.226 +    SDL_JoystickType type;
   4.227 +    SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
   4.228 +
   4.229 +    type = SDL_GetJoystickGUIDType(guid);
   4.230 +    if (type == SDL_JOYSTICK_TYPE_UNKNOWN) {
   4.231 +        if (joystick && joystick->is_game_controller) {
   4.232 +            type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
   4.233 +        }
   4.234 +    }
   4.235 +    return type;
   4.236 +}
   4.237 +
   4.238  /* convert the guid to a printable string */
   4.239  void SDL_JoystickGetGUIDString(SDL_JoystickGUID guid, char *pszGUID, int cbGUID)
   4.240  {
     5.1 --- a/src/joystick/SDL_sysjoystick.h	Wed Jan 25 22:24:54 2017 -0800
     5.2 +++ b/src/joystick/SDL_sysjoystick.h	Fri Jan 27 05:59:58 2017 -0800
     5.3 @@ -62,6 +62,7 @@
     5.4  
     5.5      int ref_count;              /* Reference count for multiple opens */
     5.6  
     5.7 +    SDL_bool is_game_controller;
     5.8      SDL_bool force_recentering; /* SDL_TRUE if this device needs to have its state reset to 0 */
     5.9      SDL_JoystickPowerLevel epowerlevel; /* power level of this joystick, SDL_JOYSTICK_POWER_UNKNOWN if not supported */
    5.10      struct _SDL_Joystick *next; /* pointer to next joystick we have allocated */