From 41598aea7368e6417a310c17bcf55b77e50e4dbc Mon Sep 17 00:00:00 2001 From: Iwan Timmer Date: Tue, 28 Jan 2014 01:34:45 +0100 Subject: [PATCH] Use range from evdev device for gamepad input --- build.xml | 3 ++ jni/nv_io/build.sh | 4 ++ jni/nv_io/libnv_io.so | Bin 0 -> 6681 bytes jni/nv_io/nv_io_jni.c | 24 +++++++++ src/com/limelight/input/EvdevAbsolute.java | 55 +++++++++++++++++++++ src/com/limelight/input/EvdevHandler.java | 21 +++++--- src/com/limelight/input/IO.java | 14 ++++++ 7 files changed, 115 insertions(+), 6 deletions(-) create mode 100755 jni/nv_io/build.sh create mode 100755 jni/nv_io/libnv_io.so create mode 100644 jni/nv_io/nv_io_jni.c create mode 100644 src/com/limelight/input/EvdevAbsolute.java create mode 100644 src/com/limelight/input/IO.java diff --git a/build.xml b/build.xml index 5e02527..e9654f3 100644 --- a/build.xml +++ b/build.xml @@ -10,6 +10,7 @@ + @@ -40,6 +41,7 @@ + @@ -84,6 +86,7 @@ + diff --git a/jni/nv_io/build.sh b/jni/nv_io/build.sh new file mode 100755 index 0000000..ed03e0c --- /dev/null +++ b/jni/nv_io/build.sh @@ -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 diff --git a/jni/nv_io/libnv_io.so b/jni/nv_io/libnv_io.so new file mode 100755 index 0000000000000000000000000000000000000000..67fae4762e19c73322923765043d515a34897d60 GIT binary patch literal 6681 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 BM5O=# literal 0 HcmV?d00001 diff --git a/jni/nv_io/nv_io_jni.c b/jni/nv_io/nv_io_jni.c new file mode 100644 index 0000000..c587a37 --- /dev/null +++ b/jni/nv_io/nv_io_jni.c @@ -0,0 +1,24 @@ +#include +#include + +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; +} \ No newline at end of file diff --git a/src/com/limelight/input/EvdevAbsolute.java b/src/com/limelight/input/EvdevAbsolute.java new file mode 100644 index 0000000..be0e95d --- /dev/null +++ b/src/com/limelight/input/EvdevAbsolute.java @@ -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); + } + +} diff --git a/src/com/limelight/input/EvdevHandler.java b/src/com/limelight/input/EvdevHandler.java index 95170b4..58efa6e 100644 --- a/src/com/limelight/input/EvdevHandler.java +++ b/src/com/limelight/input/EvdevHandler.java @@ -28,6 +28,8 @@ public class EvdevHandler implements Runnable { private byte leftTrigger, rightTrigger; private short leftStickX, leftStickY, rightStickX, rightStickY; + private EvdevAbsolute absLX, absLY, absRX, absRY, absLT, absRT; + private NvConnection conn; private FileChannel deviceInput; private ByteBuffer inputBuffer; @@ -48,6 +50,13 @@ public class EvdevHandler implements Runnable { inputBuffer = ByteBuffer.allocate(EvdevConstants.MAX_STRUCT_SIZE_BYTES); 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); } @@ -140,17 +149,17 @@ public class EvdevHandler implements Runnable { conn.sendMouseMove((short) 0, (short) value); } else if (type==EvdevConstants.EV_ABS) { if (code==mapping.abs_x) - leftStickX = (short) value; + leftStickX = absLX.getShort(value); else if (code==mapping.abs_y) - leftStickY = (short) value; + leftStickY = absLY.getShort(value); else if (code==mapping.abs_rx) - rightStickX = (short) value; + rightStickX = absRX.getShort(value); else if (code==mapping.abs_ry) - rightStickY = (short) value; + rightStickY = absRY.getShort(value); else if (code==mapping.abs_throttle) - leftTrigger = (byte) value; + leftTrigger = absLT.getByte(value); else if (code==mapping.abs_rudder) - rightTrigger = (byte) value; + rightTrigger = absRT.getByte(value); conn.sendControllerInput(buttonFlags, leftTrigger, rightTrigger, leftStickX, leftStickY, rightStickX, rightStickY); } diff --git a/src/com/limelight/input/IO.java b/src/com/limelight/input/IO.java new file mode 100644 index 0000000..c919f77 --- /dev/null +++ b/src/com/limelight/input/IO.java @@ -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); + +}