Simple Directmedia Layer
at main 463 lines 11 kB view raw
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 2020 Valve Corporation 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#ifndef _CONTROLLER_STRUCTS_ 22#define _CONTROLLER_STRUCTS_ 23 24#pragma pack(1) 25 26#define HID_FEATURE_REPORT_BYTES 64 27 28// Header for all host <==> target messages 29typedef struct 30{ 31 unsigned char type; 32 unsigned char length; 33} FeatureReportHeader; 34 35// Generic controller settings structure 36typedef struct 37{ 38 unsigned char settingNum; 39 unsigned short settingValue; 40} ControllerSetting; 41 42// Generic controller attribute structure 43typedef struct 44{ 45 unsigned char attributeTag; 46 uint32_t attributeValue; 47} ControllerAttribute; 48 49// Generic controller settings structure 50typedef struct 51{ 52 ControllerSetting settings[ ( HID_FEATURE_REPORT_BYTES - sizeof( FeatureReportHeader ) ) / sizeof( ControllerSetting ) ]; 53} MsgSetSettingsValues, MsgGetSettingsValues, MsgGetSettingsDefaults, MsgGetSettingsMaxs; 54 55// Generic controller settings structure 56typedef struct 57{ 58 ControllerAttribute attributes[ ( HID_FEATURE_REPORT_BYTES - sizeof( FeatureReportHeader ) ) / sizeof( ControllerAttribute ) ]; 59} MsgGetAttributes; 60 61typedef struct 62{ 63 unsigned char attributeTag; 64 char attributeValue[20]; 65} MsgGetStringAttribute; 66 67typedef struct 68{ 69 unsigned char mode; 70} MsgSetControllerMode; 71 72// Trigger a haptic pulse 73typedef struct { 74 unsigned char which_pad; 75 unsigned short pulse_duration; 76 unsigned short pulse_interval; 77 unsigned short pulse_count; 78 short dBgain; 79 unsigned char priority; 80} MsgFireHapticPulse; 81 82typedef struct { 83 uint8_t mode; 84} MsgHapticSetMode; 85 86typedef enum { 87 HAPTIC_TYPE_OFF, 88 HAPTIC_TYPE_TICK, 89 HAPTIC_TYPE_CLICK, 90 HAPTIC_TYPE_TONE, 91 HAPTIC_TYPE_RUMBLE, 92 HAPTIC_TYPE_NOISE, 93 HAPTIC_TYPE_SCRIPT, 94 HAPTIC_TYPE_LOG_SWEEP, 95} haptic_type_t; 96 97typedef enum { 98 HAPTIC_INTENSITY_SYSTEM, 99 HAPTIC_INTENSITY_SHORT, 100 HAPTIC_INTENSITY_MEDIUM, 101 HAPTIC_INTENSITY_LONG, 102 HAPTIC_INTENSITY_INSANE, 103} haptic_intensity_t; 104 105typedef struct { 106 uint8_t side; // 0x01 = L, 0x02 = R, 0x03 = Both 107 uint8_t cmd; // 0 = Off, 1 = tick, 2 = click, 3 = tone, 4 = rumble, 5 = 108 // rumble_noise, 6 = script, 7 = sweep, 109 uint8_t ui_intensity; // 0-4 (0 = default) 110 int8_t dBgain; // dB Can be positive (reasonable clipping / limiting will apply) 111 uint16_t freq; // Frequency of tone (if applicable) 112 int16_t dur_ms; // Duration of tone / rumble (if applicable) (neg = infinite) 113 114 uint16_t noise_intensity; 115 uint16_t lfo_freq; // Drives both tone and rumble geneators 116 uint8_t lfo_depth; // percentage, typically 100 117 uint8_t rand_tone_gain; // Randomize each LFO cycle's gain 118 uint8_t script_id; // Used w/ dBgain for scripted haptics 119 120 uint16_t lss_start_freq; // Used w/ Log Sine Sweep 121 uint16_t lss_end_freq; // Ditto 122} MsgTriggerHaptic; 123 124typedef struct { 125 uint8_t unRumbleType; 126 uint16_t unIntensity; 127 uint16_t unLeftMotorSpeed; 128 uint16_t unRightMotorSpeed; 129 int8_t nLeftGain; 130 int8_t nRightGain; 131} MsgSimpleRumbleCmd; 132 133// This is the only message struct that application code should use to interact with feature request messages. Any new 134// messages should be added to the union. The structures defined here should correspond to the ones defined in 135// ValveDeviceCore.cpp. 136// 137typedef struct 138{ 139 FeatureReportHeader header; 140 union 141 { 142 MsgSetSettingsValues setSettingsValues; 143 MsgGetSettingsValues getSettingsValues; 144 MsgGetSettingsMaxs getSettingsMaxs; 145 MsgGetSettingsDefaults getSettingsDefaults; 146 MsgGetAttributes getAttributes; 147 MsgSetControllerMode controllerMode; 148 MsgFireHapticPulse fireHapticPulse; 149 MsgGetStringAttribute getStringAttribute; 150 MsgHapticSetMode hapticMode; 151 MsgTriggerHaptic triggerHaptic; 152 MsgSimpleRumbleCmd simpleRumble; 153 } payload; 154 155} FeatureReportMsg; 156 157// Roll this version forward anytime that you are breaking compatibility of existing 158// message types within ValveInReport_t or the header itself. Hopefully this should 159// be super rare and instead you should just add new message payloads to the union, 160// or just add fields to the end of existing payload structs which is expected to be 161// safe in all code consuming these as they should just consume/copy up to the prior size 162// they were aware of when processing. 163#define k_ValveInReportMsgVersion 0x01 164 165typedef enum 166{ 167 ID_CONTROLLER_STATE = 1, 168 ID_CONTROLLER_DEBUG = 2, 169 ID_CONTROLLER_WIRELESS = 3, 170 ID_CONTROLLER_STATUS = 4, 171 ID_CONTROLLER_DEBUG2 = 5, 172 ID_CONTROLLER_SECONDARY_STATE = 6, 173 ID_CONTROLLER_BLE_STATE = 7, 174 ID_CONTROLLER_DECK_STATE = 9, 175 ID_CONTROLLER_MSG_COUNT 176} ValveInReportMessageIDs; 177 178typedef struct 179{ 180 unsigned short unReportVersion; 181 182 unsigned char ucType; 183 unsigned char ucLength; 184 185} ValveInReportHeader_t; 186 187// State payload 188typedef struct 189{ 190 // If packet num matches that on your prior call, then the controller state hasn't been changed since 191 // your last call and there is no need to process it 192 Uint32 unPacketNum; 193 194 // Button bitmask and trigger data. 195 union 196 { 197 Uint64 ulButtons; 198 struct 199 { 200 unsigned char _pad0[3]; 201 unsigned char nLeft; 202 unsigned char nRight; 203 unsigned char _pad1[3]; 204 } Triggers; 205 } ButtonTriggerData; 206 207 // Left pad coordinates 208 short sLeftPadX; 209 short sLeftPadY; 210 211 // Right pad coordinates 212 short sRightPadX; 213 short sRightPadY; 214 215 // This is redundant, packed above, but still sent over wired 216 unsigned short sTriggerL; 217 unsigned short sTriggerR; 218 219 // FIXME figure out a way to grab this stuff over wireless 220 short sAccelX; 221 short sAccelY; 222 short sAccelZ; 223 224 short sGyroX; 225 short sGyroY; 226 short sGyroZ; 227 228 short sGyroQuatW; 229 short sGyroQuatX; 230 short sGyroQuatY; 231 short sGyroQuatZ; 232 233} ValveControllerStatePacket_t; 234 235// BLE State payload this has to be re-formatted from the normal state because BLE controller shows up as 236//a HID device and we don't want to send all the optional parts of the message. Keep in sync with struct above. 237typedef struct 238{ 239 // If packet num matches that on your prior call, then the controller state hasn't been changed since 240 // your last call and there is no need to process it 241 Uint32 unPacketNum; 242 243 // Button bitmask and trigger data. 244 union 245 { 246 Uint64 ulButtons; 247 struct 248 { 249 unsigned char _pad0[3]; 250 unsigned char nLeft; 251 unsigned char nRight; 252 unsigned char _pad1[3]; 253 } Triggers; 254 } ButtonTriggerData; 255 256 // Left pad coordinates 257 short sLeftPadX; 258 short sLeftPadY; 259 260 // Right pad coordinates 261 short sRightPadX; 262 short sRightPadY; 263 264 //This mimcs how the dongle reconstitutes HID packets, there will be 0-4 shorts depending on gyro mode 265 unsigned char ucGyroDataType; //TODO could maybe find some unused bits in the button field for this info (is only 2bits) 266 short sGyro[4]; 267 268} ValveControllerBLEStatePacket_t; 269 270// Define a payload for reporting debug information 271typedef struct 272{ 273 // Left pad coordinates 274 short sLeftPadX; 275 short sLeftPadY; 276 277 // Right pad coordinates 278 short sRightPadX; 279 short sRightPadY; 280 281 // Left mouse deltas 282 short sLeftPadMouseDX; 283 short sLeftPadMouseDY; 284 285 // Right mouse deltas 286 short sRightPadMouseDX; 287 short sRightPadMouseDY; 288 289 // Left mouse filtered deltas 290 short sLeftPadMouseFilteredDX; 291 short sLeftPadMouseFilteredDY; 292 293 // Right mouse filtered deltas 294 short sRightPadMouseFilteredDX; 295 short sRightPadMouseFilteredDY; 296 297 // Pad Z values 298 unsigned char ucLeftZ; 299 unsigned char ucRightZ; 300 301 // FingerPresent 302 unsigned char ucLeftFingerPresent; 303 unsigned char ucRightFingerPresent; 304 305 // Timestamps 306 unsigned char ucLeftTimestamp; 307 unsigned char ucRightTimestamp; 308 309 // Double tap state 310 unsigned char ucLeftTapState; 311 unsigned char ucRightTapState; 312 313 unsigned int unDigitalIOStates0; 314 unsigned int unDigitalIOStates1; 315 316} ValveControllerDebugPacket_t; 317 318typedef struct 319{ 320 unsigned char ucPadNum; 321 unsigned char ucPad[3]; // need Data to be word aligned 322 short Data[20]; 323 unsigned short unNoise; 324} ValveControllerTrackpadImage_t; 325 326typedef struct 327{ 328 unsigned char ucPadNum; 329 unsigned char ucOffset; 330 unsigned char ucPad[2]; // need Data to be word aligned 331 short rgData[28]; 332} ValveControllerRawTrackpadImage_t; 333 334// Payload for wireless metadata 335typedef struct 336{ 337 unsigned char ucEventType; 338} SteamControllerWirelessEvent_t; 339 340typedef struct 341{ 342 // Current packet number. 343 unsigned int unPacketNum; 344 345 // Event codes and state information. 346 unsigned short sEventCode; 347 unsigned short unStateFlags; 348 349 // Current battery voltage (mV). 350 unsigned short sBatteryVoltage; 351 352 // Current battery level (0-100). 353 unsigned char ucBatteryLevel; 354} SteamControllerStatusEvent_t; 355 356// Deck State payload 357typedef struct 358{ 359 // If packet num matches that on your prior call, then the controller 360 // state hasn't been changed since your last call and there is no need to 361 // process it 362 Uint32 unPacketNum; 363 364 // Button bitmask and trigger data. 365 union 366 { 367 Uint64 ulButtons; 368 struct 369 { 370 Uint32 ulButtonsL; 371 Uint32 ulButtonsH; 372 }; 373 }; 374 375 // Left pad coordinates 376 short sLeftPadX; 377 short sLeftPadY; 378 379 // Right pad coordinates 380 short sRightPadX; 381 short sRightPadY; 382 383 // Accelerometer values 384 short sAccelX; 385 short sAccelY; 386 short sAccelZ; 387 388 // Gyroscope values 389 short sGyroX; 390 short sGyroY; 391 short sGyroZ; 392 393 // Gyro quaternions 394 short sGyroQuatW; 395 short sGyroQuatX; 396 short sGyroQuatY; 397 short sGyroQuatZ; 398 399 // Uncalibrated trigger values 400 unsigned short sTriggerRawL; 401 unsigned short sTriggerRawR; 402 403 // Left stick values 404 short sLeftStickX; 405 short sLeftStickY; 406 407 // Right stick values 408 short sRightStickX; 409 short sRightStickY; 410 411 // Touchpad pressures 412 unsigned short sPressurePadLeft; 413 unsigned short sPressurePadRight; 414} SteamDeckStatePacket_t; 415 416typedef struct 417{ 418 ValveInReportHeader_t header; 419 420 union 421 { 422 ValveControllerStatePacket_t controllerState; 423 ValveControllerBLEStatePacket_t controllerBLEState; 424 ValveControllerDebugPacket_t debugState; 425 ValveControllerTrackpadImage_t padImage; 426 ValveControllerRawTrackpadImage_t rawPadImage; 427 SteamControllerWirelessEvent_t wirelessEvent; 428 SteamControllerStatusEvent_t statusEvent; 429 SteamDeckStatePacket_t deckState; 430 } payload; 431 432} ValveInReport_t; 433 434 435// Enumeration for BLE packet protocol 436enum EBLEPacketReportNums 437{ 438 // Skipping past 2-3 because they are escape characters in Uart protocol 439 k_EBLEReportState = 4, 440 k_EBLEReportStatus = 5, 441}; 442 443 444// Enumeration of data chunks in BLE state packets 445enum EBLEOptionDataChunksBitmask 446{ 447 // First byte upper nibble 448 k_EBLEButtonChunk1 = 0x10, 449 k_EBLEButtonChunk2 = 0x20, 450 k_EBLEButtonChunk3 = 0x40, 451 k_EBLELeftJoystickChunk = 0x80, 452 453 // Second full byte 454 k_EBLELeftTrackpadChunk = 0x100, 455 k_EBLERightTrackpadChunk = 0x200, 456 k_EBLEIMUAccelChunk = 0x400, 457 k_EBLEIMUGyroChunk = 0x800, 458 k_EBLEIMUQuatChunk = 0x1000, 459}; 460 461#pragma pack() 462 463#endif // _CONTROLLER_STRUCTS