diff --git a/include/SDL3/SDL_hidapi.h b/include/SDL3/SDL_hidapi.h index 131b03723a..521599af35 100644 --- a/include/SDL3/SDL_hidapi.h +++ b/include/SDL3/SDL_hidapi.h @@ -283,6 +283,23 @@ extern SDL_DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open(unsigned short vendor_ */ extern SDL_DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open_path(const char *path); +/** + * Get the properties associated with an SDL_hid_device. + * + * The following read-only properties are provided by SDL: + * + * - `SDL_PROP_HIDAPI_LIBUSB_DEVICE_HANDLE_POINTER`: the libusb_device_handle associated with the device, if it was opened using libusb. + * + * \param dev a device handle returned from SDL_hid_open(). + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_hid_get_properties(SDL_hid_device *dev); + +#define SDL_PROP_HIDAPI_LIBUSB_DEVICE_HANDLE_POINTER "SDL.hidapi.libusb.device.handle" + /** * Write an Output report to a HID device. * diff --git a/src/hidapi/SDL_hidapi.c b/src/hidapi/SDL_hidapi.c index a68cc13066..7ec04e2039 100644 --- a/src/hidapi/SDL_hidapi.c +++ b/src/hidapi/SDL_hidapi.c @@ -960,13 +960,14 @@ struct SDL_hid_device void *device; const struct hidapi_backend *backend; SDL_hid_device_info info; + SDL_PropertiesID props; }; #if defined(HAVE_PLATFORM_BACKEND) || defined(HAVE_DRIVER_BACKEND) || defined(HAVE_LIBUSB) static SDL_hid_device *CreateHIDDeviceWrapper(void *device, const struct hidapi_backend *backend) { - SDL_hid_device *wrapper = (SDL_hid_device *)SDL_malloc(sizeof(*wrapper)); + SDL_hid_device *wrapper = (SDL_hid_device *)SDL_calloc(1, sizeof(*wrapper)); SDL_SetObjectValid(wrapper, SDL_OBJECT_TYPE_HIDAPI_DEVICE, true); wrapper->device = device; wrapper->backend = backend; @@ -1433,7 +1434,9 @@ SDL_hid_device *SDL_hid_open(unsigned short vendor_id, unsigned short product_id if (libusb_ctx) { pDevice = LIBUSB_hid_open(vendor_id, product_id, serial_number); if (pDevice != NULL) { - return CreateHIDDeviceWrapper(pDevice, &LIBUSB_Backend); + SDL_hid_device *dev = CreateHIDDeviceWrapper(pDevice, &LIBUSB_Backend); + SDL_SetPointerProperty(SDL_hid_get_properties(dev), SDL_PROP_HIDAPI_LIBUSB_DEVICE_HANDLE_POINTER, ((LIBUSB_hid_device *)pDevice)->device_handle); + return dev; } } #endif // HAVE_LIBUSB @@ -1472,7 +1475,9 @@ SDL_hid_device *SDL_hid_open_path(const char *path) if (libusb_ctx) { pDevice = LIBUSB_hid_open_path(path); if (pDevice != NULL) { - return CreateHIDDeviceWrapper(pDevice, &LIBUSB_Backend); + SDL_hid_device *dev = CreateHIDDeviceWrapper(pDevice, &LIBUSB_Backend); + SDL_SetPointerProperty(SDL_hid_get_properties(dev), SDL_PROP_HIDAPI_LIBUSB_DEVICE_HANDLE_POINTER, ((LIBUSB_hid_device *)pDevice)->device_handle); + return dev; } } #endif // HAVE_LIBUSB @@ -1482,6 +1487,16 @@ SDL_hid_device *SDL_hid_open_path(const char *path) return NULL; } +SDL_PropertiesID SDL_hid_get_properties(SDL_hid_device *device) +{ + CHECK_DEVICE_MAGIC(device, 0); + + if (!device->props) { + device->props = SDL_CreateProperties(); + } + return device->props; +} + int SDL_hid_write(SDL_hid_device *device, const unsigned char *data, size_t length) { CHECK_DEVICE_MAGIC(device, -1); @@ -1536,6 +1551,7 @@ int SDL_hid_close(SDL_hid_device *device) CHECK_DEVICE_MAGIC(device, -1); device->backend->hid_close(device->device); + SDL_DestroyProperties(device->props); DeleteHIDDeviceWrapper(device); return 0; }