Use the correct update rate for Steam Controller sensors
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c
index caa1051..b015e6b 100644
--- a/src/joystick/hidapi/SDL_hidapi_steam.c
+++ b/src/joystick/hidapi/SDL_hidapi_steam.c
@@ -421,13 +421,15 @@ static int ReadResponse( hid_device *dev, uint8_t uBuffer[65], int nExpectedResp
//---------------------------------------------------------------------------
// Reset steam controller (unmap buttons and pads) and re-fetch capability bits
//---------------------------------------------------------------------------
-static bool ResetSteamController( hid_device *dev, bool bSuppressErrorSpew )
+static bool ResetSteamController( hid_device *dev, bool bSuppressErrorSpew, uint32_t *punUpdateRateUS )
{
// Firmware quirk: Set Feature and Get Feature requests always require a 65-byte buffer.
unsigned char buf[65];
- int res = -1;
+ int res = -1, i;
int nSettings = 0;
int nAttributesLength;
+ FeatureReportMsg *msg;
+ uint32_t unUpdateRateUS = 9000; // Good default rate
DPRINTF( "ResetSteamController hid=%p\n", dev );
@@ -459,7 +461,33 @@ static bool ResetSteamController( hid_device *dev, bool bSuppressErrorSpew )
printf( "Bad GET_ATTRIBUTES_VALUES response for controller %p\n", dev );
return false;
}
-
+
+ msg = (FeatureReportMsg *)&buf[1];
+ for ( i = 0; i < (int)msg->header.length / sizeof( ControllerAttribute ); ++i )
+ {
+ uint8_t unAttribute = msg->payload.getAttributes.attributes[i].attributeTag;
+ uint32_t unValue = msg->payload.getAttributes.attributes[i].attributeValue;
+
+ switch ( unAttribute )
+ {
+ case ATTRIB_UNIQUE_ID:
+ break;
+ case ATTRIB_PRODUCT_ID:
+ break;
+ case ATTRIB_CAPABILITIES:
+ break;
+ case ATTRIB_CONNECTION_INTERVAL_IN_US:
+ unUpdateRateUS = unValue;
+ break;
+ default:
+ break;
+ }
+ }
+ if ( punUpdateRateUS )
+ {
+ *punUpdateRateUS = unUpdateRateUS;
+ }
+
// Clear digital button mappings
buf[0] = 0;
buf[1] = ID_CLEAR_DIGITAL_MAPPINGS;
@@ -1002,6 +1030,8 @@ static SDL_bool
HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
SDL_DriverSteam_Context *ctx;
+ uint32_t update_rate_in_us = 0;
+ float update_rate_in_hz = 0.0f;
ctx = (SDL_DriverSteam_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
@@ -1017,9 +1047,13 @@ HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystic
}
hid_set_nonblocking(device->dev, 1);
- if (!ResetSteamController(device->dev, false)) {
+ if (!ResetSteamController(device->dev, false, &update_rate_in_us)) {
+ SDL_SetError("Couldn't reset controller");
goto error;
}
+ if (update_rate_in_us > 0) {
+ update_rate_in_hz = 1000000.0f / update_rate_in_us;
+ }
InitializeSteamControllerPacketAssembler(&ctx->m_assembler);
@@ -1027,8 +1061,8 @@ HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystic
joystick->nbuttons = 17;
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
- SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 0.0f);
- SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 0.0f);
+ SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, update_rate_in_hz);
+ SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, update_rate_in_hz);
return SDL_TRUE;
diff --git a/src/joystick/hidapi/steam/controller_structs.h b/src/joystick/hidapi/steam/controller_structs.h
index 967c96f..c8fd612 100644
--- a/src/joystick/hidapi/steam/controller_structs.h
+++ b/src/joystick/hidapi/steam/controller_structs.h
@@ -23,6 +23,43 @@
#pragma pack(1)
+#define HID_FEATURE_REPORT_BYTES 64
+
+// Header for all host <==> target messages
+typedef struct
+{
+ unsigned char type;
+ unsigned char length;
+} FeatureReportHeader;
+
+// Generic controller attribute structure
+typedef struct
+{
+ unsigned char attributeTag;
+ uint32_t attributeValue;
+} ControllerAttribute;
+
+// Generic controller settings structure
+typedef struct
+{
+ ControllerAttribute attributes[ ( HID_FEATURE_REPORT_BYTES - sizeof( FeatureReportHeader ) ) / sizeof( ControllerAttribute ) ];
+} MsgGetAttributes;
+
+
+// This is the only message struct that application code should use to interact with feature request messages. Any new
+// messages should be added to the union. The structures defined here should correspond to the ones defined in
+// ValveDeviceCore.cpp.
+//
+typedef struct
+{
+ FeatureReportHeader header;
+ union
+ {
+ MsgGetAttributes getAttributes;
+ } payload;
+
+} FeatureReportMsg;
+
// Roll this version forward anytime that you are breaking compatibility of existing
// message types within ValveInReport_t or the header itself. Hopefully this should
// be super rare and instead you shoudl just add new message payloads to the union,