24 #include "../../SDL_internal.h"
26 #ifdef SDL_JOYSTICK_HIDAPI
34 #include "../SDL_sysjoystick.h"
38 #ifdef SDL_JOYSTICK_HIDAPI_PS4
40 #define SONY_USB_VID 0x054C
41 #define SONY_DS4_PID 0x05C4
42 #define SONY_DS4_DONGLE_PID 0x0BA0
43 #define SONY_DS4_SLIM_PID 0x09CC
45 #define RAZER_USB_VID 0x1532
46 #define RAZER_PANTHERA_PID 0X0401
47 #define RAZER_PANTHERA_EVO_PID 0x1008
49 #define USB_PACKET_LENGTH 64
51 #define VOLUME_CHECK_INTERVAL_MS (10 * 1000)
55 k_EPS4ReportIdUsbState = 1,
56 k_EPS4ReportIdUsbEffects = 5,
57 k_EPS4ReportIdBluetoothState = 17,
58 k_EPS4ReportIdBluetoothEffects = 17,
59 k_EPS4ReportIdDisconnectMessage = 226,
64 k_ePS4FeatureReportIdGyroCalibration_USB = 0x02,
65 k_ePS4FeatureReportIdGyroCalibration_BT = 0x05,
66 k_ePS4FeatureReportIdSerialNumber = 0x12,
67 } EPS4FeatureReportID;
71 Uint8 ucLeftJoystickX;
72 Uint8 ucLeftJoystickY;
73 Uint8 ucRightJoystickX;
74 Uint8 ucRightJoystickY;
75 Uint8 rgucButtonsHatAndCounter[ 3 ];
88 Uint8 ucTrackpadCounter1;
89 Uint8 rgucTrackpadData1[ 3 ];
90 Uint8 ucTrackpadCounter2;
91 Uint8 rgucTrackpadData2[ 3 ];
103 Uint8 _rgucPad0[ 8 ];
107 Uint8 ucVolumeSpeaker;
118 PS4StatePacket_t last_state;
119 } SDL_DriverPS4_Context;
128 for(
i = 0;
i < 8; ++
i) {
129 r = (
r & 1? 0: (
Uint32)0xEDB88320L) ^
r >> 1;
131 return r ^ (
Uint32)0xFF000000L;
143 #if defined(__WIN32__) && defined(HAVE_ENDPOINTVOLUME_H)
144 #include "../../core/windows/SDL_windows.h"
147 #define NTDDI_VISTA 0x06000000
149 #ifndef _WIN32_WINNT_VISTA
150 #define _WIN32_WINNT_VISTA 0x0600
155 #define NTDDI_VERSION NTDDI_VISTA
157 #define _WIN32_WINNT _WIN32_WINNT_VISTA
159 #include <mmdeviceapi.h>
160 #include <audioclient.h>
161 #include <endpointvolume.h>
164 #define DEFINE_GUID(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) static const GUID n = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
165 DEFINE_GUID(SDL_CLSID_MMDeviceEnumerator, 0xBCDE0395, 0xE52F, 0x467C, 0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E);
166 DEFINE_GUID(SDL_IID_IMMDeviceEnumerator, 0xA95664D2, 0x9614, 0x4F35, 0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6);
167 DEFINE_GUID(SDL_IID_IAudioEndpointVolume, 0x5CDF2C82, 0x841E, 0x4546, 0x97, 0x22, 0x0C, 0xF7, 0x40, 0x78, 0x22, 0x9A);
172 static float GetSystemVolume(
void)
174 float volume = -1.0f;
176 #if defined(__WIN32__) && defined(HAVE_ENDPOINTVOLUME_H)
179 IMMDeviceEnumerator *pEnumerator;
182 hr = CoCreateInstance(&SDL_CLSID_MMDeviceEnumerator,
NULL, CLSCTX_ALL, &SDL_IID_IMMDeviceEnumerator, (LPVOID*)&pEnumerator);
186 hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(pEnumerator, eRender, eConsole, &pDevice);
188 IAudioEndpointVolume *pEndpointVolume;
190 hr = IMMDevice_Activate(pDevice, &SDL_IID_IAudioEndpointVolume, CLSCTX_ALL,
NULL, (LPVOID*)&pEndpointVolume);
192 IAudioEndpointVolume_GetMasterVolumeLevelScalar(pEndpointVolume, &volume);
193 IUnknown_Release(pEndpointVolume);
195 IUnknown_Release(pDevice);
197 IUnknown_Release(pEnumerator);
206 static uint8_t GetPlaystationVolumeFromFloat(
float fVolume)
208 const int k_nVolumeFitRatio = 15;
209 const int k_nVolumeFitOffset = 9;
212 if (fVolume > 1.0
f || fVolume < 0.0
f) {
217 return (
Uint8)((fVolLog * k_nVolumeFitRatio) + k_nVolumeFitOffset);
221 HIDAPI_DriverPS4_IsSupportedDevice(
Uint16 vendor_id,
Uint16 product_id,
Uint16 version,
int interface_number)
227 HIDAPI_DriverPS4_GetDeviceName(
Uint16 vendor_id,
Uint16 product_id)
229 if (vendor_id == SONY_USB_VID) {
230 return "PS4 Controller";
237 Uint8 report[USB_PACKET_LENGTH + 1];
240 report[0] = report_id;
254 if (ReadFeatureReport(dev, k_ePS4FeatureReportIdSerialNumber,
data,
sizeof(
data))) {
255 for (
i = 0;
i <
sizeof(
data); ++
i) {
256 if (
data[
i] != 0x00) {
268 if (vendor_id == RAZER_USB_VID &&
269 (product_id == RAZER_PANTHERA_PID || product_id == RAZER_PANTHERA_EVO_PID)) {
280 SDL_DriverPS4_Context *
ctx;
290 ctx->is_dongle = (vendor_id == SONY_USB_VID && product_id == SONY_DS4_DONGLE_PID);
291 if (
ctx->is_dongle) {
293 }
else if (vendor_id == SONY_USB_VID) {
294 ctx->is_bluetooth = !CheckUSBConnected(dev);
300 SDL_Log(
"PS4 dongle = %s, bluetooth = %s\n",
ctx->is_dongle ?
"TRUE" :
"FALSE",
ctx->is_bluetooth ?
"TRUE" :
"FALSE");
304 if (vendor_id == SONY_USB_VID &&
305 (product_id == SONY_DS4_SLIM_PID || product_id == SONY_DS4_DONGLE_PID )) {
309 if (HIDAPI_DriverPS4_CanRumble(vendor_id, product_id)) {
310 if (
ctx->is_bluetooth) {
318 HIDAPI_DriverPS4_Rumble(joystick, dev,
ctx, 0, 0, 0);
321 joystick->nbuttons = 16;
331 SDL_DriverPS4_Context *
ctx = (SDL_DriverPS4_Context *)
context;
332 DS4EffectsState_t *effects;
336 if (!
ctx->rumble_supported) {
343 if (
ctx->is_bluetooth) {
344 data[0] = k_EPS4ReportIdBluetoothEffects;
345 data[1] = 0xC0 | 0x04;
351 data[0] = k_EPS4ReportIdUsbEffects;
359 effects->ucRumbleLeft = (low_frequency_rumble >> 8);
360 effects->ucRumbleRight = (high_frequency_rumble >> 8);
362 effects->ucLedRed = 0;
363 effects->ucLedGreen = 0;
364 effects->ucLedBlue = 80;
366 if (
ctx->audio_supported) {
368 if (!
ctx->last_volume_check ||
370 ctx->volume = GetPlaystationVolumeFromFloat(GetSystemVolume());
371 ctx->last_volume_check = now;
374 effects->ucVolumeRight =
ctx->volume;
375 effects->ucVolumeLeft =
ctx->volume;
376 effects->ucVolumeSpeaker =
ctx->volume;
377 effects->ucVolumeMic = 0xFF;
380 if (
ctx->is_bluetooth) {
384 unCRC = crc32(0, &ubHdr, 1);
385 unCRC = crc32(unCRC,
data, (
Uint32)(report_size -
sizeof(unCRC)));
386 SDL_memcpy(&
data[report_size -
sizeof(unCRC)], &unCRC,
sizeof(unCRC));
393 if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) {
396 ctx->rumble_expiration = 0;
402 HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick,
hid_device *dev, SDL_DriverPS4_Context *
ctx, PS4StatePacket_t *packet)
406 if (
ctx->last_state.rgucButtonsHatAndCounter[0] != packet->rgucButtonsHatAndCounter[0]) {
408 Uint8 data = (packet->rgucButtonsHatAndCounter[0] >> 4);
416 Uint8 data = (packet->rgucButtonsHatAndCounter[0] & 0x0F);
461 if (
ctx->last_state.rgucButtonsHatAndCounter[1] != packet->rgucButtonsHatAndCounter[1]) {
462 Uint8 data = packet->rgucButtonsHatAndCounter[1];
472 if (
ctx->last_state.rgucButtonsHatAndCounter[2] != packet->rgucButtonsHatAndCounter[2]) {
473 Uint8 data = (packet->rgucButtonsHatAndCounter[2] & 0x03);
479 axis = ((int)packet->ucTriggerLeft * 257) - 32768;
481 axis = ((int)packet->ucTriggerRight * 257) - 32768;
483 axis = ((int)packet->ucLeftJoystickX * 257) - 32768;
485 axis = ((int)packet->ucLeftJoystickY * 257) - 32768;
487 axis = ((int)packet->ucRightJoystickX * 257) - 32768;
489 axis = ((int)packet->ucRightJoystickY * 257) - 32768;
492 if (packet->ucBatteryLevel & 0x10) {
496 int level = (packet->ucBatteryLevel & 0xF);
499 }
else if (
level <= 2) {
501 }
else if (
level <= 7) {
514 SDL_DriverPS4_Context *
ctx = (SDL_DriverPS4_Context *)
context;
520 case k_EPS4ReportIdUsbState:
521 HIDAPI_DriverPS4_HandleStatePacket(joystick, dev,
ctx, (PS4StatePacket_t *)&
data[1]);
523 case k_EPS4ReportIdBluetoothState:
525 HIDAPI_DriverPS4_HandleStatePacket(joystick, dev,
ctx, (PS4StatePacket_t *)&
data[3]);
528 #ifdef DEBUG_JOYSTICK
535 if (
ctx->rumble_expiration) {
538 HIDAPI_DriverPS4_Rumble(joystick, dev,
context, 0, 0, 0);
555 HIDAPI_DriverPS4_IsSupportedDevice,
556 HIDAPI_DriverPS4_GetDeviceName,
557 HIDAPI_DriverPS4_Init,
558 HIDAPI_DriverPS4_Rumble,
559 HIDAPI_DriverPS4_Update,
560 HIDAPI_DriverPS4_Quit