Set Lights on XBOX360 Wireless Controllers for New Android/Google TVs Through 2023 - Fixes: #1061 (#1157)

This commit is contained in:
sivan-koren
2022-12-14 20:29:41 -07:00
committed by GitHub
parent aa41bf8d97
commit fa7eb1c4b1
2 changed files with 110 additions and 1 deletions

View File

@@ -20,6 +20,7 @@ import com.limelight.LimeLog;
import com.limelight.R;
import com.limelight.preferences.PreferenceConfiguration;
import java.io.File;
import java.util.ArrayList;
public class UsbDriverService extends Service implements UsbDriverListener {
@@ -183,6 +184,9 @@ public class UsbDriverService extends Service implements UsbDriverListener {
else if (Xbox360Controller.canClaimDevice(device)) {
controller = new Xbox360Controller(device, connection, nextDeviceId++, this);
}
else if (Xbox360WirelessController.canClaimDevice(device)) {
controller = new Xbox360WirelessController(device, connection, nextDeviceId++, this);
}
else {
// Unreachable
return;
@@ -248,9 +252,32 @@ public class UsbDriverService extends Service implements UsbDriverListener {
}
}
public static boolean kernelSupportsXbox360W() {
File systemDir = new File("/sys/class/leds");
File[] files = systemDir.listFiles();
if (files != null) {
for (File f : files) {
if (f.getName().equals("xpad0") ||
f.getName().equals("xpad1") ||
f.getName().equals("xpad2") ||
f.getName().equals("xpad3") ||
f.getName().equals("xpad4") ||
f.getName().equals("xpad5") ||
f.getName().equals("xpad6") ||
f.getName().equals("xpad7") ||
f.getName().equals("xpad8") ||
f.getName().equals("xpad9")) {
return true;
}
}
}
return false;
}
public static boolean shouldClaimDevice(UsbDevice device, boolean claimAllAvailable) {
return ((!kernelSupportsXboxOne() || !isRecognizedInputDevice(device) || claimAllAvailable) && XboxOneController.canClaimDevice(device)) ||
((!isRecognizedInputDevice(device) || claimAllAvailable) && Xbox360Controller.canClaimDevice(device));
((!isRecognizedInputDevice(device) || claimAllAvailable) && Xbox360Controller.canClaimDevice(device)) ||
((!kernelSupportsXbox360W() || !isRecognizedInputDevice(device) || claimAllAvailable) && Xbox360WirelessController.canClaimDevice(device));
}
private void start() {

View File

@@ -0,0 +1,82 @@
package com.limelight.binding.input.driver;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import com.limelight.LimeLog;
import com.limelight.nvstream.input.ControllerPacket;
import java.nio.ByteBuffer;
public class Xbox360WirelessController extends AbstractXboxController {
private static final int XB360W_IFACE_SUBCLASS = 93;
private static final int XB360W_IFACE_PROTOCOL = 129; // Wireless only
private static final int[] SUPPORTED_VENDORS = {
0x045e, // Microsoft
};
public static boolean canClaimDevice(UsbDevice device) {
for (int supportedVid : SUPPORTED_VENDORS) {
if (device.getVendorId() == supportedVid &&
device.getInterfaceCount() >= 1 &&
device.getInterface(0).getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC &&
device.getInterface(0).getInterfaceSubclass() == XB360W_IFACE_SUBCLASS &&
device.getInterface(0).getInterfaceProtocol() == XB360W_IFACE_PROTOCOL) {
return true;
}
}
return false;
}
public Xbox360WirelessController(UsbDevice device, UsbDeviceConnection connection, int deviceId, UsbDriverListener listener) {
super(device, connection, deviceId, listener);
}
@Override
protected boolean handleRead(ByteBuffer buffer) {
// Unreachable
return true;
}
private boolean sendLedCommand(byte command) {
byte[] commandBuffer = {
0x00,
0x00,
0x08,
(byte) (0x40 + command),
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00};
int res = connection.bulkTransfer(outEndpt, commandBuffer, commandBuffer.length, 3000);
if (res != commandBuffer.length) {
LimeLog.warning("LED set transfer failed: "+res);
return false;
}
return true;
}
@Override
protected boolean doInit() {
// Turn the LED on corresponding to our device ID
sendLedCommand((byte)(2 + (getControllerId() % 4)));
// Close the interface and return false to give control back to the kernel.
connection.releaseInterface(device.getInterface(0));
return false;
}
@Override
public void rumble(short lowFreqMotor, short highFreqMotor) {
// Unreachable.
}
}