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