Added API for sensors on game controllers

Added support for the PS4 controller gyro and accelerometer on iOS and HIDAPI drivers

Also fixed an issue with the accelerometer on iOS having inverted axes
This commit is contained in:
Sam Lantinga 2020-11-17 10:30:20 -08:00
parent b79e1baa36
commit fcb21aa883
33 changed files with 810 additions and 118 deletions

View File

@ -128,6 +128,7 @@ typedef enum
SDL_CONTROLLERTOUCHPADDOWN, /**< Game controller touchpad was touched */ SDL_CONTROLLERTOUCHPADDOWN, /**< Game controller touchpad was touched */
SDL_CONTROLLERTOUCHPADMOTION, /**< Game controller touchpad finger was moved */ SDL_CONTROLLERTOUCHPADMOTION, /**< Game controller touchpad finger was moved */
SDL_CONTROLLERTOUCHPADUP, /**< Game controller touchpad finger was lifted */ SDL_CONTROLLERTOUCHPADUP, /**< Game controller touchpad finger was lifted */
SDL_CONTROLLERSENSORUPDATE, /**< Game controller sensor was updated */
/* Touch events */ /* Touch events */
SDL_FINGERDOWN = 0x700, SDL_FINGERDOWN = 0x700,
@ -426,13 +427,24 @@ typedef struct SDL_ControllerTouchpadEvent
Uint32 type; /**< ::SDL_CONTROLLERTOUCHPADDOWN or ::SDL_CONTROLLERTOUCHPADMOTION or ::SDL_CONTROLLERTOUCHPADUP */ Uint32 type; /**< ::SDL_CONTROLLERTOUCHPADDOWN or ::SDL_CONTROLLERTOUCHPADMOTION or ::SDL_CONTROLLERTOUCHPADUP */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
SDL_JoystickID which; /**< The joystick instance id */ SDL_JoystickID which; /**< The joystick instance id */
int touchpad; /**< The index of the touchpad */ Sint32 touchpad; /**< The index of the touchpad */
int finger; /**< The index of the finger on the touchpad */ Sint32 finger; /**< The index of the finger on the touchpad */
float x; /**< Normalized in the range 0...1 with 0 being on the left */ float x; /**< Normalized in the range 0...1 with 0 being on the left */
float y; /**< Normalized in the range 0...1 with 0 being at the top */ float y; /**< Normalized in the range 0...1 with 0 being at the top */
float pressure; /**< Normalized in the range 0...1 */ float pressure; /**< Normalized in the range 0...1 */
} SDL_ControllerTouchpadEvent; } SDL_ControllerTouchpadEvent;
/**
* \brief Game controller sensor event structure (event.csensor.*)
*/
typedef struct SDL_ControllerSensorEvent
{
Uint32 type; /**< ::SDL_CONTROLLERSENSORUPDATE */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
SDL_JoystickID which; /**< The joystick instance id */
Sint32 sensor; /**< The type of the sensor, one of the values of ::SDL_SensorType */
float data[3]; /**< Up to 3 values from the sensor, as defined in SDL_sensor.h */
} SDL_ControllerSensorEvent;
/** /**
* \brief Audio device event structure (event.adevice.*) * \brief Audio device event structure (event.adevice.*)
@ -597,6 +609,7 @@ typedef union SDL_Event
SDL_ControllerButtonEvent cbutton; /**< Game Controller button event data */ SDL_ControllerButtonEvent cbutton; /**< Game Controller button event data */
SDL_ControllerDeviceEvent cdevice; /**< Game Controller device event data */ SDL_ControllerDeviceEvent cdevice; /**< Game Controller device event data */
SDL_ControllerTouchpadEvent ctouchpad; /**< Game Controller touchpad event data */ SDL_ControllerTouchpadEvent ctouchpad; /**< Game Controller touchpad event data */
SDL_ControllerSensorEvent csensor; /**< Game Controller sensor event data */
SDL_AudioDeviceEvent adevice; /**< Audio device event data */ SDL_AudioDeviceEvent adevice; /**< Audio device event data */
SDL_SensorEvent sensor; /**< Sensor event data */ SDL_SensorEvent sensor; /**< Sensor event data */
SDL_QuitEvent quit; /**< Quit request event data */ SDL_QuitEvent quit; /**< Quit request event data */

View File

