src/joystick/hidapi/SDL_hidapijoystick.c
changeset 12641 64597a7e8771
parent 12503 806492103856
child 12787 0411f841b035
equal deleted inserted replaced
12640:b708d2c3fe08 12641:64597a7e8771
    48 #ifdef SDL_USE_LIBUDEV
    48 #ifdef SDL_USE_LIBUDEV
    49 #include <poll.h>
    49 #include <poll.h>
    50 #endif
    50 #endif
    51 #endif
    51 #endif
    52 
    52 
    53 struct joystick_hwdata
    53 typedef struct _SDL_HIDAPI_Device
    54 {
    54 {
    55     SDL_HIDAPI_DeviceDriver *driver;
    55     SDL_HIDAPI_DriverData devdata;
    56     void *context;
       
    57 
       
    58     SDL_mutex *mutex;
    56     SDL_mutex *mutex;
    59     hid_device *dev;
       
    60 };
       
    61 
       
    62 typedef struct _SDL_HIDAPI_Device
       
    63 {
       
    64     SDL_JoystickID instance_id;
       
    65     char *name;
    57     char *name;
    66     char *path;
    58     char *path;
    67     Uint16 vendor_id;
    59     Uint16 vendor_id;
    68     Uint16 product_id;
    60     Uint16 product_id;
    69     Uint16 version;
    61     Uint16 version;
    92 #ifdef SDL_JOYSTICK_HIDAPI_XBOX360
    84 #ifdef SDL_JOYSTICK_HIDAPI_XBOX360
    93     &SDL_HIDAPI_DriverXbox360,
    85     &SDL_HIDAPI_DriverXbox360,
    94 #endif
    86 #endif
    95 #ifdef SDL_JOYSTICK_HIDAPI_XBOXONE
    87 #ifdef SDL_JOYSTICK_HIDAPI_XBOXONE
    96     &SDL_HIDAPI_DriverXboxOne,
    88     &SDL_HIDAPI_DriverXboxOne,
       
    89 #endif
       
    90 #ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE
       
    91     &SDL_HIDAPI_DriverGameCube,
    97 #endif
    92 #endif
    98 };
    93 };
    99 static SDL_HIDAPI_Device *SDL_HIDAPI_devices;
    94 static SDL_HIDAPI_Device *SDL_HIDAPI_devices;
   100 static int SDL_HIDAPI_numjoysticks = 0;
    95 static int SDL_HIDAPI_numjoysticks = 0;
   101 
    96 
   391         usyms = NULL;
   386         usyms = NULL;
   392     }
   387     }
   393 #endif
   388 #endif
   394 }
   389 }
   395 
   390 
       
   391 static void
       
   392 HIDAPI_InitDriver(SDL_HIDAPI_Device *device)
       
   393 {
       
   394     device->devdata.device = hid_open_path(device->path, 0);
       
   395     if (!device->devdata.device) {
       
   396         SDL_SetError("Couldn't open HID device %s", device->path);
       
   397         device->driver = NULL;
       
   398     } else {
       
   399         device->driver->InitDriver(
       
   400             &device->devdata,
       
   401             device->vendor_id,
       
   402             device->product_id,
       
   403             &SDL_HIDAPI_numjoysticks
       
   404         );
       
   405         device->mutex = SDL_CreateMutex();
       
   406     }
       
   407 }
       
   408 
       
   409 static void
       
   410 HIDAPI_QuitDriver(SDL_HIDAPI_Device *device, SDL_bool send_event)
       
   411 {
       
   412     device->driver->QuitDriver(
       
   413         &device->devdata,
       
   414         send_event,
       
   415         &SDL_HIDAPI_numjoysticks
       
   416     );
       
   417     hid_close(device->devdata.device);
       
   418     SDL_DestroyMutex(device->mutex);
       
   419     device->driver = NULL;
       
   420 }
   396 
   421 
   397 const char *
   422 const char *
   398 HIDAPI_XboxControllerName(Uint16 vendor_id, Uint16 product_id)
   423 HIDAPI_XboxControllerName(Uint16 vendor_id, Uint16 product_id)
   399 {
   424 {
   400     static struct
   425     static struct
   603     }
   628     }
   604     return NULL;
   629     return NULL;
   605 }
   630 }
   606 
   631 
   607 static SDL_HIDAPI_Device *
   632 static SDL_HIDAPI_Device *
   608 HIDAPI_GetJoystickByIndex(int device_index)
   633 HIDAPI_GetDeviceByIndex(int device_index)
   609 {
   634 {
   610     SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
   635     SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
       
   636     int joysticks;
   611     while (device) {
   637     while (device) {
   612         if (device->driver) {
   638         if (device->driver) {
   613             if (device_index == 0) {
   639             joysticks = device->driver->NumJoysticks(&device->devdata);
       
   640             if (device_index < joysticks) {
   614                 break;
   641                 break;
   615             }
   642             }
   616             --device_index;
   643             device_index -= joysticks;
   617         }
   644         }
   618         device = device->next;
   645         device = device->next;
   619     }
   646     }
   620     return device;
   647     return device;
   621 }
   648 }
   658 
   685 
   659     /* Update device list if driver availability changes */
   686     /* Update device list if driver availability changes */
   660     while (device) {
   687     while (device) {
   661         if (device->driver) {
   688         if (device->driver) {
   662             if (!device->driver->enabled) {
   689             if (!device->driver->enabled) {
   663                 device->driver = NULL;
   690                 HIDAPI_QuitDriver(device, SDL_TRUE);
   664 
       
   665                 --SDL_HIDAPI_numjoysticks;
       
   666 
       
   667                 SDL_PrivateJoystickRemoved(device->instance_id);
       
   668             }
   691             }
   669         } else {
   692         } else {
   670             device->driver = HIDAPI_GetDeviceDriver(device);
   693             device->driver = HIDAPI_GetDeviceDriver(device);
   671             if (device->driver) {
   694             if (device->driver) {
   672                 device->instance_id = SDL_GetNextJoystickInstanceID();
   695                 HIDAPI_InitDriver(device);
   673 
       
   674                 ++SDL_HIDAPI_numjoysticks;
       
   675 
       
   676                 SDL_PrivateJoystickAdded(device->instance_id);
       
   677             }
   696             }
   678         }
   697         }
   679         device = device->next;
   698         device = device->next;
   680     }
   699     }
   681 }
   700 }
   721 
   740 
   722     device = (SDL_HIDAPI_Device *)SDL_calloc(1, sizeof(*device));
   741     device = (SDL_HIDAPI_Device *)SDL_calloc(1, sizeof(*device));
   723     if (!device) {
   742     if (!device) {
   724         return;
   743         return;
   725     }
   744     }
   726     device->instance_id = -1;
       
   727     device->seen = SDL_TRUE;
   745     device->seen = SDL_TRUE;
   728     device->vendor_id = info->vendor_id;
   746     device->vendor_id = info->vendor_id;
   729     device->product_id = info->product_id;
   747     device->product_id = info->product_id;
   730     device->version = info->release_number;
   748     device->version = info->release_number;
   731     device->interface_number = info->interface_number;
   749     device->interface_number = info->interface_number;
   816     } else {
   834     } else {
   817         SDL_HIDAPI_devices = device;
   835         SDL_HIDAPI_devices = device;
   818     }
   836     }
   819 
   837 
   820     if (device->driver) {
   838     if (device->driver) {
   821         /* It's a joystick! */
   839         /* It's a joystick device! */
   822         device->instance_id = SDL_GetNextJoystickInstanceID();
   840         HIDAPI_InitDriver(device);
   823 
       
   824         ++SDL_HIDAPI_numjoysticks;
       
   825 
       
   826         SDL_PrivateJoystickAdded(device->instance_id);
       
   827     }
   841     }
   828 }
   842 }
   829 
   843 
   830 
   844 
   831 static void
   845 static void
   838                 last->next = curr->next;
   852                 last->next = curr->next;
   839             } else {
   853             } else {
   840                 SDL_HIDAPI_devices = curr->next;
   854                 SDL_HIDAPI_devices = curr->next;
   841             }
   855             }
   842 
   856 
   843             if (device->driver && send_event) {
   857             if (device->driver) {
   844                 /* Need to decrement the joystick count before we post the event */
   858                 HIDAPI_QuitDriver(device, send_event);
   845                 --SDL_HIDAPI_numjoysticks;
       
   846 
       
   847                 SDL_PrivateJoystickRemoved(device->instance_id);
       
   848             }
   859             }
   849 
   860 
   850             SDL_free(device->name);
   861             SDL_free(device->name);
   851             SDL_free(device->path);
   862             SDL_free(device->path);
   852             SDL_free(device);
   863             SDL_free(device);
   929 }
   940 }
   930 
   941 
   931 static const char *
   942 static const char *
   932 HIDAPI_JoystickGetDeviceName(int device_index)
   943 HIDAPI_JoystickGetDeviceName(int device_index)
   933 {
   944 {
   934     return HIDAPI_GetJoystickByIndex(device_index)->name;
   945     return HIDAPI_GetDeviceByIndex(device_index)->name;
   935 }
   946 }
   936 
   947 
   937 static int
   948 static int
   938 HIDAPI_JoystickGetDevicePlayerIndex(int device_index)
   949 HIDAPI_JoystickGetDevicePlayerIndex(int device_index)
   939 {
   950 {
   941 }
   952 }
   942 
   953 
   943 static SDL_JoystickGUID
   954 static SDL_JoystickGUID
   944 HIDAPI_JoystickGetDeviceGUID(int device_index)
   955 HIDAPI_JoystickGetDeviceGUID(int device_index)
   945 {
   956 {
   946     return HIDAPI_GetJoystickByIndex(device_index)->guid;
   957     return HIDAPI_GetDeviceByIndex(device_index)->guid;
   947 }
   958 }
   948 
   959 
   949 static SDL_JoystickID
   960 static SDL_JoystickID
   950 HIDAPI_JoystickGetDeviceInstanceID(int device_index)
   961 HIDAPI_JoystickGetDeviceInstanceID(int device_index)
   951 {
   962 {
   952     return HIDAPI_GetJoystickByIndex(device_index)->instance_id;
   963     SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
       
   964     int joysticks;
       
   965     while (device) {
       
   966         if (device->driver) {
       
   967             joysticks = device->driver->NumJoysticks(&device->devdata);
       
   968             if (device_index < joysticks) {
       
   969                 break;
       
   970             }
       
   971             device_index -= joysticks;
       
   972         }
       
   973         device = device->next;
       
   974     }
       
   975     return device->driver->InstanceIDForIndex(&device->devdata, device_index);
   953 }
   976 }
   954 
   977 
   955 static int
   978 static int
   956 HIDAPI_JoystickOpen(SDL_Joystick * joystick, int device_index)
   979 HIDAPI_JoystickOpen(SDL_Joystick * joystick, int device_index)
   957 {
   980 {
   958     SDL_HIDAPI_Device *device = HIDAPI_GetJoystickByIndex(device_index);
   981     SDL_HIDAPI_Device *device = HIDAPI_GetDeviceByIndex(device_index);
   959     struct joystick_hwdata *hwdata;
   982 
   960 
   983     if (!device->driver->OpenJoystick(&device->devdata, joystick)) {
   961     hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(*hwdata));
       
   962     if (!hwdata) {
       
   963         return SDL_OutOfMemory();
       
   964     }
       
   965 
       
   966     hwdata->driver = device->driver;
       
   967     hwdata->dev = hid_open_path(device->path, 0);
       
   968     if (!hwdata->dev) {
       
   969         SDL_free(hwdata);
       
   970         return SDL_SetError("Couldn't open HID device %s", device->path);
       
   971     }
       
   972     hwdata->mutex = SDL_CreateMutex();
       
   973 
       
   974     if (!device->driver->Init(joystick, hwdata->dev, device->vendor_id, device->product_id, &hwdata->context)) {
       
   975         hid_close(hwdata->dev);
       
   976         SDL_free(hwdata);
       
   977         return -1;
   984         return -1;
   978     }
   985     }
   979 
   986 
   980     joystick->hwdata = hwdata;
   987     joystick->hwdata = (struct joystick_hwdata *)device;
   981     return 0;
   988     return 0;
   982 }
   989 }
   983 
   990 
   984 static int
   991 static int
   985 HIDAPI_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
   992 HIDAPI_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
   986 {
   993 {
   987     struct joystick_hwdata *hwdata = joystick->hwdata;
   994     SDL_HIDAPI_Device *device = (SDL_HIDAPI_Device *)joystick->hwdata;
   988     SDL_HIDAPI_DeviceDriver *driver = hwdata->driver;
       
   989     int result;
   995     int result;
   990 
   996 
   991     SDL_LockMutex(hwdata->mutex);
   997     SDL_LockMutex(device->mutex);
   992     result = driver->Rumble(joystick, hwdata->dev, hwdata->context, low_frequency_rumble, high_frequency_rumble, duration_ms);
   998     result = device->driver->Rumble(&device->devdata, joystick, low_frequency_rumble, high_frequency_rumble, duration_ms);
   993     SDL_UnlockMutex(hwdata->mutex);
   999     SDL_UnlockMutex(device->mutex);
   994     return result;
  1000     return result;
   995 }
  1001 }
   996 
  1002 
   997 static void
  1003 static void
   998 HIDAPI_JoystickUpdate(SDL_Joystick * joystick)
  1004 HIDAPI_JoystickUpdate(SDL_Joystick * joystick)
   999 {
  1005 {
  1000     struct joystick_hwdata *hwdata = joystick->hwdata;
  1006     /* No-op, all updates are done in SDL_HIDAPI_UpdateDevices */
  1001     SDL_HIDAPI_DeviceDriver *driver = hwdata->driver;
       
  1002     SDL_bool succeeded;
       
  1003 
       
  1004     SDL_LockMutex(hwdata->mutex);
       
  1005     succeeded = driver->Update(joystick, hwdata->dev, hwdata->context);
       
  1006     SDL_UnlockMutex(hwdata->mutex);
       
  1007     
       
  1008     if (!succeeded) {
       
  1009         SDL_HIDAPI_Device *device;
       
  1010         for (device = SDL_HIDAPI_devices; device; device = device->next) {
       
  1011             if (device->instance_id == joystick->instance_id) {
       
  1012                 HIDAPI_DelDevice(device, SDL_TRUE);
       
  1013                 break;
       
  1014             }
       
  1015         }
       
  1016     }
       
  1017 }
  1007 }
  1018 
  1008 
  1019 static void
  1009 static void
  1020 HIDAPI_JoystickClose(SDL_Joystick * joystick)
  1010 HIDAPI_JoystickClose(SDL_Joystick * joystick)
  1021 {
  1011 {
  1022     struct joystick_hwdata *hwdata = joystick->hwdata;
       
  1023     SDL_HIDAPI_DeviceDriver *driver = hwdata->driver;
       
  1024     driver->Quit(joystick, hwdata->dev, hwdata->context);
       
  1025 
       
  1026     hid_close(hwdata->dev);
       
  1027     SDL_DestroyMutex(hwdata->mutex);
       
  1028     SDL_free(hwdata);
       
  1029     joystick->hwdata = NULL;
  1012     joystick->hwdata = NULL;
  1030 }
  1013 }
  1031 
  1014 
  1032 static void
  1015 static void
  1033 HIDAPI_JoystickQuit(void)
  1016 HIDAPI_JoystickQuit(void)
  1046     SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI,
  1029     SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI,
  1047                         SDL_HIDAPIDriverHintChanged, NULL);
  1030                         SDL_HIDAPIDriverHintChanged, NULL);
  1048     SDL_HIDAPI_numjoysticks = 0;
  1031     SDL_HIDAPI_numjoysticks = 0;
  1049 
  1032 
  1050     hid_exit();
  1033     hid_exit();
       
  1034 }
       
  1035 
       
  1036 void
       
  1037 SDL_HIDAPI_UpdateDevices(void)
       
  1038 {
       
  1039     SDL_HIDAPI_Device *next, *device = SDL_HIDAPI_devices;
       
  1040     SDL_bool succeeded;
       
  1041 
       
  1042     while (device) {
       
  1043         if (device->driver) {
       
  1044             SDL_LockMutex(device->mutex);
       
  1045             succeeded = device->driver->UpdateDriver(&device->devdata, &SDL_HIDAPI_numjoysticks);
       
  1046             SDL_UnlockMutex(device->mutex);
       
  1047             if (!succeeded) {
       
  1048                 next = device->next;
       
  1049                 HIDAPI_DelDevice(device, SDL_TRUE);
       
  1050                 device = next;
       
  1051             } else {
       
  1052                 device = device->next;
       
  1053             }
       
  1054         } else {
       
  1055             device = device->next;
       
  1056         }
       
  1057     }
  1051 }
  1058 }
  1052 
  1059 
  1053 SDL_JoystickDriver SDL_HIDAPI_JoystickDriver =
  1060 SDL_JoystickDriver SDL_HIDAPI_JoystickDriver =
  1054 {
  1061 {
  1055     HIDAPI_JoystickInit,
  1062     HIDAPI_JoystickInit,