diff --git a/CHANGES.md b/CHANGES.md
index 55bf4046901..87fea157f7f 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -25,6 +25,7 @@
- INPUT: Enable Caps, Num, Scroll Lock modifiers on multiple platforms
- INPUT: Autoconfig extension with alternative name/vid/pid
- 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/UDEV: Enable mouse buttons 4 and 5
- INPUT/WAYLAND: Enable horizontal scroll and mouse buttons 4 and 5
diff --git a/input/common/linux_common.c b/input/common/linux_common.c
index a29d0561565..784da46f860 100644
--- a/input/common/linux_common.c
+++ b/input/common/linux_common.c
@@ -14,22 +14,57 @@
* If not, see .
*/
+#include
#include
-
+#include
#include
+#include
+#include
#include
#include
#include
#include
#include "linux_common.h"
+#include "verbosity.h"
+#include
+#include
+#include
+
+/* We can assume that pthreads are available on Linux. */
+#include
+#include
+
+#define IIO_DEVICES_DIR "/sys/bus/iio/devices"
+#define IIO_ILLUMINANCE_SENSOR "in_illuminance_input"
+#define DEFAULT_POLL_RATE 5
/* TODO/FIXME - static globals */
static struct termios old_term, new_term;
static long old_kbmd = 0xffff;
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)
{
if (old_kbmd == 0xffff)
@@ -121,3 +156,222 @@ bool linux_terminal_disable_input(void)
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)
+{
+ DIR *devices = NULL;
+ struct dirent *d = 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;
+
+ devices = opendir(IIO_DEVICES_DIR);
+ if (!devices)
+ { /* If we couldn't find the IIO device directory... */
+ char errmesg[NAME_MAX_LENGTH];
+ strerror_r(errno, errmesg, sizeof(errmesg));
+ RARCH_ERR("Failed to open " IIO_DEVICES_DIR ": %s\n", errmesg);
+ goto error;
+ }
+
+ /*
+ * Must clear errno at the start of each iteration,
+ * as an error code that came from one run of the loop
+ * can leak into the next iteration and hide serious errors.
+ * (Ex: trying to open a file that doesn't exist,
+ * which we handle here.)
+ */
+ errno = 0;
+ for (d = readdir(devices); d != NULL; errno = 0, d = readdir(devices))
+ { /* For each IIO device... */
+ /* First ensure that the readdir call succeeded... */
+ int err = errno;
+ double lux;
+
+ if (d->d_name[0] == '.')
+ /* Skip hidden files, ".", and ".." */
+ continue;
+
+ if (err != 0)
+ {
+ char errmesg[NAME_MAX_LENGTH];
+ strerror_r(err, errmesg, sizeof(errmesg));
+ RARCH_ERR("readdir(" IIO_DEVICES_DIR ") failed: %s\n", errmesg);
+ goto error;
+ }
+
+ /* 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, d->d_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");
+ if (devices)
+ closedir(devices);
+
+ free(sensor);
+
+ return NULL;
+done:
+ if (devices)
+ closedir(devices);
+
+ 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);
+ }
+
+ 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;
+ int err;
+ FILE* in_illuminance_input = NULL;
+
+ if (!sensor || sensor->path[0] == '\0')
+ return -1.0;
+
+ in_illuminance_input = fopen(sensor->path, "r");
+ if (!in_illuminance_input)
+ {
+ char errmesg[NAME_MAX_LENGTH];
+ strerror_r(errno, errmesg, sizeof(errmesg));
+ RARCH_ERR("Failed to open %s: %s\n", sensor->path, errmesg);
+ illuminance = -1.0;
+ goto done;
+ }
+
+ if (!fgets(buffer, sizeof(buffer), in_illuminance_input))
+ { /* Read the illuminance value from the file. If that fails... */
+ char errmesg[NAME_MAX_LENGTH];
+ strerror_r(errno, errmesg, sizeof(errmesg));
+ RARCH_ERR("Illuminance sensor read failed: %s\n", errmesg);
+ illuminance = -1.0;
+ goto done;
+ }
+
+ /* TODO: This may be locale-sensitive */
+ errno = 0;
+ illuminance = strtod(buffer, NULL);
+ err = errno;
+ if (err != 0)
+ {
+ char errmesg[NAME_MAX_LENGTH];
+ strerror_r(err, errmesg, sizeof(errmesg));
+ RARCH_ERR("Failed to parse input \"%s\" into a floating-point value: %s", buffer, errmesg);
+ illuminance = -1.0;
+ goto done;
+ }
+
+done:
+ if (in_illuminance_input)
+ fclose(in_illuminance_input);
+
+ return illuminance;
+}
diff --git a/input/common/linux_common.h b/input/common/linux_common.h
index b530b71c433..3b3df499d8f 100644
--- a/input/common/linux_common.h
+++ b/input/common/linux_common.h
@@ -27,4 +27,25 @@ bool linux_terminal_grab_stdin(void *data);
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
diff --git a/input/drivers/linuxraw_input.c b/input/drivers/linuxraw_input.c
index 098b70ab48c..1788c1f283c 100644
--- a/input/drivers/linuxraw_input.c
+++ b/input/drivers/linuxraw_input.c
@@ -35,6 +35,7 @@
typedef struct linuxraw_input
{
bool state[0x80];
+ linux_illuminance_sensor_t *illuminance_sensor;
} linuxraw_input_t;
static void *linuxraw_input_init(const char *joypad_driver)
@@ -165,9 +166,62 @@ static void linuxraw_input_free(void *data)
return;
linux_terminal_restore_input();
+ linux_close_illuminance_sensor(linuxraw->illuminance_sensor);
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)
{
uint8_t c;
@@ -194,7 +248,7 @@ static void linuxraw_input_poll(void *data)
static uint64_t linuxraw_get_capabilities(void *data)
{
- return (1 << RETRO_DEVICE_JOYPAD)
+ return (1 << RETRO_DEVICE_JOYPAD)
| (1 << RETRO_DEVICE_ANALOG);
}
@@ -203,8 +257,8 @@ input_driver_t input_linuxraw = {
linuxraw_input_poll,
linuxraw_input_state,
linuxraw_input_free,
- NULL,
- NULL,
+ linuxraw_input_set_sensor_state,
+ linuxraw_input_get_sensor_input,
linuxraw_get_capabilities,
"linuxraw",
NULL, /* grab_mouse */
diff --git a/input/drivers/sdl_input.c b/input/drivers/sdl_input.c
index 169e92bffa7..83c9419fe32 100644
--- a/input/drivers/sdl_input.c
+++ b/input/drivers/sdl_input.c
@@ -30,6 +30,10 @@
#include "../../retroarch.h"
#include "../../tasks/tasks_internal.h"
+#ifdef __linux__
+#include "../common/linux_common.h"
+#endif
+
#ifdef HAVE_SDL2
#include "../../gfx/common/sdl2_common.h"
#endif
@@ -54,6 +58,10 @@ typedef struct sdl_input
int mouse_wd;
int mouse_wl;
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;
#ifdef WEBOS
@@ -249,7 +257,7 @@ static int16_t sdl_input_state(
if (idx == 0)
{
struct video_viewport vp;
- bool screen = device ==
+ bool screen = device ==
RARCH_DEVICE_POINTER_SCREEN;
const int edge_detect = 32700;
bool inside = false;
@@ -275,7 +283,7 @@ static int16_t sdl_input_state(
res_y = res_screen_y;
}
- inside = (res_x >= -edge_detect)
+ inside = (res_x >= -edge_detect)
&& (res_y >= -edge_detect)
&& (res_x <= edge_detect)
&& (res_y <= edge_detect);
@@ -325,6 +333,7 @@ static void sdl_input_free(void *data)
#ifndef HAVE_SDL2
SDL_Event event;
#endif
+ sdl_input_t *sdl = (sdl_input_t*)data;
if (!data)
return;
@@ -336,9 +345,73 @@ static void sdl_input_free(void *data)
while (SDL_PollEvent(&event));
#endif
+#ifdef __linux__
+ linux_close_illuminance_sensor(sdl->illuminance_sensor); /* noop if NULL */
+#endif
+
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
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)
{
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 */
sdl_webos_special_keymap[sdl_webos_spkey_back] |= event.type == SDL_KEYDOWN;
code = RETROK_BACKSPACE;
@@ -478,8 +551,8 @@ input_driver_t input_sdl = {
sdl_input_poll,
sdl_input_state,
sdl_input_free,
- NULL,
- NULL,
+ sdl_set_sensor_state,
+ sdl_get_sensor_input,
sdl_get_capabilities,
#ifdef HAVE_SDL2
"sdl2",
diff --git a/input/drivers/udev_input.c b/input/drivers/udev_input.c
index 294aaa27e0d..bfa5f6afabc 100644
--- a/input/drivers/udev_input.c
+++ b/input/drivers/udev_input.c
@@ -569,6 +569,8 @@ typedef struct udev_input
#ifdef UDEV_XKB_HANDLING
bool xkb_handling;
#endif
+
+ linux_illuminance_sensor_t *illuminance_sensor;
} udev_input_t;
#ifdef UDEV_XKB_HANDLING
@@ -4013,9 +4015,63 @@ static void udev_input_free(void *data)
udev_input_kb_free(udev);
+ linux_close_illuminance_sensor(udev->illuminance_sensor);
+
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,
enum udev_input_dev_type type, device_handle_cb cb)
{
@@ -4227,8 +4283,8 @@ input_driver_t input_udev = {
udev_input_poll,
udev_input_state,
udev_input_free,
- NULL,
- NULL,
+ udev_set_sensor_state,
+ udev_get_sensor_input,
udev_input_get_capabilities,
"udev",
udev_input_grab_mouse,
diff --git a/input/drivers/x11_input.c b/input/drivers/x11_input.c
index 69d7b68176a..8c6bcad13f3 100644
--- a/input/drivers/x11_input.c
+++ b/input/drivers/x11_input.c
@@ -27,6 +27,7 @@
#include "../input_keymaps.h"
#include "../common/input_x11_common.h"
+#include "../common/linux_common.h"
#include "../../configuration.h"
#include "../../retroarch.h"
@@ -45,6 +46,10 @@ typedef struct x11_input
bool mouse_l;
bool mouse_r;
bool mouse_m;
+#ifdef __linux__
+ /* X11 is mostly used on Linux, but not exclusively. */
+ linux_illuminance_sensor_t *illuminance_sensor;
+#endif
} x11_input_t;
/* Public global variable */
@@ -342,7 +347,7 @@ static int16_t x_input_state(
x11->mouse_x, x11->mouse_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_x <= edge_detect)
&& (res_y <= edge_detect);
@@ -397,10 +402,10 @@ static int16_t x_input_state(
joyport, (uint16_t)joykey))
return 1;
if (joyaxis != AXIS_NONE &&
- ((float)abs(joypad->axis(joyport, joyaxis))
+ ((float)abs(joypad->axis(joyport, joyaxis))
/ 0x8000) > axis_threshold)
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
&& 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;
if (x11)
+ {
+#ifdef __linux__
+ linux_close_illuminance_sensor(x11->illuminance_sensor);
+#endif
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)
@@ -488,7 +556,7 @@ static void x_input_poll(void *data)
x11->mouse_m = mask & Button2Mask;
x11->mouse_r = mask & Button3Mask;
/* Buttons 4 and 5 are not returned here, so they are handled elsewhere. */
-
+
/* > Mouse pointer */
if (!x11->mouse_grabbed)
{
@@ -538,13 +606,13 @@ static void x_input_poll(void *data)
x11->mouse_y += x11->mouse_delta_y;
/* Clamp X */
- if (x11->mouse_x < 0)
+ if (x11->mouse_x < 0)
x11->mouse_x = 0;
if (x11->mouse_x >= win_attr.width)
x11->mouse_x = (win_attr.width - 1);
/* Clamp Y */
- if (x11->mouse_y < 0)
+ if (x11->mouse_y < 0)
x11->mouse_y = 0;
if (x11->mouse_y >= win_attr.height)
x11->mouse_y = (win_attr.height - 1);
@@ -604,8 +672,14 @@ input_driver_t input_x = {
x_input_poll,
x_input_state,
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,
+#endif
x_input_get_capabilities,
"x",
x_grab_mouse,