mirror of
https://github.com/libretro/RetroArch
synced 2025-04-10 15:45:19 +00:00
Add Linux support for illuminance sensors (#17208)
* First crack at light sensor support for Linux * Add light-sensor support to most Linux input drivers * Fix a compiler error - Whoops, forgot to declare `sdl` * Refactor linux_illuminance_sensor_t - Allow the poll rate to be specified - Poll the sensor on a separate thread - Open a file handle each time we poll the sensor, since sysfs doesn't update the contents of an existing handle * Set the `done` flag when closing the light sensor - Whoops * Avoid a division by zero when updating the poll rate of an existing sensor * Don't try to open illuminance sensors from ".", "..", or hidden files * Never mind * Fix some silly mistakes * Skip hidden files, ".", and ".." * Cancel the sensor poll thread mid-sleep when closing it - POSIX says it's fine * Add to CHANGES.md * Address feedback given on PR * Use libretro-common's file system instead of stdio
This commit is contained in:
parent
a4b478524a
commit
d682917e44
@ -35,6 +35,7 @@
|
|||||||
- INPUT: Fix autoconfig profile saving when device is not in the default port
|
- INPUT: Fix autoconfig profile saving when device is not in the default port
|
||||||
- INPUT/DINPUT: Fix detection of quick shift key presses
|
- INPUT/DINPUT: Fix detection of quick shift key presses
|
||||||
- INPUT/HID: Fix crash on macOS when disconnecting the controller a second time
|
- INPUT/HID: Fix crash on macOS when disconnecting the controller a second time
|
||||||
|
- INPUT/LINUX: Add illuminance sensor support to the linuxraw, sdl2, udev, and x11 input drivers
|
||||||
- INPUT/Remaps: Sort and apply remaps based on the specific connected controller
|
- INPUT/Remaps: Sort and apply remaps based on the specific connected controller
|
||||||
- INPUT/UDEV: Enable mouse buttons 4 and 5
|
- INPUT/UDEV: Enable mouse buttons 4 and 5
|
||||||
- INPUT/WAYLAND: Enable horizontal scroll and mouse buttons 4 and 5
|
- INPUT/WAYLAND: Enable horizontal scroll and mouse buttons 4 and 5
|
||||||
|
@ -15,21 +15,56 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <linux/kd.h>
|
#include <linux/kd.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "linux_common.h"
|
#include "linux_common.h"
|
||||||
|
#include "verbosity.h"
|
||||||
|
#include <retro_assert.h>
|
||||||
|
#include <retro_timers.h>
|
||||||
|
#include <rthreads/rthreads.h>
|
||||||
|
|
||||||
|
/* We can assume that pthreads are available on Linux. */
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <retro_dirent.h>
|
||||||
|
#include <streams/file_stream.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define IIO_DEVICES_DIR "/sys/bus/iio/devices"
|
||||||
|
#define IIO_ILLUMINANCE_SENSOR "in_illuminance_input"
|
||||||
|
#define DEFAULT_POLL_RATE 5
|
||||||
|
|
||||||
/* TODO/FIXME - static globals */
|
/* TODO/FIXME - static globals */
|
||||||
static struct termios old_term, new_term;
|
static struct termios old_term, new_term;
|
||||||
static long old_kbmd = 0xffff;
|
static long old_kbmd = 0xffff;
|
||||||
static bool linux_stdin_claimed = false;
|
static bool linux_stdin_claimed = false;
|
||||||
|
|
||||||
|
struct linux_illuminance_sensor
|
||||||
|
{
|
||||||
|
sthread_t *thread;
|
||||||
|
|
||||||
|
/* Poll rate in Hz (i.e. in queries per second) */
|
||||||
|
volatile unsigned poll_rate;
|
||||||
|
|
||||||
|
/* We store the lux reading in millilux (as an int)
|
||||||
|
* so that we can make the access atomic and avoid locks.
|
||||||
|
* A little bit of precision is lost, but not enough to matter.
|
||||||
|
*/
|
||||||
|
volatile int millilux;
|
||||||
|
|
||||||
|
/* If true, the associated thread must finish its work and exit. */
|
||||||
|
volatile bool done;
|
||||||
|
|
||||||
|
char path[PATH_MAX_LENGTH];
|
||||||
|
};
|
||||||
|
static double linux_read_illuminance_sensor(const linux_illuminance_sensor_t *sensor);
|
||||||
|
|
||||||
void linux_terminal_restore_input(void)
|
void linux_terminal_restore_input(void)
|
||||||
{
|
{
|
||||||
if (old_kbmd == 0xffff)
|
if (old_kbmd == 0xffff)
|
||||||
@ -121,3 +156,190 @@ bool linux_terminal_disable_input(void)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void linux_poll_illuminance_sensor(void *data)
|
||||||
|
{
|
||||||
|
linux_illuminance_sensor_t *sensor = data;
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (!sensor->done)
|
||||||
|
{ /* Aligned int reads are atomic on most CPUs */
|
||||||
|
double lux;
|
||||||
|
int millilux;
|
||||||
|
unsigned poll_rate = sensor->poll_rate;
|
||||||
|
|
||||||
|
/* Don't allow cancellation inside the critical section,
|
||||||
|
* as it opens up a file; we don't want to leak it! */
|
||||||
|
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
||||||
|
lux = linux_read_illuminance_sensor(sensor);
|
||||||
|
millilux = (int)(lux * 1000.0);
|
||||||
|
retro_assert(poll_rate != 0);
|
||||||
|
|
||||||
|
sensor->millilux = millilux;
|
||||||
|
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
||||||
|
|
||||||
|
/* Allow cancellation here so that the main thread doesn't block
|
||||||
|
* while waiting for this thread to wake up and exit. */
|
||||||
|
retro_sleep(1000 / poll_rate);
|
||||||
|
if (errno == EINTR)
|
||||||
|
{
|
||||||
|
RARCH_ERR("Illuminance sensor thread interrupted\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RARCH_DBG("Illuminance sensor thread for %s exiting\n", sensor->path);
|
||||||
|
}
|
||||||
|
|
||||||
|
linux_illuminance_sensor_t *linux_open_illuminance_sensor(unsigned rate)
|
||||||
|
{
|
||||||
|
RDIR *device = NULL;
|
||||||
|
linux_illuminance_sensor_t *sensor = malloc(sizeof(*sensor));
|
||||||
|
|
||||||
|
if (!sensor)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
sensor->millilux = 0;
|
||||||
|
sensor->poll_rate = rate ? rate : DEFAULT_POLL_RATE;
|
||||||
|
sensor->thread = NULL; /* We'll spawn a thread later, once we find a sensor */
|
||||||
|
sensor->done = false;
|
||||||
|
|
||||||
|
while (retro_readdir(device))
|
||||||
|
{ /* For each IIO device... */
|
||||||
|
const char *name = retro_dirent_get_name(device);
|
||||||
|
double lux = 0.0;
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
{
|
||||||
|
RARCH_ERR("Error reading " IIO_DEVICES_DIR "\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name[0] == '.')
|
||||||
|
/* Skip hidden files, ".", and ".." */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* If that worked out, look to see if this device represents an illuminance sensor */
|
||||||
|
snprintf(sensor->path, sizeof(sensor->path), IIO_DEVICES_DIR "/%s/" IIO_ILLUMINANCE_SENSOR, name);
|
||||||
|
|
||||||
|
lux = linux_read_illuminance_sensor(sensor);
|
||||||
|
if (lux >= 0)
|
||||||
|
{ /* If we found an illuminance sensor that works... */
|
||||||
|
sensor->millilux = (int)(lux * 1000.0); /* Set the first reading */
|
||||||
|
sensor->thread = sthread_create(linux_poll_illuminance_sensor, sensor);
|
||||||
|
|
||||||
|
if (!sensor->thread)
|
||||||
|
{
|
||||||
|
RARCH_ERR("Failed to spawn thread for illuminance sensor\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
RARCH_LOG("Opened illuminance sensor at %s, polling at %u Hz\n", sensor->path, sensor->poll_rate);
|
||||||
|
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
RARCH_ERR("Failed to find an illuminance sensor\n");
|
||||||
|
retro_closedir(device);
|
||||||
|
|
||||||
|
free(sensor);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
done:
|
||||||
|
retro_closedir(device);
|
||||||
|
|
||||||
|
return sensor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void linux_close_illuminance_sensor(linux_illuminance_sensor_t *sensor)
|
||||||
|
{
|
||||||
|
if (!sensor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sensor->thread)
|
||||||
|
{
|
||||||
|
pthread_t thread = sthread_get_thread_id(sensor->thread);
|
||||||
|
sensor->done = true;
|
||||||
|
|
||||||
|
if (pthread_cancel(thread) != 0)
|
||||||
|
{
|
||||||
|
int err = errno;
|
||||||
|
char errmesg[NAME_MAX_LENGTH];
|
||||||
|
strerror_r(err, errmesg, sizeof(errmesg));
|
||||||
|
RARCH_ERR("Failed to cancel illuminance sensor thread: %s\n", errmesg);
|
||||||
|
/* this doesn't happen often, it should probably be logged */
|
||||||
|
}
|
||||||
|
|
||||||
|
sthread_join(sensor->thread);
|
||||||
|
/* sthread_join will free the thread */
|
||||||
|
}
|
||||||
|
|
||||||
|
free(sensor);
|
||||||
|
}
|
||||||
|
|
||||||
|
float linux_get_illuminance_reading(const linux_illuminance_sensor_t *sensor)
|
||||||
|
{
|
||||||
|
int millilux;
|
||||||
|
if (!sensor)
|
||||||
|
return -1.0f;
|
||||||
|
|
||||||
|
/* Reading an int is atomic on most CPUs */
|
||||||
|
millilux = sensor->millilux;
|
||||||
|
|
||||||
|
return (float)millilux / 1000.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void linux_set_illuminance_sensor_rate(linux_illuminance_sensor_t *sensor, unsigned rate)
|
||||||
|
{
|
||||||
|
if (!sensor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Set a default rate of 5 Hz if none is provided */
|
||||||
|
rate = rate ? rate : DEFAULT_POLL_RATE;
|
||||||
|
|
||||||
|
sensor->poll_rate = rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double linux_read_illuminance_sensor(const linux_illuminance_sensor_t *sensor)
|
||||||
|
{
|
||||||
|
char buffer[256];
|
||||||
|
double illuminance = 0.0;
|
||||||
|
RFILE *in_illuminance_input = NULL;
|
||||||
|
|
||||||
|
if (!sensor || sensor->path[0] == '\0')
|
||||||
|
return -1.0;
|
||||||
|
|
||||||
|
in_illuminance_input = filestream_open(sensor->path, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||||
|
if (!in_illuminance_input)
|
||||||
|
{
|
||||||
|
RARCH_ERR("Failed to open %s\n", sensor->path);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!filestream_gets(in_illuminance_input, buffer, sizeof(buffer)))
|
||||||
|
{ /* Read the illuminance value from the file. If that fails... */
|
||||||
|
RARCH_ERR("Illuminance sensor read failed\n");
|
||||||
|
illuminance = -1.0;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: This may be locale-sensitive */
|
||||||
|
illuminance = strtod(buffer, NULL);
|
||||||
|
if (errno != 0)
|
||||||
|
{
|
||||||
|
RARCH_ERR("Failed to parse input \"%s\" into a floating-point value\n", buffer);
|
||||||
|
illuminance = -1.0;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (in_illuminance_input)
|
||||||
|
filestream_close(in_illuminance_input);
|
||||||
|
|
||||||
|
return illuminance;
|
||||||
|
}
|
||||||
|
@ -27,4 +27,25 @@ bool linux_terminal_grab_stdin(void *data);
|
|||||||
|
|
||||||
bool linux_terminal_disable_input(void);
|
bool linux_terminal_disable_input(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Corresponds to the illuminance sensor exposed via the IIO interface.
|
||||||
|
* @see https://github.com/torvalds/linux/blob/master/Documentation/ABI/testing/sysfs-bus-iio
|
||||||
|
*/
|
||||||
|
typedef struct linux_illuminance_sensor linux_illuminance_sensor_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates through /sys/bus/iio/devices and returns the first illuminance sensor found,
|
||||||
|
* or NULL if none was found.
|
||||||
|
*
|
||||||
|
* @param rate The rate at which to poll the sensor, in Hz.
|
||||||
|
*/
|
||||||
|
linux_illuminance_sensor_t *linux_open_illuminance_sensor(unsigned rate);
|
||||||
|
|
||||||
|
void linux_close_illuminance_sensor(linux_illuminance_sensor_t *sensor);
|
||||||
|
|
||||||
|
/** Returns the light sensor's most recent reading in lux, or a negative number on error. */
|
||||||
|
float linux_get_illuminance_reading(const linux_illuminance_sensor_t *sensor);
|
||||||
|
|
||||||
|
void linux_set_illuminance_sensor_rate(linux_illuminance_sensor_t *sensor, unsigned rate);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
typedef struct linuxraw_input
|
typedef struct linuxraw_input
|
||||||
{
|
{
|
||||||
bool state[0x80];
|
bool state[0x80];
|
||||||
|
linux_illuminance_sensor_t *illuminance_sensor;
|
||||||
} linuxraw_input_t;
|
} linuxraw_input_t;
|
||||||
|
|
||||||
static void *linuxraw_input_init(const char *joypad_driver)
|
static void *linuxraw_input_init(const char *joypad_driver)
|
||||||
@ -165,9 +166,62 @@ static void linuxraw_input_free(void *data)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
linux_terminal_restore_input();
|
linux_terminal_restore_input();
|
||||||
|
linux_close_illuminance_sensor(linuxraw->illuminance_sensor);
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool linuxraw_input_set_sensor_state(void *data, unsigned port, enum retro_sensor_action action, unsigned rate)
|
||||||
|
{
|
||||||
|
linuxraw_input_t *linuxraw = (linuxraw_input_t*)data;
|
||||||
|
|
||||||
|
if (!linuxraw)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case RETRO_SENSOR_ILLUMINANCE_DISABLE:
|
||||||
|
/* If already disabled, then do nothing */
|
||||||
|
linux_close_illuminance_sensor(linuxraw->illuminance_sensor); /* noop if NULL */
|
||||||
|
linuxraw->illuminance_sensor = NULL;
|
||||||
|
case RETRO_SENSOR_GYROSCOPE_DISABLE:
|
||||||
|
case RETRO_SENSOR_ACCELEROMETER_DISABLE:
|
||||||
|
/** Unimplemented sensor actions that probably shouldn't fail */
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case RETRO_SENSOR_ILLUMINANCE_ENABLE:
|
||||||
|
if (linuxraw->illuminance_sensor)
|
||||||
|
/* If the light sensor is already open, just set the rate */
|
||||||
|
linux_set_illuminance_sensor_rate(linuxraw->illuminance_sensor, rate);
|
||||||
|
else
|
||||||
|
linuxraw->illuminance_sensor = linux_open_illuminance_sensor(rate);
|
||||||
|
|
||||||
|
return linuxraw->illuminance_sensor != NULL;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float linuxraw_input_get_sensor_input(void *data, unsigned port, unsigned id)
|
||||||
|
{
|
||||||
|
linuxraw_input_t *linuxraw = (linuxraw_input_t*)data;
|
||||||
|
|
||||||
|
if (!linuxraw)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case RETRO_SENSOR_ILLUMINANCE:
|
||||||
|
if (linuxraw->illuminance_sensor)
|
||||||
|
return linux_get_illuminance_reading(linuxraw->illuminance_sensor);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
static void linuxraw_input_poll(void *data)
|
static void linuxraw_input_poll(void *data)
|
||||||
{
|
{
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
@ -194,7 +248,7 @@ static void linuxraw_input_poll(void *data)
|
|||||||
|
|
||||||
static uint64_t linuxraw_get_capabilities(void *data)
|
static uint64_t linuxraw_get_capabilities(void *data)
|
||||||
{
|
{
|
||||||
return (1 << RETRO_DEVICE_JOYPAD)
|
return (1 << RETRO_DEVICE_JOYPAD)
|
||||||
| (1 << RETRO_DEVICE_ANALOG);
|
| (1 << RETRO_DEVICE_ANALOG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,8 +257,8 @@ input_driver_t input_linuxraw = {
|
|||||||
linuxraw_input_poll,
|
linuxraw_input_poll,
|
||||||
linuxraw_input_state,
|
linuxraw_input_state,
|
||||||
linuxraw_input_free,
|
linuxraw_input_free,
|
||||||
NULL,
|
linuxraw_input_set_sensor_state,
|
||||||
NULL,
|
linuxraw_input_get_sensor_input,
|
||||||
linuxraw_get_capabilities,
|
linuxraw_get_capabilities,
|
||||||
"linuxraw",
|
"linuxraw",
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
|
@ -30,6 +30,10 @@
|
|||||||
#include "../../retroarch.h"
|
#include "../../retroarch.h"
|
||||||
#include "../../tasks/tasks_internal.h"
|
#include "../../tasks/tasks_internal.h"
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include "../common/linux_common.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SDL2
|
#ifdef HAVE_SDL2
|
||||||
#include "../../gfx/common/sdl2_common.h"
|
#include "../../gfx/common/sdl2_common.h"
|
||||||
#endif
|
#endif
|
||||||
@ -54,6 +58,10 @@ typedef struct sdl_input
|
|||||||
int mouse_wd;
|
int mouse_wd;
|
||||||
int mouse_wl;
|
int mouse_wl;
|
||||||
int mouse_wr;
|
int mouse_wr;
|
||||||
|
#ifdef __linux__
|
||||||
|
/* Light sensors aren't exposed through SDL, and they're not usually part of controllers */
|
||||||
|
linux_illuminance_sensor_t *illuminance_sensor;
|
||||||
|
#endif
|
||||||
} sdl_input_t;
|
} sdl_input_t;
|
||||||
|
|
||||||
#ifdef WEBOS
|
#ifdef WEBOS
|
||||||
@ -249,7 +257,7 @@ static int16_t sdl_input_state(
|
|||||||
if (idx == 0)
|
if (idx == 0)
|
||||||
{
|
{
|
||||||
struct video_viewport vp;
|
struct video_viewport vp;
|
||||||
bool screen = device ==
|
bool screen = device ==
|
||||||
RARCH_DEVICE_POINTER_SCREEN;
|
RARCH_DEVICE_POINTER_SCREEN;
|
||||||
const int edge_detect = 32700;
|
const int edge_detect = 32700;
|
||||||
bool inside = false;
|
bool inside = false;
|
||||||
@ -275,7 +283,7 @@ static int16_t sdl_input_state(
|
|||||||
res_y = res_screen_y;
|
res_y = res_screen_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
inside = (res_x >= -edge_detect)
|
inside = (res_x >= -edge_detect)
|
||||||
&& (res_y >= -edge_detect)
|
&& (res_y >= -edge_detect)
|
||||||
&& (res_x <= edge_detect)
|
&& (res_x <= edge_detect)
|
||||||
&& (res_y <= edge_detect);
|
&& (res_y <= edge_detect);
|
||||||
@ -325,6 +333,7 @@ static void sdl_input_free(void *data)
|
|||||||
#ifndef HAVE_SDL2
|
#ifndef HAVE_SDL2
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
#endif
|
#endif
|
||||||
|
sdl_input_t *sdl = (sdl_input_t*)data;
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
return;
|
return;
|
||||||
@ -336,9 +345,73 @@ static void sdl_input_free(void *data)
|
|||||||
while (SDL_PollEvent(&event));
|
while (SDL_PollEvent(&event));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
linux_close_illuminance_sensor(sdl->illuminance_sensor); /* noop if NULL */
|
||||||
|
#endif
|
||||||
|
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool sdl_set_sensor_state(void *data, unsigned port, enum retro_sensor_action action, unsigned rate)
|
||||||
|
{
|
||||||
|
sdl_input_t *sdl = (sdl_input_t*)data;
|
||||||
|
|
||||||
|
if (!sdl)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case RETRO_SENSOR_ILLUMINANCE_DISABLE:
|
||||||
|
#ifdef __linux__
|
||||||
|
/* If already disabled, then do nothing */
|
||||||
|
linux_close_illuminance_sensor(sdl->illuminance_sensor); /* noop if NULL */
|
||||||
|
sdl->illuminance_sensor = NULL;
|
||||||
|
#endif
|
||||||
|
case RETRO_SENSOR_GYROSCOPE_DISABLE:
|
||||||
|
case RETRO_SENSOR_ACCELEROMETER_DISABLE:
|
||||||
|
/** Unimplemented sensor actions that probably shouldn't fail */
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case RETRO_SENSOR_ILLUMINANCE_ENABLE:
|
||||||
|
#ifdef __linux__
|
||||||
|
/* Unsupported on non-Linux platforms */
|
||||||
|
if (sdl->illuminance_sensor)
|
||||||
|
/* If we already have a sensor, just set the rate */
|
||||||
|
linux_set_illuminance_sensor_rate(sdl->illuminance_sensor, rate);
|
||||||
|
else
|
||||||
|
sdl->illuminance_sensor = linux_open_illuminance_sensor(rate);
|
||||||
|
|
||||||
|
return sdl->illuminance_sensor != NULL;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float sdl_get_sensor_input(void *data, unsigned port, unsigned id)
|
||||||
|
{
|
||||||
|
sdl_input_t *sdl = (sdl_input_t*)data;
|
||||||
|
|
||||||
|
if (!sdl)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case RETRO_SENSOR_ILLUMINANCE:
|
||||||
|
#ifdef __linux__
|
||||||
|
if (sdl->illuminance_sensor)
|
||||||
|
return linux_get_illuminance_reading(sdl->illuminance_sensor);
|
||||||
|
#endif
|
||||||
|
/* Unsupported on non-Linux platforms */
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SDL2
|
#ifdef HAVE_SDL2
|
||||||
static void sdl2_grab_mouse(void *data, bool state)
|
static void sdl2_grab_mouse(void *data, bool state)
|
||||||
{
|
{
|
||||||
@ -397,7 +470,7 @@ static void sdl_input_poll(void *data)
|
|||||||
switch ((int) event.key.keysym.scancode)
|
switch ((int) event.key.keysym.scancode)
|
||||||
{
|
{
|
||||||
case SDL_WEBOS_SCANCODE_BACK:
|
case SDL_WEBOS_SCANCODE_BACK:
|
||||||
/* Because webOS is sending DOWN/UP at the same time,
|
/* Because webOS is sending DOWN/UP at the same time,
|
||||||
we save this flag for later */
|
we save this flag for later */
|
||||||
sdl_webos_special_keymap[sdl_webos_spkey_back] |= event.type == SDL_KEYDOWN;
|
sdl_webos_special_keymap[sdl_webos_spkey_back] |= event.type == SDL_KEYDOWN;
|
||||||
code = RETROK_BACKSPACE;
|
code = RETROK_BACKSPACE;
|
||||||
@ -478,8 +551,8 @@ input_driver_t input_sdl = {
|
|||||||
sdl_input_poll,
|
sdl_input_poll,
|
||||||
sdl_input_state,
|
sdl_input_state,
|
||||||
sdl_input_free,
|
sdl_input_free,
|
||||||
NULL,
|
sdl_set_sensor_state,
|
||||||
NULL,
|
sdl_get_sensor_input,
|
||||||
sdl_get_capabilities,
|
sdl_get_capabilities,
|
||||||
#ifdef HAVE_SDL2
|
#ifdef HAVE_SDL2
|
||||||
"sdl2",
|
"sdl2",
|
||||||
|
@ -569,6 +569,8 @@ typedef struct udev_input
|
|||||||
#ifdef UDEV_XKB_HANDLING
|
#ifdef UDEV_XKB_HANDLING
|
||||||
bool xkb_handling;
|
bool xkb_handling;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
linux_illuminance_sensor_t *illuminance_sensor;
|
||||||
} udev_input_t;
|
} udev_input_t;
|
||||||
|
|
||||||
#ifdef UDEV_XKB_HANDLING
|
#ifdef UDEV_XKB_HANDLING
|
||||||
@ -4013,9 +4015,63 @@ static void udev_input_free(void *data)
|
|||||||
|
|
||||||
udev_input_kb_free(udev);
|
udev_input_kb_free(udev);
|
||||||
|
|
||||||
|
linux_close_illuminance_sensor(udev->illuminance_sensor);
|
||||||
|
|
||||||
free(udev);
|
free(udev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool udev_set_sensor_state(void *data, unsigned port, enum retro_sensor_action action, unsigned rate)
|
||||||
|
{
|
||||||
|
udev_input_t *udev = (udev_input_t*)data;
|
||||||
|
|
||||||
|
if (!udev)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case RETRO_SENSOR_ILLUMINANCE_DISABLE:
|
||||||
|
/* If already disabled, then do nothing */
|
||||||
|
linux_close_illuminance_sensor(udev->illuminance_sensor); /* noop if NULL */
|
||||||
|
udev->illuminance_sensor = NULL;
|
||||||
|
case RETRO_SENSOR_GYROSCOPE_DISABLE:
|
||||||
|
case RETRO_SENSOR_ACCELEROMETER_DISABLE:
|
||||||
|
/** Unimplemented sensor actions that probably shouldn't fail */
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case RETRO_SENSOR_ILLUMINANCE_ENABLE:
|
||||||
|
if (udev->illuminance_sensor)
|
||||||
|
/* If we already have a sensor, just set the rate */
|
||||||
|
linux_set_illuminance_sensor_rate(udev->illuminance_sensor, rate);
|
||||||
|
else
|
||||||
|
udev->illuminance_sensor = linux_open_illuminance_sensor(rate);
|
||||||
|
|
||||||
|
return udev->illuminance_sensor != NULL;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float udev_get_sensor_input(void *data, unsigned port, unsigned id)
|
||||||
|
{
|
||||||
|
udev_input_t *udev = (udev_input_t*)data;
|
||||||
|
|
||||||
|
if (!udev)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case RETRO_SENSOR_ILLUMINANCE:
|
||||||
|
if (udev->illuminance_sensor)
|
||||||
|
return linux_get_illuminance_reading(udev->illuminance_sensor);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
static bool open_devices(udev_input_t *udev,
|
static bool open_devices(udev_input_t *udev,
|
||||||
enum udev_input_dev_type type, device_handle_cb cb)
|
enum udev_input_dev_type type, device_handle_cb cb)
|
||||||
{
|
{
|
||||||
@ -4227,8 +4283,8 @@ input_driver_t input_udev = {
|
|||||||
udev_input_poll,
|
udev_input_poll,
|
||||||
udev_input_state,
|
udev_input_state,
|
||||||
udev_input_free,
|
udev_input_free,
|
||||||
NULL,
|
udev_set_sensor_state,
|
||||||
NULL,
|
udev_get_sensor_input,
|
||||||
udev_input_get_capabilities,
|
udev_input_get_capabilities,
|
||||||
"udev",
|
"udev",
|
||||||
udev_input_grab_mouse,
|
udev_input_grab_mouse,
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "../input_keymaps.h"
|
#include "../input_keymaps.h"
|
||||||
|
|
||||||
#include "../common/input_x11_common.h"
|
#include "../common/input_x11_common.h"
|
||||||
|
#include "../common/linux_common.h"
|
||||||
|
|
||||||
#include "../../configuration.h"
|
#include "../../configuration.h"
|
||||||
#include "../../retroarch.h"
|
#include "../../retroarch.h"
|
||||||
@ -45,6 +46,10 @@ typedef struct x11_input
|
|||||||
bool mouse_l;
|
bool mouse_l;
|
||||||
bool mouse_r;
|
bool mouse_r;
|
||||||
bool mouse_m;
|
bool mouse_m;
|
||||||
|
#ifdef __linux__
|
||||||
|
/* X11 is mostly used on Linux, but not exclusively. */
|
||||||
|
linux_illuminance_sensor_t *illuminance_sensor;
|
||||||
|
#endif
|
||||||
} x11_input_t;
|
} x11_input_t;
|
||||||
|
|
||||||
/* Public global variable */
|
/* Public global variable */
|
||||||
@ -342,7 +347,7 @@ static int16_t x_input_state(
|
|||||||
x11->mouse_x, x11->mouse_y,
|
x11->mouse_x, x11->mouse_y,
|
||||||
&res_x, &res_y, &res_screen_x, &res_screen_y))
|
&res_x, &res_y, &res_screen_x, &res_screen_y))
|
||||||
{
|
{
|
||||||
inside = (res_x >= -edge_detect)
|
inside = (res_x >= -edge_detect)
|
||||||
&& (res_y >= -edge_detect)
|
&& (res_y >= -edge_detect)
|
||||||
&& (res_x <= edge_detect)
|
&& (res_x <= edge_detect)
|
||||||
&& (res_y <= edge_detect);
|
&& (res_y <= edge_detect);
|
||||||
@ -397,10 +402,10 @@ static int16_t x_input_state(
|
|||||||
joyport, (uint16_t)joykey))
|
joyport, (uint16_t)joykey))
|
||||||
return 1;
|
return 1;
|
||||||
if (joyaxis != AXIS_NONE &&
|
if (joyaxis != AXIS_NONE &&
|
||||||
((float)abs(joypad->axis(joyport, joyaxis))
|
((float)abs(joypad->axis(joyport, joyaxis))
|
||||||
/ 0x8000) > axis_threshold)
|
/ 0x8000) > axis_threshold)
|
||||||
return 1;
|
return 1;
|
||||||
else if ((binds[port][new_id].key && binds[port][new_id].key < RETROK_LAST)
|
else if ((binds[port][new_id].key && binds[port][new_id].key < RETROK_LAST)
|
||||||
&& !keyboard_mapping_blocked
|
&& !keyboard_mapping_blocked
|
||||||
&& x_keyboard_pressed(x11, binds[port][new_id].key)
|
&& x_keyboard_pressed(x11, binds[port][new_id].key)
|
||||||
)
|
)
|
||||||
@ -431,7 +436,70 @@ static void x_input_free(void *data)
|
|||||||
x11_input_t *x11 = (x11_input_t*)data;
|
x11_input_t *x11 = (x11_input_t*)data;
|
||||||
|
|
||||||
if (x11)
|
if (x11)
|
||||||
|
{
|
||||||
|
#ifdef __linux__
|
||||||
|
linux_close_illuminance_sensor(x11->illuminance_sensor);
|
||||||
|
#endif
|
||||||
free(x11);
|
free(x11);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool x_set_sensor_state(void *data, unsigned port, enum retro_sensor_action action, unsigned rate)
|
||||||
|
{
|
||||||
|
x11_input_t *x11 = (x11_input_t*)data;
|
||||||
|
|
||||||
|
if (!x11)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case RETRO_SENSOR_ILLUMINANCE_DISABLE:
|
||||||
|
/* If already disabled, then do nothing */
|
||||||
|
#ifdef __linux__
|
||||||
|
linux_close_illuminance_sensor(x11->illuminance_sensor); /* noop if NULL */
|
||||||
|
x11->illuminance_sensor = NULL;
|
||||||
|
#endif
|
||||||
|
case RETRO_SENSOR_GYROSCOPE_DISABLE:
|
||||||
|
case RETRO_SENSOR_ACCELEROMETER_DISABLE:
|
||||||
|
/** Unimplemented sensor actions that probably shouldn't fail */
|
||||||
|
return true;
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
case RETRO_SENSOR_ILLUMINANCE_ENABLE:
|
||||||
|
if (x11->illuminance_sensor)
|
||||||
|
/* If we already have a sensor, just set the rate */
|
||||||
|
linux_set_illuminance_sensor_rate(x11->illuminance_sensor, rate);
|
||||||
|
else
|
||||||
|
x11->illuminance_sensor = linux_open_illuminance_sensor(rate);
|
||||||
|
|
||||||
|
return x11->illuminance_sensor != NULL;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float x_get_sensor_input(void *data, unsigned port, unsigned id)
|
||||||
|
{
|
||||||
|
x11_input_t *x11 = (x11_input_t*)data;
|
||||||
|
|
||||||
|
if (!x11)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
#ifdef __linux__
|
||||||
|
case RETRO_SENSOR_ILLUMINANCE:
|
||||||
|
if (x11->illuminance_sensor)
|
||||||
|
return linux_get_illuminance_reading(x11->illuminance_sensor);
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void x_input_poll(void *data)
|
static void x_input_poll(void *data)
|
||||||
@ -488,7 +556,7 @@ static void x_input_poll(void *data)
|
|||||||
x11->mouse_m = mask & Button2Mask;
|
x11->mouse_m = mask & Button2Mask;
|
||||||
x11->mouse_r = mask & Button3Mask;
|
x11->mouse_r = mask & Button3Mask;
|
||||||
/* Buttons 4 and 5 are not returned here, so they are handled elsewhere. */
|
/* Buttons 4 and 5 are not returned here, so they are handled elsewhere. */
|
||||||
|
|
||||||
/* > Mouse pointer */
|
/* > Mouse pointer */
|
||||||
if (!x11->mouse_grabbed)
|
if (!x11->mouse_grabbed)
|
||||||
{
|
{
|
||||||
@ -538,13 +606,13 @@ static void x_input_poll(void *data)
|
|||||||
x11->mouse_y += x11->mouse_delta_y;
|
x11->mouse_y += x11->mouse_delta_y;
|
||||||
|
|
||||||
/* Clamp X */
|
/* Clamp X */
|
||||||
if (x11->mouse_x < 0)
|
if (x11->mouse_x < 0)
|
||||||
x11->mouse_x = 0;
|
x11->mouse_x = 0;
|
||||||
if (x11->mouse_x >= win_attr.width)
|
if (x11->mouse_x >= win_attr.width)
|
||||||
x11->mouse_x = (win_attr.width - 1);
|
x11->mouse_x = (win_attr.width - 1);
|
||||||
|
|
||||||
/* Clamp Y */
|
/* Clamp Y */
|
||||||
if (x11->mouse_y < 0)
|
if (x11->mouse_y < 0)
|
||||||
x11->mouse_y = 0;
|
x11->mouse_y = 0;
|
||||||
if (x11->mouse_y >= win_attr.height)
|
if (x11->mouse_y >= win_attr.height)
|
||||||
x11->mouse_y = (win_attr.height - 1);
|
x11->mouse_y = (win_attr.height - 1);
|
||||||
@ -604,8 +672,14 @@ input_driver_t input_x = {
|
|||||||
x_input_poll,
|
x_input_poll,
|
||||||
x_input_state,
|
x_input_state,
|
||||||
x_input_free,
|
x_input_free,
|
||||||
|
#ifdef __linux__
|
||||||
|
/* Right now this driver only supports the illuminance sensor on Linux. */
|
||||||
|
x_set_sensor_state,
|
||||||
|
x_get_sensor_input,
|
||||||
|
#else
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
#endif
|
||||||
x_input_get_capabilities,
|
x_input_get_capabilities,
|
||||||
"x",
|
"x",
|
||||||
x_grab_mouse,
|
x_grab_mouse,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user