src/joystick/hidapi/SDL_hidapijoystick.c
changeset 12641 64597a7e8771
parent 12503 806492103856
child 12787 0411f841b035
     1.1 --- a/src/joystick/hidapi/SDL_hidapijoystick.c	Sat Mar 16 17:47:59 2019 -0700
     1.2 +++ b/src/joystick/hidapi/SDL_hidapijoystick.c	Tue Mar 12 20:27:54 2019 -0400
     1.3 @@ -50,18 +50,10 @@
     1.4  #endif
     1.5  #endif
     1.6  
     1.7 -struct joystick_hwdata
     1.8 -{
     1.9 -    SDL_HIDAPI_DeviceDriver *driver;
    1.10 -    void *context;
    1.11 -
    1.12 -    SDL_mutex *mutex;
    1.13 -    hid_device *dev;
    1.14 -};
    1.15 -
    1.16  typedef struct _SDL_HIDAPI_Device
    1.17  {
    1.18 -    SDL_JoystickID instance_id;
    1.19 +    SDL_HIDAPI_DriverData devdata;
    1.20 +    SDL_mutex *mutex;
    1.21      char *name;
    1.22      char *path;
    1.23      Uint16 vendor_id;
    1.24 @@ -95,6 +87,9 @@
    1.25  #ifdef SDL_JOYSTICK_HIDAPI_XBOXONE
    1.26      &SDL_HIDAPI_DriverXboxOne,
    1.27  #endif
    1.28 +#ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE
    1.29 +    &SDL_HIDAPI_DriverGameCube,
    1.30 +#endif
    1.31  };
    1.32  static SDL_HIDAPI_Device *SDL_HIDAPI_devices;
    1.33  static int SDL_HIDAPI_numjoysticks = 0;
    1.34 @@ -393,6 +388,36 @@
    1.35  #endif
    1.36  }
    1.37  
    1.38 +static void
    1.39 +HIDAPI_InitDriver(SDL_HIDAPI_Device *device)
    1.40 +{
    1.41 +    device->devdata.device = hid_open_path(device->path, 0);
    1.42 +    if (!device->devdata.device) {
    1.43 +        SDL_SetError("Couldn't open HID device %s", device->path);
    1.44 +        device->driver = NULL;
    1.45 +    } else {
    1.46 +        device->driver->InitDriver(
    1.47 +            &device->devdata,
    1.48 +            device->vendor_id,
    1.49 +            device->product_id,
    1.50 +            &SDL_HIDAPI_numjoysticks
    1.51 +        );
    1.52 +        device->mutex = SDL_CreateMutex();
    1.53 +    }
    1.54 +}
    1.55 +
    1.56 +static void
    1.57 +HIDAPI_QuitDriver(SDL_HIDAPI_Device *device, SDL_bool send_event)
    1.58 +{
    1.59 +    device->driver->QuitDriver(
    1.60 +        &device->devdata,
    1.61 +        send_event,
    1.62 +        &SDL_HIDAPI_numjoysticks
    1.63 +    );
    1.64 +    hid_close(device->devdata.device);
    1.65 +    SDL_DestroyMutex(device->mutex);
    1.66 +    device->driver = NULL;
    1.67 +}
    1.68  
    1.69  const char *
    1.70  HIDAPI_XboxControllerName(Uint16 vendor_id, Uint16 product_id)
    1.71 @@ -605,15 +630,17 @@
    1.72  }
    1.73  
    1.74  static SDL_HIDAPI_Device *
    1.75 -HIDAPI_GetJoystickByIndex(int device_index)
    1.76 +HIDAPI_GetDeviceByIndex(int device_index)
    1.77  {
    1.78      SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
    1.79 +    int joysticks;
    1.80      while (device) {
    1.81          if (device->driver) {
    1.82 -            if (device_index == 0) {
    1.83 +            joysticks = device->driver->NumJoysticks(&device->devdata);
    1.84 +            if (device_index < joysticks) {
    1.85                  break;
    1.86              }
    1.87 -            --device_index;
    1.88 +            device_index -= joysticks;
    1.89          }
    1.90          device = device->next;
    1.91      }
    1.92 @@ -660,20 +687,12 @@
    1.93      while (device) {
    1.94          if (device->driver) {
    1.95              if (!device->driver->enabled) {
    1.96 -                device->driver = NULL;
    1.97 -
    1.98 -                --SDL_HIDAPI_numjoysticks;
    1.99 -
   1.100 -                SDL_PrivateJoystickRemoved(device->instance_id);
   1.101 +                HIDAPI_QuitDriver(device, SDL_TRUE);
   1.102              }
   1.103          } else {
   1.104              device->driver = HIDAPI_GetDeviceDriver(device);
   1.105              if (device->driver) {
   1.106 -                device->instance_id = SDL_GetNextJoystickInstanceID();
   1.107 -
   1.108 -                ++SDL_HIDAPI_numjoysticks;
   1.109 -
   1.110 -                SDL_PrivateJoystickAdded(device->instance_id);
   1.111 +                HIDAPI_InitDriver(device);
   1.112              }
   1.113          }
   1.114          device = device->next;
   1.115 @@ -723,7 +742,6 @@
   1.116      if (!device) {
   1.117          return;
   1.118      }
   1.119 -    device->instance_id = -1;
   1.120      device->seen = SDL_TRUE;
   1.121      device->vendor_id = info->vendor_id;
   1.122      device->product_id = info->product_id;
   1.123 @@ -818,12 +836,8 @@
   1.124      }
   1.125  
   1.126      if (device->driver) {
   1.127 -        /* It's a joystick! */
   1.128 -        device->instance_id = SDL_GetNextJoystickInstanceID();
   1.129 -
   1.130 -        ++SDL_HIDAPI_numjoysticks;
   1.131 -
   1.132 -        SDL_PrivateJoystickAdded(device->instance_id);
   1.133 +        /* It's a joystick device! */
   1.134 +        HIDAPI_InitDriver(device);
   1.135      }
   1.136  }
   1.137  
   1.138 @@ -840,11 +854,8 @@
   1.139                  SDL_HIDAPI_devices = curr->next;
   1.140              }
   1.141  
   1.142 -            if (device->driver && send_event) {
   1.143 -                /* Need to decrement the joystick count before we post the event */
   1.144 -                --SDL_HIDAPI_numjoysticks;
   1.145 -
   1.146 -                SDL_PrivateJoystickRemoved(device->instance_id);
   1.147 +            if (device->driver) {
   1.148 +                HIDAPI_QuitDriver(device, send_event);
   1.149              }
   1.150  
   1.151              SDL_free(device->name);
   1.152 @@ -931,7 +942,7 @@
   1.153  static const char *
   1.154  HIDAPI_JoystickGetDeviceName(int device_index)
   1.155  {
   1.156 -    return HIDAPI_GetJoystickByIndex(device_index)->name;
   1.157 +    return HIDAPI_GetDeviceByIndex(device_index)->name;
   1.158  }
   1.159  
   1.160  static int
   1.161 @@ -943,89 +954,61 @@
   1.162  static SDL_JoystickGUID
   1.163  HIDAPI_JoystickGetDeviceGUID(int device_index)
   1.164  {
   1.165 -    return HIDAPI_GetJoystickByIndex(device_index)->guid;
   1.166 +    return HIDAPI_GetDeviceByIndex(device_index)->guid;
   1.167  }
   1.168  
   1.169  static SDL_JoystickID
   1.170  HIDAPI_JoystickGetDeviceInstanceID(int device_index)
   1.171  {
   1.172 -    return HIDAPI_GetJoystickByIndex(device_index)->instance_id;
   1.173 +    SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
   1.174 +    int joysticks;
   1.175 +    while (device) {
   1.176 +        if (device->driver) {
   1.177 +            joysticks = device->driver->NumJoysticks(&device->devdata);
   1.178 +            if (device_index < joysticks) {
   1.179 +                break;
   1.180 +            }
   1.181 +            device_index -= joysticks;
   1.182 +        }
   1.183 +        device = device->next;
   1.184 +    }
   1.185 +    return device->driver->InstanceIDForIndex(&device->devdata, device_index);
   1.186  }
   1.187  
   1.188  static int
   1.189  HIDAPI_JoystickOpen(SDL_Joystick * joystick, int device_index)
   1.190  {
   1.191 -    SDL_HIDAPI_Device *device = HIDAPI_GetJoystickByIndex(device_index);
   1.192 -    struct joystick_hwdata *hwdata;
   1.193 +    SDL_HIDAPI_Device *device = HIDAPI_GetDeviceByIndex(device_index);
   1.194  
   1.195 -    hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(*hwdata));
   1.196 -    if (!hwdata) {
   1.197 -        return SDL_OutOfMemory();
   1.198 -    }
   1.199 -
   1.200 -    hwdata->driver = device->driver;
   1.201 -    hwdata->dev = hid_open_path(device->path, 0);
   1.202 -    if (!hwdata->dev) {
   1.203 -        SDL_free(hwdata);
   1.204 -        return SDL_SetError("Couldn't open HID device %s", device->path);
   1.205 -    }
   1.206 -    hwdata->mutex = SDL_CreateMutex();
   1.207 -
   1.208 -    if (!device->driver->Init(joystick, hwdata->dev, device->vendor_id, device->product_id, &hwdata->context)) {
   1.209 -        hid_close(hwdata->dev);
   1.210 -        SDL_free(hwdata);
   1.211 +    if (!device->driver->OpenJoystick(&device->devdata, joystick)) {
   1.212          return -1;
   1.213      }
   1.214  
   1.215 -    joystick->hwdata = hwdata;
   1.216 +    joystick->hwdata = (struct joystick_hwdata *)device;
   1.217      return 0;
   1.218  }
   1.219  
   1.220  static int
   1.221  HIDAPI_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
   1.222  {
   1.223 -    struct joystick_hwdata *hwdata = joystick->hwdata;
   1.224 -    SDL_HIDAPI_DeviceDriver *driver = hwdata->driver;
   1.225 +    SDL_HIDAPI_Device *device = (SDL_HIDAPI_Device *)joystick->hwdata;
   1.226      int result;
   1.227  
   1.228 -    SDL_LockMutex(hwdata->mutex);
   1.229 -    result = driver->Rumble(joystick, hwdata->dev, hwdata->context, low_frequency_rumble, high_frequency_rumble, duration_ms);
   1.230 -    SDL_UnlockMutex(hwdata->mutex);
   1.231 +    SDL_LockMutex(device->mutex);
   1.232 +    result = device->driver->Rumble(&device->devdata, joystick, low_frequency_rumble, high_frequency_rumble, duration_ms);
   1.233 +    SDL_UnlockMutex(device->mutex);
   1.234      return result;
   1.235  }
   1.236  
   1.237  static void
   1.238  HIDAPI_JoystickUpdate(SDL_Joystick * joystick)
   1.239  {
   1.240 -    struct joystick_hwdata *hwdata = joystick->hwdata;
   1.241 -    SDL_HIDAPI_DeviceDriver *driver = hwdata->driver;
   1.242 -    SDL_bool succeeded;
   1.243 -
   1.244 -    SDL_LockMutex(hwdata->mutex);
   1.245 -    succeeded = driver->Update(joystick, hwdata->dev, hwdata->context);
   1.246 -    SDL_UnlockMutex(hwdata->mutex);
   1.247 -    
   1.248 -    if (!succeeded) {
   1.249 -        SDL_HIDAPI_Device *device;
   1.250 -        for (device = SDL_HIDAPI_devices; device; device = device->next) {
   1.251 -            if (device->instance_id == joystick->instance_id) {
   1.252 -                HIDAPI_DelDevice(device, SDL_TRUE);
   1.253 -                break;
   1.254 -            }
   1.255 -        }
   1.256 -    }
   1.257 +    /* No-op, all updates are done in SDL_HIDAPI_UpdateDevices */
   1.258  }
   1.259  
   1.260  static void
   1.261  HIDAPI_JoystickClose(SDL_Joystick * joystick)
   1.262  {
   1.263 -    struct joystick_hwdata *hwdata = joystick->hwdata;
   1.264 -    SDL_HIDAPI_DeviceDriver *driver = hwdata->driver;
   1.265 -    driver->Quit(joystick, hwdata->dev, hwdata->context);
   1.266 -
   1.267 -    hid_close(hwdata->dev);
   1.268 -    SDL_DestroyMutex(hwdata->mutex);
   1.269 -    SDL_free(hwdata);
   1.270      joystick->hwdata = NULL;
   1.271  }
   1.272  
   1.273 @@ -1050,6 +1033,30 @@
   1.274      hid_exit();
   1.275  }
   1.276  
   1.277 +void
   1.278 +SDL_HIDAPI_UpdateDevices(void)
   1.279 +{
   1.280 +    SDL_HIDAPI_Device *next, *device = SDL_HIDAPI_devices;
   1.281 +    SDL_bool succeeded;
   1.282 +
   1.283 +    while (device) {
   1.284 +        if (device->driver) {
   1.285 +            SDL_LockMutex(device->mutex);
   1.286 +            succeeded = device->driver->UpdateDriver(&device->devdata, &SDL_HIDAPI_numjoysticks);
   1.287 +            SDL_UnlockMutex(device->mutex);
   1.288 +            if (!succeeded) {
   1.289 +                next = device->next;
   1.290 +                HIDAPI_DelDevice(device, SDL_TRUE);
   1.291 +                device = next;
   1.292 +            } else {
   1.293 +                device = device->next;
   1.294 +            }
   1.295 +        } else {
   1.296 +            device = device->next;
   1.297 +        }
   1.298 +    }
   1.299 +}
   1.300 +
   1.301  SDL_JoystickDriver SDL_HIDAPI_JoystickDriver =
   1.302  {
   1.303      HIDAPI_JoystickInit,