Raw mouse input is working

This commit is contained in:
Cameron Gutman 2014-09-02 00:41:33 -07:00
parent 124037ce27
commit 3e017625a9
4 changed files with 136 additions and 81 deletions

View File

@ -1,7 +1,7 @@
package com.limelight.binding.input.evdev;
public class EvdevEvent {
public static final int EVDEV_MIN_EVENT_SIZE = 18;
public static final int EVDEV_MIN_EVENT_SIZE = 16;
public static final int EVDEV_MAX_EVENT_SIZE = 24;
/* Event types */

View File

@ -1,6 +1,7 @@
package com.limelight.binding.input.evdev;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import com.limelight.LimeLog;
@ -17,13 +18,6 @@ public class EvdevHandler {
// but it's important that we get this right to avoid causing
// system-wide input problems.
// Modify permissions to allow us access
if (!EvdevReader.setPermissions(absolutePath, 0666)) {
LimeLog.warning("Unable to chmod "+absolutePath);
return;
}
try {
// Open the /dev/input/eventX file
int fd = EvdevReader.open(absolutePath);
if (fd == -1) {
@ -46,9 +40,12 @@ public class EvdevHandler {
LimeLog.info("Grabbed device for raw mouse input: "+absolutePath);
ByteBuffer buffer = ByteBuffer.allocate(EvdevEvent.EVDEV_MAX_EVENT_SIZE);
ByteBuffer buffer = ByteBuffer.allocate(EvdevEvent.EVDEV_MAX_EVENT_SIZE).order(ByteOrder.nativeOrder());
try {
int deltaX = 0;
int deltaY = 0;
while (!isInterrupted() && !shutdown) {
EvdevEvent event = EvdevReader.read(fd, buffer);
if (event == null) {
@ -58,17 +55,20 @@ public class EvdevHandler {
switch (event.type)
{
case EvdevEvent.EV_SYN:
// Do nothing
if (deltaX != 0 || deltaY != 0) {
listener.mouseMove(deltaX, deltaY);
deltaX = deltaY = 0;
}
break;
case EvdevEvent.EV_REL:
switch (event.code)
{
case EvdevEvent.REL_X:
listener.mouseMove(event.value, 0);
deltaX = event.value;
break;
case EvdevEvent.REL_Y:
listener.mouseMove(0, event.value);
deltaY = event.value;
break;
}
break;
@ -99,10 +99,6 @@ public class EvdevHandler {
// Close the file
EvdevReader.close(fd);
}
} finally {
// Set permissions back
EvdevReader.setPermissions(absolutePath, 0066);
}
}
};

View File

@ -1,5 +1,7 @@
package com.limelight.binding.input.evdev;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import com.limelight.LimeLog;
@ -10,7 +12,29 @@ public class EvdevReader {
}
// Requires root to chmod /dev/input/eventX
public static native boolean setPermissions(String fileName, int octalPermissions);
public static boolean setPermissions(int octalPermissions) {
String chmodString = String.format("chmod %o /dev/input/*\n", octalPermissions);
ProcessBuilder builder = new ProcessBuilder("su");
try {
Process p = builder.start();
OutputStream stdin = p.getOutputStream();
stdin.write(chmodString.getBytes("UTF-8"));
stdin.write("exit\n".getBytes("UTF-8"));
stdin.flush();
p.waitFor();
p.destroy();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return false;
}
// Returns the fd to be passed to other function or -1 on error
public static native int open(String fileName);

View File

@ -13,7 +13,9 @@ public class EvdevWatcher {
private HashMap<String, EvdevHandler> handlers = new HashMap<String, EvdevHandler>();
private boolean shutdown = false;
private boolean init = false;
private EvdevListener listener;
private Thread startThread;
private FileObserver observer = new FileObserver(PATH, FileObserver.CREATE | FileObserver.DELETE) {
@Override
@ -34,6 +36,11 @@ public class EvdevWatcher {
if ((event & FileObserver.CREATE) != 0) {
LimeLog.info("Starting evdev handler for "+fileName);
if (!init) {
// If this a real new device, update permissions again so we can read it
EvdevReader.setPermissions(0666);
}
EvdevHandler handler = new EvdevHandler(PATH + "/" + fileName, listener);
handler.start();
@ -43,7 +50,7 @@ public class EvdevWatcher {
if ((event & FileObserver.DELETE) != 0) {
LimeLog.info("Halting evdev handler for "+fileName);
EvdevHandler handler = handlers.get(fileName);
EvdevHandler handler = handlers.remove(fileName);
if (handler != null) {
handler.notifyDeleted();
}
@ -57,8 +64,12 @@ public class EvdevWatcher {
}
public void start() {
// Start watching for new files
observer.startWatching();
startThread = new Thread() {
@Override
public void run() {
// Get permissions to read the eventX files
EvdevReader.setPermissions(0666);
init = true;
// Rundown existing files and generate synthetic events
File devInputDir = new File(PATH);
@ -66,9 +77,33 @@ public class EvdevWatcher {
for (File f : files) {
observer.onEvent(FileObserver.CREATE, f.getName());
}
// Done with initial onEvent calls
init = false;
// Start watching for new files
observer.startWatching();
synchronized (startThread) {
// Wait to be awoken again by shutdown()
try {
startThread.wait();
} catch (InterruptedException e) {}
}
// Giveup eventX permissions
EvdevReader.setPermissions(0066);
}
};
startThread.start();
}
public void shutdown() {
// Let start thread cleanup on it's own sweet time
synchronized (startThread) {
startThread.notify();
}
// Stop the observer
observer.stopWatching();