Skip to content

Commit d2c6f80

Browse files
authored
sdl: add support for controller sensors (#18255)
1 parent 5aa3663 commit d2c6f80

3 files changed

Lines changed: 110 additions & 18 deletions

File tree

input/drivers_joypad/sdl_joypad.c

Lines changed: 87 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
#include "../../tasks/tasks_internal.h"
2828
#include "../../verbosity.h"
2929

30+
#define SDL_SUPPORTS_RUMBLE SDL_VERSION_ATLEAST(2, 0, 9)
31+
#define SDL_SUPPORTS_SENSORS SDL_VERSION_ATLEAST(2, 0, 14)
32+
3033
typedef struct _sdl_joypad
3134
{
3235
SDL_Joystick *joypad;
@@ -216,7 +219,7 @@ static void sdl_pad_connect(unsigned id)
216219
RARCH_WARN("[SDL] Device #%u does not support leftright haptic effect.\n", id);
217220
}
218221
}
219-
#if SDL_VERSION_ATLEAST(2, 0, 9)
222+
#if SDL_SUPPORTS_RUMBLE
220223
if (!pad->haptic || pad->rumble_effect == -2)
221224
{
222225
pad->rumble_effect = -3;
@@ -299,7 +302,7 @@ static void *sdl_joypad_init(void *data)
299302
else
300303
g_has_haptic = true;
301304

302-
#if SDL_VERSION_ATLEAST(2, 0, 9)
305+
#if SDL_SUPPORTS_RUMBLE
303306
/* enable extended hid reports to support ps4/ps5 rumble over bluetooth */
304307
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
305308
#endif
@@ -504,7 +507,7 @@ static bool sdl_joypad_set_rumble(unsigned pad, enum retro_rumble_effect effect,
504507
return false;
505508
}
506509

507-
#if SDL_VERSION_ATLEAST(2, 0, 9)
510+
#if SDK_SUPPORTS_RUMBLE
508511
if (joypad->rumble_effect == -3)
509512
{
510513
if (SDL_JoystickRumble(joypad->joypad, efx.leftright.large_magnitude, efx.leftright.small_magnitude, efx.leftright.length) == -1)
@@ -548,6 +551,85 @@ static bool sdl_joypad_set_rumble(unsigned pad, enum retro_rumble_effect effect,
548551
}
549552
#endif
550553

554+
static bool sdl_joypad_set_sensor_state(unsigned pad, enum retro_sensor_action action, unsigned rate)
555+
{
556+
sdl_joypad_t *joypad = (sdl_joypad_t*)&sdl_pads[pad];
557+
(void)joypad; /* maybe unused */
558+
559+
switch (action)
560+
{
561+
#if SDL_SUPPORTS_SENSORS
562+
case RETRO_SENSOR_GYROSCOPE_DISABLE:
563+
case RETRO_SENSOR_GYROSCOPE_ENABLE:
564+
if (SDL_GameControllerHasSensor(joypad->controller, SDL_SENSOR_GYRO))
565+
return !SDL_GameControllerSetSensorEnabled(joypad->controller, SDL_SENSOR_GYRO,
566+
action == RETRO_SENSOR_GYROSCOPE_ENABLE);
567+
else
568+
return false;
569+
570+
case RETRO_SENSOR_ACCELEROMETER_DISABLE:
571+
case RETRO_SENSOR_ACCELEROMETER_ENABLE:
572+
if (SDL_GameControllerHasSensor(joypad->controller, SDL_SENSOR_ACCEL))
573+
return !SDL_GameControllerSetSensorEnabled(joypad->controller, SDL_SENSOR_ACCEL,
574+
action == RETRO_SENSOR_ACCELEROMETER_ENABLE);
575+
else
576+
return false;
577+
#endif
578+
579+
default:
580+
return false;
581+
}
582+
return false;
583+
}
584+
585+
static bool sdl_joypad_get_sensor_input(unsigned pad, unsigned id, float *value)
586+
{
587+
#if SDL_SUPPORTS_SENSORS
588+
sdl_joypad_t *joypad = (sdl_joypad_t*)&sdl_pads[pad];
589+
SDL_SensorType sensor_type;
590+
float sensor_data[3];
591+
592+
if (!joypad->controller)
593+
return false;
594+
595+
if ((id >= RETRO_SENSOR_ACCELEROMETER_X) && (id <= RETRO_SENSOR_ACCELEROMETER_Z))
596+
sensor_type = SDL_SENSOR_ACCEL;
597+
else if ((id >= RETRO_SENSOR_GYROSCOPE_X) && (id <= RETRO_SENSOR_GYROSCOPE_Z))
598+
sensor_type = SDL_SENSOR_GYRO;
599+
else
600+
return false;
601+
602+
if (SDL_GameControllerGetSensorData(joypad->controller, sensor_type, sensor_data, 3) < 0)
603+
return false;
604+
605+
switch (id)
606+
{
607+
case RETRO_SENSOR_ACCELEROMETER_X:
608+
*value = sensor_data[0] / SDL_STANDARD_GRAVITY;
609+
break;
610+
case RETRO_SENSOR_ACCELEROMETER_Y:
611+
*value = sensor_data[2] / SDL_STANDARD_GRAVITY;
612+
break;
613+
case RETRO_SENSOR_ACCELEROMETER_Z:
614+
*value = sensor_data[1] / SDL_STANDARD_GRAVITY;
615+
break;
616+
case RETRO_SENSOR_GYROSCOPE_X:
617+
*value = sensor_data[0];
618+
break;
619+
case RETRO_SENSOR_GYROSCOPE_Y:
620+
*value = -sensor_data[2];
621+
break;
622+
case RETRO_SENSOR_GYROSCOPE_Z:
623+
*value = sensor_data[1];
624+
break;
625+
}
626+
627+
return true;
628+
#else
629+
return false;
630+
#endif
631+
}
632+
551633
static bool sdl_joypad_query_pad(unsigned pad)
552634
{
553635
return pad < MAX_USERS && sdl_pads[pad].joypad;
@@ -568,8 +650,8 @@ input_device_driver_t sdl_joypad = {
568650
NULL, /* set_rumble */
569651
#endif
570652
NULL, /* set_rumble_gain */
571-
NULL, /* set_sensor_state */
572-
NULL, /* get_sensor_input */
653+
sdl_joypad_set_sensor_state,
654+
sdl_joypad_get_sensor_input,
573655
sdl_joypad_name,
574656
#ifdef HAVE_SDL2
575657
"sdl2",

input/input_driver.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,7 @@ bool input_driver_set_sensor(
511511
enum retro_sensor_action action, unsigned rate)
512512
{
513513
const input_driver_t *current_driver;
514+
bool enabled = false;
514515

515516
if (!input_driver_st.current_data)
516517
return false;
@@ -521,36 +522,44 @@ bool input_driver_set_sensor(
521522
|| (action == RETRO_SENSOR_GYROSCOPE_ENABLE)
522523
|| (action == RETRO_SENSOR_ILLUMINANCE_ENABLE)))
523524
return false;
524-
if ( (current_driver = input_driver_st.current_driver)
525+
526+
if (input_driver_st.primary_joypad && input_driver_st.primary_joypad->set_sensor_state)
527+
enabled = input_driver_st.primary_joypad->set_sensor_state(port, action, rate);
528+
529+
if ( !enabled
530+
&& (current_driver = input_driver_st.current_driver)
525531
&& current_driver->set_sensor_state)
526532
{
527533
void *current_data = input_driver_st.current_data;
528-
return current_driver->set_sensor_state(current_data,
534+
enabled |= current_driver->set_sensor_state(current_data,
529535
port, action, rate);
530536
}
531-
else if (input_driver_st.primary_joypad && input_driver_st.primary_joypad->set_sensor_state)
532-
return input_driver_st.primary_joypad->set_sensor_state(NULL,
533-
port, action, rate);
534-
return false;
537+
return enabled;
535538
}
536539

537540
/**************************************/
538541

539542
float input_driver_get_sensor(
540543
unsigned port, bool sensors_enable, unsigned id)
541544
{
545+
if (!sensors_enable)
546+
return 0.0f;
547+
548+
if (input_driver_st.primary_joypad && input_driver_st.primary_joypad->get_sensor_input)
549+
{
550+
float value;
551+
/* if joypad driver's get_sensor_input returns false, let input driver try */
552+
if (input_driver_st.primary_joypad->get_sensor_input(port, id, &value))
553+
return value;
554+
}
542555
if (input_driver_st.current_data)
543556
{
544557
const input_driver_t *current_driver = input_driver_st.current_driver;
545-
if (sensors_enable && current_driver->get_sensor_input)
558+
if (current_driver->get_sensor_input)
546559
{
547560
void *current_data = input_driver_st.current_data;
548561
return current_driver->get_sensor_input(current_data, port, id);
549562
}
550-
else if (sensors_enable && input_driver_st.primary_joypad &&
551-
input_driver_st.primary_joypad->get_sensor_input)
552-
return input_driver_st.primary_joypad->get_sensor_input(NULL,
553-
port, id);
554563
}
555564

556565
return 0.0f;

input/input_driver.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -548,9 +548,10 @@ struct rarch_joypad_driver
548548
void (*poll)(void);
549549
bool (*set_rumble)(unsigned, enum retro_rumble_effect, uint16_t);
550550
bool (*set_rumble_gain)(unsigned, unsigned);
551-
bool (*set_sensor_state)(void *data, unsigned port,
551+
bool (*set_sensor_state)(unsigned port,
552552
enum retro_sensor_action action, unsigned rate);
553-
float (*get_sensor_input)(void *data, unsigned port, unsigned id);
553+
/* return true if handled; false to fall back to input driver */
554+
bool (*get_sensor_input)(unsigned port, unsigned id, float *value);
554555
const char *(*name)(unsigned);
555556

556557
const char *ident;

0 commit comments

Comments
 (0)