src/joystick/hidapi/SDL_hidapi_ps4.c
author Ethan Lee <flibitijibibo@flibitijibibo.com>
Tue, 12 Mar 2019 20:27:54 -0400
changeset 12641 64597a7e8771
parent 12503 806492103856
child 12787 0411f841b035
permissions -rw-r--r--
hidapi: Add support for Wii U/Switch USB GameCube controller adapter.

Note that a single USB device is responsible for all 4 joysticks, so a large
rewrite of the DeviceDriver functions was necessary to allow a single device to
produce multiple joysticks.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2019 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_log.h"
    30 #include "SDL_events.h"
    31 #include "SDL_timer.h"
    32 #include "SDL_joystick.h"
    33 #include "SDL_gamecontroller.h"
    34 #include "../SDL_sysjoystick.h"
    35 #include "SDL_hidapijoystick_c.h"
    36 
    37 
    38 #ifdef SDL_JOYSTICK_HIDAPI_PS4
    39 
    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
    44 
    45 #define RAZER_USB_VID       0x1532
    46 #define RAZER_PANTHERA_PID  0X0401
    47 #define RAZER_PANTHERA_EVO_PID  0x1008
    48 
    49 #define USB_PACKET_LENGTH   64
    50 
    51 #define VOLUME_CHECK_INTERVAL_MS    (10 * 1000)
    52 
    53 typedef enum
    54 {
    55     k_EPS4ReportIdUsbState = 1,
    56     k_EPS4ReportIdUsbEffects = 5,
    57     k_EPS4ReportIdBluetoothState = 17,
    58     k_EPS4ReportIdBluetoothEffects = 17,
    59     k_EPS4ReportIdDisconnectMessage = 226,
    60 } EPS4ReportId;
    61 
    62 typedef enum 
    63 {
    64     k_ePS4FeatureReportIdGyroCalibration_USB = 0x02,
    65     k_ePS4FeatureReportIdGyroCalibration_BT = 0x05,
    66     k_ePS4FeatureReportIdSerialNumber = 0x12,
    67 } EPS4FeatureReportID;
    68 
    69 typedef struct
    70 {
    71     Uint8 ucLeftJoystickX;
    72     Uint8 ucLeftJoystickY;
    73     Uint8 ucRightJoystickX;
    74     Uint8 ucRightJoystickY;
    75     Uint8 rgucButtonsHatAndCounter[ 3 ];
    76     Uint8 ucTriggerLeft;
    77     Uint8 ucTriggerRight;
    78     Uint8 _rgucPad0[ 3 ];
    79     Sint16 sGyroX;
    80     Sint16 sGyroY;
    81     Sint16 sGyroZ;
    82     Sint16 sAccelX;
    83     Sint16 sAccelY;
    84     Sint16 sAccelZ;
    85     Uint8 _rgucPad1[ 5 ];
    86     Uint8 ucBatteryLevel;
    87     Uint8 _rgucPad2[ 4 ];
    88     Uint8 ucTrackpadCounter1;
    89     Uint8 rgucTrackpadData1[ 3 ];
    90     Uint8 ucTrackpadCounter2;
    91     Uint8 rgucTrackpadData2[ 3 ];
    92 } PS4StatePacket_t;
    93 
    94 typedef struct
    95 {
    96     Uint8 ucRumbleRight;
    97     Uint8 ucRumbleLeft;
    98     Uint8 ucLedRed;
    99     Uint8 ucLedGreen;
   100     Uint8 ucLedBlue;
   101     Uint8 ucLedDelayOn;
   102     Uint8 ucLedDelayOff;
   103     Uint8 _rgucPad0[ 8 ];
   104     Uint8 ucVolumeLeft;
   105     Uint8 ucVolumeRight;
   106     Uint8 ucVolumeMic;
   107     Uint8 ucVolumeSpeaker;
   108 } DS4EffectsState_t;
   109 
   110 typedef struct {
   111     SDL_JoystickID joystickID;
   112     SDL_bool is_dongle;
   113     SDL_bool is_bluetooth;
   114     SDL_bool audio_supported;
   115     SDL_bool rumble_supported;
   116     Uint8 volume;
   117     Uint32 last_volume_check;
   118     Uint32 rumble_expiration;
   119     PS4StatePacket_t last_state;
   120 } SDL_DriverPS4_Context;
   121 
   122 
   123 /* Public domain CRC implementation adapted from:
   124    http://home.thep.lu.se/~bjorn/crc/crc32_simple.c
   125 */
   126 static Uint32 crc32_for_byte(Uint32 r)
   127 {
   128     int i;
   129     for(i = 0; i < 8; ++i) {
   130         r = (r & 1? 0: (Uint32)0xEDB88320L) ^ r >> 1;
   131     }
   132     return r ^ (Uint32)0xFF000000L;
   133 }
   134 
   135 static Uint32 crc32(Uint32 crc, const void *data, int count)
   136 {
   137     int i;
   138     for(i = 0; i < count; ++i) {
   139         crc = crc32_for_byte((Uint8)crc ^ ((const Uint8*)data)[i]) ^ crc >> 8;
   140     }
   141     return crc;
   142 }
   143 
   144 #if defined(__WIN32__) && defined(HAVE_ENDPOINTVOLUME_H)
   145 #include "../../core/windows/SDL_windows.h"
   146 
   147 #ifndef NTDDI_VISTA
   148 #define NTDDI_VISTA    0x06000000
   149 #endif
   150 #ifndef _WIN32_WINNT_VISTA
   151 #define _WIN32_WINNT_VISTA 0x0600
   152 #endif
   153 
   154 /* Define Vista for the Audio related includes below to work */
   155 #undef NTDDI_VERSION
   156 #define NTDDI_VERSION NTDDI_VISTA
   157 #undef _WIN32_WINNT
   158 #define _WIN32_WINNT _WIN32_WINNT_VISTA
   159 #define COBJMACROS
   160 #include <mmdeviceapi.h>
   161 #include <audioclient.h>
   162 #include <endpointvolume.h>
   163 
   164 #undef DEFINE_GUID
   165 #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}}
   166 DEFINE_GUID(SDL_CLSID_MMDeviceEnumerator, 0xBCDE0395, 0xE52F, 0x467C, 0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E);
   167 DEFINE_GUID(SDL_IID_IMMDeviceEnumerator, 0xA95664D2, 0x9614, 0x4F35, 0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6);
   168 DEFINE_GUID(SDL_IID_IAudioEndpointVolume, 0x5CDF2C82, 0x841E, 0x4546, 0x97, 0x22, 0x0C, 0xF7, 0x40, 0x78, 0x22, 0x9A);
   169 #endif
   170 
   171 
   172 
   173 static float GetSystemVolume(void)
   174 {
   175     float volume = -1.0f;    /* Return this if we can't get system volume */
   176 
   177 #if defined(__WIN32__) && defined(HAVE_ENDPOINTVOLUME_H)
   178     HRESULT hr = WIN_CoInitialize();
   179     if (SUCCEEDED(hr)) {
   180         IMMDeviceEnumerator *pEnumerator;
   181 
   182         /* This should gracefully fail on XP and succeed on everything Vista and above */
   183         hr = CoCreateInstance(&SDL_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &SDL_IID_IMMDeviceEnumerator, (LPVOID*)&pEnumerator);
   184         if (SUCCEEDED(hr)) {
   185             IMMDevice *pDevice;
   186 
   187             hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(pEnumerator, eRender, eConsole, &pDevice);
   188             if (SUCCEEDED(hr)) {
   189                 IAudioEndpointVolume *pEndpointVolume;
   190 
   191                 hr = IMMDevice_Activate(pDevice, &SDL_IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (LPVOID*)&pEndpointVolume);
   192                 if (SUCCEEDED(hr)) {
   193                     IAudioEndpointVolume_GetMasterVolumeLevelScalar(pEndpointVolume, &volume);
   194                     IUnknown_Release(pEndpointVolume);
   195                 }
   196                 IUnknown_Release(pDevice);
   197             }
   198             IUnknown_Release(pEnumerator);
   199         }
   200         WIN_CoUninitialize();
   201     }
   202 #endif /* __WIN32__ */
   203 
   204     return volume;
   205 }
   206 
   207 static uint8_t GetPlaystationVolumeFromFloat(float fVolume)
   208 {
   209     const int k_nVolumeFitRatio = 15;
   210     const int k_nVolumeFitOffset = 9;
   211     float fVolLog;
   212 
   213     if (fVolume > 1.0f || fVolume < 0.0f) {
   214         fVolume = 0.30f;
   215     }
   216     fVolLog = SDL_logf(fVolume * 100);
   217 
   218     return (Uint8)((fVolLog * k_nVolumeFitRatio) + k_nVolumeFitOffset);
   219 }
   220 
   221 static SDL_bool
   222 HIDAPI_DriverPS4_IsSupportedDevice(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number)
   223 {
   224     return SDL_IsJoystickPS4(vendor_id, product_id);
   225 }
   226 
   227 static const char *
   228 HIDAPI_DriverPS4_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
   229 {
   230     if (vendor_id == SONY_USB_VID) {
   231         return "PS4 Controller";
   232     }
   233     return NULL;
   234 }
   235 
   236 static SDL_bool ReadFeatureReport(hid_device *dev, Uint8 report_id, Uint8 *data, size_t size)
   237 {
   238     Uint8 report[USB_PACKET_LENGTH + 1];
   239 
   240     SDL_memset(report, 0, sizeof(report));
   241     report[0] = report_id;
   242     if (hid_get_feature_report(dev, report, sizeof(report)) < 0) {
   243         return SDL_FALSE;
   244     }
   245     SDL_memcpy(data, report, SDL_min(size, sizeof(report)));
   246     return SDL_TRUE;
   247 }
   248 
   249 static SDL_bool CheckUSBConnected(hid_device *dev)
   250 {
   251     int i;
   252     Uint8 data[16];
   253 
   254     /* This will fail if we're on Bluetooth */
   255     if (ReadFeatureReport(dev, k_ePS4FeatureReportIdSerialNumber, data, sizeof(data))) {
   256         for (i = 0; i < sizeof(data); ++i) {
   257             if (data[i] != 0x00) {
   258                 return SDL_TRUE;
   259             }
   260         }
   261         /* Maybe the dongle without a connected controller? */
   262     }
   263     return SDL_FALSE;
   264 }
   265 
   266 static SDL_bool HIDAPI_DriverPS4_CanRumble(Uint16 vendor_id, Uint16 product_id)
   267 {
   268     /* The Razer Panthera fight stick hangs when trying to rumble */
   269     if (vendor_id == RAZER_USB_VID &&
   270         (product_id == RAZER_PANTHERA_PID || product_id == RAZER_PANTHERA_EVO_PID)) {
   271         return SDL_FALSE;
   272     }
   273     return SDL_TRUE;
   274 }
   275 
   276 static SDL_bool
   277 HIDAPI_DriverPS4_InitDriver(SDL_HIDAPI_DriverData *context, Uint16 vendor_id, Uint16 product_id, int *num_joysticks)
   278 {
   279     SDL_DriverPS4_Context *ctx;
   280 
   281     ctx = (SDL_DriverPS4_Context *)SDL_calloc(1, sizeof(*ctx));
   282     if (!ctx) {
   283         SDL_OutOfMemory();
   284         return SDL_FALSE;
   285     }
   286     context->context = ctx;
   287 
   288     /* Check for type of connection */
   289     ctx->is_dongle = (vendor_id == SONY_USB_VID && product_id == SONY_DS4_DONGLE_PID);
   290     if (ctx->is_dongle) {
   291         ctx->is_bluetooth = SDL_FALSE;
   292     } else if (vendor_id == SONY_USB_VID) {
   293         ctx->is_bluetooth = !CheckUSBConnected(context->device);
   294     } else {
   295         /* Third party controllers appear to all be wired */
   296         ctx->is_bluetooth = SDL_FALSE;
   297     }
   298 #ifdef DEBUG_PS4
   299     SDL_Log("PS4 dongle = %s, bluetooth = %s\n", ctx->is_dongle ? "TRUE" : "FALSE", ctx->is_bluetooth ? "TRUE" : "FALSE");
   300 #endif
   301 
   302     /* Check to see if audio is supported */
   303     if (vendor_id == SONY_USB_VID &&
   304         (product_id == SONY_DS4_SLIM_PID || product_id == SONY_DS4_DONGLE_PID )) {
   305         ctx->audio_supported = SDL_TRUE;
   306     }
   307 
   308     if (HIDAPI_DriverPS4_CanRumble(vendor_id, product_id)) {
   309         if (ctx->is_bluetooth) {
   310             ctx->rumble_supported = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, SDL_FALSE);
   311         } else {
   312             ctx->rumble_supported = SDL_TRUE;
   313         }
   314     }
   315 
   316     ctx->joystickID = SDL_GetNextJoystickInstanceID();
   317     *num_joysticks += 1;
   318     SDL_PrivateJoystickAdded(ctx->joystickID);
   319 
   320     return SDL_TRUE;
   321 }
   322 
   323 static void
   324 HIDAPI_DriverPS4_QuitDriver(SDL_HIDAPI_DriverData *context, SDL_bool send_event, int *num_joysticks)
   325 {
   326     SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context->context;
   327 
   328     *num_joysticks -= 1;
   329     if (send_event) {
   330         SDL_PrivateJoystickRemoved(ctx->joystickID);
   331     }
   332     SDL_free(context->context);
   333 }
   334 
   335 static int
   336 HIDAPI_DriverPS4_NumJoysticks(SDL_HIDAPI_DriverData *context)
   337 {
   338     return 1;
   339 }
   340 
   341 static SDL_JoystickID
   342 HIDAPI_DriverPS4_InstanceIDForIndex(SDL_HIDAPI_DriverData *context, int index)
   343 {
   344     SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context->context;
   345     return ctx->joystickID;
   346 }
   347 
   348 static int HIDAPI_DriverPS4_Rumble(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
   349 
   350 static SDL_bool
   351 HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick)
   352 {
   353     /* Initialize LED and effect state */
   354     HIDAPI_DriverPS4_Rumble(context, joystick, 0, 0, 0);
   355 
   356     /* Initialize the joystick capabilities */
   357     joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
   358     joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
   359     joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
   360 
   361     return SDL_TRUE;
   362 }
   363 
   364 static int
   365 HIDAPI_DriverPS4_Rumble(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
   366 {
   367     SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context->context;
   368     DS4EffectsState_t *effects;
   369     Uint8 data[78];
   370     int report_size, offset;
   371 
   372     if (!ctx->rumble_supported) {
   373         return SDL_Unsupported();
   374     }
   375 
   376     /* In order to send rumble, we have to send a complete effect packet */
   377     SDL_memset(data, 0, sizeof(data));
   378 
   379     if (ctx->is_bluetooth) {
   380         data[0] = k_EPS4ReportIdBluetoothEffects;
   381         data[1] = 0xC0 | 0x04;  /* Magic value HID + CRC, also sets interval to 4ms for samples */
   382         data[3] = 0x03;  /* 0x1 is rumble, 0x2 is lightbar, 0x4 is the blink interval */
   383 
   384         report_size = 78;
   385         offset = 6;
   386     } else {
   387         data[0] = k_EPS4ReportIdUsbEffects;
   388         data[1] = 0x07;  /* Magic value */
   389 
   390         report_size = 32;
   391         offset = 4;
   392     }
   393     effects = (DS4EffectsState_t *)&data[offset];
   394 
   395     effects->ucRumbleLeft = (low_frequency_rumble >> 8);
   396     effects->ucRumbleRight = (high_frequency_rumble >> 8);
   397 
   398     effects->ucLedRed = 0;
   399     effects->ucLedGreen = 0;
   400     effects->ucLedBlue = 80;
   401 
   402     if (ctx->audio_supported) {
   403         Uint32 now = SDL_GetTicks();
   404         if (!ctx->last_volume_check ||
   405             SDL_TICKS_PASSED(now, ctx->last_volume_check + VOLUME_CHECK_INTERVAL_MS)) {
   406             ctx->volume = GetPlaystationVolumeFromFloat(GetSystemVolume());
   407             ctx->last_volume_check = now;
   408         }
   409 
   410         effects->ucVolumeRight = ctx->volume;
   411         effects->ucVolumeLeft = ctx->volume;
   412         effects->ucVolumeSpeaker = ctx->volume;
   413         effects->ucVolumeMic = 0xFF;
   414     }
   415 
   416     if (ctx->is_bluetooth) {
   417         /* Bluetooth reports need a CRC at the end of the packet (at least on Linux) */
   418         Uint8 ubHdr = 0xA2; /* hidp header is part of the CRC calculation */
   419         Uint32 unCRC;
   420         unCRC = crc32(0, &ubHdr, 1);
   421         unCRC = crc32(unCRC, data, (Uint32)(report_size - sizeof(unCRC)));
   422         SDL_memcpy(&data[report_size - sizeof(unCRC)], &unCRC, sizeof(unCRC));
   423     }
   424 
   425     if (hid_write(context->device, data, report_size) != report_size) {
   426         return SDL_SetError("Couldn't send rumble packet");
   427     }
   428 
   429     if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) {
   430         ctx->rumble_expiration = SDL_GetTicks() + duration_ms;
   431     } else {
   432         ctx->rumble_expiration = 0;
   433     }
   434     return 0;
   435 }
   436 
   437 static void
   438 HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS4_Context *ctx, PS4StatePacket_t *packet)
   439 {
   440     Sint16 axis;
   441 
   442     if (ctx->last_state.rgucButtonsHatAndCounter[0] != packet->rgucButtonsHatAndCounter[0]) {
   443         {
   444             Uint8 data = (packet->rgucButtonsHatAndCounter[0] >> 4);
   445 
   446             SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
   447             SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
   448             SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
   449             SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
   450         }
   451         {
   452             Uint8 data = (packet->rgucButtonsHatAndCounter[0] & 0x0F);
   453             SDL_bool dpad_up = SDL_FALSE;
   454             SDL_bool dpad_down = SDL_FALSE;
   455             SDL_bool dpad_left = SDL_FALSE;
   456             SDL_bool dpad_right = SDL_FALSE;
   457 
   458             switch (data) {
   459             case 0:
   460                 dpad_up = SDL_TRUE;
   461                 break;
   462             case 1:
   463                 dpad_up = SDL_TRUE;
   464                 dpad_right = SDL_TRUE;
   465                 break;
   466             case 2:
   467                 dpad_right = SDL_TRUE;
   468                 break;
   469             case 3:
   470                 dpad_right = SDL_TRUE;
   471                 dpad_down = SDL_TRUE;
   472                 break;
   473             case 4:
   474                 dpad_down = SDL_TRUE;
   475                 break;
   476             case 5:
   477                 dpad_left = SDL_TRUE;
   478                 dpad_down = SDL_TRUE;
   479                 break;
   480             case 6:
   481                 dpad_left = SDL_TRUE;
   482                 break;
   483             case 7:
   484                 dpad_up = SDL_TRUE;
   485                 dpad_left = SDL_TRUE;
   486                 break;
   487             default:
   488                 break;
   489             }
   490             SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, dpad_down);
   491             SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, dpad_up);
   492             SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, dpad_right);
   493             SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left);
   494         }
   495     }
   496 
   497     if (ctx->last_state.rgucButtonsHatAndCounter[1] != packet->rgucButtonsHatAndCounter[1]) {
   498         Uint8 data = packet->rgucButtonsHatAndCounter[1];
   499 
   500         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
   501         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
   502         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
   503         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
   504         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
   505         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED);
   506     }
   507 
   508     if (ctx->last_state.rgucButtonsHatAndCounter[2] != packet->rgucButtonsHatAndCounter[2]) {
   509         Uint8 data = (packet->rgucButtonsHatAndCounter[2] & 0x03);
   510 
   511         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
   512     }
   513 
   514     axis = ((int)packet->ucTriggerLeft * 257) - 32768;
   515     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
   516     axis = ((int)packet->ucTriggerRight * 257) - 32768;
   517     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
   518     axis = ((int)packet->ucLeftJoystickX * 257) - 32768;
   519     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
   520     axis = ((int)packet->ucLeftJoystickY * 257) - 32768;
   521     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
   522     axis = ((int)packet->ucRightJoystickX * 257) - 32768;
   523     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
   524     axis = ((int)packet->ucRightJoystickY * 257) - 32768;
   525     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
   526 
   527     if (packet->ucBatteryLevel & 0x10) {
   528         joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
   529     } else {
   530         /* Battery level ranges from 0 to 10 */
   531         int level = (packet->ucBatteryLevel & 0xF);
   532         if (level == 0) {
   533             joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
   534         } else if (level <= 2) {
   535             joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
   536         } else if (level <= 7) {
   537             joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
   538         } else {
   539             joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
   540         }
   541     }
   542 
   543     SDL_memcpy(&ctx->last_state, packet, sizeof(ctx->last_state));
   544 }
   545 
   546 static SDL_bool
   547 HIDAPI_DriverPS4_UpdateDriver(SDL_HIDAPI_DriverData *context, int *num_joysticks)
   548 {
   549     SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context->context;
   550     SDL_Joystick *joystick = SDL_JoystickFromInstanceID(ctx->joystickID);
   551     Uint8 data[USB_PACKET_LENGTH];
   552     int size;
   553 
   554     if (joystick == NULL) {
   555         return SDL_TRUE; /* Nothing to do right now! */
   556     }
   557 
   558     while ((size = hid_read_timeout(context->device, data, sizeof(data), 0)) > 0) {
   559         switch (data[0]) {
   560         case k_EPS4ReportIdUsbState:
   561             HIDAPI_DriverPS4_HandleStatePacket(joystick, context->device, ctx, (PS4StatePacket_t *)&data[1]);
   562             break;
   563         case k_EPS4ReportIdBluetoothState:
   564             /* Bluetooth state packets have two additional bytes at the beginning */
   565             HIDAPI_DriverPS4_HandleStatePacket(joystick, context->device, ctx, (PS4StatePacket_t *)&data[3]);
   566             break;
   567         default:
   568 #ifdef DEBUG_JOYSTICK
   569             SDL_Log("Unknown PS4 packet: 0x%.2x\n", data[0]);
   570 #endif
   571             break;
   572         }
   573     }
   574 
   575     if (ctx->rumble_expiration) {
   576         Uint32 now = SDL_GetTicks();
   577         if (SDL_TICKS_PASSED(now, ctx->rumble_expiration)) {
   578             HIDAPI_DriverPS4_Rumble(context, joystick, 0, 0, 0);
   579         }
   580     }
   581 
   582     return (size >= 0);
   583 }
   584 
   585 SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4 =
   586 {
   587     SDL_HINT_JOYSTICK_HIDAPI_PS4,
   588     SDL_TRUE,
   589     HIDAPI_DriverPS4_IsSupportedDevice,
   590     HIDAPI_DriverPS4_GetDeviceName,
   591     HIDAPI_DriverPS4_InitDriver,
   592     HIDAPI_DriverPS4_QuitDriver,
   593     HIDAPI_DriverPS4_UpdateDriver,
   594     HIDAPI_DriverPS4_NumJoysticks,
   595     HIDAPI_DriverPS4_InstanceIDForIndex,
   596     HIDAPI_DriverPS4_OpenJoystick,
   597     HIDAPI_DriverPS4_Rumble
   598 };
   599 
   600 #endif /* SDL_JOYSTICK_HIDAPI_PS4 */
   601 
   602 #endif /* SDL_JOYSTICK_HIDAPI */
   603 
   604 /* vi: set ts=4 sw=4 expandtab: */