Atlas - controller_structs.h
Home / ext / SDL / src / joystick / hidapi / steam Lines: 1 | Size: 15531 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]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 generators 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// Triton and derivatives utilize output reports for haptic commands. This is a 158// snapshot from Nov 2024 -- things may change. 159 160// Triton Output Report Lengths #defs include +1 for the OR ID 161 162// Output Report Haptic Messages for Triton 163typedef struct 164{ 165 uint8_t type; 166 uint16_t intensity; 167 struct 168 { 169 uint16_t speed; 170 int8_t gain; 171 } left, right; 172} MsgHapticRumble; 173#define HID_RUMBLE_OUTPUT_REPORT_BYTES 10 174 175 176typedef struct 177{ 178 uint8_t side; 179 uint16_t on_us; 180 uint16_t off_us; 181 uint16_t repeat_count; 182 uint16_t gain_db; 183} MsgHapticPulse; 184#define HID_HAPTIC_PULSE_OUTPUT_REPORT_BYTES 10 185 186typedef struct 187{ 188 uint8_t side; 189 uint8_t command; 190 int8_t gain_db; 191} MsgHapticCommand; 192#define HID_HAPTIC_COMMAND_REPORT_BYTES 4 193 194typedef struct 195{ 196 uint8_t side; 197 int8_t gain_db; 198 uint16_t frequency; 199 uint16_t duration_ms; 200 uint16_t lfo_freq; 201 uint8_t lfo_depth; 202} MsgHapticLfoTone; 203#define HID_HAPTIC_LFO_TONE_REPORT_BYTES 10 204 205typedef struct 206{ 207 uint8_t side; 208 int8_t gain_db; 209 uint16_t duration_ms; 210 struct 211 { 212 uint16_t frequency; 213 } start, end; 214} MsgHapticLogSweep; 215#define HID_HAPTIC_LOG_SWEEP_REPORT_BYTES 9 216 217typedef struct m 218{ 219 uint8_t side; 220 uint8_t script_id; 221 int8_t gain_db; 222} MsgHapticScript; 223#define HID_HAPTIC_SCRIPT_REPORT_BYTES 4 224 225typedef enum 226{ 227 ID_OUT_REPORT_HAPTIC_RUMBLE = 0x80, 228 ID_OUT_REPORT_HAPTIC_PULSE = 0x81, 229 ID_OUT_REPORT_HAPTIC_COMMAND = 0x82, 230 ID_OUT_REPORT_HAPTIC_LFO_TONE = 0x83, 231 ID_OUT_REPORT_HAPTIC_LOG_SWEEP = 0x85, 232 ID_OUT_REPORT_HAPTIC_SCRIPT = 0x86, 233} ValveTritonOutReportMessageIDs; 234 235typedef struct 236{ 237 uint8_t report_id; 238 union 239 { 240 MsgHapticRumble hapticRumble; 241 MsgHapticPulse hapticPulse; 242 MsgHapticCommand hapticCommand; 243 MsgHapticLfoTone hapticLfoTone; 244 MsgHapticLogSweep hapticLogSweep; 245 MsgHapticScript hapticScript; 246 } payload; 247 248} OutputReportMsg; 249 250 251// Roll this version forward anytime that you are breaking compatibility of existing 252// message types within ValveInReport_t or the header itself. Hopefully this should 253// be super rare and instead you should just add new message payloads to the union, 254// or just add fields to the end of existing payload structs which is expected to be 255// safe in all code consuming these as they should just consume/copy up to the prior size 256// they were aware of when processing. 257#define k_ValveInReportMsgVersion 0x01 258 259typedef enum 260{ 261 ID_CONTROLLER_STATE = 1, 262 ID_CONTROLLER_DEBUG = 2, 263 ID_CONTROLLER_WIRELESS = 3, 264 ID_CONTROLLER_STATUS = 4, 265 ID_CONTROLLER_DEBUG2 = 5, 266 ID_CONTROLLER_SECONDARY_STATE = 6, 267 ID_CONTROLLER_BLE_STATE = 7, 268 ID_CONTROLLER_DECK_STATE = 9, 269 ID_CONTROLLER_MSG_COUNT 270} ValveInReportMessageIDs; 271 272typedef struct 273{ 274 unsigned short unReportVersion; 275 276 unsigned char ucType; 277 unsigned char ucLength; 278 279} ValveInReportHeader_t; 280 281// State payload 282typedef struct 283{ 284 // If packet num matches that on your prior call, then the controller state hasn't been changed since 285 // your last call and there is no need to process it 286 Uint32 unPacketNum; 287 288 // Button bitmask and trigger data. 289 union 290 { 291 Uint64 ulButtons; 292 struct 293 { 294 unsigned char _pad0[3]; 295 unsigned char nLeft; 296 unsigned char nRight; 297 unsigned char _pad1[3]; 298 } Triggers; 299 } ButtonTriggerData; 300 301 // Left pad coordinates 302 short sLeftPadX; 303 short sLeftPadY; 304 305 // Right pad coordinates 306 short sRightPadX; 307 short sRightPadY; 308 309 // This is redundant, packed above, but still sent over wired 310 unsigned short sTriggerL; 311 unsigned short sTriggerR; 312 313 // FIXME figure out a way to grab this stuff over wireless 314 short sAccelX; 315 short sAccelY; 316 short sAccelZ; 317 318 short sGyroX; 319 short sGyroY; 320 short sGyroZ; 321 322 short sGyroQuatW; 323 short sGyroQuatX; 324 short sGyroQuatY; 325 short sGyroQuatZ; 326 327} ValveControllerStatePacket_t; 328 329// BLE State payload this has to be re-formatted from the normal state because BLE controller shows up as 330//a HID device and we don't want to send all the optional parts of the message. Keep in sync with struct above. 331typedef struct 332{ 333 // If packet num matches that on your prior call, then the controller state hasn't been changed since 334 // your last call and there is no need to process it 335 Uint32 unPacketNum; 336 337 // Button bitmask and trigger data. 338 union 339 { 340 Uint64 ulButtons; 341 struct 342 { 343 unsigned char _pad0[3]; 344 unsigned char nLeft; 345 unsigned char nRight; 346 unsigned char _pad1[3]; 347 } Triggers; 348 } ButtonTriggerData; 349 350 // Left pad coordinates 351 short sLeftPadX; 352 short sLeftPadY; 353 354 // Right pad coordinates 355 short sRightPadX; 356 short sRightPadY; 357 358 //This mimics how the dongle reconstitutes HID packets, there will be 0-4 shorts depending on gyro mode 359 unsigned char ucGyroDataType; //TODO could maybe find some unused bits in the button field for this info (is only 2bits) 360 short sGyro[4]; 361 362} ValveControllerBLEStatePacket_t; 363 364// Define a payload for reporting debug information 365typedef struct 366{ 367 // Left pad coordinates 368 short sLeftPadX; 369 short sLeftPadY; 370 371 // Right pad coordinates 372 short sRightPadX; 373 short sRightPadY; 374 375 // Left mouse deltas 376 short sLeftPadMouseDX; 377 short sLeftPadMouseDY; 378 379 // Right mouse deltas 380 short sRightPadMouseDX; 381 short sRightPadMouseDY; 382 383 // Left mouse filtered deltas 384 short sLeftPadMouseFilteredDX; 385 short sLeftPadMouseFilteredDY; 386 387 // Right mouse filtered deltas 388 short sRightPadMouseFilteredDX; 389 short sRightPadMouseFilteredDY; 390 391 // Pad Z values 392 unsigned char ucLeftZ; 393 unsigned char ucRightZ; 394 395 // FingerPresent 396 unsigned char ucLeftFingerPresent; 397 unsigned char ucRightFingerPresent; 398 399 // Timestamps 400 unsigned char ucLeftTimestamp; 401 unsigned char ucRightTimestamp; 402 403 // Double tap state 404 unsigned char ucLeftTapState; 405 unsigned char ucRightTapState; 406 407 unsigned int unDigitalIOStates0; 408 unsigned int unDigitalIOStates1; 409 410} ValveControllerDebugPacket_t; 411 412typedef struct 413{ 414 unsigned char ucPadNum; 415 unsigned char ucPad[3]; // need Data to be word aligned 416 short Data[20]; 417 unsigned short unNoise; 418} ValveControllerTrackpadImage_t; 419 420typedef struct 421{ 422 unsigned char ucPadNum; 423 unsigned char ucOffset; 424 unsigned char ucPad[2]; // need Data to be word aligned 425 short rgData[28]; 426} ValveControllerRawTrackpadImage_t; 427 428// Payload for wireless metadata 429typedef struct 430{ 431 unsigned char ucEventType; 432} SteamControllerWirelessEvent_t; 433 434typedef struct 435{ 436 // Current packet number. 437 unsigned int unPacketNum; 438 439 // Event codes and state information. 440 unsigned short sEventCode; 441 unsigned short unStateFlags; 442 443 // Current battery voltage (mV). 444 unsigned short sBatteryVoltage; 445 446 // Current battery level (0-100). 447 unsigned char ucBatteryLevel; 448} SteamControllerStatusEvent_t; 449 450// Deck State payload 451typedef struct 452{ 453 // If packet num matches that on your prior call, then the controller 454 // state hasn't been changed since your last call and there is no need to 455 // process it 456 Uint32 unPacketNum; 457 458 // Button bitmask and trigger data. 459 union 460 { 461 Uint64 ulButtons; 462 struct 463 { 464 Uint32 ulButtonsL; 465 Uint32 ulButtonsH; 466 }; 467 }; 468 469 // Left pad coordinates 470 short sLeftPadX; 471 short sLeftPadY; 472 473 // Right pad coordinates 474 short sRightPadX; 475 short sRightPadY; 476 477 // Accelerometer values 478 short sAccelX; 479 short sAccelY; 480 short sAccelZ; 481 482 // Gyroscope values 483 short sGyroX; 484 short sGyroY; 485 short sGyroZ; 486 487 // Gyro quaternions 488 short sGyroQuatW; 489 short sGyroQuatX; 490 short sGyroQuatY; 491 short sGyroQuatZ; 492 493 // Uncalibrated trigger values 494 unsigned short sTriggerRawL; 495 unsigned short sTriggerRawR; 496 497 // Left stick values 498 short sLeftStickX; 499 short sLeftStickY; 500 501 // Right stick values 502 short sRightStickX; 503 short sRightStickY; 504 505 // Touchpad pressures 506 unsigned short sPressurePadLeft; 507 unsigned short sPressurePadRight; 508} SteamDeckStatePacket_t; 509 510 511typedef struct 512{ 513 ValveInReportHeader_t header; 514 515 union 516 { 517 ValveControllerStatePacket_t controllerState; 518 ValveControllerBLEStatePacket_t controllerBLEState; 519 ValveControllerDebugPacket_t debugState; 520 ValveControllerTrackpadImage_t padImage; 521 ValveControllerRawTrackpadImage_t rawPadImage; 522 SteamControllerWirelessEvent_t wirelessEvent; 523 SteamControllerStatusEvent_t statusEvent; 524 SteamDeckStatePacket_t deckState; 525 } payload; 526 527} ValveInReport_t; 528 529enum EBLEPacketReportNums 530{ 531 k_EBLEReportState = 4, 532 k_EBLEReportStatus = 5, 533}; 534// Enumeration of data chunks in BLE state packets 535enum EBLEOptionDataChunksBitmask 536{ 537 // First byte upper nibble 538 k_EBLEButtonChunk1 = 0x10, 539 k_EBLEButtonChunk2 = 0x20, 540 k_EBLEButtonChunk3 = 0x40, 541 k_EBLELeftJoystickChunk = 0x80, 542 543 // Second full byte 544 k_EBLELeftTrackpadChunk = 0x100, 545 k_EBLERightTrackpadChunk = 0x200, 546 k_EBLEIMUAccelChunk = 0x400, 547 k_EBLEIMUGyroChunk = 0x800, 548 k_EBLEIMUQuatChunk = 0x1000, 549}; 550 551// Triton and derivatives do not use the ValveInReport_t structure 552 553enum ETritonReportIDTypes 554{ 555 ID_TRITON_CONTROLLER_STATE = 0x42, 556 ID_TRITON_BATTERY_STATUS = 0x43, 557 ID_TRITON_CONTROLLER_STATE_BLE = 0x45, 558 ID_TRITON_WIRELESS_STATUS_X = 0x46, 559 ID_TRITON_WIRELESS_STATUS = 0x79, 560}; 561 562enum ETritonWirelessState 563{ 564 k_ETritonWirelessStateDisconnect = 1, 565 k_ETritonWirelessStateConnect = 2, 566}; 567 568typedef struct 569{ 570 uint32_t timestamp; 571 short sAccelX; 572 short sAccelY; 573 short sAccelZ; 574 575 short sGyroX; 576 short sGyroY; 577 short sGyroZ; 578 579 short sGyroQuatW; 580 short sGyroQuatX; 581 short sGyroQuatY; 582 short sGyroQuatZ; 583} TritonMTUIMU_t; 584 585typedef struct { 586 uint32_t timestamp; 587 short sAccelX; 588 short sAccelY; 589 short sAccelZ; 590 591 short sGyroX; 592 short sGyroY; 593 short sGyroZ; 594} TritonMTUIMUNoQuat_t; 595 596typedef struct 597{ 598 uint8_t seq_num; 599 uint32_t buttons; 600 short sTriggerLeft; 601 short sTriggerRight; 602 603 short sLeftStickX; 604 short sLeftStickY; 605 short sRightStickX; 606 short sRightStickY; 607 608 short sLeftPadX; 609 short sLeftPadY; 610 unsigned short ucPressureLeft; 611 612 short sRightPadX; 613 short sRightPadY; 614 unsigned short ucPressureRight; 615 TritonMTUIMU_t imu; 616} TritonMTUFull_t; 617 618typedef struct { 619 uint8_t seq_num; 620 uint32_t buttons; 621 short sTriggerLeft; 622 short sTriggerRight; 623 624 short sLeftStickX; 625 short sLeftStickY; 626 short sRightStickX; 627 short sRightStickY; 628 629 short sLeftPadX; 630 short sLeftPadY; 631 unsigned short ucPressureLeft; 632 633 short sRightPadX; 634 short sRightPadY; 635 unsigned short ucPressureRight; 636 TritonMTUIMUNoQuat_t imu; 637} TritonMTUNoQuat_t; 638 639enum EChargeState 640{ 641 k_EChargeStateReset, 642 k_EChargeStateDischarging, 643 k_EChargeStateCharging, 644 k_EChargeStateSrcValidate, 645 k_EChargeStateChargingDone, 646}; 647 648typedef struct 649{ 650 unsigned char ucChargeState; // EChargeState 651 unsigned char ucBatteryLevel; 652 unsigned short sBatteryVoltage; 653 unsigned short sSystemVoltage; 654 unsigned short sInputVoltage; 655 unsigned short sCurrent; 656 unsigned short sInputCurrent; 657 unsigned short sTemperature; 658} TritonBatteryStatus_t; 659 660typedef struct 661{ 662 unsigned char state; 663} TritonWirelessStatus_t; 664 665#pragma pack() 666 667#endif // _CONTROLLER_STRUCTS_ 668[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.