24 #include "../../SDL_internal.h"
26 #ifdef SDL_JOYSTICK_HIDAPI
33 #include "../SDL_sysjoystick.h"
38 #ifdef SDL_JOYSTICK_HIDAPI_PS4
46 #define GYRO_RES_PER_DEGREE 1024.0f
47 #define ACCEL_RES_PER_G 8192.0f
49 #define LOAD16(A, B) (Sint16)((Uint16)(A) | (((Uint16)(B)) << 8))
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,
70 k_ePS4FeatureReportIdGyroCalibration_USB = 0x02,
71 k_ePS4FeatureReportIdGyroCalibration_BT = 0x05,
72 k_ePS4FeatureReportIdSerialNumber = 0x12,
73 } EPS4FeatureReportID;
77 Uint8 ucLeftJoystickX;
78 Uint8 ucLeftJoystickY;
79 Uint8 ucRightJoystickX;
80 Uint8 ucRightJoystickY;
81 Uint8 rgucButtonsHatAndCounter[ 3 ];
94 Uint8 ucTouchpadCounter1;
95 Uint8 rgucTouchpadData1[ 3 ];
96 Uint8 ucTouchpadCounter2;
97 Uint8 rgucTouchpadData2[ 3 ];
109 Uint8 _rgucPad0[ 8 ];
113 Uint8 ucVolumeSpeaker;
119 } IMUCalibrationData;
129 IMUCalibrationData calibration[6];
139 PS4StatePacket_t last_state;
140 } SDL_DriverPS4_Context;
150 HIDAPI_DriverPS4_GetDeviceName(
Uint16 vendor_id,
Uint16 product_id)
153 return "PS4 Controller";
161 report[0] = report_id;
176 SetLedsForPlayerIndex(DS4EffectsState_t *effects,
int player_index)
182 { 0x00, 0x00, 0x40 },
183 { 0x40, 0x00, 0x00 },
184 { 0x00, 0x40, 0x00 },
185 { 0x20, 0x00, 0x20 },
186 { 0x02, 0x01, 0x00 },
187 { 0x00, 0x01, 0x01 },
191 if (player_index >= 0) {
197 effects->ucLedRed =
colors[player_index][0];
198 effects->ucLedGreen =
colors[player_index][1];
199 effects->ucLedBlue =
colors[player_index][2];
217 SDL_DriverPS4_Context *
ctx = (SDL_DriverPS4_Context *)
device->context;
222 if (!
ctx->official_controller) {
223 #ifdef DEBUG_PS4_CALIBRATION
224 SDL_Log(
"Not an official controller, ignoring calibration\n");
229 for( tries = 0; tries < 5; ++tries ) {
231 size = ReadFeatureReport(
device->dev, k_ePS4FeatureReportIdGyroCalibration_USB,
data,
sizeof(
data));
233 #ifdef DEBUG_PS4_CALIBRATION
234 SDL_Log(
"Short read of calibration data: %d, ignoring calibration\n",
size);
239 if (
ctx->is_bluetooth) {
240 size = ReadFeatureReport(
device->dev, k_ePS4FeatureReportIdGyroCalibration_BT,
data,
sizeof(
data));
242 #ifdef DEBUG_PS4_CALIBRATION
243 SDL_Log(
"Short read of calibration data: %d, ignoring calibration\n",
size);
264 Sint16 sGyroPitchBias, sGyroYawBias, sGyroRollBias;
265 Sint16 sGyroPitchPlus, sGyroPitchMinus;
266 Sint16 sGyroYawPlus, sGyroYawMinus;
267 Sint16 sGyroRollPlus, sGyroRollMinus;
268 Sint16 sGyroSpeedPlus, sGyroSpeedMinus;
270 Sint16 sAccXPlus, sAccXMinus;
271 Sint16 sAccYPlus, sAccYMinus;
272 Sint16 sAccZPlus, sAccZMinus;
277 #ifdef DEBUG_PS4_CALIBRATION
281 sGyroPitchBias = LOAD16(
data[1],
data[2]);
282 sGyroYawBias = LOAD16(
data[3],
data[4]);
283 sGyroRollBias = LOAD16(
data[5],
data[6]);
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]);
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]);
301 sGyroSpeedPlus = LOAD16(
data[19],
data[20]);
302 sGyroSpeedMinus = LOAD16(
data[21],
data[22]);
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]);
311 flNumerator = (sGyroSpeedPlus + sGyroSpeedMinus) * GYRO_RES_PER_DEGREE;
312 ctx->calibration[0].bias = sGyroPitchBias;
313 ctx->calibration[0].sensitivity = flNumerator / (sGyroPitchPlus - sGyroPitchMinus);
315 ctx->calibration[1].bias = sGyroYawBias;
316 ctx->calibration[1].sensitivity = flNumerator / (sGyroYawPlus - sGyroYawMinus);
318 ctx->calibration[2].bias = sGyroRollBias;
319 ctx->calibration[2].sensitivity = flNumerator / (sGyroRollPlus - sGyroRollMinus);
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;
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;
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;
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);
341 #ifdef DEBUG_PS4_CALIBRATION
342 SDL_Log(
"invalid calibration, ignoring\n");
348 #ifdef DEBUG_PS4_CALIBRATION
349 SDL_Log(
"Calibration data not available\n");
359 if (
ctx->hardware_calibration) {
360 IMUCalibrationData *calibration = &
ctx->calibration[
index];
362 result = (
value - calibration->bias) * calibration->sensitivity;
363 }
else if (
index < 3) {
371 result = (
result / GYRO_RES_PER_DEGREE) * (
float)M_PI / 180.0f;
381 SDL_DriverPS4_Context *
ctx = (SDL_DriverPS4_Context *)
device->context;
382 DS4EffectsState_t *effects;
386 if (!
ctx->effects_supported) {
392 if (
ctx->is_bluetooth) {
393 data[0] = k_EPS4ReportIdBluetoothEffects;
394 data[1] = 0xC0 | 0x04;
400 data[0] = k_EPS4ReportIdUsbEffects;
408 effects->ucRumbleLeft =
ctx->rumble_left;
409 effects->ucRumbleRight =
ctx->rumble_right;
412 if (
ctx->color_set) {
413 effects->ucLedRed =
ctx->led_red;
414 effects->ucLedGreen =
ctx->led_green;
415 effects->ucLedBlue =
ctx->led_blue;
417 SetLedsForPlayerIndex(effects,
ctx->player_index);
420 if (
ctx->is_bluetooth) {
425 unCRC =
SDL_crc32(unCRC,
data, (
size_t)(report_size -
sizeof(unCRC)));
426 SDL_memcpy(&
data[report_size -
sizeof(unCRC)], &unCRC,
sizeof(unCRC));
429 if (SDL_HIDAPI_SendRumble(
device,
data, report_size) != report_size) {
438 SDL_DriverPS4_Context *
ctx = (SDL_DriverPS4_Context *)
device->context;
444 ctx->player_index = player_index;
447 HIDAPI_DriverPS4_UpdateEffects(
device);
453 SDL_DriverPS4_Context *
ctx;
471 if (
ctx->is_dongle) {
479 size = ReadFeatureReport(
device->dev, k_ePS4FeatureReportIdSerialNumber,
data,
sizeof(
data));
483 SDL_snprintf(serial,
sizeof(serial),
"%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
496 SDL_Log(
"PS4 dongle = %s, bluetooth = %s\n",
ctx->is_dongle ?
"TRUE" :
"FALSE",
ctx->is_bluetooth ?
"TRUE" :
"FALSE");
505 if (HIDAPI_DriverPS4_CanRumble(
device->vendor_id,
device->product_id)) {
506 if (
ctx->is_bluetooth) {
517 HIDAPI_DriverPS4_UpdateEffects(
device);
534 SDL_DriverPS4_Context *
ctx = (SDL_DriverPS4_Context *)
device->context;
536 ctx->rumble_left = (low_frequency_rumble >> 8);
537 ctx->rumble_right = (high_frequency_rumble >> 8);
539 return HIDAPI_DriverPS4_UpdateEffects(
device);
557 SDL_DriverPS4_Context *
ctx = (SDL_DriverPS4_Context *)
device->context;
564 return HIDAPI_DriverPS4_UpdateEffects(
device);
570 SDL_DriverPS4_Context *
ctx = (SDL_DriverPS4_Context *)
device->context;
573 HIDAPI_DriverPS4_LoadCalibrationData(
device);
581 HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *
joystick,
hid_device *dev, SDL_DriverPS4_Context *
ctx, PS4StatePacket_t *packet)
583 static const float TOUCHPAD_SCALEX = 1.0f / 1920;
584 static const float TOUCHPAD_SCALEY = 1.0f / 920;
586 Uint8 touchpad_state;
587 int touchpad_x, touchpad_y;
589 if (
ctx->last_state.rgucButtonsHatAndCounter[0] != packet->rgucButtonsHatAndCounter[0]) {
591 Uint8 data = (packet->rgucButtonsHatAndCounter[0] >> 4);
599 Uint8 data = (packet->rgucButtonsHatAndCounter[0] & 0x0F);
644 if (
ctx->last_state.rgucButtonsHatAndCounter[1] != packet->rgucButtonsHatAndCounter[1]) {
645 Uint8 data = packet->rgucButtonsHatAndCounter[1];
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;
664 if (
ctx->last_state.rgucButtonsHatAndCounter[2] != packet->rgucButtonsHatAndCounter[2]) {
665 Uint8 data = (packet->rgucButtonsHatAndCounter[2] & 0x03);
671 axis = ((
int)packet->ucTriggerLeft * 257) - 32768;
673 axis = ((
int)packet->ucTriggerRight * 257) - 32768;
675 axis = ((
int)packet->ucLeftJoystickX * 257) - 32768;
677 axis = ((
int)packet->ucLeftJoystickY * 257) - 32768;
679 axis = ((
int)packet->ucRightJoystickX * 257) - 32768;
681 axis = ((
int)packet->ucRightJoystickY * 257) - 32768;
684 if (packet->ucBatteryLevel & 0x10) {
688 int level = (packet->ucBatteryLevel & 0xF);
691 }
else if (
level <= 2) {
693 }
else if (
level <= 7) {
701 touchpad_x = packet->rgucTouchpadData1[0] | (((
int)packet->rgucTouchpadData1[1] & 0x0F) << 8);
702 touchpad_y = (packet->rgucTouchpadData1[1] >> 4) | ((
int)packet->rgucTouchpadData1[2] << 4);
706 touchpad_x = packet->rgucTouchpadData2[0] | (((
int)packet->rgucTouchpadData2[1] & 0x0F) << 8);
707 touchpad_y = (packet->rgucTouchpadData2[1] >> 4) | ((
int)packet->rgucTouchpadData2[2] << 4);
710 if (
ctx->report_sensors) {
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]));
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]));
730 SDL_DriverPS4_Context *
ctx = (SDL_DriverPS4_Context *)
device->context;
743 #ifdef DEBUG_PS4_PROTOCOL
747 case k_EPS4ReportIdUsbState:
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:
760 if (
data[1] & 0x80) {
765 #ifdef DEBUG_JOYSTICK
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,
#define SDL_JoystickGetPlayerIndex
#define SDL_JoystickFromInstanceID
#define SDL_GetHintBoolean
#define SDL_OutOfMemory()
#define SDL_Unsupported()
@ SDL_CONTROLLER_AXIS_LEFTX
@ SDL_CONTROLLER_AXIS_TRIGGERRIGHT
@ SDL_CONTROLLER_AXIS_RIGHTY
@ SDL_CONTROLLER_AXIS_RIGHTX
@ SDL_CONTROLLER_AXIS_MAX
@ SDL_CONTROLLER_AXIS_TRIGGERLEFT
@ SDL_CONTROLLER_AXIS_LEFTY
@ SDL_CONTROLLER_BUTTON_B
@ SDL_CONTROLLER_BUTTON_BACK
@ SDL_CONTROLLER_BUTTON_LEFTSTICK
@ SDL_CONTROLLER_BUTTON_START
@ SDL_CONTROLLER_BUTTON_DPAD_LEFT
@ SDL_CONTROLLER_BUTTON_RIGHTSHOULDER
@ SDL_CONTROLLER_BUTTON_DPAD_DOWN
@ SDL_CONTROLLER_BUTTON_DPAD_UP
@ SDL_CONTROLLER_BUTTON_LEFTSHOULDER
@ SDL_CONTROLLER_BUTTON_GUIDE
@ SDL_CONTROLLER_BUTTON_DPAD_RIGHT
@ SDL_CONTROLLER_BUTTON_X
@ SDL_CONTROLLER_BUTTON_RIGHTSTICK
@ SDL_CONTROLLER_BUTTON_Y
@ SDL_CONTROLLER_BUTTON_A
@ SDL_CONTROLLER_TYPE_PS4
#define USB_PACKET_LENGTH
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4
void HIDAPI_DumpPacket(const char *prefix, Uint8 *data, int size)
SDL_bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
void HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID)
#define SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE
A variable controlling whether extended input reports should be used for PS4 controllers when using t...
#define SDL_HINT_JOYSTICK_HIDAPI_PS4
A variable controlling whether the HIDAPI driver for PS4 controllers should be used.
int SDL_PrivateJoystickTouchpad(SDL_Joystick *joystick, int touchpad, int finger, Uint8 state, float x, float y, float pressure)
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
void SDL_PrivateJoystickAddTouchpad(SDL_Joystick *joystick, int nfingers)
int SDL_PrivateJoystickSensor(SDL_Joystick *joystick, SDL_SensorType type, const float *data, int num_values)
void SDL_PrivateJoystickAddSensor(SDL_Joystick *joystick, SDL_SensorType type)
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
@ SDL_JOYSTICK_POWER_FULL
@ SDL_JOYSTICK_POWER_MEDIUM
@ SDL_JOYSTICK_POWER_EMPTY
@ SDL_JOYSTICK_POWER_WIRED
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLuint GLuint GLsizei GLenum type
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLuint const GLchar * name
GLuint GLsizei GLsizei * length
GLsizei const GLfloat * value
#define SDL_STANDARD_GRAVITY
#define SDL_arraysize(array)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds)
Read an Input report from a HID device with timeout.
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length)
Get a feature report from a HID device.
HID_API_EXPORT hid_device *HID_API_CALL hid_open_path(const char *path, int bExclusive)
Open a HID device by its path name.
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device)
Close a HID device.
struct hid_device_ hid_device
static SDL_AudioDeviceID device
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d ®2 endm macro vzip8 reg2 vzip d d ®2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
static SDL_Joystick * joystick
#define USB_PRODUCT_RAZER_PANTHERA_EVO
#define USB_PRODUCT_RAZER_PANTHERA
#define USB_PRODUCT_SONY_DS4_SLIM
#define USB_PRODUCT_SONY_DS4_DONGLE
typedef int(__stdcall *FARPROC)()