diff --git a/android/native/jni/input_android.c b/android/native/jni/input_android.c index 6234174b52..500e22cff6 100644 --- a/android/native/jni/input_android.c +++ b/android/native/jni/input_android.c @@ -16,6 +16,7 @@ */ #include +#include #include #include #include "input_autodetect.h" @@ -37,6 +38,13 @@ typedef struct int16_t rx, ry; } analog_t; +typedef struct +{ + float x; + float y; + float z; +} sensor_t; + struct input_pointer { int16_t x, y; @@ -62,12 +70,19 @@ typedef struct android_input uint64_t state[MAX_PADS]; uint64_t keycode_lut[LAST_KEYCODE]; analog_t analog_state[MAX_PADS]; + sensor_t accelerometer_state; + unsigned accelerometer_event_rate; unsigned dpad_emulation[MAX_PLAYERS]; struct input_pointer pointer[MAX_TOUCH]; unsigned pointer_count; + ASensorManager* sensorManager; + const ASensor* accelerometerSensor; + ASensorEventQueue* sensorEventQueue; + uint64_t sensor_state_mask; } android_input_t; void (*engine_handle_dpad)(void *data, AInputEvent*, size_t, int, char*, size_t, int, bool, unsigned); +static void android_input_set_sensor_state(void *data, unsigned port, unsigned action, unsigned event_rate); extern float AMotionEvent_getAxisValue(const AInputEvent* motion_event, int32_t axis, size_t pointer_index); @@ -79,6 +94,7 @@ static typeof(AMotionEvent_getAxisValue) *p_AMotionEvent_getAxisValue; void engine_handle_cmd(void) { struct android_app *android_app = (struct android_app*)g_android; + android_input_t *android = (android_input_t*)driver.input_data; int8_t cmd; if (read(android_app->msgread, &cmd, sizeof(cmd)) != sizeof(cmd)) @@ -170,9 +186,18 @@ void engine_handle_cmd(void) case APP_CMD_GAINED_FOCUS: g_extern.lifecycle_state &= ~(1ULL << RARCH_PAUSE_TOGGLE); - break; + if (android->sensor_state_mask & (1ULL << RETRO_SENSOR_ACCELEROMETER_ENABLE) + && android->accelerometerSensor == NULL) + android_input_set_sensor_state(android, 0, RETRO_SENSOR_ACCELEROMETER_ENABLE, + android->accelerometer_event_rate); + break; case APP_CMD_LOST_FOCUS: + // Avoid draining battery while app is not being used + if (android->sensor_state_mask & (1ULL << RETRO_SENSOR_ACCELEROMETER_ENABLE) + && android->accelerometerSensor != NULL) + android_input_set_sensor_state(android, 0, RETRO_SENSOR_ACCELEROMETER_DISABLE, + android->accelerometer_event_rate); break; case APP_CMD_DESTROY: @@ -1899,6 +1924,19 @@ static void android_input_poll(void *data) #endif } } + else if (ident == LOOPER_ID_USER) + { + if (android->sensor_state_mask & (1ULL << RETRO_SENSOR_ACCELEROMETER_ENABLE)) + { + ASensorEvent event; + while (ASensorEventQueue_getEvents(android->sensorEventQueue, &event, 1) > 0) + { + android->accelerometer_state.x = event.acceleration.x; + android->accelerometer_state.y = event.acceleration.y; + android->accelerometer_state.z = event.acceleration.z; + } + } + } else if (ident == LOOPER_ID_MAIN) engine_handle_cmd(); } @@ -1950,6 +1988,19 @@ static int16_t android_input_state(void *data, const struct retro_keybind **bind default: return 0; } + case RETRO_DEVICE_SENSOR_ACCELEROMETER: + switch (id) + { + case RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_X: + return android->accelerometer_state.x; + case RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_Y: + return android->accelerometer_state.y; + case RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_Z: + return android->accelerometer_state.z; + default: + return 0; + } + break; default: return 0; } @@ -1972,10 +2023,64 @@ static uint64_t android_input_get_capabilities(void *data) caps |= (1 << RETRO_DEVICE_JOYPAD); caps |= (1 << RETRO_DEVICE_POINTER); caps |= (1 << RETRO_DEVICE_ANALOG); + caps |= (1 << RETRO_DEVICE_SENSOR_ACCELEROMETER); return caps; } +static void android_input_enable_sensor_manager(void *data) +{ + android_input_t *android = (android_input_t*)data; + struct android_app *android_app = (struct android_app*)g_android; + + android->sensorManager = ASensorManager_getInstance(); + android->accelerometerSensor = ASensorManager_getDefaultSensor(android->sensorManager, + ASENSOR_TYPE_ACCELEROMETER); + android->sensorEventQueue = ASensorManager_createEventQueue(android->sensorManager, + android_app->looper, LOOPER_ID_USER, NULL, NULL); +} + +static void android_input_set_sensor_state(void *data, unsigned port, unsigned action, unsigned event_rate) +{ + android_input_t *android = (android_input_t*)data; + + if (event_rate == 0) + event_rate = 60; + + switch (action) + { + case RETRO_SENSOR_ACCELEROMETER_ENABLE: + if (android->sensor_state_mask & + (1ULL << RETRO_SENSOR_ACCELEROMETER_ENABLE)) + return; + + if (android->accelerometerSensor == NULL) + android_input_enable_sensor_manager(android); + + ASensorEventQueue_enableSensor(android->sensorEventQueue, + android->accelerometerSensor); + + // events per second (in us). + ASensorEventQueue_setEventRate(android->sensorEventQueue, + android->accelerometerSensor, (1000L / event_rate) * 1000); + + android->sensor_state_mask &= ~(1ULL << RETRO_SENSOR_ACCELEROMETER_DISABLE); + android->sensor_state_mask |= (1ULL << RETRO_SENSOR_ACCELEROMETER_ENABLE); + break; + case RETRO_SENSOR_ACCELEROMETER_DISABLE: + if (android->sensor_state_mask & + (1ULL << RETRO_SENSOR_ACCELEROMETER_DISABLE)) + return; + + ASensorEventQueue_disableSensor(android->sensorEventQueue, + android->accelerometerSensor); + + android->sensor_state_mask &= ~(1ULL << RETRO_SENSOR_ACCELEROMETER_ENABLE); + android->sensor_state_mask |= (1ULL << RETRO_SENSOR_ACCELEROMETER_DISABLE); + break; + } +} + const input_driver_t input_android = { android_input_init, android_input_poll, @@ -1983,6 +2088,7 @@ const input_driver_t input_android = { android_input_key_pressed, android_input_free_input, android_input_set_keybinds, + android_input_set_sensor_state, android_input_get_capabilities, "android_input", }; diff --git a/apple/common/apple_input.c b/apple/common/apple_input.c index 0995e9a02c..9e2b2819b8 100644 --- a/apple/common/apple_input.c +++ b/apple/common/apple_input.c @@ -329,6 +329,7 @@ const input_driver_t input_apple = { apple_bind_button_pressed, apple_input_free_input, apple_input_set_keybinds, + NULL, apple_input_get_capabilities, "apple_input", NULL, diff --git a/blackberry-qnx/qnx_input.c b/blackberry-qnx/qnx_input.c index 76ba315521..67cb4c7b97 100644 --- a/blackberry-qnx/qnx_input.c +++ b/blackberry-qnx/qnx_input.c @@ -859,6 +859,7 @@ const input_driver_t input_qnx = { qnx_input_key_pressed, qnx_input_free_input, qnx_input_set_keybinds, + NULL, qnx_input_get_capabilities, "qnx_input", }; diff --git a/driver.h b/driver.h index cadeadc0a5..055cf8ba7e 100644 --- a/driver.h +++ b/driver.h @@ -322,6 +322,7 @@ typedef struct input_driver bool (*key_pressed)(void *data, int key); void (*free)(void *data); void (*set_keybinds)(void *data, unsigned device, unsigned port, unsigned id, unsigned keybind_action); + void (*set_sensor_state)(void *data, unsigned port, unsigned action, unsigned event_rate); uint64_t (*get_capabilities)(void *data); const char *ident; diff --git a/frontend/frontend_android.h b/frontend/frontend_android.h index 1403724a71..480e62f5cc 100644 --- a/frontend/frontend_android.h +++ b/frontend/frontend_android.h @@ -30,24 +30,18 @@ struct android_app { ANativeActivity* activity; - ALooper* looper; AInputQueue* inputQueue; - + AInputQueue* pendingInputQueue; ANativeWindow* window; - int activityState; - + ANativeWindow* pendingWindow; slock_t *mutex; scond_t *cond; - + int activityState; int msgread; int msgwrite; - - sthread_t *thread; - int running; - AInputQueue* pendingInputQueue; - ANativeWindow* pendingWindow; + sthread_t *thread; char current_ime[PATH_MAX]; }; diff --git a/gx/gx_input.c b/gx/gx_input.c index bec84d7c23..ab30056598 100644 --- a/gx/gx_input.c +++ b/gx/gx_input.c @@ -519,6 +519,7 @@ const input_driver_t input_gx = { gx_input_key_pressed, gx_input_free_input, gx_input_set_keybinds, + NULL, gx_input_get_capabilities, "gx", }; diff --git a/input/dinput.c b/input/dinput.c index 6b780edf12..8d178c8a38 100644 --- a/input/dinput.c +++ b/input/dinput.c @@ -367,6 +367,7 @@ const input_driver_t input_dinput = { dinput_key_pressed, dinput_free, NULL, + NULL, dinput_get_capabilities, "dinput", diff --git a/input/linuxraw_input.c b/input/linuxraw_input.c index 5f2a74a8b9..b364e5bfb1 100644 --- a/input/linuxraw_input.c +++ b/input/linuxraw_input.c @@ -339,6 +339,7 @@ const input_driver_t input_linuxraw = { linuxraw_bind_button_pressed, linuxraw_input_free, NULL, + NULL, linuxraw_get_capabilities, "linuxraw", NULL, diff --git a/input/rwebinput_input.c b/input/rwebinput_input.c index d53e1b25a6..b9001275e4 100644 --- a/input/rwebinput_input.c +++ b/input/rwebinput_input.c @@ -154,6 +154,7 @@ const input_driver_t input_rwebinput = { rwebinput_bind_button_pressed, rwebinput_input_free, NULL, + NULL, rwebinput_get_capabilities, "rwebinput", rwebinput_grab_mouse, diff --git a/input/sdl_input.c b/input/sdl_input.c index 50194a2bd8..93ca002cdc 100644 --- a/input/sdl_input.c +++ b/input/sdl_input.c @@ -265,6 +265,7 @@ const input_driver_t input_sdl = { sdl_bind_button_pressed, sdl_input_free, NULL, + NULL, sdl_get_capabilities, "sdl", NULL, diff --git a/input/x11_input.c b/input/x11_input.c index ac312d719a..57a1c5ab69 100644 --- a/input/x11_input.c +++ b/input/x11_input.c @@ -302,6 +302,7 @@ const input_driver_t input_x = { x_bind_button_pressed, x_input_free, NULL, + NULL, x_input_get_capabilities, "x", x_grab_mouse, diff --git a/libretro.h b/libretro.h index 22c51d72e0..24a440bbb8 100755 --- a/libretro.h +++ b/libretro.h @@ -94,6 +94,8 @@ extern "C" { // Eventually _PRESSED will return false for an index. No further presses are registered at this point. #define RETRO_DEVICE_POINTER 6 +#define RETRO_DEVICE_SENSOR_ACCELEROMETER 7 + // These device types are specializations of the base types above. // They should only be used in retro_set_controller_type() to inform libretro implementations // about use of a very specific device type. @@ -150,6 +152,11 @@ extern "C" { #define RETRO_DEVICE_ID_POINTER_Y 1 #define RETRO_DEVICE_ID_POINTER_PRESSED 2 +// Id values for SENSOR types. +#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_X 0 +#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_Y 1 +#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_Z 2 + // Returned from retro_get_region(). #define RETRO_REGION_NTSC 0 #define RETRO_REGION_PAL 1 @@ -536,6 +543,14 @@ enum retro_rumble_effect RETRO_RUMBLE_DUMMY = INT_MAX }; +enum retro_sensor_action +{ + RETRO_SENSOR_ACCELEROMETER_ENABLE = 0, + RETRO_SENSOR_ACCELEROMETER_DISABLE, +}; + +typedef bool (*retro_set_sensor_state_t)(unsigned port, enum retro_sensor_action action, unsigned event_rate); + // Sets rumble state for joypad plugged in port 'port'. Rumble effects are controlled independently, // and setting e.g. strong rumble does not override weak rumble. // Strength has a range of [0, 0xffff]. diff --git a/ps3/ps3_input.c b/ps3/ps3_input.c index 8871ab4f81..bd51ae97bd 100644 --- a/ps3/ps3_input.c +++ b/ps3/ps3_input.c @@ -393,6 +393,7 @@ const input_driver_t input_ps3 = { ps3_input_key_pressed, ps3_input_free_input, ps3_input_set_keybinds, + NULL, ps3_input_get_capabilities, "ps3", }; diff --git a/psp/psp_input.c b/psp/psp_input.c index a948db42d8..dbefecc6cb 100644 --- a/psp/psp_input.c +++ b/psp/psp_input.c @@ -177,12 +177,23 @@ static bool psp_input_key_pressed(void *data, int key) } } +static uint64_t psp_input_get_capabilities(void *data) +{ + uint64_t caps = 0; + + caps |= (1 << RETRO_DEVICE_JOYPAD); + + return caps; +} + const input_driver_t input_psp = { - .init = psp_input_initialize, - .poll = psp_input_poll, - .input_state = psp_input_state, - .key_pressed = psp_input_key_pressed, - .free = psp_input_free_input, - .set_keybinds = psp_input_set_keybinds, - .ident = "psp", + psp_input_initialize, + psp_input_poll, + psp_input_state, + psp_input_key_pressed, + psp_input_free_input, + psp_input_set_keybinds, + NULL, + psp_input_get_capabilities, + "psp", }; diff --git a/xdk/xdk_xinput_input.c b/xdk/xdk_xinput_input.c index 5f00b2e5e4..9d4a55b99f 100644 --- a/xdk/xdk_xinput_input.c +++ b/xdk/xdk_xinput_input.c @@ -284,6 +284,7 @@ const input_driver_t input_xinput = xdk_input_key_pressed, xdk_input_free_input, xdk_input_set_keybinds, + NULL, xdk_input_get_capabilities, "xinput" }; diff --git a/xenon/xenon360_input.c b/xenon/xenon360_input.c index f0aab56e94..ed58a77a13 100644 --- a/xenon/xenon360_input.c +++ b/xenon/xenon360_input.c @@ -125,6 +125,7 @@ const input_driver_t input_xenon360 = { xenon360_input_key_pressed, xenon360_input_free_input, xenon360_input_set_keybinds, + NULL, xenon360_input_get_capabilities, "xenon360", };