1
0
Fork 0
forked from len0rd/rockbox

Android port: add support for hardware keys

* Forward Java KeyEvents to C layer and translate them to Rockbox BUTTON_*.
 * Add a basic Android keymap

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27832 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Maurus Cuelenaere 2010-08-16 20:12:06 +00:00
parent e726e53da6
commit 934a5a5808
11 changed files with 413 additions and 34 deletions

View file

@ -22,23 +22,28 @@
package org.rockbox;
import java.nio.ByteBuffer;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
public class RockboxFramebuffer extends View
public class RockboxFramebuffer extends View
{
private Bitmap btm;
private ByteBuffer native_buf;
public RockboxFramebuffer(Context c)
{
super(c);
btm = null;
/* Needed so we can catch KeyEvents */
setFocusable(true);
requestFocus();
}
public void onDraw(Canvas c)
@ -55,7 +60,6 @@ public class RockboxFramebuffer extends View
public void java_lcd_update()
{
btm.copyPixelsFromBuffer(native_buf);
postInvalidate();
}
@ -64,6 +68,7 @@ public class RockboxFramebuffer extends View
{
/* can't copy a partial buffer */
btm.copyPixelsFromBuffer(native_buf);
postInvalidate(x, y, x+w, y+h);
}
@ -90,7 +95,17 @@ public class RockboxFramebuffer extends View
pixelHandler((int)me.getX(), (int)me.getY());
return true;
}
public boolean onKeyDown(int keyCode, KeyEvent event)
{
return buttonHandler(keyCode, true);
}
public boolean onKeyUp(int keyCode, KeyEvent event)
{
return buttonHandler(keyCode, false);
}
/* the two below should only be called from the activity thread */
public void suspend()
{ /* suspend, Rockbox will not make any lcd updates */
@ -105,4 +120,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 boolean buttonHandler(int keycode, boolean state);
}

View file

@ -293,4 +293,6 @@ keymaps/keymap-mini2440.c
keymaps/keymap-vibe500.c
#elif CONFIG_KEYPAD == MPIO_HD200_PAD
keymaps/keymap-mpio-hd200.c
#elif CONFIG_KEYPAD == ANDROID_PAD
keymaps/keymap-android.c
#endif

View file

