atar-axis / xpadneo

Advanced Linux Driver for Xbox One Wireless Controller (shipped with Xbox One S)
https://atar-axis.github.io/xpadneo/
GNU General Public License v3.0
1.92k stars 111 forks source link

[Question] Detect loss of bluetooth connection earlier #298

Closed nulaft closed 3 years ago

nulaft commented 3 years ago

I have a wireless controller for XBox One, connected via bluetooth. I want to use it to remove control a robot. It has happened before that the robot drives itself into a wall if the connection to the controller is lost.

If I turn the controller off by holding the XBox button, the /dev/input/js0 device is closed immediately, which is what I want. However, if the connection is lost unexpectedly, the js0 device will exist for another 20 seconds until it is closed. This can happen if the controller goes out of range or one pulls out the batteries (possibly also if the batteries deplete).

Is it possible to configure the connection lost timeout period? For my application, it should be half a second or less.

kakra commented 3 years ago

If the controller turns off, it sends some sort of "goodbye packet" to xpadneo via the battery protocol, but there's nothing we can do with it, we'll just log it to the dmesg console. Immediately after this, the controller will disconnect from Bluetooth actively, saying goodbye to the Bluetooth stack. That's actually when xpadneo becomes torn down but xpadneo absolutely has no control over it.

Your problem is that nothing of this happens in case of a connection loss, and there's also absolutely no way for xpadneo to do some sort of keep alive. Everything is handled in the Bluetooth stack. There are no packets that we could send on a regular basis to receive a reply because there are no such packets in the HID protocol to do that, neither we can expect the controller to send us HID data in a timely manner: Only as long as input changes occur, it will send HID data, and once in a while there will be a battery event.

Apparently, and unfortunately, xpadneo cannot do what you ask for. If you want to do anything with some defined latency, your best bet is probably doing a layer 2 ping to the MAC address of the controller every second or so to see if it replies. There's l2ping which can do that and could be a starting point but you will probably want to program your own supervisor process/thread that integrates with your remote control software. At this point, what you can get from the input layer (and thus xpadneo) is at least the MAC address of the controller, it will be in the "unique" property of the sysfs device tree for the parent input device.

If we would be able to do what you ask for from xpadneo, I would have already implemented it to solve the same problem for games which don't detect the disconnect until the Bluetooth stack eventually times out (after 20-30s) - until then, your virtual character may already have run over the cliff - which is actually your robot problem. ;-)

kakra commented 3 years ago

BTW: xpadneo itself doesn't know anything about Bluetooth, xpadneo is a HID driver. The kernel HID layer enumerates a device interface for us that sits on the Bluetooth bus, but everything about Bluetooth or other layer 2 specifics is abstracted away from us: xpadneo sees a HID protocol only.

IOW, xpadneo/HID relates to Bluetooth like TCP/IP relates to ethernet: It doesn't know how the packets are exchanged between the driver and the device, Bluetooth is just the transport, it could be anything else, xpadneo does not (and cannot) care about it.

xpadneo has no knowledge about whether the controller is idle, or whether it was disconnected unclean and thus sends no more packets. And we have no HID report type to ping it.

kakra commented 3 years ago

or one pulls out the batteries (possibly also if the batteries deplete).

In case of depleted battery, actually, no. In this case, the controller will send us a final battery report stating that the battery is offline. Actually, this means the device is shutting down cleanly, it's not really related to the depleted battery. It's just coincidence: Battery is critical, the device actively shuts down cleanly on its own, and such a clean shutdown will send the "battery offline" packet. The same packet is sent when you turn the controller off. We cannot do anything with it, tho: What happens next (as already outlined above) is the device disconnecting from Bluetooth, which in turn instructs the kernel to disconnect our driver from the bus. In this moment, xpadneo already has lost control over the device, and it will clean up memory allocations and exit.

no-response[bot] commented 3 years ago

This issue has been automatically closed because there has been no response to our request for more information from the original author. With only the information that is currently in the issue, we don't have enough information to take action. Please reach out if you have or find the answers we need so that we can investigate further.