1 | /* |
2 | Simple DirectMedia Layer |
3 | Copyright (C) 2023 Max Maisel <max.maisel@posteo.de> |
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 | #include "SDL_internal.h" |
22 | |
23 | #ifdef SDL_JOYSTICK_HIDAPI |
24 | |
25 | #include "../SDL_sysjoystick.h" |
26 | #include "SDL_hidapijoystick_c.h" |
27 | |
28 | #ifdef SDL_JOYSTICK_HIDAPI_STEAMDECK |
29 | |
30 | /*****************************************************************************************************/ |
31 | |
32 | #include "steam/controller_constants.h" |
33 | #include "steam/controller_structs.h" |
34 | |
35 | enum |
36 | { |
37 | SDL_GAMEPAD_BUTTON_STEAM_DECK_QAM = 11, |
38 | SDL_GAMEPAD_BUTTON_STEAM_DECK_RIGHT_PADDLE1, |
39 | SDL_GAMEPAD_BUTTON_STEAM_DECK_LEFT_PADDLE1, |
40 | SDL_GAMEPAD_BUTTON_STEAM_DECK_RIGHT_PADDLE2, |
41 | SDL_GAMEPAD_BUTTON_STEAM_DECK_LEFT_PADDLE2, |
42 | SDL_GAMEPAD_NUM_STEAM_DECK_BUTTONS, |
43 | }; |
44 | |
45 | typedef enum |
46 | { |
47 | STEAMDECK_LBUTTON_R2 = 0x00000001, |
48 | STEAMDECK_LBUTTON_L2 = 0x00000002, |
49 | STEAMDECK_LBUTTON_R = 0x00000004, |
50 | STEAMDECK_LBUTTON_L = 0x00000008, |
51 | STEAMDECK_LBUTTON_Y = 0x00000010, |
52 | STEAMDECK_LBUTTON_B = 0x00000020, |
53 | STEAMDECK_LBUTTON_X = 0x00000040, |
54 | STEAMDECK_LBUTTON_A = 0x00000080, |
55 | STEAMDECK_LBUTTON_DPAD_UP = 0x00000100, |
56 | STEAMDECK_LBUTTON_DPAD_RIGHT = 0x00000200, |
57 | STEAMDECK_LBUTTON_DPAD_LEFT = 0x00000400, |
58 | STEAMDECK_LBUTTON_DPAD_DOWN = 0x00000800, |
59 | STEAMDECK_LBUTTON_VIEW = 0x00001000, |
60 | STEAMDECK_LBUTTON_STEAM = 0x00002000, |
61 | = 0x00004000, |
62 | STEAMDECK_LBUTTON_L5 = 0x00008000, |
63 | STEAMDECK_LBUTTON_R5 = 0x00010000, |
64 | STEAMDECK_LBUTTON_LEFT_PAD = 0x00020000, |
65 | STEAMDECK_LBUTTON_RIGHT_PAD = 0x00040000, |
66 | STEAMDECK_LBUTTON_L3 = 0x00400000, |
67 | STEAMDECK_LBUTTON_R3 = 0x04000000, |
68 | |
69 | STEAMDECK_HBUTTON_L4 = 0x00000200, |
70 | STEAMDECK_HBUTTON_R4 = 0x00000400, |
71 | STEAMDECK_HBUTTON_QAM = 0x00040000, |
72 | } SteamDeckButtons; |
73 | |
74 | typedef struct |
75 | { |
76 | Uint32 update_rate_us; |
77 | Uint32 sensor_timestamp_us; |
78 | Uint64 last_button_state; |
79 | Uint8 watchdog_counter; |
80 | } SDL_DriverSteamDeck_Context; |
81 | |
82 | static bool DisableDeckLizardMode(SDL_hid_device *dev) |
83 | { |
84 | int rc; |
85 | Uint8 buffer[HID_FEATURE_REPORT_BYTES + 1] = { 0 }; |
86 | FeatureReportMsg *msg = (FeatureReportMsg *)(buffer + 1); |
87 | |
88 | msg->header.type = ID_CLEAR_DIGITAL_MAPPINGS; |
89 | |
90 | rc = SDL_hid_send_feature_report(dev, buffer, sizeof(buffer)); |
91 | if (rc != sizeof(buffer)) |
92 | return false; |
93 | |
94 | msg->header.type = ID_SET_SETTINGS_VALUES; |
95 | msg->header.length = 5 * sizeof(ControllerSetting); |
96 | msg->payload.setSettingsValues.settings[0].settingNum = SETTING_SMOOTH_ABSOLUTE_MOUSE; |
97 | msg->payload.setSettingsValues.settings[0].settingValue = 0; |
98 | msg->payload.setSettingsValues.settings[1].settingNum = SETTING_LEFT_TRACKPAD_MODE; |
99 | msg->payload.setSettingsValues.settings[1].settingValue = TRACKPAD_NONE; |
100 | msg->payload.setSettingsValues.settings[2].settingNum = SETTING_RIGHT_TRACKPAD_MODE; // disable mouse |
101 | msg->payload.setSettingsValues.settings[2].settingValue = TRACKPAD_NONE; |
102 | msg->payload.setSettingsValues.settings[3].settingNum = SETTING_LEFT_TRACKPAD_CLICK_PRESSURE; // disable clicky pad |
103 | msg->payload.setSettingsValues.settings[3].settingValue = 0xFFFF; |
104 | msg->payload.setSettingsValues.settings[4].settingNum = SETTING_RIGHT_TRACKPAD_CLICK_PRESSURE; // disable clicky pad |
105 | msg->payload.setSettingsValues.settings[4].settingValue = 0xFFFF; |
106 | |
107 | rc = SDL_hid_send_feature_report(dev, buffer, sizeof(buffer)); |
108 | if (rc != sizeof(buffer)) |
109 | return false; |
110 | |
111 | // There may be a lingering report read back after changing settings. |
112 | // Discard it. |
113 | SDL_hid_get_feature_report(dev, buffer, sizeof(buffer)); |
114 | |
115 | return true; |
116 | } |
117 | |
118 | static bool FeedDeckLizardWatchdog(SDL_hid_device *dev) |
119 | { |
120 | int rc; |
121 | Uint8 buffer[HID_FEATURE_REPORT_BYTES + 1] = { 0 }; |
122 | FeatureReportMsg *msg = (FeatureReportMsg *)(buffer + 1); |
123 | |
124 | msg->header.type = ID_CLEAR_DIGITAL_MAPPINGS; |
125 | |
126 | rc = SDL_hid_send_feature_report(dev, buffer, sizeof(buffer)); |
127 | if (rc != sizeof(buffer)) |
128 | return false; |
129 | |
130 | msg->header.type = ID_SET_SETTINGS_VALUES; |
131 | msg->header.length = 1 * sizeof(ControllerSetting); |
132 | msg->payload.setSettingsValues.settings[0].settingNum = SETTING_RIGHT_TRACKPAD_MODE; |
133 | msg->payload.setSettingsValues.settings[0].settingValue = TRACKPAD_NONE; |
134 | |
135 | rc = SDL_hid_send_feature_report(dev, buffer, sizeof(buffer)); |
136 | if (rc != sizeof(buffer)) |
137 | return false; |
138 | |
139 | // There may be a lingering report read back after changing settings. |
140 | // Discard it. |
141 | SDL_hid_get_feature_report(dev, buffer, sizeof(buffer)); |
142 | |
143 | return true; |
144 | } |
145 | |
146 | static void HIDAPI_DriverSteamDeck_HandleState(SDL_HIDAPI_Device *device, |
147 | SDL_Joystick *joystick, |
148 | ValveInReport_t *pInReport) |
149 | { |
150 | float values[3]; |
151 | SDL_DriverSteamDeck_Context *ctx = (SDL_DriverSteamDeck_Context *)device->context; |
152 | Uint64 timestamp = SDL_GetTicksNS(); |
153 | |
154 | if (pInReport->payload.deckState.ulButtons != ctx->last_button_state) { |
155 | Uint8 hat = 0; |
156 | |
157 | SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, |
158 | ((pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_A) != 0)); |
159 | SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, |
160 | ((pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_B) != 0)); |
161 | SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, |
162 | ((pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_X) != 0)); |
163 | SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, |
164 | ((pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_Y) != 0)); |
165 | |
166 | SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, |
167 | ((pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_L) != 0)); |
168 | SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, |
169 | ((pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_R) != 0)); |
170 | |
171 | SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, |
172 | ((pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_VIEW) != 0)); |
173 | SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, |
174 | ((pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_MENU) != 0)); |
175 | SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, |
176 | ((pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_STEAM) != 0)); |
177 | SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_DECK_QAM, |
178 | ((pInReport->payload.deckState.ulButtonsH & STEAMDECK_HBUTTON_QAM) != 0)); |
179 | |
180 | SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, |
181 | ((pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_L3) != 0)); |
182 | SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, |
183 | ((pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_R3) != 0)); |
184 | |
185 | SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_DECK_RIGHT_PADDLE1, |
186 | ((pInReport->payload.deckState.ulButtonsH & STEAMDECK_HBUTTON_R4) != 0)); |
187 | SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_DECK_LEFT_PADDLE1, |
188 | ((pInReport->payload.deckState.ulButtonsH & STEAMDECK_HBUTTON_L4) != 0)); |
189 | SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_DECK_RIGHT_PADDLE2, |
190 | ((pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_R5) != 0)); |
191 | SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_DECK_LEFT_PADDLE2, |
192 | ((pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_L5) != 0)); |
193 | |
194 | if (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_UP) { |
195 | hat |= SDL_HAT_UP; |
196 | } |
197 | if (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_DOWN) { |
198 | hat |= SDL_HAT_DOWN; |
199 | } |
200 | if (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_LEFT) { |
201 | hat |= SDL_HAT_LEFT; |
202 | } |
203 | if (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_RIGHT) { |
204 | hat |= SDL_HAT_RIGHT; |
205 | } |
206 | SDL_SendJoystickHat(timestamp, joystick, 0, hat); |
207 | |
208 | ctx->last_button_state = pInReport->payload.deckState.ulButtons; |
209 | } |
210 | |
211 | SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, |
212 | (int)pInReport->payload.deckState.sTriggerRawL * 2 - 32768); |
213 | SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, |
214 | (int)pInReport->payload.deckState.sTriggerRawR * 2 - 32768); |
215 | |
216 | SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, |
217 | pInReport->payload.deckState.sLeftStickX); |
218 | SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, |
219 | -pInReport->payload.deckState.sLeftStickY); |
220 | SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, |
221 | pInReport->payload.deckState.sRightStickX); |
222 | SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, |
223 | -pInReport->payload.deckState.sRightStickY); |
224 | |
225 | ctx->sensor_timestamp_us += ctx->update_rate_us; |
226 | |
227 | values[0] = (pInReport->payload.deckState.sGyroX / 32768.0f) * (2000.0f * (SDL_PI_F / 180.0f)); |
228 | values[1] = (pInReport->payload.deckState.sGyroZ / 32768.0f) * (2000.0f * (SDL_PI_F / 180.0f)); |
229 | values[2] = (-pInReport->payload.deckState.sGyroY / 32768.0f) * (2000.0f * (SDL_PI_F / 180.0f)); |
230 | SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, ctx->sensor_timestamp_us, values, 3); |
231 | |
232 | values[0] = (pInReport->payload.deckState.sAccelX / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY; |
233 | values[1] = (pInReport->payload.deckState.sAccelZ / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY; |
234 | values[2] = (-pInReport->payload.deckState.sAccelY / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY; |
235 | SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, ctx->sensor_timestamp_us, values, 3); |
236 | } |
237 | |
238 | /*****************************************************************************************************/ |
239 | |
240 | static void HIDAPI_DriverSteamDeck_RegisterHints(SDL_HintCallback callback, void *userdata) |
241 | { |
242 | SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK, callback, userdata); |
243 | } |
244 | |
245 | static void HIDAPI_DriverSteamDeck_UnregisterHints(SDL_HintCallback callback, void *userdata) |
246 | { |
247 | SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK, callback, userdata); |
248 | } |
249 | |
250 | static bool HIDAPI_DriverSteamDeck_IsEnabled(void) |
251 | { |
252 | return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK, |
253 | SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, SDL_HIDAPI_DEFAULT)); |
254 | } |
255 | |
256 | static bool HIDAPI_DriverSteamDeck_IsSupportedDevice( |
257 | SDL_HIDAPI_Device *device, |
258 | const char *name, |
259 | SDL_GamepadType type, |
260 | Uint16 vendor_id, |
261 | Uint16 product_id, |
262 | Uint16 version, |
263 | int interface_number, |
264 | int interface_class, |
265 | int interface_subclass, |
266 | int interface_protocol) |
267 | { |
268 | return SDL_IsJoystickSteamDeck(vendor_id, product_id); |
269 | } |
270 | |
271 | static bool HIDAPI_DriverSteamDeck_InitDevice(SDL_HIDAPI_Device *device) |
272 | { |
273 | int size; |
274 | Uint8 data[64]; |
275 | SDL_DriverSteamDeck_Context *ctx; |
276 | |
277 | ctx = (SDL_DriverSteamDeck_Context *)SDL_calloc(1, sizeof(*ctx)); |
278 | if (ctx == NULL) { |
279 | return false; |
280 | } |
281 | |
282 | // Always 1kHz according to USB descriptor, but actually about 4 ms. |
283 | ctx->update_rate_us = 4000; |
284 | |
285 | device->context = ctx; |
286 | |
287 | // Read a report to see if this is the correct endpoint. |
288 | // Mouse, Keyboard and Controller have the same VID/PID but |
289 | // only the controller hidraw device receives hid reports. |
290 | size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 16); |
291 | if (size == 0) |
292 | return false; |
293 | |
294 | if (!DisableDeckLizardMode(device->dev)) |
295 | return false; |
296 | |
297 | HIDAPI_SetDeviceName(device, "Steam Deck" ); |
298 | |
299 | return HIDAPI_JoystickConnected(device, NULL); |
300 | } |
301 | |
302 | static int HIDAPI_DriverSteamDeck_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) |
303 | { |
304 | return -1; |
305 | } |
306 | |
307 | static void HIDAPI_DriverSteamDeck_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) |
308 | { |
309 | } |
310 | |
311 | static bool HIDAPI_DriverSteamDeck_UpdateDevice(SDL_HIDAPI_Device *device) |
312 | { |
313 | SDL_DriverSteamDeck_Context *ctx = (SDL_DriverSteamDeck_Context *)device->context; |
314 | SDL_Joystick *joystick = NULL; |
315 | int r; |
316 | uint8_t data[64]; |
317 | ValveInReport_t *pInReport = (ValveInReport_t *)data; |
318 | |
319 | if (device->num_joysticks > 0) { |
320 | joystick = SDL_GetJoystickFromID(device->joysticks[0]); |
321 | if (joystick == NULL) { |
322 | return false; |
323 | } |
324 | } else { |
325 | return false; |
326 | } |
327 | |
328 | if (ctx->watchdog_counter++ > 200) { |
329 | ctx->watchdog_counter = 0; |
330 | if (!FeedDeckLizardWatchdog(device->dev)) |
331 | return false; |
332 | } |
333 | |
334 | SDL_memset(data, 0, sizeof(data)); |
335 | |
336 | do { |
337 | r = SDL_hid_read(device->dev, data, sizeof(data)); |
338 | |
339 | if (r < 0) { |
340 | // Failed to read from controller |
341 | HIDAPI_JoystickDisconnected(device, device->joysticks[0]); |
342 | return false; |
343 | } else if (r == 64 && |
344 | pInReport->header.unReportVersion == k_ValveInReportMsgVersion && |
345 | pInReport->header.ucType == ID_CONTROLLER_DECK_STATE && |
346 | pInReport->header.ucLength == 64) { |
347 | HIDAPI_DriverSteamDeck_HandleState(device, joystick, pInReport); |
348 | } |
349 | } while (r > 0); |
350 | |
351 | return true; |
352 | } |
353 | |
354 | static bool HIDAPI_DriverSteamDeck_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) |
355 | { |
356 | SDL_DriverSteamDeck_Context *ctx = (SDL_DriverSteamDeck_Context *)device->context; |
357 | float update_rate_in_hz = 1.0f / (float)(ctx->update_rate_us) * 1.0e6f; |
358 | |
359 | SDL_AssertJoysticksLocked(); |
360 | |
361 | // Initialize the joystick capabilities |
362 | joystick->nbuttons = SDL_GAMEPAD_NUM_STEAM_DECK_BUTTONS; |
363 | joystick->naxes = SDL_GAMEPAD_AXIS_COUNT; |
364 | joystick->nhats = 1; |
365 | |
366 | SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, update_rate_in_hz); |
367 | SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, update_rate_in_hz); |
368 | |
369 | return true; |
370 | } |
371 | |
372 | static bool HIDAPI_DriverSteamDeck_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) |
373 | { |
374 | int rc; |
375 | Uint8 buffer[HID_FEATURE_REPORT_BYTES + 1] = { 0 }; |
376 | FeatureReportMsg *msg = (FeatureReportMsg *)(buffer + 1); |
377 | |
378 | msg->header.type = ID_TRIGGER_RUMBLE_CMD; |
379 | msg->payload.simpleRumble.unRumbleType = 0; |
380 | msg->payload.simpleRumble.unIntensity = HAPTIC_INTENSITY_SYSTEM; |
381 | msg->payload.simpleRumble.unLeftMotorSpeed = low_frequency_rumble; |
382 | msg->payload.simpleRumble.unRightMotorSpeed = high_frequency_rumble; |
383 | msg->payload.simpleRumble.nLeftGain = 2; |
384 | msg->payload.simpleRumble.nRightGain = 0; |
385 | |
386 | rc = SDL_hid_send_feature_report(device->dev, buffer, sizeof(buffer)); |
387 | if (rc != sizeof(buffer)) |
388 | return false; |
389 | return true; |
390 | } |
391 | |
392 | static bool HIDAPI_DriverSteamDeck_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble) |
393 | { |
394 | return SDL_Unsupported(); |
395 | } |
396 | |
397 | static Uint32 HIDAPI_DriverSteamDeck_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) |
398 | { |
399 | return SDL_JOYSTICK_CAP_RUMBLE; |
400 | } |
401 | |
402 | static bool HIDAPI_DriverSteamDeck_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) |
403 | { |
404 | return SDL_Unsupported(); |
405 | } |
406 | |
407 | static bool HIDAPI_DriverSteamDeck_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *data, int size) |
408 | { |
409 | return SDL_Unsupported(); |
410 | } |
411 | |
412 | static bool HIDAPI_DriverSteamDeck_SetSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, bool enabled) |
413 | { |
414 | // On steam deck, sensors are enabled by default. Nothing to do here. |
415 | return true; |
416 | } |
417 | |
418 | static void HIDAPI_DriverSteamDeck_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) |
419 | { |
420 | // Lizard mode id automatically re-enabled by watchdog. Nothing to do here. |
421 | } |
422 | |
423 | static void HIDAPI_DriverSteamDeck_FreeDevice(SDL_HIDAPI_Device *device) |
424 | { |
425 | } |
426 | |
427 | SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteamDeck = { |
428 | SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK, |
429 | true, |
430 | HIDAPI_DriverSteamDeck_RegisterHints, |
431 | HIDAPI_DriverSteamDeck_UnregisterHints, |
432 | HIDAPI_DriverSteamDeck_IsEnabled, |
433 | HIDAPI_DriverSteamDeck_IsSupportedDevice, |
434 | HIDAPI_DriverSteamDeck_InitDevice, |
435 | HIDAPI_DriverSteamDeck_GetDevicePlayerIndex, |
436 | HIDAPI_DriverSteamDeck_SetDevicePlayerIndex, |
437 | HIDAPI_DriverSteamDeck_UpdateDevice, |
438 | HIDAPI_DriverSteamDeck_OpenJoystick, |
439 | HIDAPI_DriverSteamDeck_RumbleJoystick, |
440 | HIDAPI_DriverSteamDeck_RumbleJoystickTriggers, |
441 | HIDAPI_DriverSteamDeck_GetJoystickCapabilities, |
442 | HIDAPI_DriverSteamDeck_SetJoystickLED, |
443 | HIDAPI_DriverSteamDeck_SendJoystickEffect, |
444 | HIDAPI_DriverSteamDeck_SetSensorsEnabled, |
445 | HIDAPI_DriverSteamDeck_CloseJoystick, |
446 | HIDAPI_DriverSteamDeck_FreeDevice, |
447 | }; |
448 | |
449 | #endif // SDL_JOYSTICK_HIDAPI_STEAMDECK |
450 | |
451 | #endif // SDL_JOYSTICK_HIDAPI |
452 | |