@ -31,6 +31,7 @@
#include "SDL_stdinc.h" #include "SDL_stdinc.h"
#include "SDL_error.h" #include "SDL_error.h"
#include "SDL_rwops.h" #include "SDL_rwops.h"
#include "SDL_sensor.h"
#include "SDL_joystick.h" #include "SDL_joystick.h"
#include "begin_code.h" #include "begin_code.h"
@ -430,6 +431,52 @@ extern DECLSPEC int SDLCALL SDL_GameControllerGetNumTouchpadFingers(SDL_GameCont
*/ */
extern DECLSPEC int SDLCALL SDL_GameControllerGetTouchpadFinger(SDL_GameController *gamecontroller, int touchpad, int finger, Uint8 *state, float *x, float *y, float *pressure); extern DECLSPEC int SDLCALL SDL_GameControllerGetTouchpadFinger(SDL_GameController *gamecontroller, int touchpad, int finger, Uint8 *state, float *x, float *y, float *pressure);
/**
* Return whether a game controller has a particular sensor.
*
* \param gamecontroller The controller to query
* \param type The type of sensor to query
*
* \return SDL_TRUE if the sensor exists, SDL_FALSE otherwise.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerHasSensor(SDL_GameController *gamecontroller, SDL_SensorType type);
/**
* Set whether data reporting for a game controller sensor is enabled
*
* \param gamecontroller The controller to update
* \param type The type of sensor to enable/disable
* \param enabled Whether data reporting should be enabled
*
* \return 0 or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_GameControllerSetSensorEnabled(SDL_GameController *gamecontroller, SDL_SensorType type, SDL_bool enabled);
/**
* Query whether sensor data reporting is enabled for a game controller
*
* \param gamecontroller The controller to query
* \param type The type of sensor to query
*
* \return SDL_TRUE if the sensor is enabled, SDL_FALSE otherwise.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerIsSensorEnabled(SDL_GameController *gamecontroller, SDL_SensorType type);
/**
* Get the current state of a game controller sensor.
*
* The number of values and interpretation of the data is sensor dependent.
* See SDL_sensor.h for the details for each type of sensor.
*
* \param gamecontroller The controller to query
* \param type The type of sensor to query
* \param data A pointer filled with the current sensor state
* \param num_values The number of values to write to data
*
* \return 0 or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_GameControllerGetSensorData(SDL_GameController *gamecontroller, SDL_SensorType type, float *data, int num_values);
/** /**
* Start a rumble effect * Start a rumble effect
* Each call to this function cancels any previous rumble effect, and calling it with 0 intensity stops any rumbling. * Each call to this function cancels any previous rumble effect, and calling it with 0 intensity stops any rumbling.

View File

@ -78,14 +78,16 @@ typedef enum
* Accelerometer sensor * Accelerometer sensor
* *
* The accelerometer returns the current acceleration in SI meters per * The accelerometer returns the current acceleration in SI meters per
* second squared. This includes gravity, so a device at rest will have * second squared. This measurement includes the force of gravity, so
* an acceleration of SDL_STANDARD_GRAVITY straight down. * a device at rest will have an value of SDL_STANDARD_GRAVITY away
* from the center of the earth.
* *
* values[0]: Acceleration on the x axis * values[0]: Acceleration on the x axis
* values[1]: Acceleration on the y axis * values[1]: Acceleration on the y axis
* values[2]: Acceleration on the z axis * values[2]: Acceleration on the z axis
* *
* For phones held in portrait mode, the axes are defined as follows: * For phones held in portrait mode and game controllers held in front of you,
* the axes are defined as follows:
* -X ... +X : left ... right * -X ... +X : left ... right
* -Y ... +Y : bottom ... top * -Y ... +Y : bottom ... top
* -Z ... +Z : farther ... closer * -Z ... +Z : farther ... closer
@ -105,16 +107,17 @@ typedef enum
* see positive rotation on that axis when it appeared to be rotating * see positive rotation on that axis when it appeared to be rotating
* counter-clockwise. * counter-clockwise.
* *
* values[0]: Angular speed around the x axis * values[0]: Angular speed around the x axis (pitch)
* values[1]: Angular speed around the y axis * values[1]: Angular speed around the y axis (yaw)
* values[2]: Angular speed around the z axis * values[2]: Angular speed around the z axis (roll)
* *
* For phones held in portrait mode, the axes are defined as follows: * For phones held in portrait mode and game controllers held in front of you,
* the axes are defined as follows:
* -X ... +X : left ... right * -X ... +X : left ... right
* -Y ... +Y : bottom ... top * -Y ... +Y : bottom ... top
* -Z ... +Z : farther ... closer * -Z ... +Z : farther ... closer
* *
* The axis data is not changed when the phone is rotated. * The axis data is not changed when the phone or controller is rotated.
* *
* \sa SDL_GetDisplayOrientation() * \sa SDL_GetDisplayOrientation()
*/ */

View File

@ -782,3 +782,7 @@
#define SDL_crc32 SDL_crc32_REAL #define SDL_crc32 SDL_crc32_REAL
#define SDL_GameControllerGetSerial SDL_GameControllerGetSerial_REAL #define SDL_GameControllerGetSerial SDL_GameControllerGetSerial_REAL
#define SDL_JoystickGetSerial SDL_JoystickGetSerial_REAL #define SDL_JoystickGetSerial SDL_JoystickGetSerial_REAL
#define SDL_GameControllerHasSensor SDL_GameControllerHasSensor_REAL
#define SDL_GameControllerSetSensorEnabled SDL_GameControllerSetSensorEnabled_REAL
#define SDL_GameControllerIsSensorEnabled SDL_GameControllerIsSensorEnabled_REAL
#define SDL_GameControllerGetSensorData SDL_GameControllerGetSensorData_REAL

View File

@ -843,3 +843,7 @@ SDL_DYNAPI_PROC(int,SDL_GameControllerGetTouchpadFinger,(SDL_GameController *a,
SDL_DYNAPI_PROC(Uint32,SDL_crc32,(Uint32 a, const void *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(Uint32,SDL_crc32,(Uint32 a, const void *b, size_t c),(a,b,c),return)
SDL_DYNAPI_PROC(const char*,SDL_GameControllerGetSerial,(SDL_GameController *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GameControllerGetSerial,(SDL_GameController *a),(a),return)
SDL_DYNAPI_PROC(const char*,SDL_JoystickGetSerial,(SDL_Joystick *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_JoystickGetSerial,(SDL_Joystick *a),(a),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_GameControllerHasSensor,(SDL_GameController *a, SDL_SensorType b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_GameControllerSetSensorEnabled,(SDL_GameController *a, SDL_SensorType b, SDL_bool c),(a,b,c),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_GameControllerIsSensorEnabled,(SDL_GameController *a, SDL_SensorType b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_GameControllerGetSensorData,(SDL_GameController *a, SDL_SensorType b, float *c, int d),(a,b,c,d),return)

View File

@ -2059,6 +2059,111 @@ SDL_GameControllerGetTouchpadFinger(SDL_GameController *gamecontroller, int touc
} }
} }
/**
* Return whether a game controller has a particular sensor.
*/
SDL_bool
SDL_GameControllerHasSensor(SDL_GameController *gamecontroller, SDL_SensorType type)
{
SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller);
int i;
if (joystick) {
for (i = 0; i < joystick->nsensors; ++i) {
if (joystick->sensors[i].type == type) {
return SDL_TRUE;
}
}
}
return SDL_FALSE;
}
/*
* Set whether data reporting for a game controller sensor is enabled
*/
int SDL_GameControllerSetSensorEnabled(SDL_GameController *gamecontroller, SDL_SensorType type, SDL_bool enabled)
{
SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller);
int i;
if (!joystick) {
return SDL_InvalidParamError("gamecontroller");
}
for (i = 0; i < joystick->nsensors; ++i) {
SDL_JoystickSensorInfo *sensor = &joystick->sensors[i];
if (sensor->type == type) {
if (sensor->enabled == enabled) {
return 0;
}
if (enabled) {
if (joystick->nsensors_enabled == 0) {
if (joystick->driver->SetSensorsEnabled(joystick, SDL_TRUE) < 0) {
return -1;
}
}
++joystick->nsensors_enabled;
} else {
if (joystick->nsensors_enabled == 1) {
if (joystick->driver->SetSensorsEnabled(joystick, SDL_FALSE) < 0) {
return -1;
}
}
--joystick->nsensors_enabled;
}
sensor->enabled = enabled;
return 0;
}
}
return SDL_Unsupported();
}
/*
* Query whether sensor data reporting is enabled for a game controller
*/
SDL_bool SDL_GameControllerIsSensorEnabled(SDL_GameController *gamecontroller, SDL_SensorType type)
{
SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller);
int i;
if (joystick) {
for (i = 0; i < joystick->nsensors; ++i) {
if (joystick->sensors[i].type == type) {
return joystick->sensors[i].enabled;
}
}
}
return SDL_FALSE;
}
/*
* Get the current state of a game controller sensor.
*/
int
SDL_GameControllerGetSensorData(SDL_GameController *gamecontroller, SDL_SensorType type, float *data, int num_values)
{
SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller);
int i;
if (!joystick) {
return SDL_InvalidParamError("gamecontroller");
}
for (i = 0; i < joystick->nsensors; ++i) {
SDL_JoystickSensorInfo *sensor = &joystick->sensors[i];
if (sensor->type == type) {
num_values = SDL_min(num_values, SDL_arraysize(sensor->data));
SDL_memcpy(data, sensor->data, num_values*sizeof(*data));
return 0;
}
}
return SDL_Unsupported();
}
const char * const char *
SDL_GameControllerName(SDL_GameController *gamecontroller) SDL_GameControllerName(SDL_GameController *gamecontroller)
{ {

View File

@ -1109,7 +1109,7 @@ SDL_PrivateJoystickShouldIgnoreEvent()
void SDL_PrivateJoystickAddTouchpad(SDL_Joystick *joystick, int nfingers) void SDL_PrivateJoystickAddTouchpad(SDL_Joystick *joystick, int nfingers)
{ {
int ntouchpads = joystick->ntouchpads + 1; int ntouchpads = joystick->ntouchpads + 1;
SDL_JoystickTouchpadInfo *touchpads = (SDL_JoystickTouchpadInfo *)SDL_realloc(joystick->touchpads, sizeof(SDL_JoystickTouchpadInfo)); SDL_JoystickTouchpadInfo *touchpads = (SDL_JoystickTouchpadInfo *)SDL_realloc(joystick->touchpads, (ntouchpads * sizeof(SDL_JoystickTouchpadInfo)));
if (touchpads) { if (touchpads) {
SDL_JoystickTouchpadInfo *touchpad = &touchpads[ntouchpads - 1]; SDL_JoystickTouchpadInfo *touchpad = &touchpads[ntouchpads - 1];
SDL_JoystickTouchpadFingerInfo *fingers = (SDL_JoystickTouchpadFingerInfo *)SDL_calloc(nfingers, sizeof(SDL_JoystickTouchpadFingerInfo)); SDL_JoystickTouchpadFingerInfo *fingers = (SDL_JoystickTouchpadFingerInfo *)SDL_calloc(nfingers, sizeof(SDL_JoystickTouchpadFingerInfo));
@ -1128,6 +1128,21 @@ void SDL_PrivateJoystickAddTouchpad(SDL_Joystick *joystick, int nfingers)
} }
} }
void SDL_PrivateJoystickAddSensor(SDL_Joystick *joystick, SDL_SensorType type)
{
int nsensors = joystick->nsensors + 1;
SDL_JoystickSensorInfo *sensors = (SDL_JoystickSensorInfo *)SDL_realloc(joystick->sensors, (nsensors * sizeof(SDL_JoystickSensorInfo)));
if (sensors) {
SDL_JoystickSensorInfo *sensor = &sensors[nsensors - 1];
SDL_zerop(sensor);
sensor->type = type;
joystick->nsensors = nsensors;
joystick->sensors = sensors;
}
}
void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance) void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
{ {
SDL_JoystickDriver *driver; SDL_JoystickDriver *driver;
@ -2463,8 +2478,8 @@ int SDL_PrivateJoystickTouchpad(SDL_Joystick *joystick, int touchpad, int finger
{ {
SDL_JoystickTouchpadInfo *touchpad_info; SDL_JoystickTouchpadInfo *touchpad_info;
SDL_JoystickTouchpadFingerInfo *finger_info; SDL_JoystickTouchpadFingerInfo *finger_info;
#if !SDL_EVENTS_DISABLED
int posted; int posted;
#if !SDL_EVENTS_DISABLED
Uint32 event_type; Uint32 event_type;
#endif #endif
@ -2544,4 +2559,41 @@ int SDL_PrivateJoystickTouchpad(SDL_Joystick *joystick, int touchpad, int finger
return posted; return posted;
} }
int SDL_PrivateJoystickSensor(SDL_Joystick *joystick, SDL_SensorType type, const float *data, int num_values)
{
int i;
int posted = 0;
for (i = 0; i < joystick->nsensors; ++i) {
SDL_JoystickSensorInfo *sensor = &joystick->sensors[i];
if (sensor->type == type) {
if (sensor->enabled) {
/* Allow duplicate events, for things like gyro updates */
/* Update internal sensor state */
num_values = SDL_min(num_values, SDL_arraysize(sensor->data));
SDL_memcpy(sensor->data, data, num_values*sizeof(*data));
/* Post the event, if desired */
posted = 0;
#if !SDL_EVENTS_DISABLED
if (SDL_GetEventState(SDL_CONTROLLERSENSORUPDATE) == SDL_ENABLE) {
SDL_Event event;
event.type = SDL_CONTROLLERSENSORUPDATE;
event.csensor.which = joystick->instance_id;
event.csensor.sensor = type;
num_values = SDL_min(num_values, SDL_arraysize(event.csensor.data));
SDL_memset(event.csensor.data, 0, sizeof(event.csensor.data));
SDL_memcpy(event.csensor.data, data, num_values*sizeof(*data));
posted = SDL_PushEvent(&event) == 1;
}
#endif /* !SDL_EVENTS_DISABLED */
}
break;
}
}
return posted;
}
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */

View File

@ -109,6 +109,7 @@ extern void SDL_GameControllerHandleDelayedGuideButton(SDL_Joystick *joystick);
/* Internal event queueing functions */ /* Internal event queueing functions */
extern void SDL_PrivateJoystickAddTouchpad(SDL_Joystick *joystick, int nfingers); extern void SDL_PrivateJoystickAddTouchpad(SDL_Joystick *joystick, int nfingers);
extern void SDL_PrivateJoystickAddSensor(SDL_Joystick *joystick, SDL_SensorType type);
extern void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance); extern void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance);
extern void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance); extern void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance);
extern int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, extern int SDL_PrivateJoystickAxis(SDL_Joystick *joystick,
@ -121,6 +122,8 @@ extern int SDL_PrivateJoystickButton(SDL_Joystick *joystick,
Uint8 button, Uint8 state); Uint8 button, Uint8 state);
extern int SDL_PrivateJoystickTouchpad(SDL_Joystick *joystick, extern int SDL_PrivateJoystickTouchpad(SDL_Joystick *joystick,
int touchpad, int finger, Uint8 state, float x, float y, float pressure); int touchpad, int finger, Uint8 state, float x, float y, float pressure);
extern int SDL_PrivateJoystickSensor(SDL_Joystick *joystick,
SDL_SensorType type, const float *data, int num_values);
extern void SDL_PrivateJoystickBatteryLevel(SDL_Joystick *joystick, extern void SDL_PrivateJoystickBatteryLevel(SDL_Joystick *joystick,
SDL_JoystickPowerLevel ePowerLevel); SDL_JoystickPowerLevel ePowerLevel);

View File

@ -53,6 +53,13 @@ typedef struct _SDL_JoystickTouchpadInfo
SDL_JoystickTouchpadFingerInfo *fingers; SDL_JoystickTouchpadFingerInfo *fingers;
} SDL_JoystickTouchpadInfo; } SDL_JoystickTouchpadInfo;
typedef struct _SDL_JoystickSensorInfo
{
SDL_SensorType type;
SDL_bool enabled;
float data[3]; /* If this needs to expand, update SDL_ControllerSensorEvent */
} SDL_JoystickSensorInfo;
struct _SDL_Joystick struct _SDL_Joystick
{ {
SDL_JoystickID instance_id; /* Device instance, monotonically increasing from 0 */ SDL_JoystickID instance_id; /* Device instance, monotonically increasing from 0 */
@ -78,6 +85,10 @@ struct _SDL_Joystick
int ntouchpads; /* Number of touchpads on the joystick */ int ntouchpads; /* Number of touchpads on the joystick */
SDL_JoystickTouchpadInfo *touchpads; /* Current touchpad states */ SDL_JoystickTouchpadInfo *touchpads; /* Current touchpad states */
int nsensors; /* Number of sensors on the joystick */
int nsensors_enabled;
SDL_JoystickSensorInfo *sensors;
Uint16 low_frequency_rumble; Uint16 low_frequency_rumble;
Uint16 high_frequency_rumble; Uint16 high_frequency_rumble;
Uint32 rumble_expiration; Uint32 rumble_expiration;
@ -94,6 +105,7 @@ struct _SDL_Joystick
SDL_bool is_game_controller; SDL_bool is_game_controller;
SDL_bool delayed_guide_button; /* SDL_TRUE if this device has the guide button event delayed */ SDL_bool delayed_guide_button; /* SDL_TRUE if this device has the guide button event delayed */
SDL_JoystickPowerLevel epowerlevel; /* power level of this joystick, SDL_JOYSTICK_POWER_UNKNOWN if not supported */ SDL_JoystickPowerLevel epowerlevel; /* power level of this joystick, SDL_JOYSTICK_POWER_UNKNOWN if not supported */
struct _SDL_JoystickDriver *driver; struct _SDL_JoystickDriver *driver;
struct joystick_hwdata *hwdata; /* Driver dependent information */ struct joystick_hwdata *hwdata; /* Driver dependent information */
@ -154,6 +166,9 @@ typedef struct _SDL_JoystickDriver
SDL_bool (*HasLED)(SDL_Joystick *joystick); SDL_bool (*HasLED)(SDL_Joystick *joystick);
int (*SetLED)(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue); int (*SetLED)(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue);
/* Sensor functionality */
int (*SetSensorsEnabled)(SDL_Joystick *joystick, SDL_bool enabled);
/* Function to update the state of a joystick - called as a device poll. /* Function to update the state of a joystick - called as a device poll.
* This function shouldn't update the joystick structure directly, * This function shouldn't update the joystick structure directly,
* but instead should call SDL_PrivateJoystick*() to deliver events * but instead should call SDL_PrivateJoystick*() to deliver events

View File

@ -630,6 +630,12 @@ ANDROID_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 bl
return SDL_Unsupported(); return SDL_Unsupported();
} }
static int
ANDROID_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
{
return SDL_Unsupported();
}
static void static void
ANDROID_JoystickUpdate(SDL_Joystick * joystick) ANDROID_JoystickUpdate(SDL_Joystick * joystick)
{ {
@ -711,6 +717,7 @@ SDL_JoystickDriver SDL_ANDROID_JoystickDriver =
ANDROID_JoystickRumbleTriggers, ANDROID_JoystickRumbleTriggers,
ANDROID_JoystickHasLED, ANDROID_JoystickHasLED,
ANDROID_JoystickSetLED, ANDROID_JoystickSetLED,
ANDROID_JoystickSetSensorsEnabled,
ANDROID_JoystickUpdate, ANDROID_JoystickUpdate,
ANDROID_JoystickClose, ANDROID_JoystickClose,
ANDROID_JoystickQuit, ANDROID_JoystickQuit,

View File

@ -206,8 +206,8 @@ static void report_free(struct report *);
static int numjoysticks = 0; static int numjoysticks = 0;
static int BSD_JoystickOpen(SDL_Joystick * joy, int device_index); static int BSD_JoystickOpen(SDL_Joystick *joy, int device_index);
static void BSD_JoystickClose(SDL_Joystick * joy); static void BSD_JoystickClose(SDL_Joystick *joy);
static int static int
BSD_JoystickInit(void) BSD_JoystickInit(void)
@ -340,7 +340,7 @@ hatval_to_sdl(Sint32 hatval)
static int static int
BSD_JoystickOpen(SDL_Joystick * joy, int device_index) BSD_JoystickOpen(SDL_Joystick *joy, int device_index)
{ {
char *path = joynames[device_index]; char *path = joynames[device_index];
struct joystick_hwdata *hw; struct joystick_hwdata *hw;
@ -532,7 +532,7 @@ desc_failed:
} }
static void static void
BSD_JoystickUpdate(SDL_Joystick * joy) BSD_JoystickUpdate(SDL_Joystick *joy)
{ {
struct hid_item hitem; struct hid_item hitem;
struct hid_data *hdata; struct hid_data *hdata;
@ -666,7 +666,7 @@ BSD_JoystickUpdate(SDL_Joystick * joy)
/* Function to close a joystick after use */ /* Function to close a joystick after use */
static void static void
BSD_JoystickClose(SDL_Joystick * joy) BSD_JoystickClose(SDL_Joystick *joy)
{ {
if (SDL_strncmp(joy->hwdata->path, "/dev/joy", 8)) { if (SDL_strncmp(joy->hwdata->path, "/dev/joy", 8)) {
report_free(&joy->hwdata->inreport); report_free(&joy->hwdata->inreport);
@ -757,13 +757,13 @@ report_free(struct report *r)
} }
static int static int
BSD_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) BSD_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
{ {
return SDL_Unsupported(); return SDL_Unsupported();
} }
static int static int
BSD_JoystickRumbleTriggers(SDL_Joystick * joystick, Uint16 left_rumble, Uint16 right_rumble) BSD_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
{ {
return SDL_Unsupported(); return SDL_Unsupported();
} }
@ -775,13 +775,19 @@ BSD_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
} }
static SDL_bool static SDL_bool
BSD_JoystickHasLED(SDL_Joystick * joystick) BSD_JoystickHasLED(SDL_Joystick *joystick)
{ {
return SDL_FALSE; return SDL_FALSE;
} }
static int static int
BSD_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) BSD_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
{
return SDL_Unsupported();
}
static int
BSD_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
{ {
return SDL_Unsupported(); return SDL_Unsupported();
} }
@ -801,6 +807,7 @@ SDL_JoystickDriver SDL_BSD_JoystickDriver =
BSD_JoystickRumbleTriggers, BSD_JoystickRumbleTriggers,
BSD_JoystickHasLED, BSD_JoystickHasLED,
BSD_JoystickSetLED, BSD_JoystickSetLED,
BSD_JoystickSetSensorsEnabled,
BSD_JoystickUpdate, BSD_JoystickUpdate,
BSD_JoystickClose, BSD_JoystickClose,
BSD_JoystickQuit, BSD_JoystickQuit,

View File

@ -940,6 +940,12 @@ DARWIN_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blu
return SDL_Unsupported(); return SDL_Unsupported();
} }
static int
DARWIN_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
{
return SDL_Unsupported();
}
static void static void
DARWIN_JoystickUpdate(SDL_Joystick * joystick) DARWIN_JoystickUpdate(SDL_Joystick * joystick)
{ {
@ -1090,6 +1096,7 @@ SDL_JoystickDriver SDL_DARWIN_JoystickDriver =
DARWIN_JoystickRumbleTriggers, DARWIN_JoystickRumbleTriggers,
DARWIN_JoystickHasLED, DARWIN_JoystickHasLED,
DARWIN_JoystickSetLED, DARWIN_JoystickSetLED,
DARWIN_JoystickSetSensorsEnabled,
DARWIN_JoystickUpdate, DARWIN_JoystickUpdate,
DARWIN_JoystickClose, DARWIN_JoystickClose,
DARWIN_JoystickQuit, DARWIN_JoystickQuit,

View File

@ -78,42 +78,48 @@ DUMMY_JoystickGetDeviceInstanceID(int device_index)
} }
static int static int
DUMMY_JoystickOpen(SDL_Joystick * joystick, int device_index) DUMMY_JoystickOpen(SDL_Joystick *joystick, int device_index)
{ {
return SDL_SetError("Logic error: No joysticks available"); return SDL_SetError("Logic error: No joysticks available");
} }
static int static int
DUMMY_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) DUMMY_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
{ {
return SDL_Unsupported(); return SDL_Unsupported();
} }
static int static int
DUMMY_JoystickRumbleTriggers(SDL_Joystick * joystick, Uint16 left_rumble, Uint16 right_rumble) DUMMY_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
{ {
return SDL_Unsupported(); return SDL_Unsupported();
} }
static SDL_bool static SDL_bool
DUMMY_JoystickHasLED(SDL_Joystick * joystick) DUMMY_JoystickHasLED(SDL_Joystick *joystick)
{ {
return SDL_FALSE; return SDL_FALSE;
} }
static int static int
DUMMY_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) DUMMY_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
{
return SDL_Unsupported();
}
static int
DUMMY_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
{ {
return SDL_Unsupported(); return SDL_Unsupported();
} }
static void static void
DUMMY_JoystickUpdate(SDL_Joystick * joystick) DUMMY_JoystickUpdate(SDL_Joystick *joystick)
{ {
} }
static void static void
DUMMY_JoystickClose(SDL_Joystick * joystick) DUMMY_JoystickClose(SDL_Joystick *joystick)
{ {
} }
@ -143,6 +149,7 @@ SDL_JoystickDriver SDL_DUMMY_JoystickDriver =
DUMMY_JoystickRumbleTriggers, DUMMY_JoystickRumbleTriggers,
DUMMY_JoystickHasLED, DUMMY_JoystickHasLED,
DUMMY_JoystickSetLED, DUMMY_JoystickSetLED,
DUMMY_JoystickSetSensorsEnabled,
DUMMY_JoystickUpdate, DUMMY_JoystickUpdate,
DUMMY_JoystickClose, DUMMY_JoystickClose,
DUMMY_JoystickQuit, DUMMY_JoystickQuit,

