diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index 955e4a57cef..6cd6d22eaa5 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -183,6 +183,7 @@ [code]raw_name[/code]: The name of the controller as it came from the OS, before getting renamed by the controller database. [code]vendor_id[/code]: The USB vendor ID of the device. [code]product_id[/code]: The USB product ID of the device. + [code]serial_number[/code]: The serial number of the device. This key won't be present if the serial number is unavailable. [code]steam_input_index[/code]: The Steam Input gamepad index, if the device is not a Steam Input device this key won't be present. On Windows, the dictionary can have an additional field: [code]xinput_index[/code]: The index of the controller in the XInput system. This key won't be present for devices not handled by XInput. diff --git a/drivers/sdl/joypad_sdl.cpp b/drivers/sdl/joypad_sdl.cpp index ee1ab101b12..4050321e7b0 100644 --- a/drivers/sdl/joypad_sdl.cpp +++ b/drivers/sdl/joypad_sdl.cpp @@ -180,6 +180,11 @@ void JoypadSDL::process_events() { joypad_info["vendor_id"] = itos(SDL_GetJoystickVendor(joy)); joypad_info["product_id"] = itos(SDL_GetJoystickProduct(joy)); + const String serial = String(SDL_GetJoystickSerial(joy)); + if (!serial.is_empty()) { + joypad_info["serial_number"] = serial; + } + const uint64_t steam_handle = SDL_GetGamepadSteamHandle(gamepad); if (steam_handle != 0) { joypad_info["steam_input_index"] = itos(steam_handle); diff --git a/thirdparty/sdl/core/linux/SDL_udev.c b/thirdparty/sdl/core/linux/SDL_udev.c index fbf2ff04440..d9e7e118491 100644 --- a/thirdparty/sdl/core/linux/SDL_udev.c +++ b/thirdparty/sdl/core/linux/SDL_udev.c @@ -277,6 +277,43 @@ bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *pr return true; } +bool SDL_UDEV_GetProductSerial(const char *device_path, const char **serial) +{ + struct stat statbuf; + char type; + struct udev_device *dev; + const char *val; + + if (!_this) { + return false; + } + + if (stat(device_path, &statbuf) < 0) { + return false; + } + + if (S_ISBLK(statbuf.st_mode)) { + type = 'b'; + } else if (S_ISCHR(statbuf.st_mode)) { + type = 'c'; + } else { + return false; + } + + dev = _this->syms.udev_device_new_from_devnum(_this->udev, type, statbuf.st_rdev); + if (!dev) { + return false; + } + + val = _this->syms.udev_device_get_property_value(dev, "ID_SERIAL_SHORT"); + if (val) { + *serial = val; + return true; + } + + return false; +} + void SDL_UDEV_UnloadLibrary(void) { if (!_this) { diff --git a/thirdparty/sdl/core/linux/SDL_udev.h b/thirdparty/sdl/core/linux/SDL_udev.h index 50bed36248e..05b79342cda 100644 --- a/thirdparty/sdl/core/linux/SDL_udev.h +++ b/thirdparty/sdl/core/linux/SDL_udev.h @@ -104,6 +104,7 @@ extern bool SDL_UDEV_LoadLibrary(void); extern void SDL_UDEV_Poll(void); extern bool SDL_UDEV_Scan(void); extern bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *product, Uint16 *version, int *class); +extern bool SDL_UDEV_GetProductSerial(const char *device_path, const char **serial); extern bool SDL_UDEV_AddCallback(SDL_UDEV_Callback cb); extern void SDL_UDEV_DelCallback(SDL_UDEV_Callback cb); extern const SDL_UDEV_Symbols *SDL_UDEV_GetUdevSyms(void); diff --git a/thirdparty/sdl/joystick/linux/SDL_sysjoystick.c b/thirdparty/sdl/joystick/linux/SDL_sysjoystick.c index 7d936d4cf51..4f86bc8a858 100644 --- a/thirdparty/sdl/joystick/linux/SDL_sysjoystick.c +++ b/thirdparty/sdl/joystick/linux/SDL_sysjoystick.c @@ -1591,6 +1591,13 @@ static bool LINUX_JoystickOpen(SDL_Joystick *joystick, int device_index) item_sensor->hwdata = joystick->hwdata; } + #ifdef SDL_USE_LIBUDEV + const char *serial = NULL; + if (SDL_UDEV_GetProductSerial(item->path, &serial)) { + joystick->serial = SDL_strdup(serial); + } + #endif + // mark joystick as fresh and ready joystick->hwdata->fresh = true; diff --git a/thirdparty/sdl/patches/0008-fix-linux-joycon-serial-num.patch b/thirdparty/sdl/patches/0008-fix-linux-joycon-serial-num.patch new file mode 100644 index 00000000000..7491f527777 --- /dev/null +++ b/thirdparty/sdl/patches/0008-fix-linux-joycon-serial-num.patch @@ -0,0 +1,78 @@ +diff --git a/thirdparty/sdl/core/linux/SDL_udev.c b/thirdparty/sdl/core/linux/SDL_udev.c +index fbf2ff0444..d9e7e11849 100644 +--- a/thirdparty/sdl/core/linux/SDL_udev.c ++++ b/thirdparty/sdl/core/linux/SDL_udev.c +@@ -277,6 +277,43 @@ bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *pr + return true; + } + ++bool SDL_UDEV_GetProductSerial(const char *device_path, const char **serial) ++{ ++ struct stat statbuf; ++ char type; ++ struct udev_device *dev; ++ const char *val; ++ ++ if (!_this) { ++ return false; ++ } ++ ++ if (stat(device_path, &statbuf) < 0) { ++ return false; ++ } ++ ++ if (S_ISBLK(statbuf.st_mode)) { ++ type = 'b'; ++ } else if (S_ISCHR(statbuf.st_mode)) { ++ type = 'c'; ++ } else { ++ return false; ++ } ++ ++ dev = _this->syms.udev_device_new_from_devnum(_this->udev, type, statbuf.st_rdev); ++ if (!dev) { ++ return false; ++ } ++ ++ val = _this->syms.udev_device_get_property_value(dev, "ID_SERIAL_SHORT"); ++ if (val) { ++ *serial = val; ++ return true; ++ } ++ ++ return false; ++} ++ + void SDL_UDEV_UnloadLibrary(void) + { + if (!_this) { +diff --git a/thirdparty/sdl/core/linux/SDL_udev.h b/thirdparty/sdl/core/linux/SDL_udev.h +index 50bed36248..05b79342cd 100644 +--- a/thirdparty/sdl/core/linux/SDL_udev.h ++++ b/thirdparty/sdl/core/linux/SDL_udev.h +@@ -104,6 +104,7 @@ extern bool SDL_UDEV_LoadLibrary(void); + extern void SDL_UDEV_Poll(void); + extern bool SDL_UDEV_Scan(void); + extern bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *product, Uint16 *version, int *class); ++extern bool SDL_UDEV_GetProductSerial(const char *device_path, const char **serial); + extern bool SDL_UDEV_AddCallback(SDL_UDEV_Callback cb); + extern void SDL_UDEV_DelCallback(SDL_UDEV_Callback cb); + extern const SDL_UDEV_Symbols *SDL_UDEV_GetUdevSyms(void); +diff --git a/thirdparty/sdl/joystick/linux/SDL_sysjoystick.c b/thirdparty/sdl/joystick/linux/SDL_sysjoystick.c +index ea73821c06..70fed1cf57 100644 +--- a/thirdparty/sdl/joystick/linux/SDL_sysjoystick.c ++++ b/thirdparty/sdl/joystick/linux/SDL_sysjoystick.c +@@ -1587,6 +1587,13 @@ static bool LINUX_JoystickOpen(SDL_Joystick *joystick, int device_index) + item_sensor->hwdata = joystick->hwdata; + } + ++ #ifdef SDL_USE_LIBUDEV ++ const char *serial = NULL; ++ if (SDL_UDEV_GetProductSerial(item->path, &serial)) { ++ joystick->serial = SDL_strdup(serial); ++ } ++ #endif ++ + // mark joystick as fresh and ready + joystick->hwdata->fresh = true; +