@ -0,0 +1,198 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2010 Maurus Cuelenaere
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
/* Button Code Definitions for Android targets */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "config.h"
#include "action.h"
#include "button.h"
#include "settings.h"
/*
* The format of the list is as follows
* { Action Code, Button code, Prereq button code }
* if there's no need to check the previous button's value, use BUTTON_NONE
* Insert LAST_ITEM_IN_LIST at the end of each mapping
*/
static const struct button_mapping button_context_standard[] = {
{ ACTION_STD_PREV, BUTTON_DPAD_UP, BUTTON_NONE },
{ ACTION_STD_PREVREPEAT, BUTTON_DPAD_UP|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_STD_NEXT, BUTTON_DPAD_DOWN, BUTTON_NONE },
{ ACTION_STD_NEXTREPEAT, BUTTON_DPAD_DOWN|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_STD_OK, BUTTON_DPAD_CENTER|BUTTON_REL, BUTTON_DPAD_CENTER },
{ ACTION_STD_OK, BUTTON_DPAD_RIGHT|BUTTON_REL, BUTTON_DPAD_RIGHT },
{ ACTION_STD_CANCEL, BUTTON_BACK, BUTTON_NONE },
{ ACTION_STD_CANCEL, BUTTON_DPAD_LEFT|BUTTON_REL, BUTTON_DPAD_LEFT },
{ ACTION_STD_CONTEXT, BUTTON_MENU, BUTTON_NONE },
LAST_ITEM_IN_LIST
}; /* button_context_standard */
static const struct button_mapping button_context_wps[] = {
{ ACTION_WPS_BROWSE, BUTTON_BACK, BUTTON_NONE },
{ ACTION_WPS_MENU, BUTTON_MENU|BUTTON_REL, BUTTON_MENU },
{ ACTION_WPS_CONTEXT, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU },
LAST_ITEM_IN_LIST
}; /* button_context_wps */
static const struct button_mapping button_context_list[] = {
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_list */
static const struct button_mapping button_context_tree[] = {
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST)
}; /* button_context_tree */
static const struct button_mapping button_context_listtree_scroll_with_combo[] = {
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_TREE),
};
static const struct button_mapping button_context_listtree_scroll_without_combo[] = {
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_TREE),
};
static const struct button_mapping button_context_settings[] = {
{ ACTION_SETTINGS_INC, BUTTON_DPAD_RIGHT, BUTTON_NONE },
{ ACTION_SETTINGS_INCREPEAT, BUTTON_DPAD_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_SETTINGS_DEC, BUTTON_DPAD_LEFT, BUTTON_NONE },
{ ACTION_SETTINGS_DECREPEAT, BUTTON_DPAD_LEFT|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_STD_OK, BUTTON_DPAD_CENTER, BUTTON_NONE },
{ ACTION_STD_CANCEL, BUTTON_BACK, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_settings */
static const struct button_mapping button_context_settings_right_is_inc[] = {
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_settingsgraphical */
static const struct button_mapping button_context_yesno[] = {
{ ACTION_YESNO_ACCEPT, BUTTON_DPAD_CENTER, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_settings_yesno */
static const struct button_mapping button_context_colorchooser[] = {
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_SETTINGS),
}; /* button_context_colorchooser */
static const struct button_mapping button_context_eq[] = {
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_SETTINGS),
}; /* button_context_eq */
/** Bookmark Screen **/
static const struct button_mapping button_context_bmark[] = {
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST),
}; /* button_context_bmark */
static const struct button_mapping button_context_time[] = {
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS),
}; /* button_context_time */
static const struct button_mapping button_context_quickscreen[] = {
{ ACTION_STD_CANCEL, BUTTON_BACK|BUTTON_REL, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_quickscreen */
static const struct button_mapping button_context_pitchscreen[] = {
{ ACTION_PS_INC_SMALL, BUTTON_DPAD_RIGHT, BUTTON_NONE },
{ ACTION_PS_INC_BIG, BUTTON_DPAD_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_PS_DEC_SMALL, BUTTON_DPAD_LEFT, BUTTON_NONE },
{ ACTION_PS_DEC_BIG, BUTTON_DPAD_LEFT|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_BACK, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_pitchcreen */
static const struct button_mapping button_context_keyboard[] = {
{ ACTION_KBD_PAGE_FLIP, BUTTON_MENU, BUTTON_NONE },
{ ACTION_KBD_CURSOR_LEFT, BUTTON_DPAD_LEFT, BUTTON_NONE },
{ ACTION_KBD_CURSOR_LEFT, BUTTON_DPAD_LEFT|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_KBD_CURSOR_RIGHT, BUTTON_DPAD_RIGHT, BUTTON_NONE },
{ ACTION_KBD_CURSOR_RIGHT, BUTTON_DPAD_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_keyboard */
static const struct button_mapping button_context_radio[] = {
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS)
}; /* button_context_radio */
const struct button_mapping* target_get_context_mapping(int context)
{
switch (context)
{
case CONTEXT_STD:
return button_context_standard;
case CONTEXT_WPS:
return button_context_wps;
case CONTEXT_LIST:
return button_context_list;
case CONTEXT_MAINMENU:
case CONTEXT_TREE:
if (global_settings.hold_lr_for_scroll_in_list)
return button_context_listtree_scroll_without_combo;
else
return button_context_listtree_scroll_with_combo;
case CONTEXT_CUSTOM|CONTEXT_TREE:
return button_context_tree;
case CONTEXT_SETTINGS:
return button_context_settings;
case CONTEXT_CUSTOM|CONTEXT_SETTINGS:
case CONTEXT_SETTINGS_RECTRIGGER:
return button_context_settings_right_is_inc;
case CONTEXT_SETTINGS_COLOURCHOOSER:
return button_context_colorchooser;
case CONTEXT_SETTINGS_EQ:
return button_context_eq;
case CONTEXT_SETTINGS_TIME:
return button_context_time;
case CONTEXT_YESNOSCREEN:
return button_context_yesno;
case CONTEXT_FM:
return button_context_radio;
case CONTEXT_BOOKMARKSCREEN:
return button_context_bmark;
case CONTEXT_QUICKSCREEN:
return button_context_quickscreen;
case CONTEXT_PITCHSCREEN:
return button_context_pitchscreen;
case CONTEXT_KEYBOARD:
return button_context_keyboard;
}
return button_context_standard;
}

View file

@ -1708,6 +1708,9 @@ target/hosted/android/button-android.c
target/hosted/android/kernel-android.c
target/hosted/android/pcm-android.c
target/hosted/android/system-android.c
#ifdef APPLICATION
target/hosted/android/app/button-application.c
#endif
drivers/audio/android.c
thread.c
#endif

View file

@ -128,6 +128,7 @@
#define PHILIPS_HDD6330_PAD 42
#define PBELL_VIBE500_PAD 43
#define MPIO_HD200_PAD 44
#define ANDROID_PAD 45
/* CONFIG_REMOTE_KEYPAD */
#define H100_REMOTE 1

View file

@ -75,7 +75,11 @@
/* Define this if you do software codec */
#define CONFIG_CODEC SWCODEC
#ifdef ANDROID
#define CONFIG_KEYPAD ANDROID_PAD
#else
#define CONFIG_KEYPAD COWON_D2_PAD
#endif
#if (CONFIG_PLATFORM & PLATFORM_SDL)
/* Use SDL audio/pcm in a SDL app build */

View file

@ -0,0 +1,97 @@
/* Ripped from http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob_plain;f=core/java/android/view/KeyEvent.java;hb=HEAD */
#define KEYCODE_UNKNOWN 0
#define KEYCODE_SOFT_LEFT 1
#define KEYCODE_SOFT_RIGHT 2
#define KEYCODE_HOME 3
#define KEYCODE_BACK 4
#define KEYCODE_CALL 5
#define KEYCODE_ENDCALL 6
#define KEYCODE_0 7
#define KEYCODE_1 8
#define KEYCODE_2 9
#define KEYCODE_3 10
#define KEYCODE_4 11
#define KEYCODE_5 12
#define KEYCODE_6 13
#define KEYCODE_7 14
#define KEYCODE_8 15
#define KEYCODE_9 16
#define KEYCODE_STAR 17
#define KEYCODE_POUND 18
#define KEYCODE_DPAD_UP 19
#define KEYCODE_DPAD_DOWN 20
#define KEYCODE_DPAD_LEFT 21
#define KEYCODE_DPAD_RIGHT 22
#define KEYCODE_DPAD_CENTER 23
#define KEYCODE_VOLUME_UP 24
#define KEYCODE_VOLUME_DOWN 25
#define KEYCODE_POWER 26
#define KEYCODE_CAMERA 27
#define KEYCODE_CLEAR 28
#define KEYCODE_A 29
#define KEYCODE_B 30
#define KEYCODE_C 31
#define KEYCODE_D 32
#define KEYCODE_E 33
#define KEYCODE_F 34
#define KEYCODE_G 35
#define KEYCODE_H 36
#define KEYCODE_I 37
#define KEYCODE_J 38
#define KEYCODE_K 39
#define KEYCODE_L 40
#define KEYCODE_M 41
#define KEYCODE_N 42
#define KEYCODE_O 43
#define KEYCODE_P 44
#define KEYCODE_Q 45
#define KEYCODE_R 46
#define KEYCODE_S 47
#define KEYCODE_T 48
#define KEYCODE_U 49
#define KEYCODE_V 50
#define KEYCODE_W 51
#define KEYCODE_X 52
#define KEYCODE_Y 53
#define KEYCODE_Z 54
#define KEYCODE_COMMA 55
#define KEYCODE_PERIOD 56
#define KEYCODE_ALT_LEFT 57
#define KEYCODE_ALT_RIGHT 58
#define KEYCODE_SHIFT_LEFT 59
#define KEYCODE_SHIFT_RIGHT 60
#define KEYCODE_TAB 61
#define KEYCODE_SPACE 62
#define KEYCODE_SYM 63
#define KEYCODE_EXPLORER 64
#define KEYCODE_ENVELOPE 65
#define KEYCODE_ENTER 66
#define KEYCODE_DEL 67
#define KEYCODE_GRAVE 68
#define KEYCODE_MINUS 69
#define KEYCODE_EQUALS 70
#define KEYCODE_LEFT_BRACKET 71
#define KEYCODE_RIGHT_BRACKET 72
#define KEYCODE_BACKSLASH 73
#define KEYCODE_SEMICOLON 74
#define KEYCODE_APOSTROPHE 75
#define KEYCODE_SLASH 76
#define KEYCODE_AT 77
#define KEYCODE_NUM 78
#define KEYCODE_HEADSETHOOK 79
#define KEYCODE_FOCUS 80
#define KEYCODE_PLUS 81
#define KEYCODE_MENU 82
#define KEYCODE_NOTIFICATION 83
#define KEYCODE_SEARCH 84
#define KEYCODE_MEDIA_PLAY_PAUSE 85
#define KEYCODE_MEDIA_STOP 86
#define KEYCODE_MEDIA_NEXT 87
#define KEYCODE_MEDIA_PREVIOUS 88
#define KEYCODE_MEDIA_REWIND 89
#define KEYCODE_MEDIA_FAST_FORWARD 90
#define KEYCODE_MUTE 91
#define KEYCODE_PAGE_UP 92
#define KEYCODE_PAGE_DOWN 93
#define KEYCODE_PICTSYMBOLS 94
#define KEYCODE_SWITCH_CHARSET 95

View file

@ -0,0 +1,9 @@
#!/bin/sh
# Simple script that converts Android's KEYCODE_* ints to preprocessor #defines
URL="http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob_plain;f=core/java/android/view/KeyEvent.java;hb=HEAD"
echo "Processing $URL..."
(echo "/* Ripped from $URL */";
curl $URL | grep "public static final int KEYCODE" | sed 's/^.*public static final int \(KEYCODE_.*\) *= *\([0-9]*\).*$/#define \1 \2/'
) > `dirname $0`/android_keyevents.h

View file

@ -17,13 +17,31 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************9*************************/
*****************************************************************************/
#include "button.h"
#include "android_keyevents.h"
int key_to_button(int keyboard_key)
{
(void)keyboard_key;
return BUTTON_NONE;
switch (keyboard_key)
{
default:
return BUTTON_NONE;
case KEYCODE_BACK:
return BUTTON_BACK;
case KEYCODE_DPAD_UP:
return BUTTON_DPAD_UP;
case KEYCODE_DPAD_DOWN:
return BUTTON_DPAD_DOWN;
case KEYCODE_DPAD_LEFT:
return BUTTON_DPAD_LEFT;
case KEYCODE_DPAD_RIGHT:
return BUTTON_DPAD_RIGHT;
case KEYCODE_DPAD_CENTER:
return BUTTON_DPAD_CENTER;
case KEYCODE_MENU:
return BUTTON_MENU;
}
}

View file

@ -30,35 +30,32 @@ void button_init_device(void);
int button_read_device(int *data);
/* Main unit's buttons */
#define BUTTON_POWER 0x00000001
#define BUTTON_PLUS 0x00000002
#define BUTTON_MINUS 0x00000004
#define BUTTON_MENU 0x00000008
#define BUTTON_MENU 0x00000001
#define BUTTON_BACK 0x00000002
#define BUTTON_DPAD_LEFT 0x00000004
#define BUTTON_DPAD_RIGHT 0x00000008
#define BUTTON_DPAD_UP 0x00000010
#define BUTTON_DPAD_DOWN 0x00000020
#define BUTTON_DPAD_CENTER 0x00000040
/* Compatibility hacks for flipping. Needs a somewhat better fix. */
#define BUTTON_LEFT BUTTON_MIDLEFT
#define BUTTON_RIGHT BUTTON_MIDRIGHT
#define BUTTON_UP BUTTON_TOPMIDDLE
#define BUTTON_DOWN BUTTON_BOTTOMMIDDLE
#define BUTTON_LEFT BUTTON_DPAD_LEFT
#define BUTTON_RIGHT BUTTON_DPAD_RIGHT
#define BUTTON_UP BUTTON_DPAD_UP
#define BUTTON_DOWN BUTTON_DPAD_DOWN
/* Touch Screen Area Buttons */
#define BUTTON_TOPLEFT 0x00000010
#define BUTTON_TOPMIDDLE 0x00000020
#define BUTTON_TOPRIGHT 0x00000040
#define BUTTON_MIDLEFT 0x00000080
#define BUTTON_CENTER 0x00000100
#define BUTTON_MIDRIGHT 0x00000200
#define BUTTON_BOTTOMLEFT 0x00000400
#define BUTTON_BOTTOMMIDDLE 0x00000800
#define BUTTON_BOTTOMRIGHT 0x00001000
#define BUTTON_MAIN 0x1FFF
#define BUTTON_TOPLEFT 0x00001000
#define BUTTON_TOPMIDDLE 0x00002000
#define BUTTON_TOPRIGHT 0x00004000
#define BUTTON_MIDLEFT 0x00008000
#define BUTTON_CENTER 0x00010000
#define BUTTON_MIDRIGHT 0x00020000
#define BUTTON_BOTTOMLEFT 0x00040000
#define BUTTON_BOTTOMMIDDLE 0x00080000
#define BUTTON_BOTTOMRIGHT 0x00100000
/* No remote */
#define BUTTON_REMOTE 0
/* Software power-off */
#define POWEROFF_BUTTON BUTTON_POWER
#define POWEROFF_COUNT 10
#endif /* _BUTTON_TARGET_H_ */

View file

@ -22,12 +22,15 @@
#include <jni.h>
#include <stdbool.h>
#include "button.h"
#include "buttonmap.h"
#include "config.h"
#include "kernel.h"
#include "system.h"
#include "touchscreen.h"
static int last_y, last_x;
static int last_btns;
static enum {
STATE_UNKNOWN,
@ -35,7 +38,6 @@ static enum {
STATE_DOWN,
} last_state = STATE_UNKNOWN;
/*
* this writes in an interrupt-like fashion the last pixel coordinates
* that the user pressed on the screen */
@ -64,13 +66,45 @@ Java_org_rockbox_RockboxFramebuffer_touchHandler(JNIEnv*env, jobject this,
last_state = STATE_UP;
}
/*
* this writes in an interrupt-like fashion the button events that the user
* generated by pressing/releasing them to a variable */
JNIEXPORT bool JNICALL
Java_org_rockbox_RockboxFramebuffer_buttonHandler(JNIEnv*env, jobject this,
int keycode, bool state)
{
(void)env;
(void)this;
int button = key_to_button(keycode);
if (button == BUTTON_NONE)
return false;
if (state)
last_btns |= button;
else
last_btns &= ~button;
return true;
}
void button_init_device(void)
{
}
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 = last_btns;
/* Get grid button/coordinates based on the current touchscreen mode
*
* Caveat: the caller seemingly depends on *data always being filled with
* the last known touchscreen position, so always call
* touchscreen_to_pixels() */
int touch = touchscreen_to_pixels(last_x, last_y, data);
if (last_state == STATE_DOWN)
btn |= touch;
return btn;
}