View File

@ -304,7 +304,7 @@ EMSCRIPTEN_JoystickGetDeviceInstanceID(int device_index)
It returns 0, or -1 if there is an error. It returns 0, or -1 if there is an error.
*/ */
static int static int
EMSCRIPTEN_JoystickOpen(SDL_Joystick * joystick, int device_index) EMSCRIPTEN_JoystickOpen(SDL_Joystick *joystick, int device_index)
{ {
SDL_joylist_item *item = JoystickByDeviceIndex(device_index); SDL_joylist_item *item = JoystickByDeviceIndex(device_index);
@ -336,7 +336,7 @@ EMSCRIPTEN_JoystickOpen(SDL_Joystick * joystick, int device_index)
* and update joystick device state. * and update joystick device state.
*/ */
static void static void
EMSCRIPTEN_JoystickUpdate(SDL_Joystick * joystick) EMSCRIPTEN_JoystickUpdate(SDL_Joystick *joystick)
{ {
EmscriptenGamepadEvent gamepadState; EmscriptenGamepadEvent gamepadState;
SDL_joylist_item *item = (SDL_joylist_item *) joystick->hwdata; SDL_joylist_item *item = (SDL_joylist_item *) joystick->hwdata;
@ -378,7 +378,7 @@ EMSCRIPTEN_JoystickUpdate(SDL_Joystick * joystick)
/* Function to close a joystick after use */ /* Function to close a joystick after use */
static void static void
EMSCRIPTEN_JoystickClose(SDL_Joystick * joystick) EMSCRIPTEN_JoystickClose(SDL_Joystick *joystick)
{ {
SDL_joylist_item *item = (SDL_joylist_item *) joystick->hwdata; SDL_joylist_item *item = (SDL_joylist_item *) joystick->hwdata;
if (item) { if (item) {
@ -398,13 +398,13 @@ EMSCRIPTEN_JoystickGetDeviceGUID(int device_index)
} }
static int static int
EMSCRIPTEN_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) EMSCRIPTEN_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
{ {
return SDL_Unsupported(); return SDL_Unsupported();
} }
static int static int
EMSCRIPTEN_JoystickRumbleTriggers(SDL_Joystick * joystick, Uint16 left_rumble, Uint16 right_rumble) EMSCRIPTEN_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
{ {
return SDL_Unsupported(); return SDL_Unsupported();
} }
@ -416,13 +416,19 @@ EMSCRIPTEN_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
} }
static SDL_bool static SDL_bool
EMSCRIPTEN_JoystickHasLED(SDL_Joystick * joystick) EMSCRIPTEN_JoystickHasLED(SDL_Joystick *joystick)
{ {
return SDL_FALSE; return SDL_FALSE;
} }
static int static int
EMSCRIPTEN_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) EMSCRIPTEN_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
{
return SDL_Unsupported();
}
static int
EMSCRIPTEN_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
{ {
return SDL_Unsupported(); return SDL_Unsupported();
} }
@ -442,6 +448,7 @@ SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver =
EMSCRIPTEN_JoystickRumbleTriggers, EMSCRIPTEN_JoystickRumbleTriggers,
EMSCRIPTEN_JoystickHasLED, EMSCRIPTEN_JoystickHasLED,
EMSCRIPTEN_JoystickSetLED, EMSCRIPTEN_JoystickSetLED,
EMSCRIPTEN_JoystickSetSensorsEnabled,
EMSCRIPTEN_JoystickUpdate, EMSCRIPTEN_JoystickUpdate,
EMSCRIPTEN_JoystickClose, EMSCRIPTEN_JoystickClose,
EMSCRIPTEN_JoystickQuit, EMSCRIPTEN_JoystickQuit,

View File

@ -114,14 +114,14 @@ extern "C"
return device_index; return device_index;
} }
static void HAIKU_JoystickClose(SDL_Joystick * joystick); static void HAIKU_JoystickClose(SDL_Joystick *joystick);
/* Function to open a joystick for use. /* Function to open a joystick for use.
The joystick to open is specified by the device index. The joystick to open is specified by the device index.
This should fill the nbuttons and naxes fields of the joystick structure. This should fill the nbuttons and naxes fields of the joystick structure.
It returns 0, or -1 if there is an error. It returns 0, or -1 if there is an error.
*/ */
static int HAIKU_JoystickOpen(SDL_Joystick * joystick, int device_index) static int HAIKU_JoystickOpen(SDL_Joystick *joystick, int device_index)
{ {
BJoystick *stick; BJoystick *stick;
@ -168,7 +168,7 @@ extern "C"
* but instead should call SDL_PrivateJoystick*() to deliver events * but instead should call SDL_PrivateJoystick*() to deliver events
* and update joystick device state. * and update joystick device state.
*/ */
static void HAIKU_JoystickUpdate(SDL_Joystick * joystick) static void HAIKU_JoystickUpdate(SDL_Joystick *joystick)
{ {
static const Uint8 hat_map[9] = { static const Uint8 hat_map[9] = {
SDL_HAT_CENTERED, SDL_HAT_CENTERED,
@ -217,7 +217,7 @@ extern "C"
} }
/* Function to close a joystick after use */ /* Function to close a joystick after use */
static void HAIKU_JoystickClose(SDL_Joystick * joystick) static void HAIKU_JoystickClose(SDL_Joystick *joystick)
{ {
if (joystick->hwdata) { if (joystick->hwdata) {
joystick->hwdata->stick->Close(); joystick->hwdata->stick->Close();
@ -254,13 +254,13 @@ extern "C"
return guid; return guid;
} }
static int HAIKU_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) static int HAIKU_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
{ {
return SDL_Unsupported(); return SDL_Unsupported();
} }
static int HAIKU_JoystickRumbleTriggers(SDL_Joystick * joystick, Uint16 left_rumble, Uint16 right_rumble) static int HAIKU_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
{ {
return SDL_Unsupported(); return SDL_Unsupported();
} }
@ -271,12 +271,17 @@ extern "C"
return SDL_FALSE; return SDL_FALSE;
} }
static SDL_bool HAIKU_JoystickHasLED(SDL_Joystick * joystick) static SDL_bool HAIKU_JoystickHasLED(SDL_Joystick *joystick)
{ {
return SDL_FALSE; return SDL_FALSE;
} }
static int HAIKU_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) static int HAIKU_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
{
return SDL_Unsupported();
}
static int HAIKU_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
{ {
return SDL_Unsupported(); return SDL_Unsupported();
} }
@ -296,6 +301,7 @@ extern "C"
HAIKU_JoystickRumbleTriggers, HAIKU_JoystickRumbleTriggers,
HAIKU_JoystickHasLED, HAIKU_JoystickHasLED,
HAIKU_JoystickSetLED, HAIKU_JoystickSetLED,
HAIKU_JoystickSetSensorsEnabled,
HAIKU_JoystickUpdate, HAIKU_JoystickUpdate,
HAIKU_JoystickClose, HAIKU_JoystickClose,
HAIKU_JoystickQuit, HAIKU_JoystickQuit,

View File

@ -381,6 +381,12 @@ HIDAPI_DriverGameCube_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *jo
return SDL_Unsupported(); return SDL_Unsupported();
} }
static int
HIDAPI_DriverGameCube_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled)
{
return SDL_Unsupported();
}
static void static void
HIDAPI_DriverGameCube_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) HIDAPI_DriverGameCube_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{ {
@ -423,6 +429,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube =
HIDAPI_DriverGameCube_RumbleJoystickTriggers, HIDAPI_DriverGameCube_RumbleJoystickTriggers,
HIDAPI_DriverGameCube_HasJoystickLED, HIDAPI_DriverGameCube_HasJoystickLED,
HIDAPI_DriverGameCube_SetJoystickLED, HIDAPI_DriverGameCube_SetJoystickLED,
HIDAPI_DriverGameCube_SetJoystickSensorsEnabled,
HIDAPI_DriverGameCube_CloseJoystick, HIDAPI_DriverGameCube_CloseJoystick,
HIDAPI_DriverGameCube_FreeDevice, HIDAPI_DriverGameCube_FreeDevice,
NULL, NULL,

View File

@ -37,6 +37,17 @@
#ifdef SDL_JOYSTICK_HIDAPI_PS4 #ifdef SDL_JOYSTICK_HIDAPI_PS4
/* Define this if you want to log all packets from the controller */
/*#define DEBUG_PS4_PROTOCOL*/
/* Define this if you want to log calibration data */
/*#define DEBUG_PS4_CALIBRATION*/
#define GYRO_RES_PER_DEGREE 1024.0f
#define ACCEL_RES_PER_G 8192.0f
#define LOAD16(A, B) (Sint16)((Uint16)(A) | (((Uint16)(B)) << 8))
typedef enum typedef enum
{ {
k_EPS4ReportIdUsbState = 1, k_EPS4ReportIdUsbState = 1,
@ -71,12 +82,12 @@ typedef struct
Uint8 ucTriggerLeft; Uint8 ucTriggerLeft;
Uint8 ucTriggerRight; Uint8 ucTriggerRight;
Uint8 _rgucPad0[ 3 ]; Uint8 _rgucPad0[ 3 ];
Sint16 sGyroX; Uint8 rgucGyroX[2];
Sint16 sGyroY; Uint8 rgucGyroY[2];
Sint16 sGyroZ; Uint8 rgucGyroZ[2];
Sint16 sAccelX; Uint8 rgucAccelX[2];
Sint16 sAccelY; Uint8 rgucAccelY[2];
Sint16 sAccelZ; Uint8 rgucAccelZ[2];
Uint8 _rgucPad1[ 5 ]; Uint8 _rgucPad1[ 5 ];
Uint8 ucBatteryLevel; Uint8 ucBatteryLevel;
Uint8 _rgucPad2[ 4 ]; Uint8 _rgucPad2[ 4 ];
@ -102,11 +113,20 @@ typedef struct
Uint8 ucVolumeSpeaker; Uint8 ucVolumeSpeaker;
} DS4EffectsState_t; } DS4EffectsState_t;
typedef struct {
Sint16 bias;
float sensitivity;
} IMUCalibrationData;
typedef struct { typedef struct {
SDL_bool is_dongle; SDL_bool is_dongle;
SDL_bool is_bluetooth; SDL_bool is_bluetooth;
SDL_bool official_controller;
SDL_bool audio_supported; SDL_bool audio_supported;
SDL_bool effects_supported; SDL_bool effects_supported;
SDL_bool report_sensors;
SDL_bool hardware_calibration;
IMUCalibrationData calibration[6];
int player_index; int player_index;
Uint8 rumble_left; Uint8 rumble_left;
Uint8 rumble_right; Uint8 rumble_right;
@ -191,6 +211,168 @@ HIDAPI_DriverPS4_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID
return -1; return -1;
} }
static void
HIDAPI_DriverPS4_LoadCalibrationData(SDL_HIDAPI_Device *device)
{
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
int i, tries, size;
SDL_bool have_data = SDL_FALSE;
Uint8 data[USB_PACKET_LENGTH];
if (!ctx->official_controller) {
#ifdef DEBUG_PS4_CALIBRATION
SDL_Log("Not an official controller, ignoring calibration\n");
#endif
return;
}
for( tries = 0; tries < 5; ++tries ) {
/* For Bluetooth controllers, this report switches them into advanced report mode */
size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdGyroCalibration_USB, data, sizeof(data));
if (size < 35) {
#ifdef DEBUG_PS4_CALIBRATION
SDL_Log("Short read of calibration data: %d, ignoring calibration\n", size);
#endif
return;
}
if (ctx->is_bluetooth) {
size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdGyroCalibration_BT, data, sizeof(data));
if (size < 35) {
#ifdef DEBUG_PS4_CALIBRATION
SDL_Log("Short read of calibration data: %d, ignoring calibration\n", size);
#endif
return;
}
}
/* In some cases this report returns all zeros. Usually immediately after connection with the PS4 Dongle */
for (i = 0; i < size; ++i) {
if (data[i]) {
have_data = SDL_TRUE;
break;
}
}
if (have_data) {
break;
}
SDL_Delay(2);
}
if (have_data) {
Sint16 sGyroPitchBias, sGyroYawBias, sGyroRollBias;
Sint16 sGyroPitchPlus, sGyroPitchMinus;
Sint16 sGyroYawPlus, sGyroYawMinus;
Sint16 sGyroRollPlus, sGyroRollMinus;
Sint16 sGyroSpeedPlus, sGyroSpeedMinus;
Sint16 sAccXPlus, sAccXMinus;
Sint16 sAccYPlus, sAccYMinus;
Sint16 sAccZPlus, sAccZMinus;
float flNumerator;
Sint16 sRange2g;
#ifdef DEBUG_PS4_CALIBRATION
HIDAPI_DumpPacket("PS4 calibration packet: size = %d", data, size);
#endif
sGyroPitchBias = LOAD16(data[1], data[2]);
sGyroYawBias = LOAD16(data[3], data[4]);
sGyroRollBias = LOAD16(data[5], data[6]);
if (ctx->is_bluetooth || ctx->is_dongle) {
sGyroPitchPlus = LOAD16(data[7], data[8]);
sGyroYawPlus = LOAD16(data[9], data[10]);
sGyroRollPlus = LOAD16(data[11], data[12]);
sGyroPitchMinus = LOAD16(data[13], data[14]);
sGyroYawMinus = LOAD16(data[15], data[16]);
sGyroRollMinus = LOAD16(data[17], data[18]);
} else {
sGyroPitchPlus = LOAD16(data[7], data[8]);
sGyroPitchMinus = LOAD16(data[9], data[10]);
sGyroYawPlus = LOAD16(data[11], data[12]);
sGyroYawMinus = LOAD16(data[13], data[14]);
sGyroRollPlus = LOAD16(data[15], data[16]);
sGyroRollMinus = LOAD16(data[17], data[18]);
}
sGyroSpeedPlus = LOAD16(data[19], data[20]);
sGyroSpeedMinus = LOAD16(data[21], data[22]);
sAccXPlus = LOAD16(data[23], data[24]);
sAccXMinus = LOAD16(data[25], data[26]);
sAccYPlus = LOAD16(data[27], data[28]);
sAccYMinus = LOAD16(data[29], data[30]);
sAccZPlus = LOAD16(data[31], data[32]);
sAccZMinus = LOAD16(data[33], data[34]);
flNumerator = (sGyroSpeedPlus + sGyroSpeedMinus) * GYRO_RES_PER_DEGREE;
ctx->calibration[0].bias = sGyroPitchBias;
ctx->calibration[0].sensitivity = flNumerator / (sGyroPitchPlus - sGyroPitchMinus);
ctx->calibration[1].bias = sGyroYawBias;
ctx->calibration[1].sensitivity = flNumerator / (sGyroYawPlus - sGyroYawMinus);
ctx->calibration[2].bias = sGyroRollBias;
ctx->calibration[2].sensitivity = flNumerator / (sGyroRollPlus - sGyroRollMinus);
sRange2g = sAccXPlus - sAccXMinus;
ctx->calibration[3].bias = sAccXPlus - sRange2g / 2;
ctx->calibration[3].sensitivity = 2.0f * ACCEL_RES_PER_G / (float)sRange2g;
sRange2g = sAccYPlus - sAccYMinus;
ctx->calibration[4].bias = sAccYPlus - sRange2g / 2;
ctx->calibration[4].sensitivity = 2.0f * ACCEL_RES_PER_G / (float)sRange2g;
sRange2g = sAccZPlus - sAccZMinus;
ctx->calibration[5].bias = sAccZPlus - sRange2g / 2;
ctx->calibration[5].sensitivity = 2.0f * ACCEL_RES_PER_G / (float)sRange2g;
ctx->hardware_calibration = SDL_TRUE;
for (i = 0; i < 6; ++i) {
float divisor = (i < 3 ? 64.0f : 1.0f);
#ifdef DEBUG_PS4_CALIBRATION
SDL_Log("calibration[%d] bias = %d, sensitivity = %f\n", i, ctx->calibration[i].bias, ctx->calibration[i].sensitivity);
#endif
/* Some controllers have a bad calibration */
if ((SDL_abs(ctx->calibration[i].bias) > 1024) || (SDL_fabs(1.0f - ctx->calibration[i].sensitivity / divisor) > 0.5f)) {
#ifdef DEBUG_PS4_CALIBRATION
SDL_Log("invalid calibration, ignoring\n");
#endif
ctx->hardware_calibration = SDL_FALSE;
}
}
} else {
#ifdef DEBUG_PS4_CALIBRATION
SDL_Log("Calibration data not available\n");
#endif
}
}
static float
HIDAPI_DriverPS4_ApplyCalibrationData(SDL_DriverPS4_Context *ctx, int index, Sint16 value)
{
float result;
if (ctx->hardware_calibration) {
IMUCalibrationData *calibration = &ctx->calibration[index];
result = (value - calibration->bias) * calibration->sensitivity;
} else {
result = value;
}
/* Convert the raw data to the units expected by SDL */
if (index < 3) {
result = (result / GYRO_RES_PER_DEGREE) * M_PI / 180.0f;
} else {
result = (result / ACCEL_RES_PER_G) * SDL_STANDARD_GRAVITY;
}
return result;
}
static int static int
HIDAPI_DriverPS4_UpdateEffects(SDL_HIDAPI_Device *device) HIDAPI_DriverPS4_UpdateEffects(SDL_HIDAPI_Device *device)
{ {
@ -286,37 +468,24 @@ HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
ctx->is_dongle = (device->vendor_id == USB_VENDOR_SONY && device->product_id == USB_PRODUCT_SONY_DS4_DONGLE); ctx->is_dongle = (device->vendor_id == USB_VENDOR_SONY && device->product_id == USB_PRODUCT_SONY_DS4_DONGLE);
if (ctx->is_dongle) { if (ctx->is_dongle) {
ctx->is_bluetooth = SDL_FALSE; ctx->is_bluetooth = SDL_FALSE;
ctx->official_controller = SDL_TRUE;
} else if (device->vendor_id == USB_VENDOR_SONY) { } else if (device->vendor_id == USB_VENDOR_SONY) {
int i;
Uint8 data[USB_PACKET_LENGTH]; Uint8 data[USB_PACKET_LENGTH];
int length; int size;
/* This will fail if we're on Bluetooth */ /* This will fail if we're on Bluetooth */
length = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdSerialNumber, data, sizeof(data)); size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdSerialNumber, data, sizeof(data));
if (length >= 7) { if (size >= 7) {
SDL_bool had_data = SDL_FALSE; char serial[18];
for (i = 0; i < length; ++i) {
if (data[i] != 0x00) {
had_data = SDL_TRUE;
break;
}
}
if (had_data) {
char serial[18];
SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
data[6], data[5], data[4], data[3], data[2], data[1]);
joystick->serial = SDL_strdup(serial);
} else {
/* Maybe the dongle without a connected controller? */
}
SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
data[6], data[5], data[4], data[3], data[2], data[1]);
joystick->serial = SDL_strdup(serial);
ctx->is_bluetooth = SDL_FALSE; ctx->is_bluetooth = SDL_FALSE;
} else { } else {
ctx->is_bluetooth = SDL_TRUE; ctx->is_bluetooth = SDL_TRUE;
} }
ctx->official_controller = SDL_TRUE;
} else { } else {
/* Third party controllers appear to all be wired */ /* Third party controllers appear to all be wired */
ctx->is_bluetooth = SDL_FALSE; ctx->is_bluetooth = SDL_FALSE;
@ -351,6 +520,8 @@ HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED; joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
SDL_PrivateJoystickAddTouchpad(joystick, 2); SDL_PrivateJoystickAddTouchpad(joystick, 2);
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO);
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL);
return SDL_TRUE; return SDL_TRUE;
} }
@ -391,6 +562,19 @@ HIDAPI_DriverPS4_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystic
return HIDAPI_DriverPS4_UpdateEffects(device); return HIDAPI_DriverPS4_UpdateEffects(device);
} }
static int
HIDAPI_DriverPS4_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled)
{
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
if (enabled) {
HIDAPI_DriverPS4_LoadCalibrationData(device);
}
ctx->report_sensors = enabled;
return 0;
}
static void static void
HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS4_Context *ctx, PS4StatePacket_t *packet) HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS4_Context *ctx, PS4StatePacket_t *packet)
{ {
@ -521,6 +705,20 @@ HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_
touchpad_y = (packet->rgucTouchpadData2[1] >> 4) | ((int)packet->rgucTouchpadData2[2] << 4); touchpad_y = (packet->rgucTouchpadData2[1] >> 4) | ((int)packet->rgucTouchpadData2[2] << 4);
SDL_PrivateJoystickTouchpad(joystick, 0, 1, touchpad_state, touchpad_x * TOUCHPAD_SCALEX, touchpad_y * TOUCHPAD_SCALEY, touchpad_state ? 1.0f : 0.0f); SDL_PrivateJoystickTouchpad(joystick, 0, 1, touchpad_state, touchpad_x * TOUCHPAD_SCALEX, touchpad_y * TOUCHPAD_SCALEY, touchpad_state ? 1.0f : 0.0f);
if (ctx->report_sensors) {
float data[3];
data[0] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 0, LOAD16(packet->rgucGyroX[0], packet->rgucGyroX[1]));
data[1] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 1, LOAD16(packet->rgucGyroY[0], packet->rgucGyroY[1]));
data[2] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 2, LOAD16(packet->rgucGyroZ[0], packet->rgucGyroZ[1]));
SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, data, 3);
data[0] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 3, LOAD16(packet->rgucAccelX[0], packet->rgucAccelX[1]));
data[1] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 4, LOAD16(packet->rgucAccelY[0], packet->rgucAccelY[1]));
data[2] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 5, LOAD16(packet->rgucAccelZ[0], packet->rgucAccelZ[1]));
SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, data, 3);
}
SDL_memcpy(&ctx->last_state, packet, sizeof(ctx->last_state)); SDL_memcpy(&ctx->last_state, packet, sizeof(ctx->last_state));
} }
@ -540,6 +738,9 @@ HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
} }
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) { while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_PS4_PROTOCOL
HIDAPI_DumpPacket("PS4 packet: size = %d", data, size);
#endif
switch (data[0]) { switch (data[0]) {
case k_EPS4ReportIdUsbState: case k_EPS4ReportIdUsbState:
HIDAPI_DriverPS4_HandleStatePacket(joystick, device->dev, ctx, (PS4StatePacket_t *)&data[1]); HIDAPI_DriverPS4_HandleStatePacket(joystick, device->dev, ctx, (PS4StatePacket_t *)&data[1]);
@ -603,6 +804,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4 =
HIDAPI_DriverPS4_RumbleJoystickTriggers, HIDAPI_DriverPS4_RumbleJoystickTriggers,
HIDAPI_DriverPS4_HasJoystickLED, HIDAPI_DriverPS4_HasJoystickLED,
HIDAPI_DriverPS4_SetJoystickLED, HIDAPI_DriverPS4_SetJoystickLED,
HIDAPI_DriverPS4_SetJoystickSensorsEnabled,
HIDAPI_DriverPS4_CloseJoystick, HIDAPI_DriverPS4_CloseJoystick,
HIDAPI_DriverPS4_FreeDevice, HIDAPI_DriverPS4_FreeDevice,
NULL NULL

View File

@ -72,8 +72,12 @@ typedef struct
Uint8 rgucButtonsAndHat[3]; /* 7 */ Uint8 rgucButtonsAndHat[3]; /* 7 */
Uint8 ucZero; /* 10 */ Uint8 ucZero; /* 10 */
Uint8 rgucPacketSequence[4]; /* 11 - 32 bit little endian */ Uint8 rgucPacketSequence[4]; /* 11 - 32 bit little endian */
Uint8 rgucAccel[6]; /* 15 */ Uint8 rgucGyroX[2]; /* 15 */
Uint8 rgucGyro[6]; /* 21 */ Uint8 rgucGyroY[2]; /* 17 */
Uint8 rgucGyroZ[2]; /* 19 */
Uint8 rgucAccelX[2]; /* 21 */
Uint8 rgucAccelY[2]; /* 23 */
Uint8 rgucAccelZ[2]; /* 25 */
Uint8 rgucTimer1[4]; /* 27 - 32 bit little endian */ Uint8 rgucTimer1[4]; /* 27 - 32 bit little endian */
Uint8 ucBatteryTemp; /* 31 */ Uint8 ucBatteryTemp; /* 31 */
Uint8 ucTouchpadCounter1; /* 32 - high bit clear + counter */ Uint8 ucTouchpadCounter1; /* 32 - high bit clear + counter */
@ -351,6 +355,12 @@ HIDAPI_DriverPS5_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystic
return HIDAPI_DriverPS5_UpdateEffects(device); return HIDAPI_DriverPS5_UpdateEffects(device);
} }
static int
HIDAPI_DriverPS5_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled)
{
return 0;
}
static void static void
HIDAPI_DriverPS5_HandleSimpleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS5_Context *ctx, PS5SimpleStatePacket_t *packet) HIDAPI_DriverPS5_HandleSimpleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS5_Context *ctx, PS5SimpleStatePacket_t *packet)
{ {
@ -649,6 +659,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS5 =
HIDAPI_DriverPS5_RumbleJoystickTriggers, HIDAPI_DriverPS5_RumbleJoystickTriggers,
HIDAPI_DriverPS5_HasJoystickLED, HIDAPI_DriverPS5_HasJoystickLED,
HIDAPI_DriverPS5_SetJoystickLED, HIDAPI_DriverPS5_SetJoystickLED,
HIDAPI_DriverPS5_SetJoystickSensorsEnabled,
HIDAPI_DriverPS5_CloseJoystick, HIDAPI_DriverPS5_CloseJoystick,
HIDAPI_DriverPS5_FreeDevice, HIDAPI_DriverPS5_FreeDevice,
NULL NULL

View File

@ -1054,6 +1054,13 @@ HIDAPI_DriverSteam_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
return SDL_Unsupported(); return SDL_Unsupported();
} }
static int
HIDAPI_DriverSteam_SetSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled)
{
/* You should use the full Steam Input API for sensor support */
return SDL_Unsupported();
}
static SDL_bool static SDL_bool
HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device) HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
{ {
@ -1191,6 +1198,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteam =
HIDAPI_DriverSteam_RumbleJoystickTriggers, HIDAPI_DriverSteam_RumbleJoystickTriggers,
HIDAPI_DriverSteam_HasJoystickLED, HIDAPI_DriverSteam_HasJoystickLED,
HIDAPI_DriverSteam_SetJoystickLED, HIDAPI_DriverSteam_SetJoystickLED,
HIDAPI_DriverSteam_SetSensorsEnabled,
HIDAPI_DriverSteam_CloseJoystick, HIDAPI_DriverSteam_CloseJoystick,
HIDAPI_DriverSteam_FreeDevice, HIDAPI_DriverSteam_FreeDevice,
NULL NULL

View File

@ -942,6 +942,12 @@ HIDAPI_DriverSwitch_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joys
return SDL_Unsupported(); return SDL_Unsupported();
} }
static int
HIDAPI_DriverSwitch_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled)
{
return SDL_Unsupported();
}
static void HandleInputOnlyControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchInputOnlyControllerStatePacket_t *packet) static void HandleInputOnlyControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchInputOnlyControllerStatePacket_t *packet)
{ {
Sint16 axis; Sint16 axis;
@ -1298,6 +1304,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch =
HIDAPI_DriverSwitch_RumbleJoystickTriggers, HIDAPI_DriverSwitch_RumbleJoystickTriggers,
HIDAPI_DriverSwitch_HasJoystickLED, HIDAPI_DriverSwitch_HasJoystickLED,
HIDAPI_DriverSwitch_SetJoystickLED, HIDAPI_DriverSwitch_SetJoystickLED,
HIDAPI_DriverSwitch_SetJoystickSensorsEnabled,
HIDAPI_DriverSwitch_CloseJoystick, HIDAPI_DriverSwitch_CloseJoystick,
HIDAPI_DriverSwitch_FreeDevice, HIDAPI_DriverSwitch_FreeDevice,
NULL NULL

View File

@ -815,6 +815,12 @@ HIDAPI_DriverXbox360_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joy
return SDL_Unsupported(); return SDL_Unsupported();
} }
static int
HIDAPI_DriverXbox360_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled)
{
return SDL_Unsupported();
}
#ifdef __WIN32__ #ifdef __WIN32__
/* This is the packet format for Xbox 360 and Xbox One controllers on Windows, /* This is the packet format for Xbox 360 and Xbox One controllers on Windows,
however with this interface there is no rumble support, no guide button, however with this interface there is no rumble support, no guide button,
@ -1326,6 +1332,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360 =
HIDAPI_DriverXbox360_RumbleJoystickTriggers, HIDAPI_DriverXbox360_RumbleJoystickTriggers,
HIDAPI_DriverXbox360_HasJoystickLED, HIDAPI_DriverXbox360_HasJoystickLED,
HIDAPI_DriverXbox360_SetJoystickLED, HIDAPI_DriverXbox360_SetJoystickLED,
HIDAPI_DriverXbox360_SetJoystickSensorsEnabled,
HIDAPI_DriverXbox360_CloseJoystick, HIDAPI_DriverXbox360_CloseJoystick,
HIDAPI_DriverXbox360_FreeDevice, HIDAPI_DriverXbox360_FreeDevice,
HIDAPI_DriverXbox360_PostUpdate, HIDAPI_DriverXbox360_PostUpdate,

View File

@ -176,6 +176,12 @@ HIDAPI_DriverXbox360W_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *jo
return SDL_Unsupported(); return SDL_Unsupported();
} }
static int
HIDAPI_DriverXbox360W_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled)
{
return SDL_Unsupported();
}
static void static void
HIDAPI_DriverXbox360W_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXbox360W_Context *ctx, Uint8 *data, int size) HIDAPI_DriverXbox360W_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXbox360W_Context *ctx, Uint8 *data, int size)
{ {
@ -316,6 +322,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360W =
HIDAPI_DriverXbox360W_RumbleJoystickTriggers, HIDAPI_DriverXbox360W_RumbleJoystickTriggers,
HIDAPI_DriverXbox360W_HasJoystickLED, HIDAPI_DriverXbox360W_HasJoystickLED,
HIDAPI_DriverXbox360W_SetJoystickLED, HIDAPI_DriverXbox360W_SetJoystickLED,
HIDAPI_DriverXbox360W_SetJoystickSensorsEnabled,
HIDAPI_DriverXbox360W_CloseJoystick, HIDAPI_DriverXbox360W_CloseJoystick,
HIDAPI_DriverXbox360W_FreeDevice, HIDAPI_DriverXbox360W_FreeDevice,
NULL NULL

View File

@ -406,6 +406,12 @@ HIDAPI_DriverXboxOne_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joy
return SDL_Unsupported(); return SDL_Unsupported();
} }
static int
HIDAPI_DriverXboxOne_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled)
{
return SDL_Unsupported();
}
static void static void
HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size) HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
{ {
@ -934,6 +940,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne =
HIDAPI_DriverXboxOne_RumbleJoystickTriggers, HIDAPI_DriverXboxOne_RumbleJoystickTriggers,
HIDAPI_DriverXboxOne_HasJoystickLED, HIDAPI_DriverXboxOne_HasJoystickLED,
HIDAPI_DriverXboxOne_SetJoystickLED, HIDAPI_DriverXboxOne_SetJoystickLED,
HIDAPI_DriverXboxOne_SetJoystickSensorsEnabled,
HIDAPI_DriverXboxOne_CloseJoystick, HIDAPI_DriverXboxOne_CloseJoystick,
HIDAPI_DriverXboxOne_FreeDevice, HIDAPI_DriverXboxOne_FreeDevice,
NULL NULL

View File

@ -1130,6 +1130,23 @@ HIDAPI_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blu
return result; return result;
} }
static int
HIDAPI_JoystickSetSensorsEnabled(SDL_Joystick * joystick, SDL_bool enabled)
{
int result;
if (joystick->hwdata) {
SDL_HIDAPI_Device *device = joystick->hwdata->device;
result = device->driver->SetJoystickSensorsEnabled(device, joystick, enabled);
} else {
SDL_SetError("SetSensorsEnabled failed, device disconnected");
result = -1;
}
return result;
}
static void static void
HIDAPI_JoystickUpdate(SDL_Joystick * joystick) HIDAPI_JoystickUpdate(SDL_Joystick * joystick)
{ {
@ -1206,6 +1223,7 @@ SDL_JoystickDriver SDL_HIDAPI_JoystickDriver =
HIDAPI_JoystickRumbleTriggers, HIDAPI_JoystickRumbleTriggers,
HIDAPI_JoystickHasLED, HIDAPI_JoystickHasLED,
HIDAPI_JoystickSetLED, HIDAPI_JoystickSetLED,
HIDAPI_JoystickSetSensorsEnabled,
HIDAPI_JoystickUpdate, HIDAPI_JoystickUpdate,
HIDAPI_JoystickClose, HIDAPI_JoystickClose,
HIDAPI_JoystickQuit, HIDAPI_JoystickQuit,

View File

@ -99,6 +99,7 @@ typedef struct _SDL_HIDAPI_DeviceDriver
int (*RumbleJoystickTriggers)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble); int (*RumbleJoystickTriggers)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble);
SDL_bool (*HasJoystickLED)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick); SDL_bool (*HasJoystickLED)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick);
int (*SetJoystickLED)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue); int (*SetJoystickLED)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue);
int (*SetJoystickSensorsEnabled)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled);
void (*CloseJoystick)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick); void (*CloseJoystick)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick);
void (*FreeDevice)(SDL_HIDAPI_Device *device); void (*FreeDevice)(SDL_HIDAPI_Device *device);
void (*PostUpdate)(void); void (*PostUpdate)(void);

View File

@ -79,6 +79,7 @@ static id disconnectObserver = nil;
#define ENABLE_MFI_BATTERY #define ENABLE_MFI_BATTERY
#define ENABLE_MFI_RUMBLE #define ENABLE_MFI_RUMBLE
#define ENABLE_MFI_LIGHT #define ENABLE_MFI_LIGHT
#define ENABLE_MFI_SENSORS
#define ENABLE_PHYSICAL_INPUT_PROFILE #define ENABLE_PHYSICAL_INPUT_PROFILE
#endif #endif
@ -569,7 +570,7 @@ IOS_JoystickGetDeviceInstanceID(int device_index)
} }
static int static int
IOS_JoystickOpen(SDL_Joystick * joystick, int device_index) IOS_JoystickOpen(SDL_Joystick *joystick, int device_index)
{ {
SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index); SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
if (device == NULL) { if (device == NULL) {
@ -611,6 +612,20 @@ IOS_JoystickOpen(SDL_Joystick * joystick, int device_index)
} }
}; };
} }
#ifdef ENABLE_MFI_SENSORS
if (@available(iOS 14.0, tvOS 14.0, *)) {
GCController *controller = joystick->hwdata->controller;
GCMotion *motion = controller.motion;
if (motion && motion.hasRotationRate) {
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO);
}
if (motion && motion.hasGravityAndUserAcceleration) {
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL);
}
}
#endif /* ENABLE_MFI_SENSORS */
#endif /* SDL_JOYSTICK_MFI */ #endif /* SDL_JOYSTICK_MFI */
} }
} }
@ -622,7 +637,7 @@ IOS_JoystickOpen(SDL_Joystick * joystick, int device_index)
} }
static void static void
IOS_AccelerometerUpdate(SDL_Joystick * joystick) IOS_AccelerometerUpdate(SDL_Joystick *joystick)
{ {
#if !TARGET_OS_TV #if !TARGET_OS_TV
const float maxgforce = SDL_IPHONE_MAX_GFORCE; const float maxgforce = SDL_IPHONE_MAX_GFORCE;
@ -692,7 +707,7 @@ IOS_MFIJoystickHatStateForDPad(GCControllerDirectionPad *dpad)
#endif #endif
static void static void
IOS_MFIJoystickUpdate(SDL_Joystick * joystick) IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
{ {
#if SDL_JOYSTICK_MFI #if SDL_JOYSTICK_MFI
@autoreleasepool { @autoreleasepool {
@ -806,6 +821,31 @@ IOS_MFIJoystickUpdate(SDL_Joystick * joystick)
for (i = 0; i < button_count; i++) { for (i = 0; i < button_count; i++) {
SDL_PrivateJoystickButton(joystick, i, buttons[i]); SDL_PrivateJoystickButton(joystick, i, buttons[i]);
} }
#ifdef ENABLE_MFI_SENSORS
if (@available(iOS 14.0, tvOS 14.0, *)) {
GCMotion *motion = controller.motion;
if (motion && motion.sensorsActive) {
float data[3];
if (motion.hasRotationRate) {
GCRotationRate rate = motion.rotationRate;
data[0] = rate.x;
data[1] = rate.z;
data[2] = -rate.y;
SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, data, 3);
}
if (motion.hasGravityAndUserAcceleration) {
GCAcceleration accel = motion.acceleration;
data[0] = -accel.x * SDL_STANDARD_GRAVITY;
data[1] = -accel.y * SDL_STANDARD_GRAVITY;
data[2] = -accel.z * SDL_STANDARD_GRAVITY;
SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, data, 3);
}
}
}
#endif /* ENABLE_MFI_SENSORS */
} else if (controller.gamepad) { } else if (controller.gamepad) {
GCGamepad *gamepad = controller.gamepad; GCGamepad *gamepad = controller.gamepad;
@ -1103,7 +1143,7 @@ static SDL_RumbleContext *IOS_JoystickInitRumble(GCController *controller)
#endif /* ENABLE_MFI_RUMBLE */ #endif /* ENABLE_MFI_RUMBLE */
static int static int
IOS_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) IOS_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
{ {
#ifdef ENABLE_MFI_RUMBLE #ifdef ENABLE_MFI_RUMBLE
SDL_JoystickDeviceItem *device = joystick->hwdata; SDL_JoystickDeviceItem *device = joystick->hwdata;
@ -1129,7 +1169,7 @@ IOS_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16
} }
static int static int
IOS_JoystickRumbleTriggers(SDL_Joystick * joystick, Uint16 left_rumble, Uint16 right_rumble) IOS_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
{ {
#ifdef ENABLE_MFI_RUMBLE #ifdef ENABLE_MFI_RUMBLE
SDL_JoystickDeviceItem *device = joystick->hwdata; SDL_JoystickDeviceItem *device = joystick->hwdata;
@ -1155,7 +1195,7 @@ IOS_JoystickRumbleTriggers(SDL_Joystick * joystick, Uint16 left_rumble, Uint16 r
} }
static SDL_bool static SDL_bool
IOS_JoystickHasLED(SDL_Joystick * joystick) IOS_JoystickHasLED(SDL_Joystick *joystick)
{ {
#ifdef ENABLE_MFI_LIGHT #ifdef ENABLE_MFI_LIGHT
@autoreleasepool { @autoreleasepool {
@ -1173,7 +1213,7 @@ IOS_JoystickHasLED(SDL_Joystick * joystick)
} }
static int static int
IOS_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) IOS_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
{ {
#ifdef ENABLE_MFI_LIGHT #ifdef ENABLE_MFI_LIGHT
@autoreleasepool { @autoreleasepool {
@ -1193,8 +1233,27 @@ IOS_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
return SDL_Unsupported(); return SDL_Unsupported();
} }
static int
IOS_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
{
#ifdef ENABLE_MFI_SENSORS
@autoreleasepool {
if (@available(iOS 14.0, tvOS 14.0, *)) {
GCController *controller = joystick->hwdata->controller;
GCMotion *motion = controller.motion;
if (motion) {
motion.sensorsActive = enabled ? YES : NO;
return 0;
}
}
}
#endif /* ENABLE_MFI_SENSORS */
return SDL_Unsupported();
}
static void static void
IOS_JoystickUpdate(SDL_Joystick * joystick) IOS_JoystickUpdate(SDL_Joystick *joystick)
{ {
SDL_JoystickDeviceItem *device = joystick->hwdata; SDL_JoystickDeviceItem *device = joystick->hwdata;
@ -1210,7 +1269,7 @@ IOS_JoystickUpdate(SDL_Joystick * joystick)
} }
static void static void
IOS_JoystickClose(SDL_Joystick * joystick) IOS_JoystickClose(SDL_Joystick *joystick)
{ {
SDL_JoystickDeviceItem *device = joystick->hwdata; SDL_JoystickDeviceItem *device = joystick->hwdata;
@ -1304,6 +1363,7 @@ SDL_JoystickDriver SDL_IOS_JoystickDriver =
IOS_JoystickRumbleTriggers, IOS_JoystickRumbleTriggers,
IOS_JoystickHasLED, IOS_JoystickHasLED,
IOS_JoystickSetLED, IOS_JoystickSetLED,
IOS_JoystickSetSensorsEnabled,
IOS_JoystickUpdate, IOS_JoystickUpdate,
IOS_JoystickClose, IOS_JoystickClose,
IOS_JoystickQuit, IOS_JoystickQuit,

View File

@ -764,7 +764,7 @@ LINUX_JoystickGetDeviceInstanceID(int device_index)
} }
static int static int
allocate_hatdata(SDL_Joystick * joystick) allocate_hatdata(SDL_Joystick *joystick)
{ {
int i; int i;
@ -782,7 +782,7 @@ allocate_hatdata(SDL_Joystick * joystick)
} }
static int static int
allocate_balldata(SDL_Joystick * joystick) allocate_balldata(SDL_Joystick *joystick)
{ {
int i; int i;
@ -800,7 +800,7 @@ allocate_balldata(SDL_Joystick * joystick)
} }
static void static void
ConfigJoystick(SDL_Joystick * joystick, int fd) ConfigJoystick(SDL_Joystick *joystick, int fd)
{ {
int i, t; int i, t;
unsigned long keybit[NBITS(KEY_MAX)] = { 0 }; unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
@ -926,7 +926,7 @@ ConfigJoystick(SDL_Joystick * joystick, int fd)
It returns 0, or -1 if there is an error. It returns 0, or -1 if there is an error.
*/ */
static int static int
LINUX_JoystickOpen(SDL_Joystick * joystick, int device_index) LINUX_JoystickOpen(SDL_Joystick *joystick, int device_index)
{ {
SDL_joylist_item *item = JoystickByDevIndex(device_index); SDL_joylist_item *item = JoystickByDevIndex(device_index);
@ -985,7 +985,7 @@ LINUX_JoystickOpen(SDL_Joystick * joystick, int device_index)
} }
static int static int
LINUX_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) LINUX_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
{ {
struct input_event event; struct input_event event;
@ -1027,25 +1027,31 @@ LINUX_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint1
} }
static int static int
LINUX_JoystickRumbleTriggers(SDL_Joystick * joystick, Uint16 left_rumble, Uint16 right_rumble) LINUX_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
{ {
return SDL_Unsupported(); return SDL_Unsupported();
} }
static SDL_bool static SDL_bool
LINUX_JoystickHasLED(SDL_Joystick * joystick) LINUX_JoystickHasLED(SDL_Joystick *joystick)
{ {
return SDL_FALSE; return SDL_FALSE;
} }
static int static int
LINUX_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) LINUX_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
{
return SDL_Unsupported();
}
static int
LINUX_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
{ {
return SDL_Unsupported(); return SDL_Unsupported();
} }
static SDL_INLINE void static SDL_INLINE void
HandleHat(SDL_Joystick * stick, Uint8 hat, int axis, int value) HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value)
{ {
struct hwdata_hat *the_hat; struct hwdata_hat *the_hat;
const Uint8 position_map[3][3] = { const Uint8 position_map[3][3] = {
@ -1070,14 +1076,14 @@ HandleHat(SDL_Joystick * stick, Uint8 hat, int axis, int value)
} }
static SDL_INLINE void static SDL_INLINE void
HandleBall(SDL_Joystick * stick, Uint8 ball, int axis, int value) HandleBall(SDL_Joystick *stick, Uint8 ball, int axis, int value)
{ {
stick->hwdata->balls[ball].axis[axis] += value; stick->hwdata->balls[ball].axis[axis] += value;
} }
static SDL_INLINE int static SDL_INLINE int
AxisCorrect(SDL_Joystick * joystick, int which, int value) AxisCorrect(SDL_Joystick *joystick, int which, int value)
{ {
struct axis_correct *correct; struct axis_correct *correct;
@ -1106,7 +1112,7 @@ AxisCorrect(SDL_Joystick * joystick, int which, int value)
} }
static SDL_INLINE void static SDL_INLINE void
PollAllValues(SDL_Joystick * joystick) PollAllValues(SDL_Joystick *joystick)
{ {
struct input_absinfo absinfo; struct input_absinfo absinfo;
unsigned long keyinfo[NBITS(KEY_MAX)]; unsigned long keyinfo[NBITS(KEY_MAX)];
@ -1166,7 +1172,7 @@ PollAllValues(SDL_Joystick * joystick)
} }
static SDL_INLINE void static SDL_INLINE void
HandleInputEvents(SDL_Joystick * joystick) HandleInputEvents(SDL_Joystick *joystick)
{ {
struct input_event events[32]; struct input_event events[32];
int i, len; int i, len;
@ -1260,7 +1266,7 @@ HandleInputEvents(SDL_Joystick * joystick)
} }
static void static void
LINUX_JoystickUpdate(SDL_Joystick * joystick) LINUX_JoystickUpdate(SDL_Joystick *joystick)
{ {
int i; int i;
@ -1287,7 +1293,7 @@ LINUX_JoystickUpdate(SDL_Joystick * joystick)
/* Function to close a joystick after use */ /* Function to close a joystick after use */
static void static void
LINUX_JoystickClose(SDL_Joystick * joystick) LINUX_JoystickClose(SDL_Joystick *joystick)
{ {
if (joystick->hwdata) { if (joystick->hwdata) {
if (joystick->hwdata->effect.id >= 0) { if (joystick->hwdata->effect.id >= 0) {
@ -1345,7 +1351,7 @@ LINUX_JoystickQuit(void)
static SDL_bool static SDL_bool
LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out) LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
{ {
SDL_Joystick * joystick; SDL_Joystick *joystick;
joystick = (SDL_Joystick *) SDL_calloc(sizeof(*joystick), 1); joystick = (SDL_Joystick *) SDL_calloc(sizeof(*joystick), 1);
if (joystick == NULL) { if (joystick == NULL) {
@ -1527,6 +1533,7 @@ SDL_JoystickDriver SDL_LINUX_JoystickDriver =
LINUX_JoystickRumbleTriggers, LINUX_JoystickRumbleTriggers,
LINUX_JoystickHasLED, LINUX_JoystickHasLED,
LINUX_JoystickSetLED, LINUX_JoystickSetLED,
LINUX_JoystickSetSensorsEnabled,
LINUX_JoystickUpdate, LINUX_JoystickUpdate,
LINUX_JoystickClose, LINUX_JoystickClose,
LINUX_JoystickQuit, LINUX_JoystickQuit,

View File

@ -358,6 +358,12 @@ VIRTUAL_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 bl
return SDL_Unsupported(); return SDL_Unsupported();
} }
static int
VIRTUAL_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
{
return SDL_Unsupported();
}
static void static void
VIRTUAL_JoystickUpdate(SDL_Joystick * joystick) VIRTUAL_JoystickUpdate(SDL_Joystick * joystick)
@ -432,6 +438,7 @@ SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver =
VIRTUAL_JoystickRumbleTriggers, VIRTUAL_JoystickRumbleTriggers,
VIRTUAL_JoystickHasLED, VIRTUAL_JoystickHasLED,
VIRTUAL_JoystickSetLED, VIRTUAL_JoystickSetLED,
VIRTUAL_JoystickSetSensorsEnabled,
VIRTUAL_JoystickUpdate, VIRTUAL_JoystickUpdate,
VIRTUAL_JoystickClose, VIRTUAL_JoystickClose,
VIRTUAL_JoystickQuit, VIRTUAL_JoystickQuit,

View File

@ -635,6 +635,12 @@ RAWINPUT_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 b
return SDL_Unsupported(); return SDL_Unsupported();
} }
static int
RAWINPUT_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
{
return SDL_Unsupported();
}
static void static void
RAWINPUT_JoystickUpdate(SDL_Joystick * joystick) RAWINPUT_JoystickUpdate(SDL_Joystick * joystick)
@ -768,6 +774,7 @@ SDL_JoystickDriver SDL_RAWINPUT_JoystickDriver =
RAWINPUT_JoystickRumbleTriggers, RAWINPUT_JoystickRumbleTriggers,
RAWINPUT_JoystickHasLED, RAWINPUT_JoystickHasLED,
RAWINPUT_JoystickSetLED, RAWINPUT_JoystickSetLED,
RAWINPUT_JoystickSetSensorsEnabled,
RAWINPUT_JoystickUpdate, RAWINPUT_JoystickUpdate,
RAWINPUT_JoystickClose, RAWINPUT_JoystickClose,
RAWINPUT_JoystickQuit, RAWINPUT_JoystickQuit,

View File

@ -607,6 +607,12 @@ WGI_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
return SDL_Unsupported(); return SDL_Unsupported();
} }
static int
WGI_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
{
return SDL_Unsupported();
}
static Uint8 static Uint8
ConvertHatValue(__x_ABI_CWindows_CGaming_CInput_CGameControllerSwitchPosition value) ConvertHatValue(__x_ABI_CWindows_CGaming_CInput_CGameControllerSwitchPosition value)
{ {
@ -752,6 +758,7 @@ SDL_JoystickDriver SDL_WGI_JoystickDriver =
WGI_JoystickRumbleTriggers, WGI_JoystickRumbleTriggers,
WGI_JoystickHasLED, WGI_JoystickHasLED,
WGI_JoystickSetLED, WGI_JoystickSetLED,
WGI_JoystickSetSensorsEnabled,
WGI_JoystickUpdate, WGI_JoystickUpdate,
WGI_JoystickClose, WGI_JoystickClose,
WGI_JoystickQuit, WGI_JoystickQuit,

View File

@ -518,6 +518,12 @@ WINDOWS_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 bl
return SDL_Unsupported(); return SDL_Unsupported();
} }
static int
WINDOWS_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
{
return SDL_Unsupported();
}
static void static void
WINDOWS_JoystickUpdate(SDL_Joystick * joystick) WINDOWS_JoystickUpdate(SDL_Joystick * joystick)
{ {
@ -604,6 +610,7 @@ SDL_JoystickDriver SDL_WINDOWS_JoystickDriver =
WINDOWS_JoystickRumbleTriggers, WINDOWS_JoystickRumbleTriggers,
WINDOWS_JoystickHasLED, WINDOWS_JoystickHasLED,
WINDOWS_JoystickSetLED, WINDOWS_JoystickSetLED,
WINDOWS_JoystickSetSensorsEnabled,
WINDOWS_JoystickUpdate, WINDOWS_JoystickUpdate,
WINDOWS_JoystickClose, WINDOWS_JoystickClose,
WINDOWS_JoystickQuit, WINDOWS_JoystickQuit,

View File

@ -158,9 +158,9 @@ SDL_COREMOTION_SensorUpdate(SDL_Sensor *sensor)
if (accelerometerData) { if (accelerometerData) {
CMAcceleration acceleration = accelerometerData.acceleration; CMAcceleration acceleration = accelerometerData.acceleration;
float data[3]; float data[3];
data[0] = acceleration.x * SDL_STANDARD_GRAVITY; data[0] = -acceleration.x * SDL_STANDARD_GRAVITY;
data[1] = acceleration.y * SDL_STANDARD_GRAVITY; data[1] = -acceleration.y * SDL_STANDARD_GRAVITY;
data[2] = acceleration.z * SDL_STANDARD_GRAVITY; data[2] = -acceleration.z * SDL_STANDARD_GRAVITY;
if (SDL_memcmp(data, sensor->hwdata->data, sizeof(data)) != 0) { if (SDL_memcmp(data, sensor->hwdata->data, sizeof(data)) != 0) {
SDL_PrivateSensorUpdate(sensor, data, SDL_arraysize(data)); SDL_PrivateSensorUpdate(sensor, data, SDL_arraysize(data));
SDL_memcpy(sensor->hwdata->data, data, sizeof(data)); SDL_memcpy(sensor->hwdata->data, data, sizeof(data));

View File

@ -98,26 +98,48 @@ LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent)
} }
static void static void
UpdateWindowTitle() InitGameController()
{ {
const char *name = SDL_GameControllerName(gamecontroller); const char *name = SDL_GameControllerName(gamecontroller);
const char *serial = SDL_GameControllerGetSerial(gamecontroller);
const char *basetitle = "Game Controller Test: ";
const size_t titlelen = SDL_strlen(basetitle) + SDL_strlen(name) + (serial ? 3 + SDL_strlen(serial) : 0) + 1;
char *title = (char *)SDL_malloc(titlelen);
retval = SDL_FALSE; SDL_Log("Opened game controller %s\n", name);
done = SDL_FALSE;
if (title) { if (SDL_GameControllerHasSensor(gamecontroller, SDL_SENSOR_ACCEL)) {
SDL_snprintf(title, titlelen, "%s%s", basetitle, name); SDL_Log("Enabling accelerometer\n");
if (serial) { SDL_GameControllerSetSensorEnabled(gamecontroller, SDL_SENSOR_ACCEL, SDL_TRUE);
SDL_strlcat(title, " (", titlelen); }
SDL_strlcat(title, serial, titlelen);
SDL_strlcat(title, ")", titlelen); if (SDL_GameControllerHasSensor(gamecontroller, SDL_SENSOR_GYRO)) {
SDL_Log("Enabling gyro\n");
SDL_GameControllerSetSensorEnabled(gamecontroller, SDL_SENSOR_GYRO, SDL_TRUE);
}
}
static void
UpdateWindowTitle()
{
if (gamecontroller) {
const char *name = SDL_GameControllerName(gamecontroller);
const char *serial = SDL_GameControllerGetSerial(gamecontroller);
const char *basetitle = "Game Controller Test: ";
const size_t titlelen = SDL_strlen(basetitle) + SDL_strlen(name) + (serial ? 3 + SDL_strlen(serial) : 0) + 1;
char *title = (char *)SDL_malloc(titlelen);
retval = SDL_FALSE;
done = SDL_FALSE;
if (title) {
SDL_snprintf(title, titlelen, "%s%s", basetitle, name);
if (serial) {
SDL_strlcat(title, " (", titlelen);
SDL_strlcat(title, serial, titlelen);
SDL_strlcat(title, ")", titlelen);
}
SDL_SetWindowTitle(window, title);
SDL_free(title);
} }
SDL_SetWindowTitle(window, title); } else {
SDL_free(title); SDL_SetWindowTitle(window, "Waiting for controller...");
} }
} }
@ -146,10 +168,11 @@ loop(void *arg)
if (!gamecontroller) { if (!gamecontroller) {
gamecontroller = SDL_GameControllerOpen(event.cdevice.which); gamecontroller = SDL_GameControllerOpen(event.cdevice.which);
if (gamecontroller) { if (gamecontroller) {
UpdateWindowTitle(); InitGameController();
} else { } else {
SDL_Log("Couldn't open controller: %s\n", SDL_GetError()); SDL_Log("Couldn't open controller: %s\n", SDL_GetError());
} }
UpdateWindowTitle();
} }
break; break;
@ -159,8 +182,9 @@ loop(void *arg)
SDL_GameControllerClose(gamecontroller); SDL_GameControllerClose(gamecontroller);
gamecontroller = SDL_GameControllerOpen(0); gamecontroller = SDL_GameControllerOpen(0);
if (gamecontroller) { if (gamecontroller) {
UpdateWindowTitle(); InitGameController();
} }
UpdateWindowTitle();
} }
break; break;
@ -178,6 +202,15 @@ loop(void *arg)
event.ctouchpad.pressure); event.ctouchpad.pressure);
break; break;
case SDL_CONTROLLERSENSORUPDATE:
SDL_Log("Controller sensor %s: %.2f, %.2f, %.2f\n",
event.csensor.sensor == SDL_SENSOR_ACCEL ? "accelerometer" :
event.csensor.sensor == SDL_SENSOR_GYRO ? "gyro" : "unknown",
event.csensor.data[0],
event.csensor.data[1],
event.csensor.data[2]);
break;
case SDL_CONTROLLERAXISMOTION: case SDL_CONTROLLERAXISMOTION:
SDL_Log("Controller axis %s changed to %d\n", SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis)event.caxis.axis), event.caxis.value); SDL_Log("Controller axis %s changed to %d\n", SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis)event.caxis.axis), event.caxis.value);
break; break;
@ -414,6 +447,8 @@ main(int argc, char *argv[])
/* !!! FIXME: */ /* !!! FIXME: */
/*SDL_RenderSetLogicalSize(screen, background->w, background->h);*/ /*SDL_RenderSetLogicalSize(screen, background->w, background->h);*/
UpdateWindowTitle();
/* Loop, getting controller events! */ /* Loop, getting controller events! */
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
emscripten_set_main_loop_arg(loop, NULL, 0, 1); emscripten_set_main_loop_arg(loop, NULL, 0, 1);