mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2026-02-16 02:20:55 +00:00
Set Lights on XBOX360 Wireless Controllers for New Android/Google TVs Through 2023 - Fixes: #1061 (#1157)
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user