src/joystick/linux/SDL_sysjoystick.c
changeset 11532 4af4e3986438
parent 11201 813a8510bd0c
child 11811 5d94cb6b24d3
     1.1 --- a/src/joystick/linux/SDL_sysjoystick.c	Fri Sep 22 08:30:46 2017 -0700
     1.2 +++ b/src/joystick/linux/SDL_sysjoystick.c	Fri Sep 22 08:30:52 2017 -0700
     1.3 @@ -38,8 +38,10 @@
     1.4  #include "SDL_assert.h"
     1.5  #include "SDL_joystick.h"
     1.6  #include "SDL_endian.h"
     1.7 +#include "../../events/SDL_events_c.h"
     1.8  #include "../SDL_sysjoystick.h"
     1.9  #include "../SDL_joystick_c.h"
    1.10 +#include "../steam/SDL_steamcontroller.h"
    1.11  #include "SDL_sysjoystick_c.h"
    1.12  
    1.13  /* This isn't defined in older Linux kernel headers */
    1.14 @@ -66,6 +68,9 @@
    1.15      dev_t devnum;
    1.16      struct joystick_hwdata *hwdata;
    1.17      struct SDL_joylist_item *next;
    1.18 +
    1.19 +    /* Steam Controller support */
    1.20 +    SDL_bool m_bSteamController;
    1.21  } SDL_joylist_item;
    1.22  
    1.23  static SDL_joylist_item *SDL_joylist = NULL;
    1.24 @@ -73,6 +78,7 @@
    1.25  static int numjoysticks = 0;
    1.26  static int instance_counter = 0;
    1.27  
    1.28 +
    1.29  #define test_bit(nr, addr) \
    1.30      (((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0)
    1.31  #define NBITS(x) ((((x)-1)/(sizeof(long) * 8))+1)
    1.32 @@ -428,6 +434,77 @@
    1.33  }
    1.34  #endif
    1.35  
    1.36 +static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickGUID guid, int *device_instance)
    1.37 +{
    1.38 +    SDL_joylist_item *item;
    1.39 +
    1.40 +    item = (SDL_joylist_item *) SDL_calloc(1, sizeof (SDL_joylist_item));
    1.41 +    if (item == NULL) {
    1.42 +        return SDL_FALSE;
    1.43 +    }
    1.44 +
    1.45 +    item->path = SDL_strdup("");
    1.46 +    item->name = SDL_strdup(name);
    1.47 +    item->guid = guid;
    1.48 +    item->m_bSteamController = SDL_TRUE;
    1.49 +
    1.50 +    if ((item->path == NULL) || (item->name == NULL)) {
    1.51 +         SDL_free(item->path);
    1.52 +         SDL_free(item->name);
    1.53 +         SDL_free(item);
    1.54 +         return SDL_FALSE;
    1.55 +    }
    1.56 +
    1.57 +    *device_instance = item->device_instance = instance_counter++;
    1.58 +    if (SDL_joylist_tail == NULL) {
    1.59 +        SDL_joylist = SDL_joylist_tail = item;
    1.60 +    } else {
    1.61 +        SDL_joylist_tail->next = item;
    1.62 +        SDL_joylist_tail = item;
    1.63 +    }
    1.64 +
    1.65 +    /* Need to increment the joystick count before we post the event */
    1.66 +    ++numjoysticks;
    1.67 +
    1.68 +    SDL_PrivateJoystickAdded(numjoysticks - 1);
    1.69 +
    1.70 +    return SDL_TRUE;
    1.71 +}
    1.72 +
    1.73 +static void SteamControllerDisconnectedCallback(int device_instance)
    1.74 +{
    1.75 +    SDL_joylist_item *item;
    1.76 +    SDL_joylist_item *prev = NULL;
    1.77 +
    1.78 +    for (item = SDL_joylist; item != NULL; item = item->next) {
    1.79 +        /* found it, remove it. */
    1.80 +        if (item->device_instance == device_instance) {
    1.81 +            if (item->hwdata) {
    1.82 +                item->hwdata->item = NULL;
    1.83 +            }
    1.84 +            if (prev != NULL) {
    1.85 +                prev->next = item->next;
    1.86 +            } else {
    1.87 +                SDL_assert(SDL_joylist == item);
    1.88 +                SDL_joylist = item->next;
    1.89 +            }
    1.90 +            if (item == SDL_joylist_tail) {
    1.91 +                SDL_joylist_tail = prev;
    1.92 +            }
    1.93 +
    1.94 +            /* Need to decrement the joystick count before we post the event */
    1.95 +            --numjoysticks;
    1.96 +
    1.97 +            SDL_PrivateJoystickRemoved(item->device_instance);
    1.98 +
    1.99 +            SDL_free(item->name);
   1.100 +            SDL_free(item);
   1.101 +            return;
   1.102 +        }
   1.103 +        prev = item;
   1.104 +    }
   1.105 +}
   1.106 +
   1.107  int
   1.108  SDL_SYS_JoystickInit(void)
   1.109  {
   1.110 @@ -447,6 +524,9 @@
   1.111          SDL_free(envcopy);
   1.112      }
   1.113  
   1.114 +    SDL_InitSteamControllers(SteamControllerConnectedCallback,
   1.115 +                             SteamControllerDisconnectedCallback);
   1.116 +
   1.117  #if SDL_USE_LIBUDEV
   1.118      return JoystickInitWithUdev();
   1.119  #else 
   1.120 @@ -466,7 +546,8 @@
   1.121  #if SDL_USE_LIBUDEV
   1.122      SDL_UDEV_Poll();
   1.123  #endif
   1.124 -    
   1.125 +
   1.126 +    SDL_UpdateSteamControllers();
   1.127  }
   1.128  
   1.129  static SDL_joylist_item *
   1.130 @@ -650,47 +731,53 @@
   1.131  SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
   1.132  {
   1.133      SDL_joylist_item *item = JoystickByDevIndex(device_index);
   1.134 -    char *fname = NULL;
   1.135 -    int fd = -1;
   1.136  
   1.137      if (item == NULL) {
   1.138          return SDL_SetError("No such device");
   1.139      }
   1.140  
   1.141 -    fname = item->path;
   1.142 -    fd = open(fname, O_RDONLY, 0);
   1.143 -    if (fd < 0) {
   1.144 -        return SDL_SetError("Unable to open %s", fname);
   1.145 -    }
   1.146 -
   1.147      joystick->instance_id = item->device_instance;
   1.148      joystick->hwdata = (struct joystick_hwdata *)
   1.149 -        SDL_malloc(sizeof(*joystick->hwdata));
   1.150 +        SDL_calloc(1, sizeof(*joystick->hwdata));
   1.151      if (joystick->hwdata == NULL) {
   1.152 -        close(fd);
   1.153          return SDL_OutOfMemory();
   1.154      }
   1.155 -    SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
   1.156      joystick->hwdata->item = item;
   1.157      joystick->hwdata->guid = item->guid;
   1.158 -    joystick->hwdata->fd = fd;
   1.159 -    joystick->hwdata->fname = SDL_strdup(item->path);
   1.160 -    if (joystick->hwdata->fname == NULL) {
   1.161 -        SDL_free(joystick->hwdata);
   1.162 -        joystick->hwdata = NULL;
   1.163 -        close(fd);
   1.164 -        return SDL_OutOfMemory();
   1.165 +    joystick->hwdata->m_bSteamController = item->m_bSteamController;
   1.166 +
   1.167 +    if (item->m_bSteamController) {
   1.168 +        joystick->hwdata->fd = -1;
   1.169 +        SDL_GetSteamControllerInputs(&joystick->nbuttons,
   1.170 +                                     &joystick->naxes,
   1.171 +                                     &joystick->nhats);
   1.172 +    } else {
   1.173 +        int fd = open(item->path, O_RDONLY, 0);
   1.174 +        if (fd < 0) {
   1.175 +            SDL_free(joystick->hwdata);
   1.176 +            joystick->hwdata = NULL;
   1.177 +            return SDL_SetError("Unable to open %s", item->path);
   1.178 +        }
   1.179 +
   1.180 +        joystick->hwdata->fd = fd;
   1.181 +        joystick->hwdata->fname = SDL_strdup(item->path);
   1.182 +        if (joystick->hwdata->fname == NULL) {
   1.183 +            SDL_free(joystick->hwdata);
   1.184 +            joystick->hwdata = NULL;
   1.185 +            close(fd);
   1.186 +            return SDL_OutOfMemory();
   1.187 +        }
   1.188 +
   1.189 +        /* Set the joystick to non-blocking read mode */
   1.190 +        fcntl(fd, F_SETFL, O_NONBLOCK);
   1.191 +
   1.192 +        /* Get the number of buttons and axes on the joystick */
   1.193 +        ConfigJoystick(joystick, fd);
   1.194      }
   1.195  
   1.196      SDL_assert(item->hwdata == NULL);
   1.197      item->hwdata = joystick->hwdata;
   1.198  
   1.199 -    /* Set the joystick to non-blocking read mode */
   1.200 -    fcntl(fd, F_SETFL, O_NONBLOCK);
   1.201 -
   1.202 -    /* Get the number of buttons and axes on the joystick */
   1.203 -    ConfigJoystick(joystick, fd);
   1.204 -
   1.205      /* mark joystick as fresh and ready */
   1.206      joystick->hwdata->fresh = 1;
   1.207  
   1.208 @@ -881,6 +968,11 @@
   1.209  {
   1.210      int i;
   1.211  
   1.212 +    if (joystick->hwdata->m_bSteamController) {
   1.213 +        SDL_UpdateSteamController(joystick);
   1.214 +        return;
   1.215 +    }
   1.216 +
   1.217      HandleInputEvents(joystick);
   1.218  
   1.219      /* Deliver ball motion updates */
   1.220 @@ -902,7 +994,9 @@
   1.221  SDL_SYS_JoystickClose(SDL_Joystick * joystick)
   1.222  {
   1.223      if (joystick->hwdata) {
   1.224 -        close(joystick->hwdata->fd);
   1.225 +        if (joystick->hwdata->fd >= 0) {
   1.226 +            close(joystick->hwdata->fd);
   1.227 +        }
   1.228          if (joystick->hwdata->item) {
   1.229              joystick->hwdata->item->hwdata = NULL;
   1.230          }
   1.231 @@ -936,6 +1030,8 @@
   1.232      SDL_UDEV_DelCallback(joystick_udev_callback);
   1.233      SDL_UDEV_Quit();
   1.234  #endif
   1.235 +
   1.236 +    SDL_QuitSteamControllers();
   1.237  }
   1.238  
   1.239  SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )