SDL_hidapi_ps4.c (29017B)
1 /* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org> 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 /* This driver supports both simplified reports and the extended input reports enabled by Steam. 22 Code and logic contributed by Valve Corporation under the SDL zlib license. 23 */ 24 #include "../../SDL_internal.h" 25 26 #ifdef SDL_JOYSTICK_HIDAPI 27 28 #include "SDL_hints.h" 29 #include "SDL_events.h" 30 #include "SDL_timer.h" 31 #include "SDL_joystick.h" 32 #include "SDL_gamecontroller.h" 33 #include "../SDL_sysjoystick.h" 34 #include "SDL_hidapijoystick_c.h" 35 #include "SDL_hidapi_rumble.h" 36 37 38 #ifdef SDL_JOYSTICK_HIDAPI_PS4 39 40 /* Define this if you want to log all packets from the controller */ 41 /*#define DEBUG_PS4_PROTOCOL*/ 42 43 /* Define this if you want to log calibration data */ 44 /*#define DEBUG_PS4_CALIBRATION*/ 45 46 #define GYRO_RES_PER_DEGREE 1024.0f 47 #define ACCEL_RES_PER_G 8192.0f 48 49 #define LOAD16(A, B) (Sint16)((Uint16)(A) | (((Uint16)(B)) << 8)) 50 51 typedef enum 52 { 53 k_EPS4ReportIdUsbState = 1, 54 k_EPS4ReportIdUsbEffects = 5, 55 k_EPS4ReportIdBluetoothState1 = 17, 56 k_EPS4ReportIdBluetoothState2 = 18, 57 k_EPS4ReportIdBluetoothState3 = 19, 58 k_EPS4ReportIdBluetoothState4 = 20, 59 k_EPS4ReportIdBluetoothState5 = 21, 60 k_EPS4ReportIdBluetoothState6 = 22, 61 k_EPS4ReportIdBluetoothState7 = 23, 62 k_EPS4ReportIdBluetoothState8 = 24, 63 k_EPS4ReportIdBluetoothState9 = 25, 64 k_EPS4ReportIdBluetoothEffects = 17, 65 k_EPS4ReportIdDisconnectMessage = 226, 66 } EPS4ReportId; 67 68 typedef enum 69 { 70 k_ePS4FeatureReportIdGyroCalibration_USB = 0x02, 71 k_ePS4FeatureReportIdGyroCalibration_BT = 0x05, 72 k_ePS4FeatureReportIdSerialNumber = 0x12, 73 } EPS4FeatureReportID; 74 75 typedef struct 76 { 77 Uint8 ucLeftJoystickX; 78 Uint8 ucLeftJoystickY; 79 Uint8 ucRightJoystickX; 80 Uint8 ucRightJoystickY; 81 Uint8 rgucButtonsHatAndCounter[ 3 ]; 82 Uint8 ucTriggerLeft; 83 Uint8 ucTriggerRight; 84 Uint8 _rgucPad0[ 3 ]; 85 Uint8 rgucGyroX[2]; 86 Uint8 rgucGyroY[2]; 87 Uint8 rgucGyroZ[2]; 88 Uint8 rgucAccelX[2]; 89 Uint8 rgucAccelY[2]; 90 Uint8 rgucAccelZ[2]; 91 Uint8 _rgucPad1[ 5 ]; 92 Uint8 ucBatteryLevel; 93 Uint8 _rgucPad2[ 4 ]; 94 Uint8 ucTouchpadCounter1; 95 Uint8 rgucTouchpadData1[ 3 ]; 96 Uint8 ucTouchpadCounter2; 97 Uint8 rgucTouchpadData2[ 3 ]; 98 } PS4StatePacket_t; 99 100 typedef struct 101 { 102 Uint8 ucRumbleRight; 103 Uint8 ucRumbleLeft; 104 Uint8 ucLedRed; 105 Uint8 ucLedGreen; 106 Uint8 ucLedBlue; 107 Uint8 ucLedDelayOn; 108 Uint8 ucLedDelayOff; 109 Uint8 _rgucPad0[ 8 ]; 110 Uint8 ucVolumeLeft; 111 Uint8 ucVolumeRight; 112 Uint8 ucVolumeMic; 113 Uint8 ucVolumeSpeaker; 114 } DS4EffectsState_t; 115 116 typedef struct { 117 Sint16 bias; 118 float sensitivity; 119 } IMUCalibrationData; 120 121 typedef struct { 122 SDL_bool is_dongle; 123 SDL_bool is_bluetooth; 124 SDL_bool official_controller; 125 SDL_bool audio_supported; 126 SDL_bool effects_supported; 127 SDL_bool report_sensors; 128 SDL_bool hardware_calibration; 129 IMUCalibrationData calibration[6]; 130 int player_index; 131 Uint8 rumble_left; 132 Uint8 rumble_right; 133 SDL_bool color_set; 134 Uint8 led_red; 135 Uint8 led_green; 136 Uint8 led_blue; 137 Uint8 volume; 138 Uint32 last_volume_check; 139 PS4StatePacket_t last_state; 140 } SDL_DriverPS4_Context; 141 142 143 static SDL_bool 144 HIDAPI_DriverPS4_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) 145 { 146 return (type == SDL_CONTROLLER_TYPE_PS4) ? SDL_TRUE : SDL_FALSE; 147 } 148 149 static const char * 150 HIDAPI_DriverPS4_GetDeviceName(Uint16 vendor_id, Uint16 product_id) 151 { 152 if (vendor_id == USB_VENDOR_SONY) { 153 return "PS4 Controller"; 154 } 155 return NULL; 156 } 157 158 static int ReadFeatureReport(hid_device *dev, Uint8 report_id, Uint8 *report, size_t length) 159 { 160 SDL_memset(report, 0, length); 161 report[0] = report_id; 162 return hid_get_feature_report(dev, report, length); 163 } 164 165 static SDL_bool HIDAPI_DriverPS4_CanRumble(Uint16 vendor_id, Uint16 product_id) 166 { 167 /* The Razer Panthera fight stick hangs when trying to rumble */ 168 if (vendor_id == USB_VENDOR_RAZER && 169 (product_id == USB_PRODUCT_RAZER_PANTHERA || product_id == USB_PRODUCT_RAZER_PANTHERA_EVO)) { 170 return SDL_FALSE; 171 } 172 return SDL_TRUE; 173 } 174 175 static void 176 SetLedsForPlayerIndex(DS4EffectsState_t *effects, int player_index) 177 { 178 /* This list is the same as what hid-sony.c uses in the Linux kernel. 179 The first 4 values correspond to what the PS4 assigns. 180 */ 181 static const Uint8 colors[7][3] = { 182 { 0x00, 0x00, 0x40 }, /* Blue */ 183 { 0x40, 0x00, 0x00 }, /* Red */ 184 { 0x00, 0x40, 0x00 }, /* Green */ 185 { 0x20, 0x00, 0x20 }, /* Pink */ 186 { 0x02, 0x01, 0x00 }, /* Orange */ 187 { 0x00, 0x01, 0x01 }, /* Teal */ 188 { 0x01, 0x01, 0x01 } /* White */ 189 }; 190 191 if (player_index >= 0) { 192 player_index %= SDL_arraysize(colors); 193 } else { 194 player_index = 0; 195 } 196 197 effects->ucLedRed = colors[player_index][0]; 198 effects->ucLedGreen = colors[player_index][1]; 199 effects->ucLedBlue = colors[player_index][2]; 200 } 201 202 static SDL_bool 203 HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device) 204 { 205 return HIDAPI_JoystickConnected(device, NULL); 206 } 207 208 static int 209 HIDAPI_DriverPS4_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) 210 { 211 return -1; 212 } 213 214 static void 215 HIDAPI_DriverPS4_LoadCalibrationData(SDL_HIDAPI_Device *device) 216 { 217 SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context; 218 int i, tries, size; 219 SDL_bool have_data = SDL_FALSE; 220 Uint8 data[USB_PACKET_LENGTH]; 221 222 if (!ctx->official_controller) { 223 #ifdef DEBUG_PS4_CALIBRATION 224 SDL_Log("Not an official controller, ignoring calibration\n"); 225 #endif 226 return; 227 } 228 229 for( tries = 0; tries < 5; ++tries ) { 230 /* For Bluetooth controllers, this report switches them into advanced report mode */ 231 size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdGyroCalibration_USB, data, sizeof(data)); 232 if (size < 35) { 233 #ifdef DEBUG_PS4_CALIBRATION 234 SDL_Log("Short read of calibration data: %d, ignoring calibration\n", size); 235 #endif 236 return; 237 } 238 239 if (ctx->is_bluetooth) { 240 size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdGyroCalibration_BT, data, sizeof(data)); 241 if (size < 35) { 242 #ifdef DEBUG_PS4_CALIBRATION 243 SDL_Log("Short read of calibration data: %d, ignoring calibration\n", size); 244 #endif 245 return; 246 } 247 } 248 249 /* In some cases this report returns all zeros. Usually immediately after connection with the PS4 Dongle */ 250 for (i = 0; i < size; ++i) { 251 if (data[i]) { 252 have_data = SDL_TRUE; 253 break; 254 } 255 } 256 if (have_data) { 257 break; 258 } 259 260 SDL_Delay(2); 261 } 262 263 if (have_data) { 264 Sint16 sGyroPitchBias, sGyroYawBias, sGyroRollBias; 265 Sint16 sGyroPitchPlus, sGyroPitchMinus; 266 Sint16 sGyroYawPlus, sGyroYawMinus; 267 Sint16 sGyroRollPlus, sGyroRollMinus; 268 Sint16 sGyroSpeedPlus, sGyroSpeedMinus; 269 270 Sint16 sAccXPlus, sAccXMinus; 271 Sint16 sAccYPlus, sAccYMinus; 272 Sint16 sAccZPlus, sAccZMinus; 273 274 float flNumerator; 275 Sint16 sRange2g; 276 277 #ifdef DEBUG_PS4_CALIBRATION 278 HIDAPI_DumpPacket("PS4 calibration packet: size = %d", data, size); 279 #endif 280 281 sGyroPitchBias = LOAD16(data[1], data[2]); 282 sGyroYawBias = LOAD16(data[3], data[4]); 283 sGyroRollBias = LOAD16(data[5], data[6]); 284 285 if (ctx->is_bluetooth || ctx->is_dongle) { 286 sGyroPitchPlus = LOAD16(data[7], data[8]); 287 sGyroYawPlus = LOAD16(data[9], data[10]); 288 sGyroRollPlus = LOAD16(data[11], data[12]); 289 sGyroPitchMinus = LOAD16(data[13], data[14]); 290 sGyroYawMinus = LOAD16(data[15], data[16]); 291 sGyroRollMinus = LOAD16(data[17], data[18]); 292 } else { 293 sGyroPitchPlus = LOAD16(data[7], data[8]); 294 sGyroPitchMinus = LOAD16(data[9], data[10]); 295 sGyroYawPlus = LOAD16(data[11], data[12]); 296 sGyroYawMinus = LOAD16(data[13], data[14]); 297 sGyroRollPlus = LOAD16(data[15], data[16]); 298 sGyroRollMinus = LOAD16(data[17], data[18]); 299 } 300 301 sGyroSpeedPlus = LOAD16(data[19], data[20]); 302 sGyroSpeedMinus = LOAD16(data[21], data[22]); 303 304 sAccXPlus = LOAD16(data[23], data[24]); 305 sAccXMinus = LOAD16(data[25], data[26]); 306 sAccYPlus = LOAD16(data[27], data[28]); 307 sAccYMinus = LOAD16(data[29], data[30]); 308 sAccZPlus = LOAD16(data[31], data[32]); 309 sAccZMinus = LOAD16(data[33], data[34]); 310 311 flNumerator = (sGyroSpeedPlus + sGyroSpeedMinus) * GYRO_RES_PER_DEGREE; 312 ctx->calibration[0].bias = sGyroPitchBias; 313 ctx->calibration[0].sensitivity = flNumerator / (sGyroPitchPlus - sGyroPitchMinus); 314 315 ctx->calibration[1].bias = sGyroYawBias; 316 ctx->calibration[1].sensitivity = flNumerator / (sGyroYawPlus - sGyroYawMinus); 317 318 ctx->calibration[2].bias = sGyroRollBias; 319 ctx->calibration[2].sensitivity = flNumerator / (sGyroRollPlus - sGyroRollMinus); 320 321 sRange2g = sAccXPlus - sAccXMinus; 322 ctx->calibration[3].bias = sAccXPlus - sRange2g / 2; 323 ctx->calibration[3].sensitivity = 2.0f * ACCEL_RES_PER_G / (float)sRange2g; 324 325 sRange2g = sAccYPlus - sAccYMinus; 326 ctx->calibration[4].bias = sAccYPlus - sRange2g / 2; 327 ctx->calibration[4].sensitivity = 2.0f * ACCEL_RES_PER_G / (float)sRange2g; 328 329 sRange2g = sAccZPlus - sAccZMinus; 330 ctx->calibration[5].bias = sAccZPlus - sRange2g / 2; 331 ctx->calibration[5].sensitivity = 2.0f * ACCEL_RES_PER_G / (float)sRange2g; 332 333 ctx->hardware_calibration = SDL_TRUE; 334 for (i = 0; i < 6; ++i) { 335 float divisor = (i < 3 ? 64.0f : 1.0f); 336 #ifdef DEBUG_PS4_CALIBRATION 337 SDL_Log("calibration[%d] bias = %d, sensitivity = %f\n", i, ctx->calibration[i].bias, ctx->calibration[i].sensitivity); 338 #endif 339 /* Some controllers have a bad calibration */ 340 if ((SDL_abs(ctx->calibration[i].bias) > 1024) || (SDL_fabs(1.0f - ctx->calibration[i].sensitivity / divisor) > 0.5f)) { 341 #ifdef DEBUG_PS4_CALIBRATION 342 SDL_Log("invalid calibration, ignoring\n"); 343 #endif 344 ctx->hardware_calibration = SDL_FALSE; 345 } 346 } 347 } else { 348 #ifdef DEBUG_PS4_CALIBRATION 349 SDL_Log("Calibration data not available\n"); 350 #endif 351 } 352 } 353 354 static float 355 HIDAPI_DriverPS4_ApplyCalibrationData(SDL_DriverPS4_Context *ctx, int index, Sint16 value) 356 { 357 float result; 358 359 if (ctx->hardware_calibration) { 360 IMUCalibrationData *calibration = &ctx->calibration[index]; 361 362 result = (value - calibration->bias) * calibration->sensitivity; 363 } else if (index < 3) { 364 result = value * 64.f; 365 } else { 366 result = value; 367 } 368 369 /* Convert the raw data to the units expected by SDL */ 370 if (index < 3) { 371 result = (result / GYRO_RES_PER_DEGREE) * (float)M_PI / 180.0f; 372 } else { 373 result = (result / ACCEL_RES_PER_G) * SDL_STANDARD_GRAVITY; 374 } 375 return result; 376 } 377 378 static int 379 HIDAPI_DriverPS4_UpdateEffects(SDL_HIDAPI_Device *device) 380 { 381 SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context; 382 DS4EffectsState_t *effects; 383 Uint8 data[78]; 384 int report_size, offset; 385 386 if (!ctx->effects_supported) { 387 return SDL_Unsupported(); 388 } 389 390 SDL_zero(data); 391 392 if (ctx->is_bluetooth) { 393 data[0] = k_EPS4ReportIdBluetoothEffects; 394 data[1] = 0xC0 | 0x04; /* Magic value HID + CRC, also sets interval to 4ms for samples */ 395 data[3] = 0x03; /* 0x1 is rumble, 0x2 is lightbar, 0x4 is the blink interval */ 396 397 report_size = 78; 398 offset = 6; 399 } else { 400 data[0] = k_EPS4ReportIdUsbEffects; 401 data[1] = 0x07; /* Magic value */ 402 403 report_size = 32; 404 offset = 4; 405 } 406 effects = (DS4EffectsState_t *)&data[offset]; 407 408 effects->ucRumbleLeft = ctx->rumble_left; 409 effects->ucRumbleRight = ctx->rumble_right; 410 411 /* Populate the LED state with the appropriate color from our lookup table */ 412 if (ctx->color_set) { 413 effects->ucLedRed = ctx->led_red; 414 effects->ucLedGreen = ctx->led_green; 415 effects->ucLedBlue = ctx->led_blue; 416 } else { 417 SetLedsForPlayerIndex(effects, ctx->player_index); 418 } 419 420 if (ctx->is_bluetooth) { 421 /* Bluetooth reports need a CRC at the end of the packet (at least on Linux) */ 422 Uint8 ubHdr = 0xA2; /* hidp header is part of the CRC calculation */ 423 Uint32 unCRC; 424 unCRC = SDL_crc32(0, &ubHdr, 1); 425 unCRC = SDL_crc32(unCRC, data, (size_t)(report_size - sizeof(unCRC))); 426 SDL_memcpy(&data[report_size - sizeof(unCRC)], &unCRC, sizeof(unCRC)); 427 } 428 429 if (SDL_HIDAPI_SendRumble(device, data, report_size) != report_size) { 430 return SDL_SetError("Couldn't send rumble packet"); 431 } 432 return 0; 433 } 434 435 static void 436 HIDAPI_DriverPS4_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) 437 { 438 SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context; 439 440 if (!ctx) { 441 return; 442 } 443 444 ctx->player_index = player_index; 445 446 /* This will set the new LED state based on the new player index */ 447 HIDAPI_DriverPS4_UpdateEffects(device); 448 } 449 450 static SDL_bool 451 HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 452 { 453 SDL_DriverPS4_Context *ctx; 454 455 ctx = (SDL_DriverPS4_Context *)SDL_calloc(1, sizeof(*ctx)); 456 if (!ctx) { 457 SDL_OutOfMemory(); 458 return SDL_FALSE; 459 } 460 461 device->dev = hid_open_path(device->path, 0); 462 if (!device->dev) { 463 SDL_free(ctx); 464 SDL_SetError("Couldn't open %s", device->path); 465 return SDL_FALSE; 466 } 467 device->context = ctx; 468 469 /* Check for type of connection */ 470 ctx->is_dongle = (device->vendor_id == USB_VENDOR_SONY && device->product_id == USB_PRODUCT_SONY_DS4_DONGLE); 471 if (ctx->is_dongle) { 472 ctx->is_bluetooth = SDL_FALSE; 473 ctx->official_controller = SDL_TRUE; 474 } else if (device->vendor_id == USB_VENDOR_SONY) { 475 Uint8 data[USB_PACKET_LENGTH]; 476 int size; 477 478 /* This will fail if we're on Bluetooth */ 479 size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdSerialNumber, data, sizeof(data)); 480 if (size >= 7) { 481 char serial[18]; 482 483 SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", 484 data[6], data[5], data[4], data[3], data[2], data[1]); 485 joystick->serial = SDL_strdup(serial); 486 ctx->is_bluetooth = SDL_FALSE; 487 } else { 488 ctx->is_bluetooth = SDL_TRUE; 489 } 490 ctx->official_controller = SDL_TRUE; 491 } else { 492 /* Third party controllers appear to all be wired */ 493 ctx->is_bluetooth = SDL_FALSE; 494 } 495 #ifdef DEBUG_PS4 496 SDL_Log("PS4 dongle = %s, bluetooth = %s\n", ctx->is_dongle ? "TRUE" : "FALSE", ctx->is_bluetooth ? "TRUE" : "FALSE"); 497 #endif 498 499 /* Check to see if audio is supported */ 500 if (device->vendor_id == USB_VENDOR_SONY && 501 (device->product_id == USB_PRODUCT_SONY_DS4_SLIM || device->product_id == USB_PRODUCT_SONY_DS4_DONGLE)) { 502 ctx->audio_supported = SDL_TRUE; 503 } 504 505 if (HIDAPI_DriverPS4_CanRumble(device->vendor_id, device->product_id)) { 506 if (ctx->is_bluetooth) { 507 ctx->effects_supported = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, SDL_FALSE); 508 } else { 509 ctx->effects_supported = SDL_TRUE; 510 } 511 } 512 513 /* Initialize player index (needed for setting LEDs) */ 514 ctx->player_index = SDL_JoystickGetPlayerIndex(joystick); 515 516 /* Initialize LED and effect state */ 517 HIDAPI_DriverPS4_UpdateEffects(device); 518 519 /* Initialize the joystick capabilities */ 520 joystick->nbuttons = 16; 521 joystick->naxes = SDL_CONTROLLER_AXIS_MAX; 522 joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED; 523 524 SDL_PrivateJoystickAddTouchpad(joystick, 2); 525 SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO); 526 SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL); 527 528 return SDL_TRUE; 529 } 530 531 static int 532 HIDAPI_DriverPS4_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) 533 { 534 SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context; 535 536 ctx->rumble_left = (low_frequency_rumble >> 8); 537 ctx->rumble_right = (high_frequency_rumble >> 8); 538 539 return HIDAPI_DriverPS4_UpdateEffects(device); 540 } 541 542 static int 543 HIDAPI_DriverPS4_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble) 544 { 545 return SDL_Unsupported(); 546 } 547 548 static SDL_bool 549 HIDAPI_DriverPS4_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 550 { 551 return SDL_TRUE; 552 } 553 554 static int 555 HIDAPI_DriverPS4_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) 556 { 557 SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context; 558 559 ctx->color_set = SDL_TRUE; 560 ctx->led_red = red; 561 ctx->led_green = green; 562 ctx->led_blue = blue; 563 564 return HIDAPI_DriverPS4_UpdateEffects(device); 565 } 566 567 static int 568 HIDAPI_DriverPS4_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled) 569 { 570 SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context; 571 572 if (enabled) { 573 HIDAPI_DriverPS4_LoadCalibrationData(device); 574 } 575 ctx->report_sensors = enabled; 576 577 return 0; 578 } 579 580 static void 581 HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS4_Context *ctx, PS4StatePacket_t *packet) 582 { 583 static const float TOUCHPAD_SCALEX = 1.0f / 1920; 584 static const float TOUCHPAD_SCALEY = 1.0f / 920; /* This is noted as being 944 resolution, but 920 feels better */ 585 Sint16 axis; 586 Uint8 touchpad_state; 587 int touchpad_x, touchpad_y; 588 589 if (ctx->last_state.rgucButtonsHatAndCounter[0] != packet->rgucButtonsHatAndCounter[0]) { 590 { 591 Uint8 data = (packet->rgucButtonsHatAndCounter[0] >> 4); 592 593 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); 594 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); 595 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); 596 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); 597 } 598 { 599 Uint8 data = (packet->rgucButtonsHatAndCounter[0] & 0x0F); 600 SDL_bool dpad_up = SDL_FALSE; 601 SDL_bool dpad_down = SDL_FALSE; 602 SDL_bool dpad_left = SDL_FALSE; 603 SDL_bool dpad_right = SDL_FALSE; 604 605 switch (data) { 606 case 0: 607 dpad_up = SDL_TRUE; 608 break; 609 case 1: 610 dpad_up = SDL_TRUE; 611 dpad_right = SDL_TRUE; 612 break; 613 case 2: 614 dpad_right = SDL_TRUE; 615 break; 616 case 3: 617 dpad_right = SDL_TRUE; 618 dpad_down = SDL_TRUE; 619 break; 620 case 4: 621 dpad_down = SDL_TRUE; 622 break; 623 case 5: 624 dpad_left = SDL_TRUE; 625 dpad_down = SDL_TRUE; 626 break; 627 case 6: 628 dpad_left = SDL_TRUE; 629 break; 630 case 7: 631 dpad_up = SDL_TRUE; 632 dpad_left = SDL_TRUE; 633 break; 634 default: 635 break; 636 } 637 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, dpad_down); 638 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, dpad_up); 639 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, dpad_right); 640 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left); 641 } 642 } 643 644 if (ctx->last_state.rgucButtonsHatAndCounter[1] != packet->rgucButtonsHatAndCounter[1]) { 645 Uint8 data = packet->rgucButtonsHatAndCounter[1]; 646 647 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); 648 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); 649 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED); 650 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); 651 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED); 652 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED); 653 } 654 655 /* Some fightsticks, ex: Victrix FS Pro will only this these digital trigger bits and not the analog values so this needs to run whenever the 656 trigger is evaluated 657 */ 658 if ((packet->rgucButtonsHatAndCounter[1] & 0x0C) != 0) { 659 Uint8 data = packet->rgucButtonsHatAndCounter[1]; 660 packet->ucTriggerLeft = (data & 0x04) && packet->ucTriggerLeft == 0 ? 255 : packet->ucTriggerLeft; 661 packet->ucTriggerRight = (data & 0x08) && packet->ucTriggerRight == 0 ? 255 : packet->ucTriggerRight; 662 } 663 664 if (ctx->last_state.rgucButtonsHatAndCounter[2] != packet->rgucButtonsHatAndCounter[2]) { 665 Uint8 data = (packet->rgucButtonsHatAndCounter[2] & 0x03); 666 667 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); 668 SDL_PrivateJoystickButton(joystick, 15, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); 669 } 670 671 axis = ((int)packet->ucTriggerLeft * 257) - 32768; 672 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis); 673 axis = ((int)packet->ucTriggerRight * 257) - 32768; 674 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis); 675 axis = ((int)packet->ucLeftJoystickX * 257) - 32768; 676 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis); 677 axis = ((int)packet->ucLeftJoystickY * 257) - 32768; 678 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis); 679 axis = ((int)packet->ucRightJoystickX * 257) - 32768; 680 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis); 681 axis = ((int)packet->ucRightJoystickY * 257) - 32768; 682 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis); 683 684 if (packet->ucBatteryLevel & 0x10) { 685 joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED; 686 } else { 687 /* Battery level ranges from 0 to 10 */ 688 int level = (packet->ucBatteryLevel & 0xF); 689 if (level == 0) { 690 joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY; 691 } else if (level <= 2) { 692 joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW; 693 } else if (level <= 7) { 694 joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM; 695 } else { 696 joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL; 697 } 698 } 699 700 touchpad_state = ((packet->ucTouchpadCounter1 & 0x80) == 0) ? SDL_PRESSED : SDL_RELEASED; 701 touchpad_x = packet->rgucTouchpadData1[0] | (((int)packet->rgucTouchpadData1[1] & 0x0F) << 8); 702 touchpad_y = (packet->rgucTouchpadData1[1] >> 4) | ((int)packet->rgucTouchpadData1[2] << 4); 703 SDL_PrivateJoystickTouchpad(joystick, 0, 0, touchpad_state, touchpad_x * TOUCHPAD_SCALEX, touchpad_y * TOUCHPAD_SCALEY, touchpad_state ? 1.0f : 0.0f); 704 705 touchpad_state = ((packet->ucTouchpadCounter2 & 0x80) == 0) ? SDL_PRESSED : SDL_RELEASED; 706 touchpad_x = packet->rgucTouchpadData2[0] | (((int)packet->rgucTouchpadData2[1] & 0x0F) << 8); 707 touchpad_y = (packet->rgucTouchpadData2[1] >> 4) | ((int)packet->rgucTouchpadData2[2] << 4); 708 SDL_PrivateJoystickTouchpad(joystick, 0, 1, touchpad_state, touchpad_x * TOUCHPAD_SCALEX, touchpad_y * TOUCHPAD_SCALEY, touchpad_state ? 1.0f : 0.0f); 709 710 if (ctx->report_sensors) { 711 float data[3]; 712 713 data[0] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 0, LOAD16(packet->rgucGyroX[0], packet->rgucGyroX[1])); 714 data[1] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 1, LOAD16(packet->rgucGyroY[0], packet->rgucGyroY[1])); 715 data[2] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 2, LOAD16(packet->rgucGyroZ[0], packet->rgucGyroZ[1])); 716 SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, data, 3); 717 718 data[0] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 3, LOAD16(packet->rgucAccelX[0], packet->rgucAccelX[1])); 719 data[1] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 4, LOAD16(packet->rgucAccelY[0], packet->rgucAccelY[1])); 720 data[2] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 5, LOAD16(packet->rgucAccelZ[0], packet->rgucAccelZ[1])); 721 SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, data, 3); 722 } 723 724 SDL_memcpy(&ctx->last_state, packet, sizeof(ctx->last_state)); 725 } 726 727 static SDL_bool 728 HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device) 729 { 730 SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context; 731 SDL_Joystick *joystick = NULL; 732 Uint8 data[USB_PACKET_LENGTH]; 733 int size; 734 735 if (device->num_joysticks > 0) { 736 joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); 737 } 738 if (!joystick) { 739 return SDL_FALSE; 740 } 741 742 while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) { 743 #ifdef DEBUG_PS4_PROTOCOL 744 HIDAPI_DumpPacket("PS4 packet: size = %d", data, size); 745 #endif 746 switch (data[0]) { 747 case k_EPS4ReportIdUsbState: 748 HIDAPI_DriverPS4_HandleStatePacket(joystick, device->dev, ctx, (PS4StatePacket_t *)&data[1]); 749 break; 750 case k_EPS4ReportIdBluetoothState1: 751 case k_EPS4ReportIdBluetoothState2: 752 case k_EPS4ReportIdBluetoothState3: 753 case k_EPS4ReportIdBluetoothState4: 754 case k_EPS4ReportIdBluetoothState5: 755 case k_EPS4ReportIdBluetoothState6: 756 case k_EPS4ReportIdBluetoothState7: 757 case k_EPS4ReportIdBluetoothState8: 758 case k_EPS4ReportIdBluetoothState9: 759 /* Bluetooth state packets have two additional bytes at the beginning, the first notes if HID is present */ 760 if (data[1] & 0x80) { 761 HIDAPI_DriverPS4_HandleStatePacket(joystick, device->dev, ctx, (PS4StatePacket_t*)&data[3]); 762 } 763 break; 764 default: 765 #ifdef DEBUG_JOYSTICK 766 SDL_Log("Unknown PS4 packet: 0x%.2x\n", data[0]); 767 #endif 768 break; 769 } 770 } 771 772 if (size < 0) { 773 /* Read error, device is disconnected */ 774 HIDAPI_JoystickDisconnected(device, joystick->instance_id); 775 } 776 return (size >= 0); 777 } 778 779 static void 780 HIDAPI_DriverPS4_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 781 { 782 hid_close(device->dev); 783 device->dev = NULL; 784 785 SDL_free(device->context); 786 device->context = NULL; 787 } 788 789 static void 790 HIDAPI_DriverPS4_FreeDevice(SDL_HIDAPI_Device *device) 791 { 792 } 793 794 SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4 = 795 { 796 SDL_HINT_JOYSTICK_HIDAPI_PS4, 797 SDL_TRUE, 798 HIDAPI_DriverPS4_IsSupportedDevice, 799 HIDAPI_DriverPS4_GetDeviceName, 800 HIDAPI_DriverPS4_InitDevice, 801 HIDAPI_DriverPS4_GetDevicePlayerIndex, 802 HIDAPI_DriverPS4_SetDevicePlayerIndex, 803 HIDAPI_DriverPS4_UpdateDevice, 804 HIDAPI_DriverPS4_OpenJoystick, 805 HIDAPI_DriverPS4_RumbleJoystick, 806 HIDAPI_DriverPS4_RumbleJoystickTriggers, 807 HIDAPI_DriverPS4_HasJoystickLED, 808 HIDAPI_DriverPS4_SetJoystickLED, 809 HIDAPI_DriverPS4_SetJoystickSensorsEnabled, 810 HIDAPI_DriverPS4_CloseJoystick, 811 HIDAPI_DriverPS4_FreeDevice, 812 }; 813 814 #endif /* SDL_JOYSTICK_HIDAPI_PS4 */ 815 816 #endif /* SDL_JOYSTICK_HIDAPI */ 817 818 /* vi: set ts=4 sw=4 expandtab: */