|
@@ -273,7 +273,7 @@ static int GuessIsSensor(int fd)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int IsJoystick(const char *path, int fd, char **name_return, Uint16 *vendor_return, Uint16 *product_return, SDL_JoystickGUID *guid)
|
|
|
+static int IsJoystick(const char *path, int *fd, char **name_return, Uint16 *vendor_return, Uint16 *product_return, SDL_JoystickGUID *guid)
|
|
|
{
|
|
|
struct input_id inpid;
|
|
|
char *name;
|
|
@@ -282,21 +282,32 @@ static int IsJoystick(const char *path, int fd, char **name_return, Uint16 *vend
|
|
|
|
|
|
SDL_zero(inpid);
|
|
|
#ifdef SDL_USE_LIBUDEV
|
|
|
- SDL_UDEV_GetProductInfo(path, &inpid.vendor, &inpid.product, &inpid.version, &class);
|
|
|
+ /* Opening input devices can generate synchronous device I/O, so avoid it if we can */
|
|
|
+ if (SDL_UDEV_GetProductInfo(path, &inpid.vendor, &inpid.product, &inpid.version, &class) &&
|
|
|
+ !(class & SDL_UDEV_DEVICE_JOYSTICK)) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
#endif
|
|
|
- if (ioctl(fd, JSIOCGNAME(sizeof(product_string)), product_string) <= 0) {
|
|
|
- /* When udev is enabled we only get joystick devices here, so there's no need to test them */
|
|
|
- if (enumeration_method != ENUMERATION_LIBUDEV &&
|
|
|
- !(class & SDL_UDEV_DEVICE_JOYSTICK) && ( class || !GuessIsJoystick(fd))) {
|
|
|
+
|
|
|
+ if (fd && *fd < 0) {
|
|
|
+ *fd = open(path, O_RDONLY | O_CLOEXEC, 0);
|
|
|
+ }
|
|
|
+ if (!fd || *fd < 0) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ioctl(*fd, JSIOCGNAME(sizeof(product_string)), product_string) <= 0) {
|
|
|
+ /* When udev enumeration or classification, we only got joysticks here, so no need to test */
|
|
|
+ if (enumeration_method != ENUMERATION_LIBUDEV && !class && !GuessIsJoystick(*fd)) {
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
/* Could have vendor and product already from udev, but should agree with evdev */
|
|
|
- if (ioctl(fd, EVIOCGID, &inpid) < 0) {
|
|
|
+ if (ioctl(*fd, EVIOCGID, &inpid) < 0) {
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- if (ioctl(fd, EVIOCGNAME(sizeof(product_string)), product_string) < 0) {
|
|
|
+ if (ioctl(*fd, EVIOCGNAME(sizeof(product_string)), product_string) < 0) {
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
@@ -315,7 +326,7 @@ static int IsJoystick(const char *path, int fd, char **name_return, Uint16 *vend
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
- FixupDeviceInfoForMapping(fd, &inpid);
|
|
|
+ FixupDeviceInfoForMapping(*fd, &inpid);
|
|
|
|
|
|
#ifdef DEBUG_JOYSTICK
|
|
|
SDL_Log("Joystick: %s, bustype = %d, vendor = 0x%.4x, product = 0x%.4x, version = %d\n", name, inpid.bustype, inpid.vendor, inpid.product, inpid.version);
|
|
@@ -333,11 +344,32 @@ static int IsJoystick(const char *path, int fd, char **name_return, Uint16 *vend
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
-static int IsSensor(const char *path, int fd)
|
|
|
+static int IsSensor(const char *path, int *fd)
|
|
|
{
|
|
|
struct input_id inpid;
|
|
|
+ int class = 0;
|
|
|
|
|
|
- if (ioctl(fd, EVIOCGID, &inpid) < 0) {
|
|
|
+ SDL_zero(inpid);
|
|
|
+#ifdef SDL_USE_LIBUDEV
|
|
|
+ /* Opening input devices can generate synchronous device I/O, so avoid it if we can */
|
|
|
+ if (SDL_UDEV_GetProductInfo(path, &inpid.vendor, &inpid.product, &inpid.version, &class) &&
|
|
|
+ !(class & SDL_UDEV_DEVICE_ACCELEROMETER)) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
+ if (fd && *fd < 0) {
|
|
|
+ *fd = open(path, O_RDONLY | O_CLOEXEC, 0);
|
|
|
+ }
|
|
|
+ if (!fd || *fd < 0) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!class && !GuessIsSensor(*fd)) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ioctl(*fd, EVIOCGID, &inpid) < 0) {
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -347,7 +379,7 @@ static int IsSensor(const char *path, int fd)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- return GuessIsSensor(fd);
|
|
|
+ return 1;
|
|
|
}
|
|
|
|
|
|
#ifdef SDL_USE_LIBUDEV
|
|
@@ -434,16 +466,11 @@ static void MaybeAddDevice(const char *path)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- fd = open(path, O_RDONLY | O_CLOEXEC, 0);
|
|
|
- if (fd < 0) {
|
|
|
- goto done;
|
|
|
- }
|
|
|
-
|
|
|
#ifdef DEBUG_INPUT_EVENTS
|
|
|
SDL_Log("Checking %s\n", path);
|
|
|
#endif
|
|
|
|
|
|
- if (IsJoystick(path, fd, &name, &vendor, &product, &guid)) {
|
|
|
+ if (IsJoystick(path, &fd, &name, &vendor, &product, &guid)) {
|
|
|
#ifdef DEBUG_INPUT_EVENTS
|
|
|
SDL_Log("found joystick: %s\n", path);
|
|
|
#endif
|
|
@@ -484,7 +511,7 @@ static void MaybeAddDevice(const char *path)
|
|
|
goto done;
|
|
|
}
|
|
|
|
|
|
- if (IsSensor(path, fd)) {
|
|
|
+ if (IsSensor(path, &fd)) {
|
|
|
#ifdef DEBUG_INPUT_EVENTS
|
|
|
SDL_Log("found sensor: %s\n", path);
|
|
|
#endif
|
|
@@ -880,11 +907,22 @@ static void LINUX_ScanSteamVirtualGamepads(void)
|
|
|
int num_virtual_gamepads = 0;
|
|
|
int virtual_gamepad_slot;
|
|
|
VirtualGamepadEntry *virtual_gamepads = NULL;
|
|
|
+ int class;
|
|
|
|
|
|
count = scandir("/dev/input", &entries, filter_entries, NULL);
|
|
|
for (i = 0; i < count; ++i) {
|
|
|
(void)SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name);
|
|
|
|
|
|
+#ifdef SDL_USE_LIBUDEV
|
|
|
+ /* Opening input devices can generate synchronous device I/O, so avoid it if we can */
|
|
|
+ class = 0;
|
|
|
+ SDL_zero(inpid);
|
|
|
+ if (SDL_UDEV_GetProductInfo(path, &inpid.vendor, &inpid.product, &inpid.version, &class) &&
|
|
|
+ (inpid.vendor != USB_VENDOR_VALVE || inpid.product != USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD)) {
|
|
|
+ free(entries[i]); /* This should NOT be SDL_free() */
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+#endif
|
|
|
fd = open(path, O_RDONLY | O_CLOEXEC, 0);
|
|
|
if (fd >= 0) {
|
|
|
if (ioctl(fd, EVIOCGID, &inpid) == 0 &&
|