godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
88.63k stars 20.1k forks source link

Gamepad support: Device 0 already taken by fingerprint reader on Android #47656

Open Eagle-Faulkner opened 3 years ago

Eagle-Faulkner commented 3 years ago

Godot version: 3.2.3

OS/device: Running Godot on Windows 10 Running game on Xiaomi Redmi 9 with Android 10 (MIUI 12 if that's relevant)

Issue description: Expected: Device 0 is nothing or bluetooth joypad that is synced Result: Device 0 is "uinput-fpc" and if a joypad is synced the joypad is device 1

Steps to reproduce: make Input.get_joy_name(0) readable while running a game on the device

minimal example.zip

Calinou commented 3 years ago

For the record, this was originally posted on Reddit. Quoting for posterity:

I've been working on a game and using gamepads on my computer for testing controls and I've noticed something that seems odd to me. On PC I have the inputs mapped to be from Device 0, which works perfectly fine there, but not at all on my Android export, however, changing to Device 1 for the Android export will get the controllers working just fine. Is that how that's supposed to be or am I missing some information?

Looking into this a bit further and I find that the device it's picking up on for device 0 is named "uinput-fpc" which seems to be my phone's fingerprint reader, so pretty sure that's an android issue, not a godot issue.

ICatRegister commented 3 years ago

The problem exists even on some devices that do not have a fingerprint sensor. I tried to fix the gamepad detection like here, but that only fixed the issue on Xiaomi devices. The only solution is to ignoring the "gamepads" with the names "uinput-fpc", "uinput-goodix", but this most likely should happen at the engine level

dannygaray60 commented 1 year ago

Godot 3.5 the same problem is reported from Redmi note 10 lite with android 11

hiulit commented 2 months ago

I did some reasearch and I came up with the following list:

Input name Company Name
uinput-fpc Fingerprint Cards AB
uinput-goodix Goodix
uinput-synaptics Synaptics
uinput-elan ElanTech
uinput-vfs Validity Sensors (acquired by Synaptics)
uinput-atrus Atrua Technologies

As @ICatRegister mentioned, I think this "blacklist" should be controlled via the engine, and disregard those names as inputs (or at least as joypad/controller inputs)

As a side note, because this issue is for Android, I found out that iOS also seems to get some kind of "ghost" controller on 0, called "Gamepad". It might be also related to the fingerprint or face ID drivers. Just wanted to let you know that.

hiulit commented 2 months ago

Someone on Twitter pointed out that those inputs might be used "to read gestures like swiping and such", so now I don't know if it might be a good idea to just disregard them, but maybe control them in some way so they are treated as "special" input or something.

Here's what I ended up doing. Basically, brute force :P

const INPUT_BLACKLIST := [
    "uinput-fpc",
    "uinput-goodix",
    "uinput-synaptics",
    "uinput-elan",
    "uinput-vfs",
    "uinput-atrus",
    "Gamepad",
]

if (
  (OS.has_feature("Android") or OS.has_feature("iOS"))
  and Input.get_joy_name(0) in INPUT_BLACKLIST
):
  return
darksylinc commented 1 week ago

I ran into this problem myself.

This is an OS bug that must be workarounded. This is the output of a POCO X4 Pro:

uinput-goodix
Device ID: 3
Vendor ID: 1638
Device ID: 2184
Sources Mask: 16778513
Virtual :false
External :false

All numbers are in decimal. "uinput-goodix" literally pretends to be a SOURCE_GAMEPAD (1025) and SOURCE_JOYSTICK (16777232). This has no proper solution since the OS is lying.

The only proper workaround is the proposed one: ignore at engine level these broken devices by name:

        if (device.name.startsWith("uinput-")) {
            // Broken OS that report fingerprint scanner and other
            // unrelated devices as both GAMEPAD and JOYSTICK.
            //
            // At the very least these are known to cause problems:
            //  uinput-fpc
            //  uinput-fortsense
            //  uinput-goodix
            Log.w("Godot", "Ignoring input device: " + device.name)
            return false;
        }
akien-mga commented 1 week ago

CC @m4gr3d