Path: blob/master/thirdparty/sdl/joystick/hidapi/steam/controller_structs.h
9913 views
/*1Simple DirectMedia Layer2Copyright (C) 2020 Valve Corporation34This software is provided 'as-is', without any express or implied5warranty. In no event will the authors be held liable for any damages6arising from the use of this software.78Permission is granted to anyone to use this software for any purpose,9including commercial applications, and to alter it and redistribute it10freely, subject to the following restrictions:11121. The origin of this software must not be misrepresented; you must not13claim that you wrote the original software. If you use this software14in a product, an acknowledgment in the product documentation would be15appreciated but is not required.162. Altered source versions must be plainly marked as such, and must not be17misrepresented as being the original software.183. This notice may not be removed or altered from any source distribution.19*/20#ifndef _CONTROLLER_STRUCTS_21#define _CONTROLLER_STRUCTS_2223#pragma pack(1)2425#define HID_FEATURE_REPORT_BYTES 642627// Header for all host <==> target messages28typedef struct29{30unsigned char type;31unsigned char length;32} FeatureReportHeader;3334// Generic controller settings structure35typedef struct36{37unsigned char settingNum;38unsigned short settingValue;39} ControllerSetting;4041// Generic controller attribute structure42typedef struct43{44unsigned char attributeTag;45uint32_t attributeValue;46} ControllerAttribute;4748// Generic controller settings structure49typedef struct50{51ControllerSetting settings[ ( HID_FEATURE_REPORT_BYTES - sizeof( FeatureReportHeader ) ) / sizeof( ControllerSetting ) ];52} MsgSetSettingsValues, MsgGetSettingsValues, MsgGetSettingsDefaults, MsgGetSettingsMaxs;5354// Generic controller settings structure55typedef struct56{57ControllerAttribute attributes[ ( HID_FEATURE_REPORT_BYTES - sizeof( FeatureReportHeader ) ) / sizeof( ControllerAttribute ) ];58} MsgGetAttributes;5960typedef struct61{62unsigned char attributeTag;63char attributeValue[20];64} MsgGetStringAttribute;6566typedef struct67{68unsigned char mode;69} MsgSetControllerMode;7071// Trigger a haptic pulse72typedef struct {73unsigned char which_pad;74unsigned short pulse_duration;75unsigned short pulse_interval;76unsigned short pulse_count;77short dBgain;78unsigned char priority;79} MsgFireHapticPulse;8081typedef struct {82uint8_t mode;83} MsgHapticSetMode;8485typedef enum {86HAPTIC_TYPE_OFF,87HAPTIC_TYPE_TICK,88HAPTIC_TYPE_CLICK,89HAPTIC_TYPE_TONE,90HAPTIC_TYPE_RUMBLE,91HAPTIC_TYPE_NOISE,92HAPTIC_TYPE_SCRIPT,93HAPTIC_TYPE_LOG_SWEEP,94} haptic_type_t;9596typedef enum {97HAPTIC_INTENSITY_SYSTEM,98HAPTIC_INTENSITY_SHORT,99HAPTIC_INTENSITY_MEDIUM,100HAPTIC_INTENSITY_LONG,101HAPTIC_INTENSITY_INSANE,102} haptic_intensity_t;103104typedef struct {105uint8_t side; // 0x01 = L, 0x02 = R, 0x03 = Both106uint8_t cmd; // 0 = Off, 1 = tick, 2 = click, 3 = tone, 4 = rumble, 5 =107// rumble_noise, 6 = script, 7 = sweep,108uint8_t ui_intensity; // 0-4 (0 = default)109int8_t dBgain; // dB Can be positive (reasonable clipping / limiting will apply)110uint16_t freq; // Frequency of tone (if applicable)111int16_t dur_ms; // Duration of tone / rumble (if applicable) (neg = infinite)112113uint16_t noise_intensity;114uint16_t lfo_freq; // Drives both tone and rumble geneators115uint8_t lfo_depth; // percentage, typically 100116uint8_t rand_tone_gain; // Randomize each LFO cycle's gain117uint8_t script_id; // Used w/ dBgain for scripted haptics118119uint16_t lss_start_freq; // Used w/ Log Sine Sweep120uint16_t lss_end_freq; // Ditto121} MsgTriggerHaptic;122123typedef struct {124uint8_t unRumbleType;125uint16_t unIntensity;126uint16_t unLeftMotorSpeed;127uint16_t unRightMotorSpeed;128int8_t nLeftGain;129int8_t nRightGain;130} MsgSimpleRumbleCmd;131132// This is the only message struct that application code should use to interact with feature request messages. Any new133// messages should be added to the union. The structures defined here should correspond to the ones defined in134// ValveDeviceCore.cpp.135//136typedef struct137{138FeatureReportHeader header;139union140{141MsgSetSettingsValues setSettingsValues;142MsgGetSettingsValues getSettingsValues;143MsgGetSettingsMaxs getSettingsMaxs;144MsgGetSettingsDefaults getSettingsDefaults;145MsgGetAttributes getAttributes;146MsgSetControllerMode controllerMode;147MsgFireHapticPulse fireHapticPulse;148MsgGetStringAttribute getStringAttribute;149MsgHapticSetMode hapticMode;150MsgTriggerHaptic triggerHaptic;151MsgSimpleRumbleCmd simpleRumble;152} payload;153154} FeatureReportMsg;155156// Roll this version forward anytime that you are breaking compatibility of existing157// message types within ValveInReport_t or the header itself. Hopefully this should158// be super rare and instead you should just add new message payloads to the union,159// or just add fields to the end of existing payload structs which is expected to be160// safe in all code consuming these as they should just consume/copy up to the prior size161// they were aware of when processing.162#define k_ValveInReportMsgVersion 0x01163164typedef enum165{166ID_CONTROLLER_STATE = 1,167ID_CONTROLLER_DEBUG = 2,168ID_CONTROLLER_WIRELESS = 3,169ID_CONTROLLER_STATUS = 4,170ID_CONTROLLER_DEBUG2 = 5,171ID_CONTROLLER_SECONDARY_STATE = 6,172ID_CONTROLLER_BLE_STATE = 7,173ID_CONTROLLER_DECK_STATE = 9,174ID_CONTROLLER_MSG_COUNT175} ValveInReportMessageIDs;176177typedef struct178{179unsigned short unReportVersion;180181unsigned char ucType;182unsigned char ucLength;183184} ValveInReportHeader_t;185186// State payload187typedef struct188{189// If packet num matches that on your prior call, then the controller state hasn't been changed since190// your last call and there is no need to process it191Uint32 unPacketNum;192193// Button bitmask and trigger data.194union195{196Uint64 ulButtons;197struct198{199unsigned char _pad0[3];200unsigned char nLeft;201unsigned char nRight;202unsigned char _pad1[3];203} Triggers;204} ButtonTriggerData;205206// Left pad coordinates207short sLeftPadX;208short sLeftPadY;209210// Right pad coordinates211short sRightPadX;212short sRightPadY;213214// This is redundant, packed above, but still sent over wired215unsigned short sTriggerL;216unsigned short sTriggerR;217218// FIXME figure out a way to grab this stuff over wireless219short sAccelX;220short sAccelY;221short sAccelZ;222223short sGyroX;224short sGyroY;225short sGyroZ;226227short sGyroQuatW;228short sGyroQuatX;229short sGyroQuatY;230short sGyroQuatZ;231232} ValveControllerStatePacket_t;233234// BLE State payload this has to be re-formatted from the normal state because BLE controller shows up as235//a HID device and we don't want to send all the optional parts of the message. Keep in sync with struct above.236typedef struct237{238// If packet num matches that on your prior call, then the controller state hasn't been changed since239// your last call and there is no need to process it240Uint32 unPacketNum;241242// Button bitmask and trigger data.243union244{245Uint64 ulButtons;246struct247{248unsigned char _pad0[3];249unsigned char nLeft;250unsigned char nRight;251unsigned char _pad1[3];252} Triggers;253} ButtonTriggerData;254255// Left pad coordinates256short sLeftPadX;257short sLeftPadY;258259// Right pad coordinates260short sRightPadX;261short sRightPadY;262263//This mimcs how the dongle reconstitutes HID packets, there will be 0-4 shorts depending on gyro mode264unsigned char ucGyroDataType; //TODO could maybe find some unused bits in the button field for this info (is only 2bits)265short sGyro[4];266267} ValveControllerBLEStatePacket_t;268269// Define a payload for reporting debug information270typedef struct271{272// Left pad coordinates273short sLeftPadX;274short sLeftPadY;275276// Right pad coordinates277short sRightPadX;278short sRightPadY;279280// Left mouse deltas281short sLeftPadMouseDX;282short sLeftPadMouseDY;283284// Right mouse deltas285short sRightPadMouseDX;286short sRightPadMouseDY;287288// Left mouse filtered deltas289short sLeftPadMouseFilteredDX;290short sLeftPadMouseFilteredDY;291292// Right mouse filtered deltas293short sRightPadMouseFilteredDX;294short sRightPadMouseFilteredDY;295296// Pad Z values297unsigned char ucLeftZ;298unsigned char ucRightZ;299300// FingerPresent301unsigned char ucLeftFingerPresent;302unsigned char ucRightFingerPresent;303304// Timestamps305unsigned char ucLeftTimestamp;306unsigned char ucRightTimestamp;307308// Double tap state309unsigned char ucLeftTapState;310unsigned char ucRightTapState;311312unsigned int unDigitalIOStates0;313unsigned int unDigitalIOStates1;314315} ValveControllerDebugPacket_t;316317typedef struct318{319unsigned char ucPadNum;320unsigned char ucPad[3]; // need Data to be word aligned321short Data[20];322unsigned short unNoise;323} ValveControllerTrackpadImage_t;324325typedef struct326{327unsigned char ucPadNum;328unsigned char ucOffset;329unsigned char ucPad[2]; // need Data to be word aligned330short rgData[28];331} ValveControllerRawTrackpadImage_t;332333// Payload for wireless metadata334typedef struct335{336unsigned char ucEventType;337} SteamControllerWirelessEvent_t;338339typedef struct340{341// Current packet number.342unsigned int unPacketNum;343344// Event codes and state information.345unsigned short sEventCode;346unsigned short unStateFlags;347348// Current battery voltage (mV).349unsigned short sBatteryVoltage;350351// Current battery level (0-100).352unsigned char ucBatteryLevel;353} SteamControllerStatusEvent_t;354355// Deck State payload356typedef struct357{358// If packet num matches that on your prior call, then the controller359// state hasn't been changed since your last call and there is no need to360// process it361Uint32 unPacketNum;362363// Button bitmask and trigger data.364union365{366Uint64 ulButtons;367struct368{369Uint32 ulButtonsL;370Uint32 ulButtonsH;371};372};373374// Left pad coordinates375short sLeftPadX;376short sLeftPadY;377378// Right pad coordinates379short sRightPadX;380short sRightPadY;381382// Accelerometer values383short sAccelX;384short sAccelY;385short sAccelZ;386387// Gyroscope values388short sGyroX;389short sGyroY;390short sGyroZ;391392// Gyro quaternions393short sGyroQuatW;394short sGyroQuatX;395short sGyroQuatY;396short sGyroQuatZ;397398// Uncalibrated trigger values399unsigned short sTriggerRawL;400unsigned short sTriggerRawR;401402// Left stick values403short sLeftStickX;404short sLeftStickY;405406// Right stick values407short sRightStickX;408short sRightStickY;409410// Touchpad pressures411unsigned short sPressurePadLeft;412unsigned short sPressurePadRight;413} SteamDeckStatePacket_t;414415typedef struct416{417ValveInReportHeader_t header;418419union420{421ValveControllerStatePacket_t controllerState;422ValveControllerBLEStatePacket_t controllerBLEState;423ValveControllerDebugPacket_t debugState;424ValveControllerTrackpadImage_t padImage;425ValveControllerRawTrackpadImage_t rawPadImage;426SteamControllerWirelessEvent_t wirelessEvent;427SteamControllerStatusEvent_t statusEvent;428SteamDeckStatePacket_t deckState;429} payload;430431} ValveInReport_t;432433434// Enumeration for BLE packet protocol435enum EBLEPacketReportNums436{437// Skipping past 2-3 because they are escape characters in Uart protocol438k_EBLEReportState = 4,439k_EBLEReportStatus = 5,440};441442443// Enumeration of data chunks in BLE state packets444enum EBLEOptionDataChunksBitmask445{446// First byte upper nibble447k_EBLEButtonChunk1 = 0x10,448k_EBLEButtonChunk2 = 0x20,449k_EBLEButtonChunk3 = 0x40,450k_EBLELeftJoystickChunk = 0x80,451452// Second full byte453k_EBLELeftTrackpadChunk = 0x100,454k_EBLERightTrackpadChunk = 0x200,455k_EBLEIMUAccelChunk = 0x400,456k_EBLEIMUGyroChunk = 0x800,457k_EBLEIMUQuatChunk = 0x1000,458};459460#pragma pack()461462#endif // _CONTROLLER_STRUCTS463464465