diff --git a/android/src/org/rockbox/RockboxActivity.java b/android/src/org/rockbox/RockboxActivity.java
index 3be9e3e..c30e302 100644
--- a/android/src/org/rockbox/RockboxActivity.java
+++ b/android/src/org/rockbox/RockboxActivity.java
@@ -113,6 +113,11 @@ public class RockboxActivity extends Activity {
super.onDestroy();
RockboxService.fb.suspend();
}
+
+ @Override
+ public boolean onTrackballEvent(android.view.MotionEvent event) {
+ return RockboxService.fb.onTrackballEvent(event);
+ };

private void LOG(CharSequence text)
{
diff --git a/android/src/org/rockbox/RockboxFramebuffer.java b/android/src/org/rockbox/RockboxFramebuffer.java
index ca11de0..606ba55 100644
--- a/android/src/org/rockbox/RockboxFramebuffer.java
+++ b/android/src/org/rockbox/RockboxFramebuffer.java
@@ -70,9 +70,27 @@ public class RockboxFramebuffer extends View

private void LOG(CharSequence text)
{
- Log.d("RockboxBootloader", (String) text);
+ Log.d("Rockbox", (String) text);
}

+ public boolean onTrackballEvent(MotionEvent me)
+ {
+ switch (me.getAction())
+ {
+ case MotionEvent.ACTION_MOVE:
+ buttonHandler(0, (int)(2*me.getX()), (int)(2*me.getY()));
+ break;
+ case MotionEvent.ACTION_DOWN:
+ buttonHandler(1, 0, 0);
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ buttonHandler(-1, 0, 0);
+ break;
+ }
+ return true;
+ }
+
public boolean onTouchEvent(MotionEvent me)
{
LOG("onTouchEvent");
@@ -106,4 +124,5 @@ public class RockboxFramebuffer extends View
public native void set_lcd_active(int active);
public native void pixelHandler(int x, int y);
public native void touchHandler(int down);
+ public native void buttonHandler(int press, int relative_x, int relative_y);
}
diff --git a/firmware/target/hosted/android/app/button-target.h b/firmware/target/hosted/android/app/button-target.h
index 329ed65..3ecb00e 100644
--- a/firmware/target/hosted/android/app/button-target.h
+++ b/firmware/target/hosted/android/app/button-target.h
@@ -40,6 +40,7 @@ int button_read_device(int *data);
#define BUTTON_RIGHT BUTTON_MIDRIGHT
#define BUTTON_UP BUTTON_TOPMIDDLE
#define BUTTON_DOWN BUTTON_BOTTOMMIDDLE
+#define BUTTON_SELECT BUTTON_CENTER

/* Touch Screen Area Buttons */
#define BUTTON_TOPLEFT 0x00000010
diff --git a/firmware/target/hosted/android/button-android.c b/firmware/target/hosted/android/button-android.c
index 1172880..4f93d12 100644
--- a/firmware/target/hosted/android/button-android.c
+++ b/firmware/target/hosted/android/button-android.c
@@ -26,9 +26,11 @@
#include "kernel.h"
#include "system.h"
#include "touchscreen.h"
+#include "button.h"

static int last_y, last_x;
-
+static int last_button;
+static int last_button_tick;
static enum {
STATE_UNKNOWN,
STATE_UP,
@@ -64,13 +66,55 @@ Java_org_rockbox_RockboxFramebuffer_touchHandler(JNIEnv*env, jobject this,
last_state = STATE_UP;
}

+/*
+ * this notifies us in an interrupt-like fashion when a hardware button is pressed */
+JNIEXPORT void JNICALL
+Java_org_rockbox_RockboxFramebuffer_buttonHandler(JNIEnv*env, jobject this,
+ jint press, jint relative_x, jint relative_y)
+{
+ (void)env;
+ (void)this;
+ int btn = last_button&BUTTON_SELECT;
+
+ LOG("%s(): %d:%d:%d\n", __func__, press, relative_x, relative_y);
+ if (press > 0)
+ btn |= BUTTON_SELECT;
+ else if (press < 0)
+ btn &= ~BUTTON_SELECT;
+
+ if (relative_y < 0)
+ btn |= BUTTON_UP;
+ else if (relative_y > 0)
+ btn |= BUTTON_DOWN;
+
+ if (relative_x > 0)
+ btn |= BUTTON_RIGHT;
+ else if (relative_x < 0)
+ btn |= BUTTON_LEFT;
+
+ last_button = btn;
+ last_button_tick = current_tick;
+}
+
void button_init_device(void)
{
+ last_button = BUTTON_NONE;
+ last_button_tick = current_tick;
}

int button_read_device(int *data)
{
- /* get grid button/coordinates based on the current touchscreen mode */
- int btn = touchscreen_to_pixels(last_x, last_y, data);
- return (last_state == STATE_DOWN ? btn : 0);
+ int btn;
+ if (last_button == BUTTON_NONE)
+ {
+ /* get grid button/coordinates based on the current touchscreen mode */
+ btn = touchscreen_to_pixels(last_x, last_y, data);
+ return (last_state == STATE_DOWN ? btn : 0);
+ }
+ else
+ {
+ if (TIME_AFTER(current_tick, last_button_tick+5))
+ last_button &= BUTTON_SELECT;
+ return last_button;
+ }
}