mirror of
https://github.com/moonlight-stream/moonlight-embedded.git
synced 2026-04-24 00:56:42 +00:00
Use range from evdev device for gamepad input
This commit is contained in:
@@ -10,6 +10,7 @@
|
|||||||
<property name="libs.opus.dir" location="${basedir}/jni/nv_opus_dec/"/>
|
<property name="libs.opus.dir" location="${basedir}/jni/nv_opus_dec/"/>
|
||||||
<property name="libs.omx.dir" location="${basedir}/jni/nv_omx_dec/"/>
|
<property name="libs.omx.dir" location="${basedir}/jni/nv_omx_dec/"/>
|
||||||
<property name="libs.alsa.dir" location="${basedir}/jni/nv_alsa/"/>
|
<property name="libs.alsa.dir" location="${basedir}/jni/nv_alsa/"/>
|
||||||
|
<property name="libs.io.dir" location="${basedir}/jni/nv_io/"/>
|
||||||
|
|
||||||
<property name="lib.dir" location="${basedir}/lib"/>
|
<property name="lib.dir" location="${basedir}/lib"/>
|
||||||
<property name="build.dir" location="${basedir}/build"/>
|
<property name="build.dir" location="${basedir}/build"/>
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
<exec executable="./build.sh" dir="${libs.omx.dir}"/>
|
<exec executable="./build.sh" dir="${libs.omx.dir}"/>
|
||||||
<exec executable="./build.sh" dir="${libs.opus.dir}"/>
|
<exec executable="./build.sh" dir="${libs.opus.dir}"/>
|
||||||
<exec executable="./build.sh" dir="${libs.alsa.dir}"/>
|
<exec executable="./build.sh" dir="${libs.alsa.dir}"/>
|
||||||
|
<exec executable="./build.sh" dir="${libs.io.dir}"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="compile-java" depends="init">
|
<target name="compile-java" depends="init">
|
||||||
@@ -84,6 +86,7 @@
|
|||||||
<fileset dir="${libs.opus.dir}" includes="*.so"/>
|
<fileset dir="${libs.opus.dir}" includes="*.so"/>
|
||||||
<fileset dir="${libs.omx.dir}" includes="*.so"/>
|
<fileset dir="${libs.omx.dir}" includes="*.so"/>
|
||||||
<fileset dir="${libs.alsa.dir}" includes="*.so"/>
|
<fileset dir="${libs.alsa.dir}" includes="*.so"/>
|
||||||
|
<fileset dir="${libs.io.dir}" includes="*.so"/>
|
||||||
</binlib>
|
</binlib>
|
||||||
</one-jar>
|
</one-jar>
|
||||||
</target>
|
</target>
|
||||||
|
|||||||
4
jni/nv_io/build.sh
Executable file
4
jni/nv_io/build.sh
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
rm *.o libnv_io.so
|
||||||
|
gcc -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -fPIC -L. -c *.c
|
||||||
|
gcc -shared -Wl,-soname,libnv_io.so -Wl,--no-undefined -o libnv_io.so *.o -L.
|
||||||
|
rm *.o
|
||||||
24
jni/nv_io/nv_io_jni.c
Normal file
24
jni/nv_io/nv_io_jni.c
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#include <fcntl.h>
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
Java_com_limelight_input_IO_ioctl(
|
||||||
|
JNIEnv *env, jobject this, // JNI parameters
|
||||||
|
jstring filename, jbyteArray buffer, jint request)
|
||||||
|
{
|
||||||
|
const char* jni_filename = (*env)->GetStringUTFChars(env, filename, NULL);
|
||||||
|
unsigned char* jni_buffer = (*env)->GetByteArrayElements(env, buffer, NULL);
|
||||||
|
|
||||||
|
jboolean retval;
|
||||||
|
int fd;
|
||||||
|
if ((fd = open(jni_filename, O_RDONLY)) < 0) {
|
||||||
|
retval = 0;
|
||||||
|
} else {
|
||||||
|
ioctl(fd, request, jni_buffer);
|
||||||
|
close(fd);
|
||||||
|
retval = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*env)->ReleaseByteArrayElements(env, buffer, jni_buffer, 0);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
55
src/com/limelight/input/EvdevAbsolute.java
Normal file
55
src/com/limelight/input/EvdevAbsolute.java
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package com.limelight.input;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that handles absolute input ranges from evdev device
|
||||||
|
* @author Iwan Timmer
|
||||||
|
*/
|
||||||
|
public class EvdevAbsolute {
|
||||||
|
|
||||||
|
private final static int ABS_OFFSET = 0x40;
|
||||||
|
private final static int READ_ONLY = 2;
|
||||||
|
private final static char EVDEV_TYPE = 'E';
|
||||||
|
|
||||||
|
private int avg;
|
||||||
|
private int range;
|
||||||
|
|
||||||
|
public EvdevAbsolute(String filename, int axis) {
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(6*4);
|
||||||
|
buffer.order(ByteOrder.nativeOrder());
|
||||||
|
byte[] data = buffer.array();
|
||||||
|
int request = getRequest(READ_ONLY, EVDEV_TYPE, ABS_OFFSET+axis, 6*4);
|
||||||
|
IO.ioctl(filename, data, request);
|
||||||
|
|
||||||
|
buffer.getInt(); //Skip current value
|
||||||
|
int min = buffer.getInt();
|
||||||
|
int max = buffer.getInt();
|
||||||
|
avg = (min+max)/2;
|
||||||
|
range = max-avg;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getRequest(int dir, int type, int nr, int size) {
|
||||||
|
return (dir << 30) | (size << 16) | (type << 8) | nr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert input value to short range
|
||||||
|
* @param value received input
|
||||||
|
* @return input value as short
|
||||||
|
*/
|
||||||
|
public short getShort(int value) {
|
||||||
|
return (short) ((value-avg) * range / Short.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert input value to byte range
|
||||||
|
* @param value received input
|
||||||
|
* @return input value as byte
|
||||||
|
*/
|
||||||
|
public byte getByte(int value) {
|
||||||
|
return (byte) ((value-avg) * range / Byte.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -28,6 +28,8 @@ public class EvdevHandler implements Runnable {
|
|||||||
private byte leftTrigger, rightTrigger;
|
private byte leftTrigger, rightTrigger;
|
||||||
private short leftStickX, leftStickY, rightStickX, rightStickY;
|
private short leftStickX, leftStickY, rightStickX, rightStickY;
|
||||||
|
|
||||||
|
private EvdevAbsolute absLX, absLY, absRX, absRY, absLT, absRT;
|
||||||
|
|
||||||
private NvConnection conn;
|
private NvConnection conn;
|
||||||
private FileChannel deviceInput;
|
private FileChannel deviceInput;
|
||||||
private ByteBuffer inputBuffer;
|
private ByteBuffer inputBuffer;
|
||||||
@@ -48,6 +50,13 @@ public class EvdevHandler implements Runnable {
|
|||||||
inputBuffer = ByteBuffer.allocate(EvdevConstants.MAX_STRUCT_SIZE_BYTES);
|
inputBuffer = ByteBuffer.allocate(EvdevConstants.MAX_STRUCT_SIZE_BYTES);
|
||||||
inputBuffer.order(ByteOrder.nativeOrder());
|
inputBuffer.order(ByteOrder.nativeOrder());
|
||||||
|
|
||||||
|
absLX = new EvdevAbsolute(device, mapping.abs_x);
|
||||||
|
absLY = new EvdevAbsolute(device, mapping.abs_y);
|
||||||
|
absRX = new EvdevAbsolute(device, mapping.abs_rx);
|
||||||
|
absRY = new EvdevAbsolute(device, mapping.abs_ry);
|
||||||
|
absLT = new EvdevAbsolute(device, mapping.abs_rudder);
|
||||||
|
absRT = new EvdevAbsolute(device, mapping.abs_throttle);
|
||||||
|
|
||||||
translator = new KeyboardTranslator(conn);
|
translator = new KeyboardTranslator(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,17 +149,17 @@ public class EvdevHandler implements Runnable {
|
|||||||
conn.sendMouseMove((short) 0, (short) value);
|
conn.sendMouseMove((short) 0, (short) value);
|
||||||
} else if (type==EvdevConstants.EV_ABS) {
|
} else if (type==EvdevConstants.EV_ABS) {
|
||||||
if (code==mapping.abs_x)
|
if (code==mapping.abs_x)
|
||||||
leftStickX = (short) value;
|
leftStickX = absLX.getShort(value);
|
||||||
else if (code==mapping.abs_y)
|
else if (code==mapping.abs_y)
|
||||||
leftStickY = (short) value;
|
leftStickY = absLY.getShort(value);
|
||||||
else if (code==mapping.abs_rx)
|
else if (code==mapping.abs_rx)
|
||||||
rightStickX = (short) value;
|
rightStickX = absRX.getShort(value);
|
||||||
else if (code==mapping.abs_ry)
|
else if (code==mapping.abs_ry)
|
||||||
rightStickY = (short) value;
|
rightStickY = absRY.getShort(value);
|
||||||
else if (code==mapping.abs_throttle)
|
else if (code==mapping.abs_throttle)
|
||||||
leftTrigger = (byte) value;
|
leftTrigger = absLT.getByte(value);
|
||||||
else if (code==mapping.abs_rudder)
|
else if (code==mapping.abs_rudder)
|
||||||
rightTrigger = (byte) value;
|
rightTrigger = absRT.getByte(value);
|
||||||
|
|
||||||
conn.sendControllerInput(buttonFlags, leftTrigger, rightTrigger, leftStickX, leftStickY, rightStickX, rightStickY);
|
conn.sendControllerInput(buttonFlags, leftTrigger, rightTrigger, leftStickX, leftStickY, rightStickX, rightStickY);
|
||||||
}
|
}
|
||||||
|
|||||||
14
src/com/limelight/input/IO.java
Normal file
14
src/com/limelight/input/IO.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package com.limelight.input;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IO bindings
|
||||||
|
* @author Iwan Timmer
|
||||||
|
*/
|
||||||
|
public class IO {
|
||||||
|
static {
|
||||||
|
System.loadLibrary("nv_io");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static native boolean ioctl(String filename, byte[] buffer, int request);
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user