Atlas - SDL_hidapi_ps3.c

Home / ext / SDL / src / joystick / hidapi Lines: 1 | Size: 54913 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2026 Sam Lantinga <[email protected]> 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_hints_c.h" 26#include "../SDL_sysjoystick.h" 27#include "SDL_hidapijoystick_c.h" 28#include "SDL_hidapi_rumble.h" 29 30#ifdef SDL_JOYSTICK_HIDAPI_PS3 31 32// Define this if you want to log all packets from the controller 33// #define DEBUG_PS3_PROTOCOL 34 35typedef enum 36{ 37 k_EPS3ReportIdState = 1, 38 k_EPS3ReportIdEffects = 1, 39} EPS3ReportId; 40 41typedef enum 42{ 43 k_EPS3SonySixaxisReportIdState = 0, 44 k_EPS3SonySixaxisReportIdEffects = 0, 45} EPS3SonySixaxisReportId; 46 47// Commands for Sony's sixaxis.sys Windows driver 48// All commands must be sent using 49-byte buffer containing output report 49// Byte 0 indicates reportId and must always be 0 50// Byte 1 indicates a command, supported values are specified below: 51typedef enum 52{ 53 // This command allows to set user LEDs. 54 // Bytes 5,6.7.8 contain mode for corresponding LED: 0 - LED is off, 1 - LED in on, 2 - LED is flashing. 55 // Bytes 9-16 specify 64-bit LED flash period in 100 ns units if some LED is flashing, otherwise not used. 56 k_EPS3SixaxisCommandSetLEDs = 1, 57 58 // This command allows to set left and right motors. 59 // Byte 5 is right motor duration (0-255) and byte 6, if not zero, activates right motor. Zero value disables right motor. 60 // Byte 7 is left motor duration (0-255) and byte 8 is left motor amplitude (0-255). 61 k_EPS3SixaxisCommandSetMotors = 2, 62 63 // This command allows to block/unblock setting device LEDs by applications. 64 // Byte 5 is used as parameter - any non-zero value blocks LEDs, zero value will unblock LEDs. 65 k_EPS3SixaxisCommandBlockLEDs = 3, 66 67 // This command refreshes driver settings. No parameters used. 68 // When sixaxis driver loads it reads 'CurrentDriverSetting' binary value from 'HKLM\System\CurrentControlSet\Services\sixaxis\Parameters' registry key. 69 // If the key is not present then default values are used. Sending this command forces sixaxis driver to re-read the registry and update driver settings. 70 k_EPS3SixaxisCommandRefreshDriverSetting = 9, 71 72 // This command clears current bluetooth pairing. No parameters used. 73 k_EPS3SixaxisCommandClearPairing = 10 74} EPS3SixaxisDriverCommands; 75 76typedef struct 77{ 78 SDL_HIDAPI_Device *device; 79 SDL_Joystick *joystick; 80 bool is_shanwan; 81 bool has_analog_buttons; 82 bool report_sensors; 83 bool effects_updated; 84 int player_index; 85 Uint8 rumble_left; 86 Uint8 rumble_right; 87 Uint8 last_state[USB_PACKET_LENGTH]; 88} SDL_DriverPS3_Context; 89 90static bool HIDAPI_DriverPS3_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *effect, int size); 91 92static void HIDAPI_DriverPS3_RegisterHints(SDL_HintCallback callback, void *userdata) 93{ 94 SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS3, callback, userdata); 95} 96 97static void HIDAPI_DriverPS3_UnregisterHints(SDL_HintCallback callback, void *userdata) 98{ 99 SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS3, callback, userdata); 100} 101 102static bool HIDAPI_DriverPS3_IsEnabled(void) 103{ 104 bool default_value; 105 106#ifdef SDL_PLATFORM_MACOS 107 // This works well on macOS 108 default_value = true; 109#elif defined(SDL_PLATFORM_WIN32) 110 /* For official Sony driver (sixaxis.sys) use SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER. 111 * 112 * See https://github.com/ViGEm/DsHidMini as an alternative driver 113 */ 114 default_value = false; 115#elif defined(SDL_PLATFORM_LINUX) 116 /* Linux drivers do a better job of managing the transition between 117 * USB and Bluetooth. There are also some quirks in communicating 118 * with PS3 controllers that have been implemented in SDL's hidapi 119 * for libusb, but are not possible to support using hidraw if the 120 * kernel doesn't already know about them. 121 */ 122 default_value = false; 123#else 124 // Untested, default off 125 default_value = false; 126#endif 127 128 if (default_value) { 129 default_value = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, SDL_HIDAPI_DEFAULT); 130 } 131 return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS3, default_value); 132} 133 134static bool HIDAPI_DriverPS3_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GamepadType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) 135{ 136 if (vendor_id == USB_VENDOR_SONY && product_id == USB_PRODUCT_SONY_DS3) { 137 return true; 138 } 139 if (vendor_id == USB_VENDOR_SHANWAN && product_id == USB_PRODUCT_SHANWAN_DS3) { 140 return true; 141 } 142 return false; 143} 144 145static int ReadFeatureReport(SDL_hid_device *dev, Uint8 report_id, Uint8 *report, size_t length) 146{ 147 SDL_memset(report, 0, length); 148 report[0] = report_id; 149 return SDL_hid_get_feature_report(dev, report, length); 150} 151 152static int SendFeatureReport(SDL_hid_device *dev, Uint8 *report, size_t length) 153{ 154 return SDL_hid_send_feature_report(dev, report, length); 155} 156 157static bool HIDAPI_DriverPS3_InitDevice(SDL_HIDAPI_Device *device) 158{ 159 SDL_DriverPS3_Context *ctx; 160 bool is_shanwan = false; 161 162 if (device->vendor_id == USB_VENDOR_SONY && 163 SDL_strncasecmp(device->name, "ShanWan", 7) == 0) { 164 is_shanwan = true; 165 } 166 if (device->vendor_id == USB_VENDOR_SHANWAN || 167 device->vendor_id == USB_VENDOR_SHANWAN_ALT) { 168 is_shanwan = true; 169 } 170 171 ctx = (SDL_DriverPS3_Context *)SDL_calloc(1, sizeof(*ctx)); 172 if (!ctx) { 173 return false; 174 } 175 ctx->device = device; 176 ctx->is_shanwan = is_shanwan; 177 ctx->has_analog_buttons = true; 178 179 device->context = ctx; 180 181 // Set the controller into report mode over Bluetooth 182 if (device->is_bluetooth) { 183 Uint8 data[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; 184 185 SendFeatureReport(device->dev, data, sizeof(data)); 186 } 187 188 // Set the controller into report mode over USB 189 if (!device->is_bluetooth) { 190 Uint8 data[USB_PACKET_LENGTH]; 191 192 int size = ReadFeatureReport(device->dev, 0xf2, data, 17); 193 if (size < 0) { 194 SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, 195 "HIDAPI_DriverPS3_InitDevice(): Couldn't read feature report 0xf2"); 196 return false; 197 } 198#ifdef DEBUG_PS3_PROTOCOL 199 HIDAPI_DumpPacket("PS3 0xF2 packet: size = %d", data, size); 200#endif 201 size = ReadFeatureReport(device->dev, 0xf5, data, 8); 202 if (size < 0) { 203 SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, 204 "HIDAPI_DriverPS3_InitDevice(): Couldn't read feature report 0xf5"); 205 return false; 206 } 207#ifdef DEBUG_PS3_PROTOCOL 208 HIDAPI_DumpPacket("PS3 0xF5 packet: size = %d", data, size); 209#endif 210 if (!ctx->is_shanwan) { 211 // An output report could cause ShanWan controllers to rumble non-stop 212 SDL_hid_write(device->dev, data, 1); 213 } 214 } 215 216 device->type = SDL_GAMEPAD_TYPE_PS3; 217 HIDAPI_SetDeviceName(device, "PS3 Controller"); 218 219 return HIDAPI_JoystickConnected(device, NULL); 220} 221 222static int HIDAPI_DriverPS3_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) 223{ 224 return -1; 225} 226 227static bool HIDAPI_DriverPS3_UpdateEffects(SDL_HIDAPI_Device *device) 228{ 229 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 230 231 Uint8 effects[] = { 232 0x01, 0xff, 0x00, 0xff, 0x00, 233 0x00, 0x00, 0x00, 0x00, 0x00, 234 0xff, 0x27, 0x10, 0x00, 0x32, 235 0xff, 0x27, 0x10, 0x00, 0x32, 236 0xff, 0x27, 0x10, 0x00, 0x32, 237 0xff, 0x27, 0x10, 0x00, 0x32, 238 0x00, 0x00, 0x00, 0x00, 0x00 239 }; 240 241 effects[2] = ctx->rumble_right ? 1 : 0; 242 effects[4] = ctx->rumble_left; 243 244 effects[9] = (0x01 << (1 + (ctx->player_index % 4))); 245 246 return HIDAPI_DriverPS3_SendJoystickEffect(device, ctx->joystick, effects, sizeof(effects)); 247} 248 249static void HIDAPI_DriverPS3_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) 250{ 251 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 252 253 if (!ctx) { 254 return; 255 } 256 257 ctx->player_index = player_index; 258 259 // This will set the new LED state based on the new player index 260 HIDAPI_DriverPS3_UpdateEffects(device); 261} 262 263static bool HIDAPI_DriverPS3_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 264{ 265 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 266 267 SDL_AssertJoysticksLocked(); 268 269 ctx->joystick = joystick; 270 ctx->effects_updated = false; 271 ctx->rumble_left = 0; 272 ctx->rumble_right = 0; 273 SDL_zeroa(ctx->last_state); 274 275 // Initialize player index (needed for setting LEDs) 276 ctx->player_index = SDL_GetJoystickPlayerIndex(joystick); 277 278 // Initialize the joystick capabilities 279 joystick->nbuttons = 11; 280 joystick->naxes = 6; 281 if (ctx->has_analog_buttons) { 282 joystick->naxes += 10; 283 } 284 joystick->nhats = 1; 285 286 SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 100.0f); 287 288 return true; 289} 290 291static bool HIDAPI_DriverPS3_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) 292{ 293 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 294 295 ctx->rumble_left = (low_frequency_rumble >> 8); 296 ctx->rumble_right = (high_frequency_rumble >> 8); 297 298 return HIDAPI_DriverPS3_UpdateEffects(device); 299} 300 301static bool HIDAPI_DriverPS3_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble) 302{ 303 return SDL_Unsupported(); 304} 305 306static Uint32 HIDAPI_DriverPS3_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 307{ 308 return SDL_JOYSTICK_CAP_RUMBLE; 309} 310 311static bool HIDAPI_DriverPS3_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) 312{ 313 return SDL_Unsupported(); 314} 315 316static bool HIDAPI_DriverPS3_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *effect, int size) 317{ 318 Uint8 data[49]; 319 int report_size, offset; 320 321 SDL_zeroa(data); 322 323 data[0] = k_EPS3ReportIdEffects; 324 report_size = sizeof(data); 325 offset = 1; 326 SDL_memcpy(&data[offset], effect, SDL_min((sizeof(data) - offset), (size_t)size)); 327 328 if (SDL_HIDAPI_SendRumble(device, data, report_size) != report_size) { 329 return SDL_SetError("Couldn't send rumble packet"); 330 } 331 return true; 332} 333 334static bool HIDAPI_DriverPS3_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, bool enabled) 335{ 336 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 337 338 ctx->report_sensors = enabled; 339 340 return true; 341} 342 343static float HIDAPI_DriverPS3_ScaleAccel(Sint16 value) 344{ 345 // Accelerometer values are in big endian order 346 value = SDL_Swap16BE(value); 347 return ((float)(value - 511) / 113.0f) * SDL_STANDARD_GRAVITY; 348} 349 350static float HIDAPI_DriverPS3ThirdParty_ScaleAccel(Sint16 value) 351{ 352 return ((float)(value - 512) / 113.0f) * SDL_STANDARD_GRAVITY; 353} 354 355static void HIDAPI_DriverPS3_HandleMiniStatePacket(SDL_Joystick *joystick, SDL_DriverPS3_Context *ctx, Uint8 *data, int size) 356{ 357 Sint16 axis; 358 Uint64 timestamp = SDL_GetTicksNS(); 359 360 if (ctx->last_state[4] != data[4]) { 361 Uint8 hat; 362 363 switch (data[4] & 0x0f) { 364 case 0: 365 hat = SDL_HAT_UP; 366 break; 367 case 1: 368 hat = SDL_HAT_RIGHTUP; 369 break; 370 case 2: 371 hat = SDL_HAT_RIGHT; 372 break; 373 case 3: 374 hat = SDL_HAT_RIGHTDOWN; 375 break; 376 case 4: 377 hat = SDL_HAT_DOWN; 378 break; 379 case 5: 380 hat = SDL_HAT_LEFTDOWN; 381 break; 382 case 6: 383 hat = SDL_HAT_LEFT; 384 break; 385 case 7: 386 hat = SDL_HAT_LEFTUP; 387 break; 388 default: 389 hat = SDL_HAT_CENTERED; 390 break; 391 } 392 SDL_SendJoystickHat(timestamp, joystick, 0, hat); 393 394 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, ((data[4] & 0x10) != 0)); 395 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, ((data[4] & 0x20) != 0)); 396 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, ((data[4] & 0x40) != 0)); 397 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, ((data[4] & 0x80) != 0)); 398 } 399 400 if (ctx->last_state[5] != data[5]) { 401 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data[5] & 0x01) != 0)); 402 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data[5] & 0x02) != 0)); 403 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, (data[5] & 0x04) ? SDL_JOYSTICK_AXIS_MAX : SDL_JOYSTICK_AXIS_MIN); 404 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, (data[5] & 0x08) ? SDL_JOYSTICK_AXIS_MAX : SDL_JOYSTICK_AXIS_MIN); 405 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data[5] & 0x10) != 0)); 406 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data[5] & 0x20) != 0)); 407 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data[5] & 0x40) != 0)); 408 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data[5] & 0x80) != 0)); 409 } 410 411 axis = ((int)data[2] * 257) - 32768; 412 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis); 413 axis = ((int)data[3] * 257) - 32768; 414 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis); 415 axis = ((int)data[0] * 257) - 32768; 416 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis); 417 axis = ((int)data[1] * 257) - 32768; 418 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis); 419 420 SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state))); 421} 422 423static void HIDAPI_DriverPS3_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverPS3_Context *ctx, Uint8 *data, int size) 424{ 425 Sint16 axis; 426 Uint64 timestamp = SDL_GetTicksNS(); 427 428 if (ctx->last_state[2] != data[2]) { 429 Uint8 hat = 0; 430 431 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data[2] & 0x01) != 0)); 432 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data[2] & 0x02) != 0)); 433 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data[2] & 0x04) != 0)); 434 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data[2] & 0x08) != 0)); 435 436 if (data[2] & 0x10) { 437 hat |= SDL_HAT_UP; 438 } 439 if (data[2] & 0x20) { 440 hat |= SDL_HAT_RIGHT; 441 } 442 if (data[2] & 0x40) { 443 hat |= SDL_HAT_DOWN; 444 } 445 if (data[2] & 0x80) { 446 hat |= SDL_HAT_LEFT; 447 } 448 SDL_SendJoystickHat(timestamp, joystick, 0, hat); 449 } 450 451 if (ctx->last_state[3] != data[3]) { 452 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data[3] & 0x04) != 0)); 453 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data[3] & 0x08) != 0)); 454 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, ((data[3] & 0x10) != 0)); 455 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, ((data[3] & 0x20) != 0)); 456 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, ((data[3] & 0x40) != 0)); 457 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, ((data[3] & 0x80) != 0)); 458 } 459 460 if (ctx->last_state[4] != data[4]) { 461 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data[4] & 0x01) != 0)); 462 } 463 464 axis = ((int)data[18] * 257) - 32768; 465 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis); 466 axis = ((int)data[19] * 257) - 32768; 467 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis); 468 axis = ((int)data[6] * 257) - 32768; 469 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis); 470 axis = ((int)data[7] * 257) - 32768; 471 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis); 472 axis = ((int)data[8] * 257) - 32768; 473 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis); 474 axis = ((int)data[9] * 257) - 32768; 475 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis); 476 477 // Buttons are mapped as axes in the order they appear in the button enumeration 478 if (ctx->has_analog_buttons) { 479 static int button_axis_offsets[] = { 480 24, // SDL_GAMEPAD_BUTTON_SOUTH 481 23, // SDL_GAMEPAD_BUTTON_EAST 482 25, // SDL_GAMEPAD_BUTTON_WEST 483 22, // SDL_GAMEPAD_BUTTON_NORTH 484 0, // SDL_GAMEPAD_BUTTON_BACK 485 0, // SDL_GAMEPAD_BUTTON_GUIDE 486 0, // SDL_GAMEPAD_BUTTON_START 487 0, // SDL_GAMEPAD_BUTTON_LEFT_STICK 488 0, // SDL_GAMEPAD_BUTTON_RIGHT_STICK 489 20, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER 490 21, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER 491 14, // SDL_GAMEPAD_BUTTON_DPAD_UP 492 16, // SDL_GAMEPAD_BUTTON_DPAD_DOWN 493 17, // SDL_GAMEPAD_BUTTON_DPAD_LEFT 494 15, // SDL_GAMEPAD_BUTTON_DPAD_RIGHT 495 }; 496 Uint8 i, axis_index = 6; 497 498 for (i = 0; i < SDL_arraysize(button_axis_offsets); ++i) { 499 int offset = button_axis_offsets[i]; 500 if (!offset) { 501 // This button doesn't report as an axis 502 continue; 503 } 504 505 axis = ((int)data[offset] * 257) - 32768; 506 SDL_SendJoystickAxis(timestamp, joystick, axis_index, axis); 507 ++axis_index; 508 } 509 } 510 511 if (ctx->report_sensors) { 512 float sensor_data[3]; 513 514 sensor_data[0] = HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[41], data[42])); 515 sensor_data[1] = -HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[45], data[46])); 516 sensor_data[2] = -HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[43], data[44])); 517 SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, timestamp, sensor_data, SDL_arraysize(sensor_data)); 518 } 519 520 SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state))); 521} 522 523static bool HIDAPI_DriverPS3_UpdateDevice(SDL_HIDAPI_Device *device) 524{ 525 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 526 SDL_Joystick *joystick = NULL; 527 Uint8 data[USB_PACKET_LENGTH]; 528 int size; 529 530 if (device->num_joysticks > 0) { 531 joystick = SDL_GetJoystickFromID(device->joysticks[0]); 532 } else { 533 return false; 534 } 535 536 while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) { 537#ifdef DEBUG_PS3_PROTOCOL 538 HIDAPI_DumpPacket("PS3 packet: size = %d", data, size); 539#endif 540 if (!joystick) { 541 continue; 542 } 543 544 if (size == 7) { 545 // Seen on a ShanWan PS2 -> PS3 USB converter 546 HIDAPI_DriverPS3_HandleMiniStatePacket(joystick, ctx, data, size); 547 548 // Wait for the first report to set the LED state after the controller stops blinking 549 if (!ctx->effects_updated) { 550 HIDAPI_DriverPS3_UpdateEffects(device); 551 ctx->effects_updated = true; 552 } 553 continue; 554 } 555 556 switch (data[0]) { 557 case k_EPS3ReportIdState: 558 if (data[1] == 0xFF) { 559 // Invalid data packet, ignore 560 break; 561 } 562 HIDAPI_DriverPS3_HandleStatePacket(joystick, ctx, data, size); 563 564 // Wait for the first report to set the LED state after the controller stops blinking 565 if (!ctx->effects_updated) { 566 HIDAPI_DriverPS3_UpdateEffects(device); 567 ctx->effects_updated = true; 568 } 569 break; 570 default: 571#ifdef DEBUG_JOYSTICK 572 SDL_Log("Unknown PS3 packet: 0x%.2x", data[0]); 573#endif 574 break; 575 } 576 } 577 578 if (size < 0) { 579 // Read error, device is disconnected 580 HIDAPI_JoystickDisconnected(device, device->joysticks[0]); 581 } 582 return (size >= 0); 583} 584 585static void HIDAPI_DriverPS3_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 586{ 587 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 588 589 ctx->joystick = NULL; 590} 591 592static void HIDAPI_DriverPS3_FreeDevice(SDL_HIDAPI_Device *device) 593{ 594} 595 596SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS3 = { 597 SDL_HINT_JOYSTICK_HIDAPI_PS3, 598 true, 599 HIDAPI_DriverPS3_RegisterHints, 600 HIDAPI_DriverPS3_UnregisterHints, 601 HIDAPI_DriverPS3_IsEnabled, 602 HIDAPI_DriverPS3_IsSupportedDevice, 603 HIDAPI_DriverPS3_InitDevice, 604 HIDAPI_DriverPS3_GetDevicePlayerIndex, 605 HIDAPI_DriverPS3_SetDevicePlayerIndex, 606 HIDAPI_DriverPS3_UpdateDevice, 607 HIDAPI_DriverPS3_OpenJoystick, 608 HIDAPI_DriverPS3_RumbleJoystick, 609 HIDAPI_DriverPS3_RumbleJoystickTriggers, 610 HIDAPI_DriverPS3_GetJoystickCapabilities, 611 HIDAPI_DriverPS3_SetJoystickLED, 612 HIDAPI_DriverPS3_SendJoystickEffect, 613 HIDAPI_DriverPS3_SetJoystickSensorsEnabled, 614 HIDAPI_DriverPS3_CloseJoystick, 615 HIDAPI_DriverPS3_FreeDevice, 616}; 617 618static bool HIDAPI_DriverPS3ThirdParty_IsEnabled(void) 619{ 620 return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS3, 621 SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, 622 SDL_HIDAPI_DEFAULT)); 623} 624 625static bool HIDAPI_DriverPS3ThirdParty_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GamepadType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) 626{ 627 Uint8 data[USB_PACKET_LENGTH]; 628 int size; 629 630 if (vendor_id == USB_VENDOR_LOGITECH && 631 product_id == USB_PRODUCT_LOGITECH_CHILLSTREAM) { 632 return true; 633 } 634 635 if ((type == SDL_GAMEPAD_TYPE_PS3 && vendor_id != USB_VENDOR_SONY) || 636 HIDAPI_SupportsPlaystationDetection(vendor_id, product_id)) { 637 if (device && device->dev) { 638 size = ReadFeatureReport(device->dev, 0x03, data, sizeof(data)); 639 if (size == 8 && data[2] == 0x26) { 640 // Supported third party controller 641 return true; 642 } else { 643 // Some third party controllers don't have report ids 644 size = ReadFeatureReport(device->dev, 0x00, data, sizeof(data)); 645 if (size == 9 && data[2] == 0x26) { 646 // Supported third party controller 647 return true; 648 } else { 649 return false; 650 } 651 } 652 } else { 653 // Might be supported by this driver, enumerate and find out 654 return true; 655 } 656 } 657 return false; 658} 659 660static bool HIDAPI_DriverPS3ThirdParty_InitDevice(SDL_HIDAPI_Device *device) 661{ 662 SDL_DriverPS3_Context *ctx; 663 664 ctx = (SDL_DriverPS3_Context *)SDL_calloc(1, sizeof(*ctx)); 665 if (!ctx) { 666 return false; 667 } 668 ctx->device = device; 669 if (device->vendor_id == USB_VENDOR_SWITCH && device->product_id == USB_PRODUCT_SWITCH_RETROBIT_CONTROLLER) { 670 ctx->has_analog_buttons = false; 671 } else { 672 ctx->has_analog_buttons = true; 673 } 674 675 device->context = ctx; 676 677 device->type = SDL_GAMEPAD_TYPE_PS3; 678 679 if (device->vendor_id == USB_VENDOR_LOGITECH && 680 device->product_id == USB_PRODUCT_LOGITECH_CHILLSTREAM) { 681 HIDAPI_SetDeviceName(device, "Logitech ChillStream"); 682 } 683 684 if (device->vendor_id == USB_VENDOR_HARMONIX) { 685 switch (device->product_id) { 686 case USB_PRODUCT_HARMONIX_WII_RB1_GUITAR: 687 case USB_PRODUCT_HARMONIX_WII_RB2_GUITAR: 688 device->joystick_type = SDL_JOYSTICK_TYPE_GUITAR; 689 break; 690 case USB_PRODUCT_HARMONIX_WII_RB1_DRUMS: 691 case USB_PRODUCT_HARMONIX_WII_RB2_DRUMS: 692 case USB_PRODUCT_HARMONIX_WII_RB3_MPA_DRUMS_MODE: 693 device->joystick_type = SDL_JOYSTICK_TYPE_DRUM_KIT; 694 break; 695 default: 696 break; 697 } 698 } 699 700 if (device->vendor_id == USB_VENDOR_SCEA) { 701 switch (device->product_id) { 702 case USB_PRODUCT_SCEA_PS3_GH_GUITAR: 703 case USB_PRODUCT_SCEA_PS3_RB_GUITAR: 704 case USB_PRODUCT_SCEA_PS3WIIU_GHLIVE: 705 device->joystick_type = SDL_JOYSTICK_TYPE_GUITAR; 706 break; 707 case USB_PRODUCT_SCEA_PS3_GH_DRUMS: 708 case USB_PRODUCT_SCEA_PS3_RB_DRUMS: 709 case USB_PRODUCT_SCEA_PS3_RB3_MPA_DRUMS_MODE: 710 device->joystick_type = SDL_JOYSTICK_TYPE_DRUM_KIT; 711 break; 712 default: 713 break; 714 } 715 } 716 717 return HIDAPI_JoystickConnected(device, NULL); 718} 719 720static int HIDAPI_DriverPS3ThirdParty_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) 721{ 722 return -1; 723} 724 725static void HIDAPI_DriverPS3ThirdParty_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) 726{ 727} 728 729static bool HIDAPI_DriverPS3ThirdParty_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 730{ 731 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 732 733 SDL_AssertJoysticksLocked(); 734 735 ctx->joystick = joystick; 736 SDL_zeroa(ctx->last_state); 737 738 // Initialize the joystick capabilities 739 joystick->nbuttons = 11; 740 joystick->naxes = 6; 741 if (ctx->has_analog_buttons) { 742 joystick->naxes += 10; 743 } 744 joystick->nhats = 1; 745 746 if (device->vendor_id == USB_VENDOR_SWITCH && device->product_id == USB_PRODUCT_SWITCH_RETROBIT_CONTROLLER) { 747 // This is a wireless controller using a USB dongle 748 joystick->connection_state = SDL_JOYSTICK_CONNECTION_WIRELESS; 749 } 750 751 SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 100.0f); 752 753 return true; 754} 755 756static bool HIDAPI_DriverPS3ThirdParty_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) 757{ 758 return SDL_Unsupported(); 759} 760 761static bool HIDAPI_DriverPS3ThirdParty_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble) 762{ 763 return SDL_Unsupported(); 764} 765 766static Uint32 HIDAPI_DriverPS3ThirdParty_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 767{ 768 return 0; 769} 770 771static bool HIDAPI_DriverPS3ThirdParty_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) 772{ 773 return SDL_Unsupported(); 774} 775 776static bool HIDAPI_DriverPS3ThirdParty_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *effect, int size) 777{ 778 return SDL_Unsupported(); 779} 780 781static bool HIDAPI_DriverPS3ThirdParty_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, bool enabled) 782{ 783 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 784 785 ctx->report_sensors = enabled; 786 787 return true; 788} 789 790static void HIDAPI_DriverPS3ThirdParty_HandleStatePacket18(SDL_Joystick *joystick, SDL_DriverPS3_Context *ctx, Uint8 *data, int size) 791{ 792 Sint16 axis; 793 Uint64 timestamp = SDL_GetTicksNS(); 794 795 if (ctx->last_state[0] != data[0]) { 796 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, ((data[0] & 0x01) != 0)); 797 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, ((data[0] & 0x02) != 0)); 798 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, ((data[0] & 0x04) != 0)); 799 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, ((data[0] & 0x08) != 0)); 800 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data[0] & 0x10) != 0)); 801 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data[0] & 0x20) != 0)); 802 } 803 804 if (ctx->last_state[1] != data[1]) { 805 Uint8 hat; 806 807 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data[1] & 0x01) != 0)); 808 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data[1] & 0x02) != 0)); 809 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data[1] & 0x04) != 0)); 810 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data[1] & 0x08) != 0)); 811 812 switch (data[1] >> 4) { 813 case 0: 814 hat = SDL_HAT_UP; 815 break; 816 case 1: 817 hat = SDL_HAT_RIGHTUP; 818 break; 819 case 2: 820 hat = SDL_HAT_RIGHT; 821 break; 822 case 3: 823 hat = SDL_HAT_RIGHTDOWN; 824 break; 825 case 4: 826 hat = SDL_HAT_DOWN; 827 break; 828 case 5: 829 hat = SDL_HAT_LEFTDOWN; 830 break; 831 case 6: 832 hat = SDL_HAT_LEFT; 833 break; 834 case 7: 835 hat = SDL_HAT_LEFTUP; 836 break; 837 default: 838 hat = SDL_HAT_CENTERED; 839 break; 840 } 841 SDL_SendJoystickHat(timestamp, joystick, 0, hat); 842 } 843 844 axis = ((int)data[16] * 257) - 32768; 845 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis); 846 axis = ((int)data[17] * 257) - 32768; 847 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis); 848 axis = ((int)data[2] * 257) - 32768; 849 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis); 850 axis = ((int)data[3] * 257) - 32768; 851 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis); 852 axis = ((int)data[4] * 257) - 32768; 853 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis); 854 axis = ((int)data[5] * 257) - 32768; 855 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis); 856 857 // Buttons are mapped as axes in the order they appear in the button enumeration 858 if (ctx->has_analog_buttons) { 859 static int button_axis_offsets[] = { 860 12, // SDL_GAMEPAD_BUTTON_SOUTH 861 11, // SDL_GAMEPAD_BUTTON_EAST 862 13, // SDL_GAMEPAD_BUTTON_WEST 863 10, // SDL_GAMEPAD_BUTTON_NORTH 864 0, // SDL_GAMEPAD_BUTTON_BACK 865 0, // SDL_GAMEPAD_BUTTON_GUIDE 866 0, // SDL_GAMEPAD_BUTTON_START 867 0, // SDL_GAMEPAD_BUTTON_LEFT_STICK 868 0, // SDL_GAMEPAD_BUTTON_RIGHT_STICK 869 14, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER 870 15, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER 871 8, // SDL_GAMEPAD_BUTTON_DPAD_UP 872 9, // SDL_GAMEPAD_BUTTON_DPAD_DOWN 873 7, // SDL_GAMEPAD_BUTTON_DPAD_LEFT 874 6, // SDL_GAMEPAD_BUTTON_DPAD_RIGHT 875 }; 876 Uint8 i, axis_index = 6; 877 878 for (i = 0; i < SDL_arraysize(button_axis_offsets); ++i) { 879 int offset = button_axis_offsets[i]; 880 if (!offset) { 881 // This button doesn't report as an axis 882 continue; 883 } 884 885 axis = ((int)data[offset] * 257) - 32768; 886 SDL_SendJoystickAxis(timestamp, joystick, axis_index, axis); 887 ++axis_index; 888 } 889 } 890 891 SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state))); 892} 893 894static void HIDAPI_DriverPS3ThirdParty_HandleStatePacket19(SDL_Joystick *joystick, SDL_DriverPS3_Context *ctx, Uint8 *data, int size) 895{ 896 Sint16 axis; 897 Uint64 timestamp = SDL_GetTicksNS(); 898 899 if (ctx->last_state[0] != data[0]) { 900 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, ((data[0] & 0x01) != 0)); 901 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, ((data[0] & 0x02) != 0)); 902 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, ((data[0] & 0x04) != 0)); 903 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, ((data[0] & 0x08) != 0)); 904 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data[0] & 0x10) != 0)); 905 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data[0] & 0x20) != 0)); 906 } 907 908 if (ctx->last_state[1] != data[1]) { 909 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data[1] & 0x01) != 0)); 910 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data[1] & 0x02) != 0)); 911 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data[1] & 0x04) != 0)); 912 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data[1] & 0x08) != 0)); 913 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data[1] & 0x10) != 0)); 914 } 915 916 if (ctx->device->vendor_id == USB_VENDOR_SAITEK && ctx->device->product_id == USB_PRODUCT_SAITEK_CYBORG_V3) { 917 // Cyborg V.3 Rumble Pad doesn't set the dpad bits as expected, so use the axes instead 918 Uint8 hat = 0; 919 920 if (data[7]) { 921 hat |= SDL_HAT_RIGHT; 922 } 923 if (data[8]) { 924 hat |= SDL_HAT_LEFT; 925 } 926 if (data[9]) { 927 hat |= SDL_HAT_UP; 928 } 929 if (data[10]) { 930 hat |= SDL_HAT_DOWN; 931 } 932 SDL_SendJoystickHat(timestamp, joystick, 0, hat); 933 } else { 934 if (ctx->last_state[2] != data[2]) { 935 Uint8 hat; 936 937 switch (data[2] & 0x0f) { 938 case 0: 939 hat = SDL_HAT_UP; 940 break; 941 case 1: 942 hat = SDL_HAT_RIGHTUP; 943 break; 944 case 2: 945 hat = SDL_HAT_RIGHT; 946 break; 947 case 3: 948 hat = SDL_HAT_RIGHTDOWN; 949 break; 950 case 4: 951 hat = SDL_HAT_DOWN; 952 break; 953 case 5: 954 hat = SDL_HAT_LEFTDOWN; 955 break; 956 case 6: 957 hat = SDL_HAT_LEFT; 958 break; 959 case 7: 960 hat = SDL_HAT_LEFTUP; 961 break; 962 default: 963 hat = SDL_HAT_CENTERED; 964 break; 965 } 966 SDL_SendJoystickHat(timestamp, joystick, 0, hat); 967 } 968 } 969 970 if (data[0] & 0x40) { 971 axis = 32767; 972 } else { 973 axis = ((int)data[17] * 257) - 32768; 974 } 975 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis); 976 if (data[0] & 0x80) { 977 axis = 32767; 978 } else { 979 axis = ((int)data[18] * 257) - 32768; 980 } 981 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis); 982 axis = ((int)data[3] * 257) - 32768; 983 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis); 984 axis = ((int)data[4] * 257) - 32768; 985 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis); 986 axis = ((int)data[5] * 257) - 32768; 987 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis); 988 axis = ((int)data[6] * 257) - 32768; 989 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis); 990 991 // Buttons are mapped as axes in the order they appear in the button enumeration 992 if (ctx->has_analog_buttons) { 993 static int button_axis_offsets[] = { 994 13, // SDL_GAMEPAD_BUTTON_SOUTH 995 12, // SDL_GAMEPAD_BUTTON_EAST 996 14, // SDL_GAMEPAD_BUTTON_WEST 997 11, // SDL_GAMEPAD_BUTTON_NORTH 998 0, // SDL_GAMEPAD_BUTTON_BACK 999 0, // SDL_GAMEPAD_BUTTON_GUIDE 1000 0, // SDL_GAMEPAD_BUTTON_START 1001 0, // SDL_GAMEPAD_BUTTON_LEFT_STICK 1002 0, // SDL_GAMEPAD_BUTTON_RIGHT_STICK 1003 15, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER 1004 16, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER 1005 9, // SDL_GAMEPAD_BUTTON_DPAD_UP 1006 10, // SDL_GAMEPAD_BUTTON_DPAD_DOWN 1007 8, // SDL_GAMEPAD_BUTTON_DPAD_LEFT 1008 7, // SDL_GAMEPAD_BUTTON_DPAD_RIGHT 1009 }; 1010 Uint8 i, axis_index = 6; 1011 1012 for (i = 0; i < SDL_arraysize(button_axis_offsets); ++i) { 1013 int offset = button_axis_offsets[i]; 1014 if (!offset) { 1015 // This button doesn't report as an axis 1016 continue; 1017 } 1018 1019 axis = ((int)data[offset] * 257) - 32768; 1020 SDL_SendJoystickAxis(timestamp, joystick, axis_index, axis); 1021 ++axis_index; 1022 } 1023 } 1024 1025 if (ctx->report_sensors) { 1026 float sensor_data[3]; 1027 1028 sensor_data[0] = -HIDAPI_DriverPS3ThirdParty_ScaleAccel(LOAD16(data[19], data[20])); 1029 sensor_data[1] = -HIDAPI_DriverPS3ThirdParty_ScaleAccel(LOAD16(data[21], data[22])); 1030 sensor_data[2] = -HIDAPI_DriverPS3ThirdParty_ScaleAccel(LOAD16(data[23], data[24])); 1031 SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, timestamp, sensor_data, SDL_arraysize(sensor_data)); 1032 } 1033 1034 SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state))); 1035} 1036 1037static bool HIDAPI_DriverPS3ThirdParty_UpdateDevice(SDL_HIDAPI_Device *device) 1038{ 1039 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 1040 SDL_Joystick *joystick = NULL; 1041 Uint8 data[USB_PACKET_LENGTH]; 1042 int size; 1043 1044 if (device->num_joysticks > 0) { 1045 joystick = SDL_GetJoystickFromID(device->joysticks[0]); 1046 } else { 1047 return false; 1048 } 1049 1050 while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) { 1051#ifdef DEBUG_PS3_PROTOCOL 1052 HIDAPI_DumpPacket("PS3 packet: size = %d", data, size); 1053#endif 1054 if (!joystick) { 1055 continue; 1056 } 1057 1058 if (size >= 19) { 1059 HIDAPI_DriverPS3ThirdParty_HandleStatePacket19(joystick, ctx, data, size); 1060 } else if (size == 18) { 1061 // This packet format was seen with the Logitech ChillStream 1062 HIDAPI_DriverPS3ThirdParty_HandleStatePacket18(joystick, ctx, data, size); 1063 } else { 1064#ifdef DEBUG_JOYSTICK 1065 SDL_Log("Unknown PS3 packet, size %d", size); 1066#endif 1067 } 1068 } 1069 1070 if (size < 0) { 1071 // Read error, device is disconnected 1072 HIDAPI_JoystickDisconnected(device, device->joysticks[0]); 1073 } 1074 return (size >= 0); 1075} 1076 1077static void HIDAPI_DriverPS3ThirdParty_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 1078{ 1079 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 1080 1081 ctx->joystick = NULL; 1082} 1083 1084static void HIDAPI_DriverPS3ThirdParty_FreeDevice(SDL_HIDAPI_Device *device) 1085{ 1086} 1087 1088SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS3ThirdParty = { 1089 SDL_HINT_JOYSTICK_HIDAPI_PS3, 1090 true, 1091 HIDAPI_DriverPS3_RegisterHints, 1092 HIDAPI_DriverPS3_UnregisterHints, 1093 HIDAPI_DriverPS3ThirdParty_IsEnabled, 1094 HIDAPI_DriverPS3ThirdParty_IsSupportedDevice, 1095 HIDAPI_DriverPS3ThirdParty_InitDevice, 1096 HIDAPI_DriverPS3ThirdParty_GetDevicePlayerIndex, 1097 HIDAPI_DriverPS3ThirdParty_SetDevicePlayerIndex, 1098 HIDAPI_DriverPS3ThirdParty_UpdateDevice, 1099 HIDAPI_DriverPS3ThirdParty_OpenJoystick, 1100 HIDAPI_DriverPS3ThirdParty_RumbleJoystick, 1101 HIDAPI_DriverPS3ThirdParty_RumbleJoystickTriggers, 1102 HIDAPI_DriverPS3ThirdParty_GetJoystickCapabilities, 1103 HIDAPI_DriverPS3ThirdParty_SetJoystickLED, 1104 HIDAPI_DriverPS3ThirdParty_SendJoystickEffect, 1105 HIDAPI_DriverPS3ThirdParty_SetJoystickSensorsEnabled, 1106 HIDAPI_DriverPS3ThirdParty_CloseJoystick, 1107 HIDAPI_DriverPS3ThirdParty_FreeDevice, 1108}; 1109 1110static bool HIDAPI_DriverPS3_UpdateRumbleSonySixaxis(SDL_HIDAPI_Device *device); 1111static bool HIDAPI_DriverPS3_UpdateLEDsSonySixaxis(SDL_HIDAPI_Device *device); 1112 1113static void HIDAPI_DriverPS3SonySixaxis_RegisterHints(SDL_HintCallback callback, void *userdata) 1114{ 1115 SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER, callback, userdata); 1116} 1117 1118static void HIDAPI_DriverPS3SonySixaxis_UnregisterHints(SDL_HintCallback callback, void *userdata) 1119{ 1120 SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER, callback, userdata); 1121} 1122 1123static bool HIDAPI_DriverPS3SonySixaxis_IsEnabled(void) 1124{ 1125#ifdef SDL_PLATFORM_WIN32 1126 return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER, false); 1127#else 1128 return false; 1129#endif 1130} 1131 1132static bool HIDAPI_DriverPS3SonySixaxis_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GamepadType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) 1133{ 1134 if (vendor_id == USB_VENDOR_SONY && product_id == USB_PRODUCT_SONY_DS3) { 1135 return true; 1136 } 1137 return false; 1138} 1139 1140static bool HIDAPI_DriverPS3SonySixaxis_InitDevice(SDL_HIDAPI_Device *device) 1141{ 1142 SDL_DriverPS3_Context *ctx; 1143 1144 ctx = (SDL_DriverPS3_Context *)SDL_calloc(1, sizeof(*ctx)); 1145 if (!ctx) { 1146 return false; 1147 } 1148 ctx->device = device; 1149 ctx->has_analog_buttons = true; 1150 1151 device->context = ctx; 1152 1153 Uint8 data[USB_PACKET_LENGTH]; 1154 1155 int size = ReadFeatureReport(device->dev, 0xf2, data, sizeof(data)); 1156 if (size < 0) { 1157 SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, 1158 "HIDAPI_DriverPS3SonySixaxis_InitDevice(): Couldn't read feature report 0xf2. Trying again with 0x0."); 1159 SDL_zeroa(data); 1160 size = ReadFeatureReport(device->dev, 0x00, data, sizeof(data)); 1161 if (size < 0) { 1162 SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, 1163 "HIDAPI_DriverPS3SonySixaxis_InitDevice(): Couldn't read feature report 0x00."); 1164 return false; 1165 } 1166#ifdef DEBUG_PS3_PROTOCOL 1167 HIDAPI_DumpPacket("PS3 0x0 packet: size = %d", data, size); 1168#endif 1169 } 1170#ifdef DEBUG_PS3_PROTOCOL 1171 HIDAPI_DumpPacket("PS3 0xF2 packet: size = %d", data, size); 1172#endif 1173 1174 device->type = SDL_GAMEPAD_TYPE_PS3; 1175 HIDAPI_SetDeviceName(device, "PS3 Controller"); 1176 1177 return HIDAPI_JoystickConnected(device, NULL); 1178} 1179 1180static int HIDAPI_DriverPS3SonySixaxis_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) 1181{ 1182 return -1; 1183} 1184 1185static void HIDAPI_DriverPS3SonySixaxis_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) 1186{ 1187 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 1188 1189 if (!ctx) { 1190 return; 1191 } 1192 1193 ctx->player_index = player_index; 1194 1195 // This will set the new LED state based on the new player index 1196 HIDAPI_DriverPS3_UpdateLEDsSonySixaxis(device); 1197} 1198 1199static bool HIDAPI_DriverPS3SonySixaxis_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 1200{ 1201 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 1202 1203 SDL_AssertJoysticksLocked(); 1204 1205 ctx->joystick = joystick; 1206 ctx->effects_updated = false; 1207 ctx->rumble_left = 0; 1208 ctx->rumble_right = 0; 1209 SDL_zeroa(ctx->last_state); 1210 1211 // Initialize player index (needed for setting LEDs) 1212 ctx->player_index = SDL_GetJoystickPlayerIndex(joystick); 1213 1214 // Initialize the joystick capabilities 1215 joystick->nbuttons = 11; 1216 joystick->naxes = 6; 1217 if (ctx->has_analog_buttons) { 1218 joystick->naxes += 10; 1219 } 1220 joystick->nhats = 1; 1221 1222 SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 100.0f); 1223 1224 return true; 1225} 1226 1227static bool HIDAPI_DriverPS3SonySixaxis_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) 1228{ 1229 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 1230 1231 ctx->rumble_left = (low_frequency_rumble >> 8); 1232 ctx->rumble_right = (high_frequency_rumble >> 8); 1233 1234 return HIDAPI_DriverPS3_UpdateRumbleSonySixaxis(device); 1235} 1236 1237static bool HIDAPI_DriverPS3SonySixaxis_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble) 1238{ 1239 return SDL_Unsupported(); 1240} 1241 1242static Uint32 HIDAPI_DriverPS3SonySixaxis_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 1243{ 1244 return 0; 1245} 1246 1247static bool HIDAPI_DriverPS3SonySixaxis_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) 1248{ 1249 return SDL_Unsupported(); 1250} 1251 1252static bool HIDAPI_DriverPS3SonySixaxis_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *effect, int size) 1253{ 1254 Uint8 data[49]; 1255 int report_size; 1256 1257 SDL_zeroa(data); 1258 1259 data[0] = k_EPS3SonySixaxisReportIdEffects; 1260 report_size = sizeof(data); 1261 1262 // No offset with Sony sixaxis.sys driver 1263 SDL_memcpy(&data, effect, SDL_min(sizeof(data), (size_t)size)); 1264 1265 if (SDL_HIDAPI_SendRumble(device, data, report_size) != report_size) { 1266 return SDL_SetError("Couldn't send rumble packet"); 1267 } 1268 return true; 1269} 1270 1271static bool HIDAPI_DriverPS3SonySixaxis_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, bool enabled) 1272{ 1273 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 1274 1275 ctx->report_sensors = enabled; 1276 1277 return true; 1278} 1279 1280static void HIDAPI_DriverPS3SonySixaxis_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverPS3_Context *ctx, Uint8 *data, int size) 1281{ 1282 Sint16 axis; 1283 Uint64 timestamp = SDL_GetTicksNS(); 1284 1285 if (ctx->last_state[2] != data[2]) { 1286 Uint8 hat = 0; 1287 1288 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data[2] & 0x01) != 0)); 1289 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data[2] & 0x02) != 0)); 1290 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data[2] & 0x04) != 0)); 1291 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data[2] & 0x08) != 0)); 1292 1293 if (data[2] & 0x10) { 1294 hat |= SDL_HAT_UP; 1295 } 1296 if (data[2] & 0x20) { 1297 hat |= SDL_HAT_RIGHT; 1298 } 1299 if (data[2] & 0x40) { 1300 hat |= SDL_HAT_DOWN; 1301 } 1302 if (data[2] & 0x80) { 1303 hat |= SDL_HAT_LEFT; 1304 } 1305 SDL_SendJoystickHat(timestamp, joystick, 0, hat); 1306 } 1307 1308 if (ctx->last_state[3] != data[3]) { 1309 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data[3] & 0x04) != 0)); 1310 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data[3] & 0x08) != 0)); 1311 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, ((data[3] & 0x10) != 0)); 1312 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, ((data[3] & 0x20) != 0)); 1313 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, ((data[3] & 0x40) != 0)); 1314 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, ((data[3] & 0x80) != 0)); 1315 } 1316 1317 if (ctx->last_state[4] != data[4]) { 1318 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data[4] & 0x01) != 0)); 1319 } 1320 1321 axis = ((int)data[18] * 257) - 32768; 1322 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis); 1323 axis = ((int)data[19] * 257) - 32768; 1324 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis); 1325 axis = ((int)data[6] * 257) - 32768; 1326 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis); 1327 axis = ((int)data[7] * 257) - 32768; 1328 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis); 1329 axis = ((int)data[8] * 257) - 32768; 1330 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis); 1331 axis = ((int)data[9] * 257) - 32768; 1332 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis); 1333 1334 // Buttons are mapped as axes in the order they appear in the button enumeration 1335 if (ctx->has_analog_buttons) { 1336 static int button_axis_offsets[] = { 1337 24, // SDL_GAMEPAD_BUTTON_SOUTH 1338 23, // SDL_GAMEPAD_BUTTON_EAST 1339 25, // SDL_GAMEPAD_BUTTON_WEST 1340 22, // SDL_GAMEPAD_BUTTON_NORTH 1341 0, // SDL_GAMEPAD_BUTTON_BACK 1342 0, // SDL_GAMEPAD_BUTTON_GUIDE 1343 0, // SDL_GAMEPAD_BUTTON_START 1344 0, // SDL_GAMEPAD_BUTTON_LEFT_STICK 1345 0, // SDL_GAMEPAD_BUTTON_RIGHT_STICK 1346 20, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER 1347 21, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER 1348 14, // SDL_GAMEPAD_BUTTON_DPAD_UP 1349 16, // SDL_GAMEPAD_BUTTON_DPAD_DOWN 1350 17, // SDL_GAMEPAD_BUTTON_DPAD_LEFT 1351 15, // SDL_GAMEPAD_BUTTON_DPAD_RIGHT 1352 }; 1353 Uint8 i, axis_index = 6; 1354 1355 for (i = 0; i < SDL_arraysize(button_axis_offsets); ++i) { 1356 int offset = button_axis_offsets[i]; 1357 if (!offset) { 1358 // This button doesn't report as an axis 1359 continue; 1360 } 1361 1362 axis = ((int)data[offset] * 257) - 32768; 1363 SDL_SendJoystickAxis(timestamp, joystick, axis_index, axis); 1364 ++axis_index; 1365 } 1366 } 1367 1368 if (ctx->report_sensors) { 1369 float sensor_data[3]; 1370 1371 sensor_data[0] = HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[41], data[42])); 1372 sensor_data[1] = -HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[45], data[46])); 1373 sensor_data[2] = -HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[43], data[44])); 1374 SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, timestamp, sensor_data, SDL_arraysize(sensor_data)); 1375 } 1376 1377 SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state))); 1378} 1379 1380static bool HIDAPI_DriverPS3SonySixaxis_UpdateDevice(SDL_HIDAPI_Device *device) 1381{ 1382 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 1383 SDL_Joystick *joystick = NULL; 1384 Uint8 data[USB_PACKET_LENGTH]; 1385 int size; 1386 1387 if (device->num_joysticks > 0) { 1388 joystick = SDL_GetJoystickFromID(device->joysticks[0]); 1389 } else { 1390 return false; 1391 } 1392 1393 if (!joystick) { 1394 return false; 1395 } 1396 1397 // With sixaxis.sys driver we need to use hid_get_feature_report instead of hid_read 1398 size = ReadFeatureReport(device->dev, 0x0, data, sizeof(data)); 1399 if (size < 0) { 1400 SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, 1401 "HIDAPI_DriverPS3SonySixaxis_UpdateDevice(): Couldn't read feature report 0x00"); 1402 return false; 1403 } 1404 1405 switch (data[0]) { 1406 case k_EPS3SonySixaxisReportIdState: 1407 HIDAPI_DriverPS3SonySixaxis_HandleStatePacket(joystick, ctx, &data[1], size - 1); // report data starts in data[1] 1408 1409 // Wait for the first report to set the LED state after the controller stops blinking 1410 if (!ctx->effects_updated) { 1411 HIDAPI_DriverPS3_UpdateLEDsSonySixaxis(device); 1412 ctx->effects_updated = true; 1413 } 1414 1415 break; 1416 default: 1417#ifdef DEBUG_JOYSTICK 1418 SDL_Log("Unknown PS3 packet: 0x%.2x", data[0]); 1419#endif 1420 break; 1421 } 1422 1423 if (size < 0) { 1424 // Read error, device is disconnected 1425 HIDAPI_JoystickDisconnected(device, device->joysticks[0]); 1426 } 1427 return (size >= 0); 1428} 1429 1430static void HIDAPI_DriverPS3SonySixaxis_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 1431{ 1432 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 1433 1434 ctx->joystick = NULL; 1435} 1436 1437static void HIDAPI_DriverPS3SonySixaxis_FreeDevice(SDL_HIDAPI_Device *device) 1438{ 1439} 1440 1441static bool HIDAPI_DriverPS3_UpdateRumbleSonySixaxis(SDL_HIDAPI_Device *device) 1442{ 1443 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 1444 1445 Uint8 effects[] = { 1446 0x0, // Report Id 1447 k_EPS3SixaxisCommandSetMotors, // 2 = Set Motors 1448 0x00, 0x00, 0x00, // padding 1449 0xff, // Small Motor duration - 0xff is forever 1450 0x00, // Small Motor off/on (0 or 1) 1451 0xff, // Large Motor duration - 0xff is forever 1452 0x00 // Large Motor force (0 to 255) 1453 }; 1454 1455 effects[6] = ctx->rumble_right ? 1 : 0; // Small motor 1456 effects[8] = ctx->rumble_left; // Large motor 1457 1458 return HIDAPI_DriverPS3SonySixaxis_SendJoystickEffect(device, ctx->joystick, effects, sizeof(effects)); 1459} 1460 1461static bool HIDAPI_DriverPS3_UpdateLEDsSonySixaxis(SDL_HIDAPI_Device *device) 1462{ 1463 SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; 1464 1465 Uint8 effects[] = { 1466 0x0, // Report Id 1467 k_EPS3SixaxisCommandSetLEDs, // 1 = Set LEDs 1468 0x00, 0x00, 0x00, // padding 1469 0x00, 0x00, 0x00, 0x00 // LED #4, LED #3, LED #2, LED #1 (0 = Off, 1 = On, 2 = Flashing) 1470 }; 1471 1472 // Turn on LED light on DS3 Controller for relevant player (player_index 0 lights up LED #1, player_index 1 lights up LED #2, etc) 1473 if (ctx->player_index < 4) { 1474 effects[8 - ctx->player_index] = 1; 1475 } 1476 1477 return HIDAPI_DriverPS3SonySixaxis_SendJoystickEffect(device, ctx->joystick, effects, sizeof(effects)); 1478} 1479 1480SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS3SonySixaxis = { 1481 SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER, 1482 true, 1483 HIDAPI_DriverPS3SonySixaxis_RegisterHints, 1484 HIDAPI_DriverPS3SonySixaxis_UnregisterHints, 1485 HIDAPI_DriverPS3SonySixaxis_IsEnabled, 1486 HIDAPI_DriverPS3SonySixaxis_IsSupportedDevice, 1487 HIDAPI_DriverPS3SonySixaxis_InitDevice, 1488 HIDAPI_DriverPS3SonySixaxis_GetDevicePlayerIndex, 1489 HIDAPI_DriverPS3SonySixaxis_SetDevicePlayerIndex, 1490 HIDAPI_DriverPS3SonySixaxis_UpdateDevice, 1491 HIDAPI_DriverPS3SonySixaxis_OpenJoystick, 1492 HIDAPI_DriverPS3SonySixaxis_RumbleJoystick, 1493 HIDAPI_DriverPS3SonySixaxis_RumbleJoystickTriggers, 1494 HIDAPI_DriverPS3SonySixaxis_GetJoystickCapabilities, 1495 HIDAPI_DriverPS3SonySixaxis_SetJoystickLED, 1496 HIDAPI_DriverPS3SonySixaxis_SendJoystickEffect, 1497 HIDAPI_DriverPS3SonySixaxis_SetJoystickSensorsEnabled, 1498 HIDAPI_DriverPS3SonySixaxis_CloseJoystick, 1499 HIDAPI_DriverPS3SonySixaxis_FreeDevice, 1500}; 1501 1502#endif // SDL_JOYSTICK_HIDAPI_PS3 1503 1504#endif // SDL_JOYSTICK_HIDAPI 1505
[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.