Skip to content

Commit

Permalink
feat: Add support of Xbox Wireless Adapter
Browse files Browse the repository at this point in the history
Driver codes mainly from https://github.com/medusalix/xow

Signed-off-by: Hakusai Zhang <[email protected]>
  • Loading branch information
summershrimp committed Sep 8, 2024
1 parent f10085f commit 7960423
Show file tree
Hide file tree
Showing 25 changed files with 9,269 additions and 2 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "app/src/main/jni/moonlight-core/moonlight-common-c"]
path = app/src/main/jni/moonlight-core/moonlight-common-c
url = https://github.com/moonlight-stream/moonlight-common-c.git
[submodule "app/src/main/jni/libusb"]
path = app/src/main/jni/libusb
url = https://github.com/libusb/libusb.git
1 change: 1 addition & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

# Our code
-keep class com.limelight.binding.input.evdev.* {*;}
-keep class com.limelight.binding.input.driver.* {*;}

# Moonlight common
-keep class com.limelight.nvstream.jni.* {*;}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public class UsbDriverService extends Service implements UsbDriverListener {
private UsbDriverStateListener stateListener;
private int nextDeviceId;

private final ArrayList<XboxWirelessDongle> xboxWirelessDongles = new ArrayList<>();

@Override
public void reportControllerState(int controllerId, int buttonFlags, float leftStickX, float leftStickY,
float rightStickX, float rightStickY, float leftTrigger, float rightTrigger) {
Expand Down Expand Up @@ -182,6 +184,15 @@ private void handleUsbDeviceState(UsbDevice device) {
return;
}

if (XboxWirelessDongle.canClaimDevice(device)) {
var dongle = new XboxWirelessDongle(device, connection, this);
if(!dongle.start()) {
connection.close();
return;
}
xboxWirelessDongles.add(dongle);
return;
}

AbstractController controller;

Expand Down Expand Up @@ -278,7 +289,8 @@ public static boolean shouldClaimDevice(UsbDevice device, boolean claimAllAvaila
return ((!kernelSupportsXboxOne() || !isRecognizedInputDevice(device) || claimAllAvailable) && XboxOneController.canClaimDevice(device)) ||
((!isRecognizedInputDevice(device) || claimAllAvailable) && Xbox360Controller.canClaimDevice(device)) ||
// We must not call isRecognizedInputDevice() because wireless controllers don't share the same product ID as the dongle
((!kernelSupportsXbox360W() || claimAllAvailable) && Xbox360WirelessDongle.canClaimDevice(device));
((!kernelSupportsXbox360W() || claimAllAvailable) && Xbox360WirelessDongle.canClaimDevice(device) ||
XboxWirelessDongle.canClaimDevice(device));
}

@SuppressLint("UnspecifiedRegisterReceiverFlag")
Expand Down Expand Up @@ -319,6 +331,12 @@ private void stop() {
// Stop the attachment receiver
unregisterReceiver(receiver);

// Stop all dongles
while (xboxWirelessDongles.size() > 0) {
// Stop and remove the dongle
xboxWirelessDongles.remove(0).stop();
}

// Stop all controllers
while (controllers.size() > 0) {
// Stop and remove the controller
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.limelight.binding.input.driver;

public class XboxWirelessController extends AbstractController{
static {
System.loadLibrary("xow-driver");
}

private final long handle;

public XboxWirelessController(int deviceId, UsbDriverListener listener, int vendorId, int productId, long handle) {
super(deviceId, listener, vendorId, productId);
this.handle = handle;
registerNative(this.handle);
}

@Override
public boolean start() {
// do nothing since mt driver will handle it.
return true;
}

@Override
public void stop() {
// do nothing since mt driver will handle it.
}

@Override
public void rumble(short lowFreqMotor, short highFreqMotor) {
sendRumble(handle, lowFreqMotor, highFreqMotor);
}

@Override
public void rumbleTriggers(short leftTrigger, short rightTrigger) {
sendrumbleTriggers(handle, leftTrigger, rightTrigger);
}

public void updateInput(int buttons,short triggerLeft, short triggerRight,
short stickLeftX, short stickLeftY,
short stickRightX, short stickRightY) {
buttonFlags = buttons;
leftTrigger = triggerLeft / 1023.0f;
rightTrigger = triggerRight / 1023.0f;
leftStickX = stickLeftX / 32767.0f;
leftStickY = stickLeftY / -32767.0f;
rightStickX = stickRightX / 32767.0f;
rightStickY = stickRightY / -32767.0f;

reportInput();
}

native void registerNative(long handle);
native void sendRumble(long handle, short lowFreqMotor, short highFreqMotor);
native void sendrumbleTriggers(long handle, short leftTrigger, short rightTrigger);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package com.limelight.binding.input.driver;

import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.util.Pair;

import com.limelight.LimeLog;
import com.limelight.binding.input.driver.UsbDriverListener;

import java.util.HashMap;
import java.util.Map;

public class XboxWirelessDongle {
private UsbDriverListener listener;
protected final UsbDevice device;
protected final UsbDeviceConnection connection;

private long driverHandle;

private Map<Integer, AbstractController> controllers = new HashMap<>();

static {
System.loadLibrary("xow-driver");
}

public XboxWirelessDongle(UsbDevice device, UsbDeviceConnection connection, UsbDriverListener listener) {
this.device = device;
this.connection = connection;
this.listener = listener;
this.driverHandle = -1;
}

public boolean start() {
if(this.driverHandle != -1) {
return false; //we already started;
}
this.driverHandle = createDriver(connection.getFileDescriptor());
boolean ok = startDriver(this.driverHandle, "");
if(!ok) {
LimeLog.info("xbox wireless dongle driver failed to start");
destroyDriver(this.driverHandle);
this.driverHandle = -1;
return false;
}
return true;
}

public void stop() {
if(this.driverHandle == -1) {
return; //we already cleaned;
}
stopDriver(this.driverHandle);
destroyDriver(this.driverHandle);
for(var i: controllers.keySet()) {
this.listener.deviceRemoved(controllers.remove(i));
}
}

public static boolean canClaimDevice(UsbDevice device) {
if (device.getVendorId() != 0x045e) {
return false;
}
if (device.getProductId() != 0x02e6 && // Older one
device.getProductId() != 0x02fe // new one
) {
return false;
}

return true;
}

public void addNewController(int id, long handle, short vid, short pid){
var controller = new XboxWirelessController(id + 0x045e0000, listener, vid, pid, handle);
controllers.put(id, controller);
this.listener.deviceAdded(controller);
}

public void removeController(int id) {
var controller = controllers.get(id);
if(controller == null) {
return;
}
controllers.remove(id);
this.listener.deviceRemoved(controller);
}

private native long createDriver(int fd);
private native boolean startDriver(long handle, String fwPath);
private native void stopDriver(long handle);
private native void destroyDriver(long handle);
}
6 changes: 5 additions & 1 deletion app/src/main/jni/Android.mk
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
include $(call all-subdir-makefiles)
LOCAL_PATH := $(call my-dir)
SUB_PROJECTS := $(call all-subdir-makefiles)

include $(LOCAL_PATH)/libusb/android/jni/libusb.mk
include $(SUB_PROJECTS)
2 changes: 2 additions & 0 deletions app/src/main/jni/Application.mk
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ APP_PLATFORM := android-21

# We support 16KB pages
APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true

APP_STL := c++_shared
1 change: 1 addition & 0 deletions app/src/main/jni/libusb
Submodule libusb added at 467b6a
24 changes: 24 additions & 0 deletions app/src/main/jni/xow_driver/Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Android.mk for xbox wireless driver
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := xow-driver
LOCAL_SRC_FILES := \
xow_driver_jni.cpp \
dongle/firmware.cpp \
dongle/usb.cpp \
dongle/mt76.cpp \
dongle/dongle.cpp \
utils/log.cpp \
controller/controller.cpp \
controller/gip.cpp

LOCAL_C_INCLUDES := $(LOCAL_PATH) $(LIBUSB_ROOT_ABS)
LOCAL_SHARED_LIBRARIES += libusb1.0
LOCAL_LDLIBS := -llog

ifeq ($(NDK_DEBUG),1)
LOCAL_CFLAGS += -D_DEBUG
endif
include $(BUILD_SHARED_LIBRARY)


Loading

0 comments on commit 7960423

Please sign in to comment.