SDL_hidapi_ps4.c 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. /* This driver supports both simplified reports and the extended input reports enabled by Steam.
  19. Code and logic contributed by Valve Corporation under the SDL zlib license.
  20. */
  21. #include "SDL_internal.h"
  22. #ifdef SDL_JOYSTICK_HIDAPI
  23. #include "../../SDL_hints_c.h"
  24. #include "../SDL_sysjoystick.h"
  25. #include "SDL_hidapijoystick_c.h"
  26. #include "SDL_hidapi_rumble.h"
  27. #ifdef SDL_JOYSTICK_HIDAPI_PS4
  28. // Define this if you want to log all packets from the controller
  29. #if 0
  30. #define DEBUG_PS4_PROTOCOL
  31. #endif
  32. // Define this if you want to log calibration data
  33. #if 0
  34. #define DEBUG_PS4_CALIBRATION
  35. #endif
  36. #define BLUETOOTH_DISCONNECT_TIMEOUT_MS 500
  37. enum
  38. {
  39. SDL_GAMEPAD_BUTTON_PS4_TOUCHPAD = 11
  40. };
  41. typedef enum
  42. {
  43. k_EPS4ReportIdUsbState = 1,
  44. k_EPS4ReportIdUsbEffects = 5,
  45. k_EPS4ReportIdBluetoothState1 = 17,
  46. k_EPS4ReportIdBluetoothState2 = 18,
  47. k_EPS4ReportIdBluetoothState3 = 19,
  48. k_EPS4ReportIdBluetoothState4 = 20,
  49. k_EPS4ReportIdBluetoothState5 = 21,
  50. k_EPS4ReportIdBluetoothState6 = 22,
  51. k_EPS4ReportIdBluetoothState7 = 23,
  52. k_EPS4ReportIdBluetoothState8 = 24,
  53. k_EPS4ReportIdBluetoothState9 = 25,
  54. k_EPS4ReportIdBluetoothEffects = 17,
  55. k_EPS4ReportIdDisconnectMessage = 226,
  56. } EPS4ReportId;
  57. typedef enum
  58. {
  59. k_ePS4FeatureReportIdGyroCalibration_USB = 0x02,
  60. k_ePS4FeatureReportIdCapabilities = 0x03,
  61. k_ePS4FeatureReportIdGyroCalibration_BT = 0x05,
  62. k_ePS4FeatureReportIdSerialNumber = 0x12,
  63. } EPS4FeatureReportID;
  64. typedef struct
  65. {
  66. Uint8 ucLeftJoystickX;
  67. Uint8 ucLeftJoystickY;
  68. Uint8 ucRightJoystickX;
  69. Uint8 ucRightJoystickY;
  70. Uint8 rgucButtonsHatAndCounter[3];
  71. Uint8 ucTriggerLeft;
  72. Uint8 ucTriggerRight;
  73. Uint8 rgucTimestamp[2];
  74. Uint8 _rgucPad0[1];
  75. Uint8 rgucGyroX[2];
  76. Uint8 rgucGyroY[2];
  77. Uint8 rgucGyroZ[2];
  78. Uint8 rgucAccelX[2];
  79. Uint8 rgucAccelY[2];
  80. Uint8 rgucAccelZ[2];
  81. Uint8 _rgucPad1[5];
  82. Uint8 ucBatteryLevel;
  83. Uint8 _rgucPad2[4];
  84. Uint8 ucTouchpadCounter1;
  85. Uint8 rgucTouchpadData1[3];
  86. Uint8 ucTouchpadCounter2;
  87. Uint8 rgucTouchpadData2[3];
  88. Uint8 rgucDeviceSpecific[12];
  89. } PS4StatePacket_t;
  90. typedef struct
  91. {
  92. Uint8 ucRumbleRight;
  93. Uint8 ucRumbleLeft;
  94. Uint8 ucLedRed;
  95. Uint8 ucLedGreen;
  96. Uint8 ucLedBlue;
  97. Uint8 ucLedDelayOn;
  98. Uint8 ucLedDelayOff;
  99. Uint8 _rgucPad0[8];
  100. Uint8 ucVolumeLeft;
  101. Uint8 ucVolumeRight;
  102. Uint8 ucVolumeMic;
  103. Uint8 ucVolumeSpeaker;
  104. } DS4EffectsState_t;
  105. // These enum values match with the validity flags in the PS4 output report
  106. typedef enum
  107. {
  108. k_EPS4EffectRumble = (1 << 0),
  109. k_EPS4EffectLED = (1 << 1),
  110. k_EPS4EffectLEDBlink = (1 << 2),
  111. } EPS4Effect;
  112. typedef struct
  113. {
  114. Sint16 bias;
  115. float scale;
  116. } IMUCalibrationData;
  117. /* Rumble hint mode:
  118. * "0": enhanced features are never used
  119. * "1": enhanced features are always used
  120. * "auto": enhanced features are advertised to the application, but SDL doesn't touch the controller state unless the application explicitly requests it.
  121. */
  122. typedef enum
  123. {
  124. PS4_ENHANCED_REPORT_HINT_OFF,
  125. PS4_ENHANCED_REPORT_HINT_ON,
  126. PS4_ENHANCED_REPORT_HINT_AUTO
  127. } HIDAPI_PS4_EnhancedReportHint;
  128. typedef struct
  129. {
  130. SDL_HIDAPI_Device *device;
  131. SDL_Joystick *joystick;
  132. bool is_dongle;
  133. bool is_nacon_dongle;
  134. bool official_controller;
  135. bool sensors_supported;
  136. bool lightbar_supported;
  137. bool vibration_supported;
  138. bool touchpad_supported;
  139. bool effects_supported;
  140. bool guitar_whammy_supported;
  141. bool guitar_tilt_supported;
  142. bool guitar_effects_selector_supported;
  143. HIDAPI_PS4_EnhancedReportHint enhanced_report_hint;
  144. bool enhanced_reports;
  145. bool enhanced_mode;
  146. bool enhanced_mode_available;
  147. Uint8 report_interval;
  148. bool report_sensors;
  149. bool report_touchpad;
  150. bool report_battery;
  151. bool hardware_calibration;
  152. IMUCalibrationData calibration[6];
  153. Uint64 last_packet;
  154. int player_index;
  155. Uint8 rumble_left;
  156. Uint8 rumble_right;
  157. bool color_set;
  158. Uint8 led_red;
  159. Uint8 led_green;
  160. Uint8 led_blue;
  161. Uint16 gyro_numerator;
  162. Uint16 gyro_denominator;
  163. Uint16 accel_numerator;
  164. Uint16 accel_denominator;
  165. Uint64 sensor_ticks;
  166. Uint16 last_tick;
  167. Uint16 valid_crc_packets; // wrapping counter
  168. PS4StatePacket_t last_state;
  169. } SDL_DriverPS4_Context;
  170. static bool HIDAPI_DriverPS4_InternalSendJoystickEffect(SDL_DriverPS4_Context *ctx, const void *effect, int size, EPS4Effect mask, bool application_usage);
  171. static void HIDAPI_DriverPS4_RegisterHints(SDL_HintCallback callback, void *userdata)
  172. {
  173. SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS4, callback, userdata);
  174. }
  175. static void HIDAPI_DriverPS4_UnregisterHints(SDL_HintCallback callback, void *userdata)
  176. {
  177. SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS4, callback, userdata);
  178. }
  179. static bool HIDAPI_DriverPS4_IsEnabled(void)
  180. {
  181. return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS4, SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, SDL_HIDAPI_DEFAULT));
  182. }
  183. static int ReadFeatureReport(SDL_hid_device *dev, Uint8 report_id, Uint8 *report, size_t length)
  184. {
  185. SDL_memset(report, 0, length);
  186. report[0] = report_id;
  187. return SDL_hid_get_feature_report(dev, report, length);
  188. }
  189. static bool HIDAPI_DriverPS4_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)
  190. {
  191. Uint8 data[USB_PACKET_LENGTH];
  192. int size;
  193. if (type == SDL_GAMEPAD_TYPE_PS4) {
  194. return true;
  195. }
  196. if (HIDAPI_SupportsPlaystationDetection(vendor_id, product_id)) {
  197. if (device && device->dev) {
  198. size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdCapabilities, data, sizeof(data));
  199. if (size == 48 && data[2] == 0x27) {
  200. // Supported third party controller
  201. return true;
  202. } else {
  203. return false;
  204. }
  205. } else {
  206. // Might be supported by this driver, enumerate and find out
  207. return true;
  208. }
  209. }
  210. return false;
  211. }
  212. static void SetLedsForPlayerIndex(DS4EffectsState_t *effects, int player_index)
  213. {
  214. /* This list is the same as what hid-sony.c uses in the Linux kernel.
  215. The first 4 values correspond to what the PS4 assigns.
  216. */
  217. static const Uint8 colors[7][3] = {
  218. { 0x00, 0x00, 0x40 }, // Blue
  219. { 0x40, 0x00, 0x00 }, // Red
  220. { 0x00, 0x40, 0x00 }, // Green
  221. { 0x20, 0x00, 0x20 }, // Pink
  222. { 0x02, 0x01, 0x00 }, // Orange
  223. { 0x00, 0x01, 0x01 }, // Teal
  224. { 0x01, 0x01, 0x01 } // White
  225. };
  226. if (player_index >= 0) {
  227. player_index %= SDL_arraysize(colors);
  228. } else {
  229. player_index = 0;
  230. }
  231. effects->ucLedRed = colors[player_index][0];
  232. effects->ucLedGreen = colors[player_index][1];
  233. effects->ucLedBlue = colors[player_index][2];
  234. }
  235. static bool ReadWiredSerial(SDL_HIDAPI_Device *device, char *serial, size_t serial_size)
  236. {
  237. Uint8 data[USB_PACKET_LENGTH];
  238. int size;
  239. size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdSerialNumber, data, sizeof(data));
  240. if (size >= 7 && (data[1] || data[2] || data[3] || data[4] || data[5] || data[6])) {
  241. (void)SDL_snprintf(serial, serial_size, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
  242. data[6], data[5], data[4], data[3], data[2], data[1]);
  243. return true;
  244. }
  245. return false;
  246. }
  247. static bool HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device)
  248. {
  249. SDL_DriverPS4_Context *ctx;
  250. Uint8 data[USB_PACKET_LENGTH];
  251. int size;
  252. char serial[18];
  253. SDL_JoystickType joystick_type = SDL_JOYSTICK_TYPE_GAMEPAD;
  254. ctx = (SDL_DriverPS4_Context *)SDL_calloc(1, sizeof(*ctx));
  255. if (!ctx) {
  256. return false;
  257. }
  258. ctx->device = device;
  259. ctx->gyro_numerator = 1;
  260. ctx->gyro_denominator = 16;
  261. ctx->accel_numerator = 1;
  262. ctx->accel_denominator = 8192;
  263. device->context = ctx;
  264. if (device->serial && SDL_strlen(device->serial) == 12) {
  265. int i, j;
  266. j = -1;
  267. for (i = 0; i < 12; i += 2) {
  268. j += 1;
  269. SDL_memmove(&serial[j], &device->serial[i], 2);
  270. j += 2;
  271. serial[j] = '-';
  272. }
  273. serial[j] = '\0';
  274. } else {
  275. serial[0] = '\0';
  276. }
  277. // Check for type of connection
  278. ctx->is_dongle = (device->vendor_id == USB_VENDOR_SONY && device->product_id == USB_PRODUCT_SONY_DS4_DONGLE);
  279. if (ctx->is_dongle) {
  280. ReadWiredSerial(device, serial, sizeof(serial));
  281. ctx->enhanced_reports = true;
  282. } else if (device->vendor_id == USB_VENDOR_SONY && device->product_id == USB_PRODUCT_SONY_DS4_STRIKEPAD) {
  283. ctx->enhanced_reports = true;
  284. } else if (device->vendor_id == USB_VENDOR_SONY) {
  285. if (device->is_bluetooth) {
  286. // Read a report to see if we're in enhanced mode
  287. size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 16);
  288. #ifdef DEBUG_PS4_PROTOCOL
  289. if (size > 0) {
  290. HIDAPI_DumpPacket("PS4 first packet: size = %d", data, size);
  291. } else {
  292. SDL_Log("PS4 first packet: size = %d", size);
  293. }
  294. #endif
  295. if (size > 0 &&
  296. data[0] >= k_EPS4ReportIdBluetoothState1 &&
  297. data[0] <= k_EPS4ReportIdBluetoothState9) {
  298. ctx->enhanced_reports = true;
  299. }
  300. } else {
  301. ReadWiredSerial(device, serial, sizeof(serial));
  302. ctx->enhanced_reports = true;
  303. }
  304. } else {
  305. // Third party controllers appear to all be wired
  306. ctx->enhanced_reports = true;
  307. }
  308. if (device->vendor_id == USB_VENDOR_SONY) {
  309. ctx->official_controller = true;
  310. ctx->sensors_supported = true;
  311. ctx->lightbar_supported = true;
  312. ctx->vibration_supported = true;
  313. ctx->touchpad_supported = true;
  314. } else {
  315. // Third party controller capability request
  316. size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdCapabilities, data, sizeof(data));
  317. // Get the device capabilities
  318. if (size == 48 && data[2] == 0x27) {
  319. Uint8 capabilities = data[4];
  320. Uint8 device_type = data[5];
  321. Uint8 device_specific_capabilities = data[24];
  322. Uint16 gyro_numerator = LOAD16(data[10], data[11]);
  323. Uint16 gyro_denominator = LOAD16(data[12], data[13]);
  324. Uint16 accel_numerator = LOAD16(data[14], data[15]);
  325. Uint16 accel_denominator = LOAD16(data[16], data[17]);
  326. #ifdef DEBUG_PS4_PROTOCOL
  327. HIDAPI_DumpPacket("PS4 capabilities: size = %d", data, size);
  328. #endif
  329. if (capabilities & 0x02) {
  330. ctx->sensors_supported = true;
  331. }
  332. if (capabilities & 0x04) {
  333. ctx->lightbar_supported = true;
  334. }
  335. if (capabilities & 0x08) {
  336. ctx->vibration_supported = true;
  337. }
  338. if (capabilities & 0x40) {
  339. ctx->touchpad_supported = true;
  340. }
  341. switch (device_type) {
  342. case 0x00:
  343. joystick_type = SDL_JOYSTICK_TYPE_GAMEPAD;
  344. break;
  345. case 0x01:
  346. joystick_type = SDL_JOYSTICK_TYPE_GUITAR;
  347. if (device_specific_capabilities & 0x01) {
  348. ctx->guitar_effects_selector_supported = true;
  349. }
  350. if (device_specific_capabilities & 0x02) {
  351. ctx->guitar_tilt_supported = true;
  352. }
  353. if (device_specific_capabilities & 0x04) {
  354. ctx->guitar_whammy_supported = true;
  355. }
  356. break;
  357. case 0x02:
  358. joystick_type = SDL_JOYSTICK_TYPE_DRUM_KIT;
  359. break;
  360. case 0x04:
  361. joystick_type = SDL_JOYSTICK_TYPE_DANCE_PAD;
  362. break;
  363. case 0x06:
  364. joystick_type = SDL_JOYSTICK_TYPE_WHEEL;
  365. break;
  366. case 0x07:
  367. joystick_type = SDL_JOYSTICK_TYPE_ARCADE_STICK;
  368. break;
  369. case 0x08:
  370. joystick_type = SDL_JOYSTICK_TYPE_FLIGHT_STICK;
  371. break;
  372. default:
  373. joystick_type = SDL_JOYSTICK_TYPE_UNKNOWN;
  374. break;
  375. }
  376. if (gyro_numerator && gyro_denominator) {
  377. ctx->gyro_numerator = gyro_numerator;
  378. ctx->gyro_denominator = gyro_denominator;
  379. }
  380. if (accel_numerator && accel_denominator) {
  381. ctx->accel_numerator = accel_numerator;
  382. ctx->accel_denominator = accel_denominator;
  383. }
  384. } else if (device->vendor_id == USB_VENDOR_RAZER) {
  385. // The Razer Raiju doesn't respond to the detection protocol, but has a touchpad and vibration
  386. ctx->vibration_supported = true;
  387. ctx->touchpad_supported = true;
  388. }
  389. }
  390. ctx->effects_supported = (ctx->lightbar_supported || ctx->vibration_supported);
  391. if (device->vendor_id == USB_VENDOR_NACON_ALT &&
  392. device->product_id == USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS4_WIRELESS) {
  393. ctx->is_nacon_dongle = true;
  394. }
  395. if (device->vendor_id == USB_VENDOR_PDP &&
  396. (device->product_id == USB_PRODUCT_VICTRIX_FS_PRO ||
  397. device->product_id == USB_PRODUCT_VICTRIX_FS_PRO_V2)) {
  398. /* The Victrix FS Pro V2 reports that it has lightbar support,
  399. * but it doesn't respond to the effects packet, and will hang
  400. * on reboot if we send it.
  401. */
  402. ctx->effects_supported = false;
  403. }
  404. device->joystick_type = joystick_type;
  405. device->type = SDL_GAMEPAD_TYPE_PS4;
  406. if (ctx->official_controller) {
  407. HIDAPI_SetDeviceName(device, "PS4 Controller");
  408. }
  409. HIDAPI_SetDeviceSerial(device, serial);
  410. // Prefer the USB device over the Bluetooth device
  411. if (device->is_bluetooth) {
  412. if (HIDAPI_HasConnectedUSBDevice(device->serial)) {
  413. return true;
  414. }
  415. } else {
  416. HIDAPI_DisconnectBluetoothDevice(device->serial);
  417. }
  418. if ((ctx->is_dongle || ctx->is_nacon_dongle) && serial[0] == '\0') {
  419. // Not yet connected
  420. return true;
  421. }
  422. return HIDAPI_JoystickConnected(device, NULL);
  423. }
  424. static int HIDAPI_DriverPS4_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
  425. {
  426. return -1;
  427. }
  428. static bool HIDAPI_DriverPS4_LoadOfficialCalibrationData(SDL_HIDAPI_Device *device)
  429. {
  430. SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
  431. int i, tries, size;
  432. bool have_data = false;
  433. Uint8 data[USB_PACKET_LENGTH];
  434. if (!ctx->official_controller) {
  435. #ifdef DEBUG_PS4_CALIBRATION
  436. SDL_Log("Not an official controller, ignoring calibration");
  437. #endif
  438. return false;
  439. }
  440. for (tries = 0; tries < 5; ++tries) {
  441. // For Bluetooth controllers, this report switches them into advanced report mode
  442. size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdGyroCalibration_USB, data, sizeof(data));
  443. if (size < 35) {
  444. #ifdef DEBUG_PS4_CALIBRATION
  445. SDL_Log("Short read of calibration data: %d, ignoring calibration", size);
  446. #endif
  447. return false;
  448. }
  449. if (device->is_bluetooth) {
  450. size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdGyroCalibration_BT, data, sizeof(data));
  451. if (size < 35) {
  452. #ifdef DEBUG_PS4_CALIBRATION
  453. SDL_Log("Short read of calibration data: %d, ignoring calibration", size);
  454. #endif
  455. return false;
  456. }
  457. }
  458. // In some cases this report returns all zeros. Usually immediately after connection with the PS4 Dongle
  459. for (i = 0; i < size; ++i) {
  460. if (data[i]) {
  461. have_data = true;
  462. break;
  463. }
  464. }
  465. if (have_data) {
  466. break;
  467. }
  468. SDL_Delay(2);
  469. }
  470. if (have_data) {
  471. Sint16 sGyroPitchBias, sGyroYawBias, sGyroRollBias;
  472. Sint16 sGyroPitchPlus, sGyroPitchMinus;
  473. Sint16 sGyroYawPlus, sGyroYawMinus;
  474. Sint16 sGyroRollPlus, sGyroRollMinus;
  475. Sint16 sGyroSpeedPlus, sGyroSpeedMinus;
  476. Sint16 sAccXPlus, sAccXMinus;
  477. Sint16 sAccYPlus, sAccYMinus;
  478. Sint16 sAccZPlus, sAccZMinus;
  479. float flNumerator;
  480. float flDenominator;
  481. Sint16 sRange2g;
  482. #ifdef DEBUG_PS4_CALIBRATION
  483. HIDAPI_DumpPacket("PS4 calibration packet: size = %d", data, size);
  484. #endif
  485. sGyroPitchBias = LOAD16(data[1], data[2]);
  486. sGyroYawBias = LOAD16(data[3], data[4]);
  487. sGyroRollBias = LOAD16(data[5], data[6]);
  488. if (device->is_bluetooth || ctx->is_dongle) {
  489. sGyroPitchPlus = LOAD16(data[7], data[8]);
  490. sGyroYawPlus = LOAD16(data[9], data[10]);
  491. sGyroRollPlus = LOAD16(data[11], data[12]);
  492. sGyroPitchMinus = LOAD16(data[13], data[14]);
  493. sGyroYawMinus = LOAD16(data[15], data[16]);
  494. sGyroRollMinus = LOAD16(data[17], data[18]);
  495. } else {
  496. sGyroPitchPlus = LOAD16(data[7], data[8]);
  497. sGyroPitchMinus = LOAD16(data[9], data[10]);
  498. sGyroYawPlus = LOAD16(data[11], data[12]);
  499. sGyroYawMinus = LOAD16(data[13], data[14]);
  500. sGyroRollPlus = LOAD16(data[15], data[16]);
  501. sGyroRollMinus = LOAD16(data[17], data[18]);
  502. }
  503. sGyroSpeedPlus = LOAD16(data[19], data[20]);
  504. sGyroSpeedMinus = LOAD16(data[21], data[22]);
  505. sAccXPlus = LOAD16(data[23], data[24]);
  506. sAccXMinus = LOAD16(data[25], data[26]);
  507. sAccYPlus = LOAD16(data[27], data[28]);
  508. sAccYMinus = LOAD16(data[29], data[30]);
  509. sAccZPlus = LOAD16(data[31], data[32]);
  510. sAccZMinus = LOAD16(data[33], data[34]);
  511. flNumerator = (float)(sGyroSpeedPlus + sGyroSpeedMinus) * ctx->gyro_denominator / ctx->gyro_numerator;
  512. flDenominator = (float)(SDL_abs(sGyroPitchPlus - sGyroPitchBias) + SDL_abs(sGyroPitchMinus - sGyroPitchBias));
  513. if (flDenominator != 0.0f) {
  514. ctx->calibration[0].bias = sGyroPitchBias;
  515. ctx->calibration[0].scale = flNumerator / flDenominator;
  516. }
  517. flDenominator = (float)(SDL_abs(sGyroYawPlus - sGyroYawBias) + SDL_abs(sGyroYawMinus - sGyroYawBias));
  518. if (flDenominator != 0.0f) {
  519. ctx->calibration[1].bias = sGyroYawBias;
  520. ctx->calibration[1].scale = flNumerator / flDenominator;
  521. }
  522. flDenominator = (float)(SDL_abs(sGyroRollPlus - sGyroRollBias) + SDL_abs(sGyroRollMinus - sGyroRollBias));
  523. if (flDenominator != 0.0f) {
  524. ctx->calibration[2].bias = sGyroRollBias;
  525. ctx->calibration[2].scale = flNumerator / flDenominator;
  526. }
  527. sRange2g = sAccXPlus - sAccXMinus;
  528. ctx->calibration[3].bias = sAccXPlus - sRange2g / 2;
  529. ctx->calibration[3].scale = (2.0f * ctx->accel_denominator / ctx->accel_numerator) / sRange2g;
  530. sRange2g = sAccYPlus - sAccYMinus;
  531. ctx->calibration[4].bias = sAccYPlus - sRange2g / 2;
  532. ctx->calibration[4].scale = (2.0f * ctx->accel_denominator / ctx->accel_numerator) / sRange2g;
  533. sRange2g = sAccZPlus - sAccZMinus;
  534. ctx->calibration[5].bias = sAccZPlus - sRange2g / 2;
  535. ctx->calibration[5].scale = (2.0f * ctx->accel_denominator / ctx->accel_numerator) / sRange2g;
  536. ctx->hardware_calibration = true;
  537. for (i = 0; i < 6; ++i) {
  538. #ifdef DEBUG_PS4_CALIBRATION
  539. SDL_Log("calibration[%d] bias = %d, sensitivity = %f", i, ctx->calibration[i].bias, ctx->calibration[i].scale);
  540. #endif
  541. // Some controllers have a bad calibration
  542. if (SDL_abs(ctx->calibration[i].bias) > 1024 || SDL_fabsf(1.0f - ctx->calibration[i].scale) > 0.5f) {
  543. #ifdef DEBUG_PS4_CALIBRATION
  544. SDL_Log("invalid calibration, ignoring");
  545. #endif
  546. ctx->hardware_calibration = false;
  547. }
  548. }
  549. } else {
  550. #ifdef DEBUG_PS4_CALIBRATION
  551. SDL_Log("Calibration data not available");
  552. #endif
  553. }
  554. return ctx->hardware_calibration;
  555. }
  556. static void HIDAPI_DriverPS4_LoadCalibrationData(SDL_HIDAPI_Device *device)
  557. {
  558. SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
  559. int i;
  560. if (!HIDAPI_DriverPS4_LoadOfficialCalibrationData(device)) {
  561. for (i = 0; i < SDL_arraysize(ctx->calibration); ++i) {
  562. ctx->calibration[i].bias = 0;
  563. ctx->calibration[i].scale = 1.0f;
  564. }
  565. }
  566. // Scale the raw data to the units expected by SDL
  567. for (i = 0; i < SDL_arraysize(ctx->calibration); ++i) {
  568. double scale = ctx->calibration[i].scale;
  569. if (i < 3) {
  570. scale *= ((double)ctx->gyro_numerator / ctx->gyro_denominator) * SDL_PI_D / 180.0;
  571. if (device->vendor_id == USB_VENDOR_SONY &&
  572. device->product_id == USB_PRODUCT_SONY_DS4_STRIKEPAD) {
  573. // The Armor-X Pro seems to only deliver half the rotation it should
  574. scale *= 2.0;
  575. }
  576. } else {
  577. scale *= ((double)ctx->accel_numerator / ctx->accel_denominator) * SDL_STANDARD_GRAVITY;
  578. if (device->vendor_id == USB_VENDOR_SONY &&
  579. device->product_id == USB_PRODUCT_SONY_DS4_STRIKEPAD) {
  580. /* The Armor-X Pro seems to only deliver half the acceleration it should,
  581. * and in the opposite direction on all axes */
  582. scale *= -2.0;
  583. }
  584. }
  585. ctx->calibration[i].scale = (float)scale;
  586. }
  587. }
  588. static float HIDAPI_DriverPS4_ApplyCalibrationData(SDL_DriverPS4_Context *ctx, int index, Sint16 value)
  589. {
  590. IMUCalibrationData *calibration = &ctx->calibration[index];
  591. return ((float)value - calibration->bias) * calibration->scale;
  592. }
  593. static bool HIDAPI_DriverPS4_UpdateEffects(SDL_DriverPS4_Context *ctx, EPS4Effect mask, bool application_usage)
  594. {
  595. DS4EffectsState_t effects;
  596. SDL_zero(effects);
  597. if (ctx->vibration_supported) {
  598. effects.ucRumbleLeft = ctx->rumble_left;
  599. effects.ucRumbleRight = ctx->rumble_right;
  600. }
  601. if (ctx->lightbar_supported) {
  602. // Populate the LED state with the appropriate color from our lookup table
  603. if (ctx->color_set) {
  604. effects.ucLedRed = ctx->led_red;
  605. effects.ucLedGreen = ctx->led_green;
  606. effects.ucLedBlue = ctx->led_blue;
  607. } else {
  608. SetLedsForPlayerIndex(&effects, ctx->player_index);
  609. }
  610. }
  611. return HIDAPI_DriverPS4_InternalSendJoystickEffect(ctx, &effects, sizeof(effects), mask, application_usage);
  612. }
  613. static void HIDAPI_DriverPS4_TickleBluetooth(SDL_HIDAPI_Device *device)
  614. {
  615. SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
  616. if (ctx->enhanced_reports) {
  617. // This is just a dummy packet that should have no effect, since we don't set the CRC
  618. Uint8 data[78];
  619. SDL_zeroa(data);
  620. data[0] = k_EPS4ReportIdBluetoothEffects;
  621. data[1] = 0xC0; // Magic value HID + CRC
  622. if (SDL_HIDAPI_LockRumble()) {
  623. SDL_HIDAPI_SendRumbleAndUnlock(device, data, sizeof(data));
  624. }
  625. } else {
  626. #if 0 /* The 8BitDo Zero 2 has perfect emulation of a PS4 controller, except it
  627. * only sends reports when the state changes, so we can't disconnect here.
  628. */
  629. // We can't even send an invalid effects packet, or it will put the controller in enhanced mode
  630. if (device->num_joysticks > 0) {
  631. HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
  632. }
  633. #endif
  634. }
  635. }
  636. static void HIDAPI_DriverPS4_SetEnhancedModeAvailable(SDL_DriverPS4_Context *ctx)
  637. {
  638. if (ctx->enhanced_mode_available) {
  639. return;
  640. }
  641. ctx->enhanced_mode_available = true;
  642. if (ctx->touchpad_supported) {
  643. SDL_PrivateJoystickAddTouchpad(ctx->joystick, 2);
  644. ctx->report_touchpad = true;
  645. }
  646. if (ctx->sensors_supported) {
  647. SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_GYRO, (float)(1000 / ctx->report_interval));
  648. SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, (float)(1000 / ctx->report_interval));
  649. }
  650. if (ctx->guitar_tilt_supported) {
  651. SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, (float)(1000 / ctx->report_interval));
  652. }
  653. if (ctx->official_controller) {
  654. ctx->report_battery = true;
  655. }
  656. HIDAPI_UpdateDeviceProperties(ctx->device);
  657. }
  658. static void HIDAPI_DriverPS4_SetEnhancedMode(SDL_DriverPS4_Context *ctx)
  659. {
  660. HIDAPI_DriverPS4_SetEnhancedModeAvailable(ctx);
  661. if (!ctx->enhanced_mode) {
  662. ctx->enhanced_mode = true;
  663. // Switch into enhanced report mode
  664. HIDAPI_DriverPS4_UpdateEffects(ctx, 0, false);
  665. }
  666. }
  667. static void HIDAPI_DriverPS4_SetEnhancedReportHint(SDL_DriverPS4_Context *ctx, HIDAPI_PS4_EnhancedReportHint enhanced_report_hint)
  668. {
  669. switch (enhanced_report_hint) {
  670. case PS4_ENHANCED_REPORT_HINT_OFF:
  671. // Nothing to do, enhanced mode is a one-way ticket
  672. break;
  673. case PS4_ENHANCED_REPORT_HINT_ON:
  674. HIDAPI_DriverPS4_SetEnhancedMode(ctx);
  675. break;
  676. case PS4_ENHANCED_REPORT_HINT_AUTO:
  677. HIDAPI_DriverPS4_SetEnhancedModeAvailable(ctx);
  678. break;
  679. }
  680. ctx->enhanced_report_hint = enhanced_report_hint;
  681. }
  682. static void HIDAPI_DriverPS4_UpdateEnhancedModeOnEnhancedReport(SDL_DriverPS4_Context *ctx)
  683. {
  684. ctx->enhanced_reports = true;
  685. if (ctx->enhanced_report_hint == PS4_ENHANCED_REPORT_HINT_AUTO) {
  686. HIDAPI_DriverPS4_SetEnhancedReportHint(ctx, PS4_ENHANCED_REPORT_HINT_ON);
  687. }
  688. }
  689. static void HIDAPI_DriverPS4_UpdateEnhancedModeOnApplicationUsage(SDL_DriverPS4_Context *ctx)
  690. {
  691. if (ctx->enhanced_report_hint == PS4_ENHANCED_REPORT_HINT_AUTO) {
  692. HIDAPI_DriverPS4_SetEnhancedReportHint(ctx, PS4_ENHANCED_REPORT_HINT_ON);
  693. }
  694. }
  695. static void SDLCALL SDL_PS4EnhancedReportsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
  696. {
  697. SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)userdata;
  698. if (ctx->device->is_bluetooth) {
  699. if (hint && SDL_strcasecmp(hint, "auto") == 0) {
  700. HIDAPI_DriverPS4_SetEnhancedReportHint(ctx, PS4_ENHANCED_REPORT_HINT_AUTO);
  701. } else if (SDL_GetStringBoolean(hint, true)) {
  702. HIDAPI_DriverPS4_SetEnhancedReportHint(ctx, PS4_ENHANCED_REPORT_HINT_ON);
  703. } else {
  704. HIDAPI_DriverPS4_SetEnhancedReportHint(ctx, PS4_ENHANCED_REPORT_HINT_OFF);
  705. }
  706. } else {
  707. HIDAPI_DriverPS4_SetEnhancedReportHint(ctx, PS4_ENHANCED_REPORT_HINT_ON);
  708. }
  709. }
  710. static void SDLCALL SDL_PS4ReportIntervalHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
  711. {
  712. const int DEFAULT_REPORT_INTERVAL = 4;
  713. SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)userdata;
  714. int new_report_interval = DEFAULT_REPORT_INTERVAL;
  715. if (hint) {
  716. int report_interval = SDL_atoi(hint);
  717. switch (report_interval) {
  718. case 1:
  719. case 2:
  720. case 4:
  721. // Valid values
  722. new_report_interval = report_interval;
  723. break;
  724. default:
  725. break;
  726. }
  727. }
  728. if (new_report_interval != ctx->report_interval) {
  729. ctx->report_interval = (Uint8)new_report_interval;
  730. HIDAPI_DriverPS4_UpdateEffects(ctx, 0, false);
  731. SDL_LockJoysticks();
  732. SDL_PrivateJoystickSensorRate(ctx->joystick, SDL_SENSOR_GYRO, (float)(1000 / ctx->report_interval));
  733. SDL_PrivateJoystickSensorRate(ctx->joystick, SDL_SENSOR_ACCEL, (float)(1000 / ctx->report_interval));
  734. SDL_UnlockJoysticks();
  735. }
  736. }
  737. static void HIDAPI_DriverPS4_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
  738. {
  739. SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
  740. if (!ctx->joystick) {
  741. return;
  742. }
  743. ctx->player_index = player_index;
  744. // This will set the new LED state based on the new player index
  745. // SDL automatically calls this, so it doesn't count as an application action to enable enhanced mode
  746. HIDAPI_DriverPS4_UpdateEffects(ctx, k_EPS4EffectLED, false);
  747. }
  748. static bool HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
  749. {
  750. SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
  751. SDL_AssertJoysticksLocked();
  752. ctx->joystick = joystick;
  753. ctx->last_packet = SDL_GetTicks();
  754. ctx->report_sensors = false;
  755. ctx->report_touchpad = false;
  756. ctx->rumble_left = 0;
  757. ctx->rumble_right = 0;
  758. ctx->color_set = false;
  759. SDL_zero(ctx->last_state);
  760. // Initialize player index (needed for setting LEDs)
  761. ctx->player_index = SDL_GetJoystickPlayerIndex(joystick);
  762. // Initialize the joystick capabilities
  763. joystick->nbuttons = 11;
  764. if (ctx->touchpad_supported) {
  765. joystick->nbuttons += 1;
  766. }
  767. joystick->naxes = SDL_GAMEPAD_AXIS_COUNT;
  768. joystick->nhats = 1;
  769. SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS4_REPORT_INTERVAL,
  770. SDL_PS4ReportIntervalHintChanged, ctx);
  771. SDL_AddHintCallback(SDL_HINT_JOYSTICK_ENHANCED_REPORTS,
  772. SDL_PS4EnhancedReportsChanged, ctx);
  773. return true;
  774. }
  775. static bool HIDAPI_DriverPS4_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
  776. {
  777. SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
  778. if (!ctx->vibration_supported) {
  779. return SDL_Unsupported();
  780. }
  781. ctx->rumble_left = (low_frequency_rumble >> 8);
  782. ctx->rumble_right = (high_frequency_rumble >> 8);
  783. return HIDAPI_DriverPS4_UpdateEffects(ctx, k_EPS4EffectRumble, true);
  784. }
  785. static bool HIDAPI_DriverPS4_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
  786. {
  787. return SDL_Unsupported();
  788. }
  789. static Uint32 HIDAPI_DriverPS4_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
  790. {
  791. SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
  792. Uint32 result = 0;
  793. if (ctx->enhanced_mode_available) {
  794. if (ctx->lightbar_supported) {
  795. result |= SDL_JOYSTICK_CAP_RGB_LED;
  796. }
  797. if (ctx->vibration_supported) {
  798. result |= SDL_JOYSTICK_CAP_RUMBLE;
  799. }
  800. }
  801. return result;
  802. }
  803. static bool HIDAPI_DriverPS4_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
  804. {
  805. SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
  806. if (!ctx->lightbar_supported) {
  807. return SDL_Unsupported();
  808. }
  809. ctx->color_set = true;
  810. ctx->led_red = red;
  811. ctx->led_green = green;
  812. ctx->led_blue = blue;
  813. return HIDAPI_DriverPS4_UpdateEffects(ctx, k_EPS4EffectLED, true);
  814. }
  815. static bool HIDAPI_DriverPS4_InternalSendJoystickEffect(SDL_DriverPS4_Context *ctx, const void *effect, int size, EPS4Effect mask, bool application_usage)
  816. {
  817. Uint8 data[78];
  818. int report_size, offset;
  819. if (!ctx->effects_supported) {
  820. // We shouldn't be sending packets to this controller
  821. return SDL_Unsupported();
  822. }
  823. if (!ctx->enhanced_mode) {
  824. if (application_usage) {
  825. HIDAPI_DriverPS4_UpdateEnhancedModeOnApplicationUsage(ctx);
  826. }
  827. if (!ctx->enhanced_mode) {
  828. // We're not in enhanced mode, effects aren't allowed
  829. return SDL_Unsupported();
  830. }
  831. }
  832. SDL_zeroa(data);
  833. if (ctx->device->is_bluetooth && ctx->official_controller) {
  834. data[0] = k_EPS4ReportIdBluetoothEffects;
  835. data[1] = 0xC0 | ctx->report_interval; // Magic value HID + CRC, also sets update interval
  836. // Some third-party PS4 gamepads expect to receive both rumble and LED together,
  837. // so we will only send them separately to official Sony gamepads. Unfortunately,
  838. // this means that we'll fight with other apps that might be controlling one or
  839. // the other separately for third-party PS4 gamepads. We can add a whitelist for
  840. // compatible third-party gamepads later if we want.
  841. data[3] = (Uint8)(ctx->official_controller ? mask : (k_EPS4EffectRumble | k_EPS4EffectLED));
  842. report_size = 78;
  843. offset = 6;
  844. } else {
  845. data[0] = k_EPS4ReportIdUsbEffects;
  846. // FIXME: Should we send a consistent default effect mask between BT and USB?
  847. data[1] = (Uint8)(ctx->official_controller ? mask : (k_EPS4EffectRumble | k_EPS4EffectLED | k_EPS4EffectLEDBlink));
  848. report_size = 32;
  849. offset = 4;
  850. }
  851. SDL_memcpy(&data[offset], effect, SDL_min((sizeof(data) - offset), (size_t)size));
  852. if (ctx->device->is_bluetooth) {
  853. // Bluetooth reports need a CRC at the end of the packet (at least on Linux)
  854. Uint8 ubHdr = 0xA2; // hidp header is part of the CRC calculation
  855. Uint32 unCRC;
  856. unCRC = SDL_crc32(0, &ubHdr, 1);
  857. unCRC = SDL_crc32(unCRC, data, (size_t)(report_size - sizeof(unCRC)));
  858. SDL_memcpy(&data[report_size - sizeof(unCRC)], &unCRC, sizeof(unCRC));
  859. }
  860. if (SDL_HIDAPI_SendRumble(ctx->device, data, report_size) != report_size) {
  861. return SDL_SetError("Couldn't send rumble packet");
  862. }
  863. return true;
  864. }
  865. static bool HIDAPI_DriverPS4_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *effect, int size)
  866. {
  867. SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
  868. EPS4Effect mask;
  869. // Unlike the PS5 driver, the PS4 driver does not expect the validity bits as part of
  870. // the provided effect data. The default values we provide also diverge for different
  871. // gamepads and connection mediums. We should probably clean this up eventually.
  872. if (ctx->device->is_bluetooth && ctx->official_controller) {
  873. mask = k_EPS4EffectRumble | k_EPS4EffectLED;
  874. } else {
  875. mask = k_EPS4EffectRumble | k_EPS4EffectLED | k_EPS4EffectLEDBlink;
  876. }
  877. return HIDAPI_DriverPS4_InternalSendJoystickEffect(ctx, effect, size, mask, true);
  878. }
  879. static bool HIDAPI_DriverPS4_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, bool enabled)
  880. {
  881. SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
  882. HIDAPI_DriverPS4_UpdateEnhancedModeOnApplicationUsage(ctx);
  883. if ((!ctx->sensors_supported || (enabled && !ctx->enhanced_mode)) && !ctx->guitar_tilt_supported) {
  884. return SDL_Unsupported();
  885. }
  886. if (enabled) {
  887. HIDAPI_DriverPS4_LoadCalibrationData(device);
  888. }
  889. ctx->report_sensors = enabled;
  890. return true;
  891. }
  892. static void HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS4_Context *ctx, PS4StatePacket_t *packet, int size)
  893. {
  894. static const float TOUCHPAD_SCALEX = 5.20833333e-4f; // 1.0f / 1920
  895. static const float TOUCHPAD_SCALEY = 1.08695652e-3f; // 1.0f / 920 // This is noted as being 944 resolution, but 920 feels better
  896. Sint16 axis;
  897. bool touchpad_down;
  898. int touchpad_x, touchpad_y;
  899. Uint64 timestamp = SDL_GetTicksNS();
  900. if (size > 9 && ctx->report_touchpad && ctx->enhanced_reports) {
  901. touchpad_down = ((packet->ucTouchpadCounter1 & 0x80) == 0);
  902. touchpad_x = packet->rgucTouchpadData1[0] | (((int)packet->rgucTouchpadData1[1] & 0x0F) << 8);
  903. touchpad_y = (packet->rgucTouchpadData1[1] >> 4) | ((int)packet->rgucTouchpadData1[2] << 4);
  904. SDL_SendJoystickTouchpad(timestamp, joystick, 0, 0, touchpad_down, touchpad_x * TOUCHPAD_SCALEX, touchpad_y * TOUCHPAD_SCALEY, touchpad_down ? 1.0f : 0.0f);
  905. touchpad_down = ((packet->ucTouchpadCounter2 & 0x80) == 0);
  906. touchpad_x = packet->rgucTouchpadData2[0] | (((int)packet->rgucTouchpadData2[1] & 0x0F) << 8);
  907. touchpad_y = (packet->rgucTouchpadData2[1] >> 4) | ((int)packet->rgucTouchpadData2[2] << 4);
  908. SDL_SendJoystickTouchpad(timestamp, joystick, 0, 1, touchpad_down, touchpad_x * TOUCHPAD_SCALEX, touchpad_y * TOUCHPAD_SCALEY, touchpad_down ? 1.0f : 0.0f);
  909. }
  910. if (ctx->last_state.rgucButtonsHatAndCounter[0] != packet->rgucButtonsHatAndCounter[0]) {
  911. {
  912. Uint8 data = (packet->rgucButtonsHatAndCounter[0] >> 4);
  913. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, ((data & 0x01) != 0));
  914. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, ((data & 0x02) != 0));
  915. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, ((data & 0x04) != 0));
  916. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, ((data & 0x08) != 0));
  917. }
  918. {
  919. Uint8 hat;
  920. Uint8 data = (packet->rgucButtonsHatAndCounter[0] & 0x0F);
  921. switch (data) {
  922. case 0:
  923. hat = SDL_HAT_UP;
  924. break;
  925. case 1:
  926. hat = SDL_HAT_RIGHTUP;
  927. break;
  928. case 2:
  929. hat = SDL_HAT_RIGHT;
  930. break;
  931. case 3:
  932. hat = SDL_HAT_RIGHTDOWN;
  933. break;
  934. case 4:
  935. hat = SDL_HAT_DOWN;
  936. break;
  937. case 5:
  938. hat = SDL_HAT_LEFTDOWN;
  939. break;
  940. case 6:
  941. hat = SDL_HAT_LEFT;
  942. break;
  943. case 7:
  944. hat = SDL_HAT_LEFTUP;
  945. break;
  946. default:
  947. hat = SDL_HAT_CENTERED;
  948. break;
  949. }
  950. SDL_SendJoystickHat(timestamp, joystick, 0, hat);
  951. }
  952. }
  953. if (ctx->last_state.rgucButtonsHatAndCounter[1] != packet->rgucButtonsHatAndCounter[1]) {
  954. Uint8 data = packet->rgucButtonsHatAndCounter[1];
  955. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data & 0x01) != 0));
  956. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data & 0x02) != 0));
  957. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data & 0x10) != 0));
  958. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data & 0x20) != 0));
  959. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data & 0x40) != 0));
  960. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data & 0x80) != 0));
  961. }
  962. /* 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
  963. trigger is evaluated
  964. */
  965. if (packet->rgucButtonsHatAndCounter[1] & 0x0C) {
  966. Uint8 data = packet->rgucButtonsHatAndCounter[1];
  967. packet->ucTriggerLeft = (data & 0x04) && packet->ucTriggerLeft == 0 ? 255 : packet->ucTriggerLeft;
  968. packet->ucTriggerRight = (data & 0x08) && packet->ucTriggerRight == 0 ? 255 : packet->ucTriggerRight;
  969. }
  970. if (ctx->last_state.rgucButtonsHatAndCounter[2] != packet->rgucButtonsHatAndCounter[2]) {
  971. Uint8 data = (packet->rgucButtonsHatAndCounter[2] & 0x03);
  972. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data & 0x01) != 0));
  973. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_PS4_TOUCHPAD, ((data & 0x02) != 0));
  974. }
  975. axis = ((int)packet->ucTriggerLeft * 257) - 32768;
  976. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis);
  977. axis = ((int)packet->ucTriggerRight * 257) - 32768;
  978. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis);
  979. axis = ((int)packet->ucLeftJoystickX * 257) - 32768;
  980. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis);
  981. axis = ((int)packet->ucLeftJoystickY * 257) - 32768;
  982. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis);
  983. axis = ((int)packet->ucRightJoystickX * 257) - 32768;
  984. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis);
  985. axis = ((int)packet->ucRightJoystickY * 257) - 32768;
  986. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis);
  987. if (size > 9 && ctx->report_battery && ctx->enhanced_reports) {
  988. SDL_PowerState state;
  989. int percent;
  990. Uint8 level = (packet->ucBatteryLevel & 0x0F);
  991. if (packet->ucBatteryLevel & 0x10) {
  992. if (level <= 10) {
  993. state = SDL_POWERSTATE_CHARGING;
  994. percent = SDL_min(level * 10 + 5, 100);
  995. } else if (level == 11) {
  996. state = SDL_POWERSTATE_CHARGED;
  997. percent = 100;
  998. } else {
  999. state = SDL_POWERSTATE_UNKNOWN;
  1000. percent = 0;
  1001. }
  1002. } else {
  1003. state = SDL_POWERSTATE_ON_BATTERY;
  1004. percent = SDL_min(level * 10 + 5, 100);
  1005. }
  1006. SDL_SendJoystickPowerInfo(joystick, state, percent);
  1007. }
  1008. if (size > 9 && ctx->report_sensors) {
  1009. Uint16 tick;
  1010. Uint16 delta;
  1011. Uint64 sensor_timestamp;
  1012. float data[3];
  1013. tick = LOAD16(packet->rgucTimestamp[0], packet->rgucTimestamp[1]);
  1014. if (ctx->last_tick <= tick) {
  1015. delta = (tick - ctx->last_tick);
  1016. } else {
  1017. delta = (SDL_MAX_UINT16 - ctx->last_tick + tick + 1);
  1018. }
  1019. ctx->sensor_ticks += delta;
  1020. ctx->last_tick = tick;
  1021. // Sensor timestamp is in 5.33us units
  1022. sensor_timestamp = (ctx->sensor_ticks * SDL_NS_PER_US * 16) / 3;
  1023. data[0] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 0, LOAD16(packet->rgucGyroX[0], packet->rgucGyroX[1]));
  1024. data[1] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 1, LOAD16(packet->rgucGyroY[0], packet->rgucGyroY[1]));
  1025. data[2] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 2, LOAD16(packet->rgucGyroZ[0], packet->rgucGyroZ[1]));
  1026. SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, sensor_timestamp, data, 3);
  1027. data[0] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 3, LOAD16(packet->rgucAccelX[0], packet->rgucAccelX[1]));
  1028. data[1] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 4, LOAD16(packet->rgucAccelY[0], packet->rgucAccelY[1]));
  1029. data[2] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 5, LOAD16(packet->rgucAccelZ[0], packet->rgucAccelZ[1]));
  1030. SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, sensor_timestamp, data, 3);
  1031. }
  1032. if (ctx->guitar_whammy_supported) {
  1033. axis = ((int)packet->rgucDeviceSpecific[1] * 257) - 32768;
  1034. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis);
  1035. }
  1036. if (ctx->guitar_effects_selector_supported) {
  1037. // Align pickup selector mappings with PS3 instruments
  1038. static const Sint16 effects_mappings[] = {24576, 11008, -1792, -13568, -26880};
  1039. if (packet->rgucDeviceSpecific[0] < SDL_arraysize(effects_mappings)) {
  1040. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, effects_mappings[packet->rgucDeviceSpecific[0]]);
  1041. }
  1042. }
  1043. if (ctx->guitar_tilt_supported) {
  1044. float sensor_data[3];
  1045. sensor_data[0] = ((float)packet->rgucDeviceSpecific[2] / 255) * SDL_STANDARD_GRAVITY;
  1046. sensor_data[1] = 0;
  1047. sensor_data[2] = 0;
  1048. SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, timestamp, sensor_data, SDL_arraysize(sensor_data));
  1049. // Align tilt mappings with PS3 instruments
  1050. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, packet->rgucDeviceSpecific[2] > 0xF0);
  1051. }
  1052. SDL_memcpy(&ctx->last_state, packet, sizeof(ctx->last_state));
  1053. }
  1054. static bool VerifyCRC(Uint8 *data, int size)
  1055. {
  1056. Uint8 ubHdr = 0xA1; // hidp header is part of the CRC calculation
  1057. Uint32 unCRC, unPacketCRC;
  1058. Uint8 *packetCRC = data + size - sizeof(unPacketCRC);
  1059. unCRC = SDL_crc32(0, &ubHdr, 1);
  1060. unCRC = SDL_crc32(unCRC, data, (size_t)(size - sizeof(unCRC)));
  1061. unPacketCRC = LOAD32(packetCRC[0],
  1062. packetCRC[1],
  1063. packetCRC[2],
  1064. packetCRC[3]);
  1065. return (unCRC == unPacketCRC);
  1066. }
  1067. static bool HIDAPI_DriverPS4_IsPacketValid(SDL_DriverPS4_Context *ctx, Uint8 *data, int size)
  1068. {
  1069. switch (data[0]) {
  1070. case k_EPS4ReportIdUsbState:
  1071. if (size == 10) {
  1072. // This is non-enhanced mode, this packet is fine
  1073. return true;
  1074. }
  1075. if (ctx->is_nacon_dongle && size >= (1 + sizeof(PS4StatePacket_t))) {
  1076. // The report timestamp doesn't change when the controller isn't connected
  1077. PS4StatePacket_t *packet = (PS4StatePacket_t *)&data[1];
  1078. if (SDL_memcmp(packet->rgucTimestamp, ctx->last_state.rgucTimestamp, sizeof(packet->rgucTimestamp)) == 0) {
  1079. return false;
  1080. }
  1081. if (ctx->last_state.rgucAccelX[0] == 0 && ctx->last_state.rgucAccelX[1] == 0 &&
  1082. ctx->last_state.rgucAccelY[0] == 0 && ctx->last_state.rgucAccelY[1] == 0 &&
  1083. ctx->last_state.rgucAccelZ[0] == 0 && ctx->last_state.rgucAccelZ[1] == 0) {
  1084. // We don't have any state to compare yet, go ahead and copy it
  1085. SDL_memcpy(&ctx->last_state, &data[1], sizeof(PS4StatePacket_t));
  1086. return false;
  1087. }
  1088. }
  1089. /* In the case of a DS4 USB dongle, bit[2] of byte 31 indicates if a DS4 is actually connected (indicated by '0').
  1090. * For non-dongle, this bit is always 0 (connected).
  1091. * This is usually the ID over USB, but the DS4v2 that started shipping with the PS4 Slim will also send this
  1092. * packet over BT with a size of 128
  1093. */
  1094. if (size >= 64 && !(data[31] & 0x04)) {
  1095. return true;
  1096. }
  1097. break;
  1098. case k_EPS4ReportIdBluetoothState1:
  1099. case k_EPS4ReportIdBluetoothState2:
  1100. case k_EPS4ReportIdBluetoothState3:
  1101. case k_EPS4ReportIdBluetoothState4:
  1102. case k_EPS4ReportIdBluetoothState5:
  1103. case k_EPS4ReportIdBluetoothState6:
  1104. case k_EPS4ReportIdBluetoothState7:
  1105. case k_EPS4ReportIdBluetoothState8:
  1106. case k_EPS4ReportIdBluetoothState9:
  1107. // Bluetooth state packets have two additional bytes at the beginning, the first notes if HID data is present
  1108. if (size >= 78 && (data[1] & 0x80)) {
  1109. if (VerifyCRC(data, 78)) {
  1110. ++ctx->valid_crc_packets;
  1111. } else {
  1112. if (ctx->valid_crc_packets > 0) {
  1113. --ctx->valid_crc_packets;
  1114. }
  1115. if (ctx->valid_crc_packets >= 3) {
  1116. // We're generally getting valid CRC, but failed one
  1117. return false;
  1118. }
  1119. }
  1120. return true;
  1121. }
  1122. break;
  1123. default:
  1124. break;
  1125. }
  1126. return false;
  1127. }
  1128. static bool HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
  1129. {
  1130. SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
  1131. SDL_Joystick *joystick = NULL;
  1132. Uint8 data[USB_PACKET_LENGTH * 2];
  1133. int size;
  1134. int packet_count = 0;
  1135. Uint64 now = SDL_GetTicks();
  1136. if (device->num_joysticks > 0) {
  1137. joystick = SDL_GetJoystickFromID(device->joysticks[0]);
  1138. }
  1139. while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
  1140. #ifdef DEBUG_PS4_PROTOCOL
  1141. HIDAPI_DumpPacket("PS4 packet: size = %d", data, size);
  1142. #endif
  1143. if (!HIDAPI_DriverPS4_IsPacketValid(ctx, data, size)) {
  1144. continue;
  1145. }
  1146. ++packet_count;
  1147. ctx->last_packet = now;
  1148. if (!joystick) {
  1149. continue;
  1150. }
  1151. switch (data[0]) {
  1152. case k_EPS4ReportIdUsbState:
  1153. HIDAPI_DriverPS4_HandleStatePacket(joystick, device->dev, ctx, (PS4StatePacket_t *)&data[1], size - 1);
  1154. break;
  1155. case k_EPS4ReportIdBluetoothState1:
  1156. case k_EPS4ReportIdBluetoothState2:
  1157. case k_EPS4ReportIdBluetoothState3:
  1158. case k_EPS4ReportIdBluetoothState4:
  1159. case k_EPS4ReportIdBluetoothState5:
  1160. case k_EPS4ReportIdBluetoothState6:
  1161. case k_EPS4ReportIdBluetoothState7:
  1162. case k_EPS4ReportIdBluetoothState8:
  1163. case k_EPS4ReportIdBluetoothState9:
  1164. // This is the extended report, we can enable effects now in auto mode
  1165. HIDAPI_DriverPS4_UpdateEnhancedModeOnEnhancedReport(ctx);
  1166. // Bluetooth state packets have two additional bytes at the beginning, the first notes if HID is present
  1167. HIDAPI_DriverPS4_HandleStatePacket(joystick, device->dev, ctx, (PS4StatePacket_t *)&data[3], size - 3);
  1168. break;
  1169. default:
  1170. #ifdef DEBUG_JOYSTICK
  1171. SDL_Log("Unknown PS4 packet: 0x%.2x", data[0]);
  1172. #endif
  1173. break;
  1174. }
  1175. }
  1176. if (device->is_bluetooth) {
  1177. if (packet_count == 0) {
  1178. // Check to see if it looks like the device disconnected
  1179. if (now >= (ctx->last_packet + BLUETOOTH_DISCONNECT_TIMEOUT_MS)) {
  1180. // Send an empty output report to tickle the Bluetooth stack
  1181. HIDAPI_DriverPS4_TickleBluetooth(device);
  1182. ctx->last_packet = now;
  1183. }
  1184. } else {
  1185. // Reconnect the Bluetooth device once the USB device is gone
  1186. if (device->num_joysticks == 0 &&
  1187. !HIDAPI_HasConnectedUSBDevice(device->serial)) {
  1188. HIDAPI_JoystickConnected(device, NULL);
  1189. }
  1190. }
  1191. }
  1192. if (ctx->is_dongle || ctx->is_nacon_dongle) {
  1193. if (packet_count == 0) {
  1194. if (device->num_joysticks > 0) {
  1195. // Check to see if it looks like the device disconnected
  1196. if (now >= (ctx->last_packet + BLUETOOTH_DISCONNECT_TIMEOUT_MS)) {
  1197. HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
  1198. }
  1199. }
  1200. } else {
  1201. if (device->num_joysticks == 0) {
  1202. char serial[18];
  1203. size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdSerialNumber, data, sizeof(data));
  1204. if (size >= 7 && (data[1] || data[2] || data[3] || data[4] || data[5] || data[6])) {
  1205. (void)SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
  1206. data[6], data[5], data[4], data[3], data[2], data[1]);
  1207. HIDAPI_SetDeviceSerial(device, serial);
  1208. }
  1209. HIDAPI_JoystickConnected(device, NULL);
  1210. }
  1211. }
  1212. }
  1213. if (packet_count == 0 && size < 0 && device->num_joysticks > 0) {
  1214. // Read error, device is disconnected
  1215. HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
  1216. }
  1217. return (size >= 0);
  1218. }
  1219. static void HIDAPI_DriverPS4_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
  1220. {
  1221. SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
  1222. SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS4_REPORT_INTERVAL,
  1223. SDL_PS4ReportIntervalHintChanged, ctx);
  1224. SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_ENHANCED_REPORTS,
  1225. SDL_PS4EnhancedReportsChanged, ctx);
  1226. ctx->joystick = NULL;
  1227. ctx->report_sensors = false;
  1228. ctx->enhanced_mode = false;
  1229. ctx->enhanced_mode_available = false;
  1230. }
  1231. static void HIDAPI_DriverPS4_FreeDevice(SDL_HIDAPI_Device *device)
  1232. {
  1233. }
  1234. SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4 = {
  1235. SDL_HINT_JOYSTICK_HIDAPI_PS4,
  1236. true,
  1237. HIDAPI_DriverPS4_RegisterHints,
  1238. HIDAPI_DriverPS4_UnregisterHints,
  1239. HIDAPI_DriverPS4_IsEnabled,
  1240. HIDAPI_DriverPS4_IsSupportedDevice,
  1241. HIDAPI_DriverPS4_InitDevice,
  1242. HIDAPI_DriverPS4_GetDevicePlayerIndex,
  1243. HIDAPI_DriverPS4_SetDevicePlayerIndex,
  1244. HIDAPI_DriverPS4_UpdateDevice,
  1245. HIDAPI_DriverPS4_OpenJoystick,
  1246. HIDAPI_DriverPS4_RumbleJoystick,
  1247. HIDAPI_DriverPS4_RumbleJoystickTriggers,
  1248. HIDAPI_DriverPS4_GetJoystickCapabilities,
  1249. HIDAPI_DriverPS4_SetJoystickLED,
  1250. HIDAPI_DriverPS4_SendJoystickEffect,
  1251. HIDAPI_DriverPS4_SetJoystickSensorsEnabled,
  1252. HIDAPI_DriverPS4_CloseJoystick,
  1253. HIDAPI_DriverPS4_FreeDevice,
  1254. };
  1255. #endif // SDL_JOYSTICK_HIDAPI_PS4
  1256. #endif // SDL_JOYSTICK_HIDAPI