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 29 typedef struct 30 { 31 unsigned char type; 32 unsigned char length; 33 } FeatureReportHeader; 34 35 // Generic controller attribute structure 36 typedef struct 37 { 38 unsigned char attributeTag; 39 uint32_t attributeValue; 40 } ControllerAttribute; 41 42 // Generic controller settings structure 43 typedef struct 44 { 45 ControllerAttribute attributes[ ( HID_FEATURE_REPORT_BYTES - sizeof( FeatureReportHeader ) ) / sizeof( ControllerAttribute ) ]; 46 } MsgGetAttributes; 47 48 49 // This is the only message struct that application code should use to interact with feature request messages. Any new 50 // messages should be added to the union. The structures defined here should correspond to the ones defined in 51 // ValveDeviceCore.cpp. 52 // 53 typedef struct 54 { 55 FeatureReportHeader header; 56 union 57 { 58 MsgGetAttributes getAttributes; 59 } payload; 60 61 } FeatureReportMsg; 62 63 // Roll this version forward anytime that you are breaking compatibility of existing 64 // message types within ValveInReport_t or the header itself. Hopefully this should 65 // be super rare and instead you shoudl just add new message payloads to the union, 66 // or just add fields to the end of existing payload structs which is expected to be 67 // safe in all code consuming these as they should just consume/copy upto the prior size 68 // they were aware of when processing. 69 #define k_ValveInReportMsgVersion 0x01 70 71 typedef enum 72 { 73 ID_CONTROLLER_STATE = 1, 74 ID_CONTROLLER_DEBUG = 2, 75 ID_CONTROLLER_WIRELESS = 3, 76 ID_CONTROLLER_STATUS = 4, 77 ID_CONTROLLER_DEBUG2 = 5, 78 ID_CONTROLLER_SECONDARY_STATE = 6, 79 ID_CONTROLLER_BLE_STATE = 7, 80 ID_CONTROLLER_MSG_COUNT 81 } ValveInReportMessageIDs; 82 83 typedef struct 84 { 85 unsigned short unReportVersion; 86 87 unsigned char ucType; 88 unsigned char ucLength; 89 90 } ValveInReportHeader_t; 91 92 // State payload 93 typedef struct 94 { 95 // If packet num matches that on your prior call, then the controller state hasn't been changed since 96 // your last call and there is no need to process it 97 uint32 unPacketNum; 98 99 // Button bitmask and trigger data. 100 union 101 { 102 uint64 ulButtons; 103 struct 104 { 105 unsigned char _pad0[3]; 106 unsigned char nLeft; 107 unsigned char nRight; 108 unsigned char _pad1[3]; 109 } Triggers; 110 } ButtonTriggerData; 111 112 // Left pad coordinates 113 short sLeftPadX; 114 short sLeftPadY; 115 116 // Right pad coordinates 117 short sRightPadX; 118 short sRightPadY; 119 120 // This is redundant, packed above, but still sent over wired 121 unsigned short sTriggerL; 122 unsigned short sTriggerR; 123 124 // FIXME figure out a way to grab this stuff over wireless 125 short sAccelX; 126 short sAccelY; 127 short sAccelZ; 128 129 short sGyroX; 130 short sGyroY; 131 short sGyroZ; 132 133 short sGyroQuatW; 134 short sGyroQuatX; 135 short sGyroQuatY; 136 short sGyroQuatZ; 137 138 } ValveControllerStatePacket_t; 139 140 // BLE State payload this has to be re-formatted from the normal state because BLE controller shows up as 141 //a HID device and we don't want to send all the optional parts of the message. Keep in sync with struct above. 142 typedef struct 143 { 144 // If packet num matches that on your prior call, then the controller state hasn't been changed since 145 // your last call and there is no need to process it 146 uint32 unPacketNum; 147 148 // Button bitmask and trigger data. 149 union 150 { 151 uint64 ulButtons; 152 struct 153 { 154 unsigned char _pad0[3]; 155 unsigned char nLeft; 156 unsigned char nRight; 157 unsigned char _pad1[3]; 158 } Triggers; 159 } ButtonTriggerData; 160 161 // Left pad coordinates 162 short sLeftPadX; 163 short sLeftPadY; 164 165 // Right pad coordinates 166 short sRightPadX; 167 short sRightPadY; 168 169 //This mimcs how the dongle reconstitutes HID packets, there will be 0-4 shorts depending on gyro mode 170 unsigned char ucGyroDataType; //TODO could maybe find some unused bits in the button field for this info (is only 2bits) 171 short sGyro[4]; 172 173 } ValveControllerBLEStatePacket_t; 174 175 // Define a payload for reporting debug information 176 typedef struct 177 { 178 // Left pad coordinates 179 short sLeftPadX; 180 short sLeftPadY; 181 182 // Right pad coordinates 183 short sRightPadX; 184 short sRightPadY; 185 186 // Left mouse deltas 187 short sLeftPadMouseDX; 188 short sLeftPadMouseDY; 189 190 // Right mouse deltas 191 short sRightPadMouseDX; 192 short sRightPadMouseDY; 193 194 // Left mouse filtered deltas 195 short sLeftPadMouseFilteredDX; 196 short sLeftPadMouseFilteredDY; 197 198 // Right mouse filtered deltas 199 short sRightPadMouseFilteredDX; 200 short sRightPadMouseFilteredDY; 201 202 // Pad Z values 203 unsigned char ucLeftZ; 204 unsigned char ucRightZ; 205 206 // FingerPresent 207 unsigned char ucLeftFingerPresent; 208 unsigned char ucRightFingerPresent; 209 210 // Timestamps 211 unsigned char ucLeftTimestamp; 212 unsigned char ucRightTimestamp; 213 214 // Double tap state 215 unsigned char ucLeftTapState; 216 unsigned char ucRightTapState; 217 218 unsigned int unDigitalIOStates0; 219 unsigned int unDigitalIOStates1; 220 221 } ValveControllerDebugPacket_t; 222 223 typedef struct 224 { 225 unsigned char ucPadNum; 226 unsigned char ucPad[3]; // need Data to be word aligned 227 short Data[20]; 228 unsigned short unNoise; 229 } ValveControllerTrackpadImage_t; 230 231 typedef struct 232 { 233 unsigned char ucPadNum; 234 unsigned char ucOffset; 235 unsigned char ucPad[2]; // need Data to be word aligned 236 short rgData[28]; 237 } ValveControllerRawTrackpadImage_t; 238 239 // Payload for wireless metadata 240 typedef struct 241 { 242 unsigned char ucEventType; 243 } SteamControllerWirelessEvent_t; 244 245 typedef struct 246 { 247 // Current packet number. 248 unsigned int unPacketNum; 249 250 // Event codes and state information. 251 unsigned short sEventCode; 252 unsigned short unStateFlags; 253 254 // Current battery voltage (mV). 255 unsigned short sBatteryVoltage; 256 257 // Current battery level (0-100). 258 unsigned char ucBatteryLevel; 259 } SteamControllerStatusEvent_t; 260 261 typedef struct 262 { 263 ValveInReportHeader_t header; 264 265 union 266 { 267 ValveControllerStatePacket_t controllerState; 268 ValveControllerBLEStatePacket_t controllerBLEState; 269 ValveControllerDebugPacket_t debugState; 270 ValveControllerTrackpadImage_t padImage; 271 ValveControllerRawTrackpadImage_t rawPadImage; 272 SteamControllerWirelessEvent_t wirelessEvent; 273 SteamControllerStatusEvent_t statusEvent; 274 } payload; 275 276 } ValveInReport_t; 277 278 279 // Enumeration for BLE packet protocol 280 enum EBLEPacketReportNums 281 { 282 // Skipping past 2-3 because they are escape characters in Uart protocol 283 k_EBLEReportState = 4, 284 k_EBLEReportStatus = 5, 285 }; 286 287 288 // Enumeration of data chunks in BLE state packets 289 enum EBLEOptionDataChunksBitmask 290 { 291 // First byte uppper nibble 292 k_EBLEButtonChunk1 = 0x10, 293 k_EBLEButtonChunk2 = 0x20, 294 k_EBLEButtonChunk3 = 0x40, 295 k_EBLELeftJoystickChunk = 0x80, 296 297 // Second full byte 298 k_EBLELeftTrackpadChunk = 0x100, 299 k_EBLERightTrackpadChunk = 0x200, 300 k_EBLEIMUAccelChunk = 0x400, 301 k_EBLEIMUGyroChunk = 0x800, 302 k_EBLEIMUQuatChunk = 0x1000, 303 }; 304 305 #pragma pack() 306 307 #endif // _CONTROLLER_STRUCTS 308