SDL_hidapi_ps5.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2020 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. #include "../../SDL_internal.h"
  19. #ifdef SDL_JOYSTICK_HIDAPI
  20. #include "SDL_hints.h"
  21. #include "SDL_events.h"
  22. #include "SDL_joystick.h"
  23. #include "SDL_gamecontroller.h"
  24. #include "../SDL_sysjoystick.h"
  25. #include "SDL_hidapijoystick_c.h"
  26. #include "SDL_hidapi_rumble.h"
  27. #ifdef SDL_JOYSTICK_HIDAPI_PS5
  28. /* Define this if you want to log all packets from the controller */
  29. /*#define DEBUG_PS5_PROTOCOL*/
  30. /* Define this if you want to log calibration data */
  31. /*#define DEBUG_PS5_CALIBRATION*/
  32. #define GYRO_RES_PER_DEGREE 1024.0f
  33. #define ACCEL_RES_PER_G 8192.0f
  34. #define LOAD16(A, B) (Sint16)((Uint16)(A) | (((Uint16)(B)) << 8))
  35. typedef enum
  36. {
  37. k_EPS5ReportIdState = 0x01,
  38. k_EPS5ReportIdUsbEffects = 0x02,
  39. k_EPS5ReportIdBluetoothEffects = 0x31,
  40. k_EPS5ReportIdBluetoothState = 0x31,
  41. } EPS5ReportId;
  42. typedef enum
  43. {
  44. k_EPS5FeatureReportIdCalibration = 0x05,
  45. k_EPS5FeatureReportIdSerialNumber = 0x09,
  46. } EPS5FeatureReportId;
  47. typedef struct
  48. {
  49. Uint8 ucLeftJoystickX;
  50. Uint8 ucLeftJoystickY;
  51. Uint8 ucRightJoystickX;
  52. Uint8 ucRightJoystickY;
  53. Uint8 rgucButtonsHatAndCounter[3];
  54. Uint8 ucTriggerLeft;
  55. Uint8 ucTriggerRight;
  56. } PS5SimpleStatePacket_t;
  57. typedef struct
  58. {
  59. Uint8 ucLeftJoystickX; /* 0 */
  60. Uint8 ucLeftJoystickY; /* 1 */
  61. Uint8 ucRightJoystickX; /* 2 */
  62. Uint8 ucRightJoystickY; /* 3 */
  63. Uint8 ucTriggerLeft; /* 4 */
  64. Uint8 ucTriggerRight; /* 5 */
  65. Uint8 ucCounter; /* 6 */
  66. Uint8 rgucButtonsAndHat[3]; /* 7 */
  67. Uint8 ucZero; /* 10 */
  68. Uint8 rgucPacketSequence[4]; /* 11 - 32 bit little endian */
  69. Uint8 rgucGyroX[2]; /* 15 */
  70. Uint8 rgucGyroY[2]; /* 17 */
  71. Uint8 rgucGyroZ[2]; /* 19 */
  72. Uint8 rgucAccelX[2]; /* 21 */
  73. Uint8 rgucAccelY[2]; /* 23 */
  74. Uint8 rgucAccelZ[2]; /* 25 */
  75. Uint8 rgucTimer1[4]; /* 27 - 32 bit little endian */
  76. Uint8 ucBatteryTemp; /* 31 */
  77. Uint8 ucTouchpadCounter1; /* 32 - high bit clear + counter */
  78. Uint8 rgucTouchpadData1[3]; /* 33 - X/Y, 12 bits per axis */
  79. Uint8 ucTouchpadCounter2; /* 36 - high bit clear + counter */
  80. Uint8 rgucTouchpadData2[3]; /* 37 - X/Y, 12 bits per axis */
  81. Uint8 rgucUnknown1[8]; /* 40 */
  82. Uint8 rgucTimer2[4]; /* 48 - 32 bit little endian */
  83. Uint8 ucBatteryLevel; /* 52 */
  84. Uint8 ucConnectState; /* 53 - 0x08 = USB, 0x01 = headphone */
  85. /* There's more unknown data at the end, and a 32-bit CRC on Bluetooth */
  86. } PS5StatePacket_t;
  87. typedef struct
  88. {
  89. Uint8 ucEnableBits1; /* 0 */
  90. Uint8 ucEnableBits2; /* 1 */
  91. Uint8 ucRumbleRight; /* 2 */
  92. Uint8 ucRumbleLeft; /* 3 */
  93. Uint8 ucHeadphoneVolume; /* 4 */
  94. Uint8 ucSpeakerVolume; /* 5 */
  95. Uint8 ucMicrophoneVolume; /* 6 */
  96. Uint8 ucAudioEnableBits; /* 7 */
  97. Uint8 ucMicLightMode; /* 8 */
  98. Uint8 ucAudioMuteBits; /* 9 */
  99. Uint8 rgucRightTriggerEffect[11]; /* 10 */
  100. Uint8 rgucLeftTriggerEffect[11]; /* 21 */
  101. Uint8 rgucUnknown1[6]; /* 32 */
  102. Uint8 ucLedFlags; /* 38 */
  103. Uint8 rgucUnknown2[2]; /* 39 */
  104. Uint8 ucLedAnim; /* 41 */
  105. Uint8 ucLedBrightness; /* 42 */
  106. Uint8 ucPadLights; /* 43 */
  107. Uint8 ucLedRed; /* 44 */
  108. Uint8 ucLedGreen; /* 45 */
  109. Uint8 ucLedBlue; /* 46 */
  110. } DS5EffectsState_t;
  111. typedef enum {
  112. k_EDS5EffectNone,
  113. k_EDS5EffectRumbleStart,
  114. k_EDS5EffectRumble,
  115. k_EDS5EffectLED,
  116. k_EDS5EffectPadLights,
  117. k_EDS5EffectMicLight,
  118. } EDS5Effect;
  119. typedef struct {
  120. Sint16 bias;
  121. float sensitivity;
  122. } IMUCalibrationData;
  123. typedef struct {
  124. SDL_bool is_bluetooth;
  125. SDL_bool report_sensors;
  126. SDL_bool hardware_calibration;
  127. IMUCalibrationData calibration[6];
  128. int player_index;
  129. Uint8 rumble_left;
  130. Uint8 rumble_right;
  131. SDL_bool color_set;
  132. Uint8 led_red;
  133. Uint8 led_green;
  134. Uint8 led_blue;
  135. union
  136. {
  137. PS5SimpleStatePacket_t simple;
  138. PS5StatePacket_t state;
  139. } last_state;
  140. } SDL_DriverPS5_Context;
  141. static SDL_bool
  142. HIDAPI_DriverPS5_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
  143. {
  144. return (type == SDL_CONTROLLER_TYPE_PS5);
  145. }
  146. static const char *
  147. HIDAPI_DriverPS5_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
  148. {
  149. if (vendor_id == USB_VENDOR_SONY) {
  150. return "PS5 Controller";
  151. }
  152. return NULL;
  153. }
  154. static int ReadFeatureReport(hid_device *dev, Uint8 report_id, Uint8 *report, size_t length)
  155. {
  156. SDL_memset(report, 0, length);
  157. report[0] = report_id;
  158. return hid_get_feature_report(dev, report, length);
  159. }
  160. static void
  161. SetLedsForPlayerIndex(DS5EffectsState_t *effects, int player_index)
  162. {
  163. /* This list is the same as what hid-sony.c uses in the Linux kernel.
  164. The first 4 values correspond to what the PS4 assigns.
  165. */
  166. static const Uint8 colors[7][3] = {
  167. { 0x00, 0x00, 0x40 }, /* Blue */
  168. { 0x40, 0x00, 0x00 }, /* Red */
  169. { 0x00, 0x40, 0x00 }, /* Green */
  170. { 0x20, 0x00, 0x20 }, /* Pink */
  171. { 0x02, 0x01, 0x00 }, /* Orange */
  172. { 0x00, 0x01, 0x01 }, /* Teal */
  173. { 0x01, 0x01, 0x01 } /* White */
  174. };
  175. if (player_index >= 0) {
  176. player_index %= SDL_arraysize(colors);
  177. } else {
  178. player_index = 0;
  179. }
  180. effects->ucLedRed = colors[player_index][0];
  181. effects->ucLedGreen = colors[player_index][1];
  182. effects->ucLedBlue = colors[player_index][2];
  183. }
  184. static SDL_bool
  185. HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device)
  186. {
  187. return HIDAPI_JoystickConnected(device, NULL, SDL_FALSE);
  188. }
  189. static int
  190. HIDAPI_DriverPS5_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
  191. {
  192. return -1;
  193. }
  194. static void
  195. HIDAPI_DriverPS5_LoadCalibrationData(SDL_HIDAPI_Device *device)
  196. {
  197. SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
  198. int i, size;
  199. Uint8 data[USB_PACKET_LENGTH];
  200. size = ReadFeatureReport(device->dev, k_EPS5FeatureReportIdCalibration, data, sizeof(data));
  201. if (size < 35) {
  202. #ifdef DEBUG_PS5_CALIBRATION
  203. SDL_Log("Short read of calibration data: %d, ignoring calibration\n", size);
  204. #endif
  205. return;
  206. }
  207. {
  208. Sint16 sGyroPitchBias, sGyroYawBias, sGyroRollBias;
  209. Sint16 sGyroPitchPlus, sGyroPitchMinus;
  210. Sint16 sGyroYawPlus, sGyroYawMinus;
  211. Sint16 sGyroRollPlus, sGyroRollMinus;
  212. Sint16 sGyroSpeedPlus, sGyroSpeedMinus;
  213. Sint16 sAccXPlus, sAccXMinus;
  214. Sint16 sAccYPlus, sAccYMinus;
  215. Sint16 sAccZPlus, sAccZMinus;
  216. float flNumerator;
  217. Sint16 sRange2g;
  218. #ifdef DEBUG_PS5_CALIBRATION
  219. HIDAPI_DumpPacket("PS5 calibration packet: size = %d", data, size);
  220. #endif
  221. sGyroPitchBias = LOAD16(data[1], data[2]);
  222. sGyroYawBias = LOAD16(data[3], data[4]);
  223. sGyroRollBias = LOAD16(data[5], data[6]);
  224. sGyroPitchPlus = LOAD16(data[7], data[8]);
  225. sGyroPitchMinus = LOAD16(data[9], data[10]);
  226. sGyroYawPlus = LOAD16(data[11], data[12]);
  227. sGyroYawMinus = LOAD16(data[13], data[14]);
  228. sGyroRollPlus = LOAD16(data[15], data[16]);
  229. sGyroRollMinus = LOAD16(data[17], data[18]);
  230. sGyroSpeedPlus = LOAD16(data[19], data[20]);
  231. sGyroSpeedMinus = LOAD16(data[21], data[22]);
  232. sAccXPlus = LOAD16(data[23], data[24]);
  233. sAccXMinus = LOAD16(data[25], data[26]);
  234. sAccYPlus = LOAD16(data[27], data[28]);
  235. sAccYMinus = LOAD16(data[29], data[30]);
  236. sAccZPlus = LOAD16(data[31], data[32]);
  237. sAccZMinus = LOAD16(data[33], data[34]);
  238. flNumerator = (sGyroSpeedPlus + sGyroSpeedMinus) * GYRO_RES_PER_DEGREE;
  239. ctx->calibration[0].bias = sGyroPitchBias;
  240. ctx->calibration[0].sensitivity = flNumerator / (sGyroPitchPlus - sGyroPitchMinus);
  241. ctx->calibration[1].bias = sGyroYawBias;
  242. ctx->calibration[1].sensitivity = flNumerator / (sGyroYawPlus - sGyroYawMinus);
  243. ctx->calibration[2].bias = sGyroRollBias;
  244. ctx->calibration[2].sensitivity = flNumerator / (sGyroRollPlus - sGyroRollMinus);
  245. sRange2g = sAccXPlus - sAccXMinus;
  246. ctx->calibration[3].bias = sAccXPlus - sRange2g / 2;
  247. ctx->calibration[3].sensitivity = 2.0f * ACCEL_RES_PER_G / (float)sRange2g;
  248. sRange2g = sAccYPlus - sAccYMinus;
  249. ctx->calibration[4].bias = sAccYPlus - sRange2g / 2;
  250. ctx->calibration[4].sensitivity = 2.0f * ACCEL_RES_PER_G / (float)sRange2g;
  251. sRange2g = sAccZPlus - sAccZMinus;
  252. ctx->calibration[5].bias = sAccZPlus - sRange2g / 2;
  253. ctx->calibration[5].sensitivity = 2.0f * ACCEL_RES_PER_G / (float)sRange2g;
  254. ctx->hardware_calibration = SDL_TRUE;
  255. for (i = 0; i < 6; ++i) {
  256. float divisor = (i < 3 ? 64.0f : 1.0f);
  257. #ifdef DEBUG_PS5_CALIBRATION
  258. SDL_Log("calibration[%d] bias = %d, sensitivity = %f\n", i, ctx->calibration[i].bias, ctx->calibration[i].sensitivity);
  259. #endif
  260. /* Some controllers have a bad calibration */
  261. if ((SDL_abs(ctx->calibration[i].bias) > 1024) || (SDL_fabs(1.0f - ctx->calibration[i].sensitivity / divisor) > 0.5f)) {
  262. #ifdef DEBUG_PS5_CALIBRATION
  263. SDL_Log("invalid calibration, ignoring\n");
  264. #endif
  265. ctx->hardware_calibration = SDL_FALSE;
  266. }
  267. }
  268. }
  269. }
  270. static float
  271. HIDAPI_DriverPS5_ApplyCalibrationData(SDL_DriverPS5_Context *ctx, int index, Sint16 value)
  272. {
  273. float result;
  274. if (ctx->hardware_calibration) {
  275. IMUCalibrationData *calibration = &ctx->calibration[index];
  276. result = (value - calibration->bias) * calibration->sensitivity;
  277. } else {
  278. result = value;
  279. }
  280. /* Convert the raw data to the units expected by SDL */
  281. if (index < 3) {
  282. result = (result / GYRO_RES_PER_DEGREE) * (float)M_PI / 180.0f;
  283. } else {
  284. result = (result / ACCEL_RES_PER_G) * SDL_STANDARD_GRAVITY;
  285. }
  286. return result;
  287. }
  288. static int
  289. HIDAPI_DriverPS5_UpdateEffects(SDL_HIDAPI_Device *device, EDS5Effect effect)
  290. {
  291. SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
  292. DS5EffectsState_t *effects;
  293. Uint8 data[78];
  294. int report_size, offset;
  295. Uint8 *pending_data;
  296. int *pending_size;
  297. int maximum_size;
  298. SDL_zero(data);
  299. if (ctx->is_bluetooth) {
  300. data[0] = k_EPS5ReportIdBluetoothEffects;
  301. data[1] = 0x02; /* Magic value */
  302. report_size = 78;
  303. offset = 2;
  304. } else {
  305. data[0] = k_EPS5ReportIdUsbEffects;
  306. report_size = 48;
  307. offset = 1;
  308. }
  309. effects = (DS5EffectsState_t *)&data[offset];
  310. if (ctx->rumble_left || ctx->rumble_right) {
  311. effects->ucEnableBits1 |= 0x01; /* Enable rumble emulation */
  312. effects->ucEnableBits1 |= 0x02; /* Disable audio haptics */
  313. /* Shift to reduce effective rumble strength to match Xbox controllers */
  314. effects->ucRumbleLeft = ctx->rumble_left >> 1;
  315. effects->ucRumbleRight = ctx->rumble_right >> 1;
  316. } else {
  317. /* Leaving emulated rumble bits off will restore audio haptics */
  318. }
  319. switch (effect) {
  320. case k_EDS5EffectRumbleStart:
  321. effects->ucEnableBits1 |= 0x02; /* Disable audio haptics */
  322. break;
  323. case k_EDS5EffectRumble:
  324. /* Already handled above */
  325. break;
  326. case k_EDS5EffectLED:
  327. effects->ucEnableBits2 |= 0x04; /* Enable LED color */
  328. /* Populate the LED state with the appropriate color from our lookup table */
  329. if (ctx->color_set) {
  330. effects->ucLedRed = ctx->led_red;
  331. effects->ucLedGreen = ctx->led_green;
  332. effects->ucLedBlue = ctx->led_blue;
  333. } else {
  334. SetLedsForPlayerIndex(effects, ctx->player_index);
  335. }
  336. break;
  337. case k_EDS5EffectPadLights:
  338. effects->ucEnableBits2 |= 0x10; /* Enable touchpad lights */
  339. effects->ucPadLights = 0x00; /* Bitmask, 0x1F enables all lights, 0x20 changes instantly instead of fade */
  340. break;
  341. case k_EDS5EffectMicLight:
  342. effects->ucEnableBits2 |= 0x01; /* Enable microphone light */
  343. effects->ucMicLightMode = 0; /* Bitmask, 0x00 = off, 0x01 = solid, 0x02 = pulse */
  344. break;
  345. default:
  346. break;
  347. }
  348. if (ctx->is_bluetooth) {
  349. /* Bluetooth reports need a CRC at the end of the packet (at least on Linux) */
  350. Uint8 ubHdr = 0xA2; /* hidp header is part of the CRC calculation */
  351. Uint32 unCRC;
  352. unCRC = SDL_crc32(0, &ubHdr, 1);
  353. unCRC = SDL_crc32(unCRC, data, (size_t)(report_size - sizeof(unCRC)));
  354. SDL_memcpy(&data[report_size - sizeof(unCRC)], &unCRC, sizeof(unCRC));
  355. }
  356. if (SDL_HIDAPI_LockRumble() < 0) {
  357. return -1;
  358. }
  359. /* See if we can update an existing pending request */
  360. if (SDL_HIDAPI_GetPendingRumbleLocked(device, &pending_data, &pending_size, &maximum_size)) {
  361. DS5EffectsState_t *pending_effects = (DS5EffectsState_t *)&pending_data[offset];
  362. if (report_size == *pending_size &&
  363. effects->ucEnableBits1 == pending_effects->ucEnableBits1 &&
  364. effects->ucEnableBits2 == pending_effects->ucEnableBits2) {
  365. /* We're simply updating the data for this request */
  366. SDL_memcpy(pending_data, data, report_size);
  367. SDL_HIDAPI_UnlockRumble();
  368. return 0;
  369. }
  370. }
  371. return SDL_HIDAPI_SendRumbleAndUnlock(device, data, report_size);
  372. }
  373. static void
  374. HIDAPI_DriverPS5_SetBluetooth(SDL_HIDAPI_Device *device, SDL_bool is_bluetooth)
  375. {
  376. SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
  377. if (ctx->is_bluetooth != is_bluetooth) {
  378. ctx->is_bluetooth = is_bluetooth;
  379. HIDAPI_DriverPS5_UpdateEffects(device, k_EDS5EffectLED);
  380. }
  381. }
  382. static void
  383. HIDAPI_DriverPS5_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
  384. {
  385. SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
  386. if (!ctx) {
  387. return;
  388. }
  389. ctx->player_index = player_index;
  390. /* This will set the new LED state based on the new player index */
  391. HIDAPI_DriverPS5_UpdateEffects(device, k_EDS5EffectLED);
  392. }
  393. static SDL_bool
  394. HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
  395. {
  396. SDL_DriverPS5_Context *ctx;
  397. Uint8 data[USB_PACKET_LENGTH];
  398. ctx = (SDL_DriverPS5_Context *)SDL_calloc(1, sizeof(*ctx));
  399. if (!ctx) {
  400. SDL_OutOfMemory();
  401. return SDL_FALSE;
  402. }
  403. device->dev = hid_open_path(device->path, 0);
  404. if (!device->dev) {
  405. SDL_free(ctx);
  406. SDL_SetError("Couldn't open %s", device->path);
  407. return SDL_FALSE;
  408. }
  409. device->context = ctx;
  410. /* Read the serial number (Bluetooth address in reverse byte order)
  411. This will also enable enhanced reports over Bluetooth
  412. */
  413. if (ReadFeatureReport(device->dev, k_EPS5FeatureReportIdSerialNumber, data, sizeof(data)) >= 7) {
  414. char serial[18];
  415. SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
  416. data[6], data[5], data[4], data[3], data[2], data[1]);
  417. joystick->serial = SDL_strdup(serial);
  418. }
  419. /* Initialize player index (needed for setting LEDs) */
  420. ctx->player_index = SDL_JoystickGetPlayerIndex(joystick);
  421. /* Initialize LED and effect state */
  422. HIDAPI_DriverPS5_UpdateEffects(device, k_EDS5EffectLED);
  423. /* Initialize the joystick capabilities */
  424. joystick->nbuttons = 17;
  425. joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
  426. joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
  427. SDL_PrivateJoystickAddTouchpad(joystick, 2);
  428. SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO);
  429. SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL);
  430. return SDL_TRUE;
  431. }
  432. static int
  433. HIDAPI_DriverPS5_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
  434. {
  435. SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
  436. if (!ctx->rumble_left && !ctx->rumble_right) {
  437. HIDAPI_DriverPS5_UpdateEffects(device, k_EDS5EffectRumbleStart);
  438. }
  439. ctx->rumble_left = (low_frequency_rumble >> 8);
  440. ctx->rumble_right = (high_frequency_rumble >> 8);
  441. return HIDAPI_DriverPS5_UpdateEffects(device, k_EDS5EffectRumble);
  442. }
  443. static int
  444. HIDAPI_DriverPS5_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
  445. {
  446. return SDL_Unsupported();
  447. }
  448. static SDL_bool
  449. HIDAPI_DriverPS5_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
  450. {
  451. return SDL_FALSE;
  452. }
  453. static int
  454. HIDAPI_DriverPS5_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
  455. {
  456. SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
  457. ctx->color_set = SDL_TRUE;
  458. ctx->led_red = red;
  459. ctx->led_green = green;
  460. ctx->led_blue = blue;
  461. return HIDAPI_DriverPS5_UpdateEffects(device, k_EDS5EffectLED);
  462. }
  463. static int
  464. HIDAPI_DriverPS5_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled)
  465. {
  466. SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
  467. if (enabled) {
  468. HIDAPI_DriverPS5_LoadCalibrationData(device);
  469. }
  470. ctx->report_sensors = enabled;
  471. return 0;
  472. }
  473. static void
  474. HIDAPI_DriverPS5_HandleSimpleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS5_Context *ctx, PS5SimpleStatePacket_t *packet)
  475. {
  476. Sint16 axis;
  477. if (ctx->last_state.simple.rgucButtonsHatAndCounter[0] != packet->rgucButtonsHatAndCounter[0]) {
  478. {
  479. Uint8 data = (packet->rgucButtonsHatAndCounter[0] >> 4);
  480. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
  481. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
  482. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
  483. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
  484. }
  485. {
  486. Uint8 data = (packet->rgucButtonsHatAndCounter[0] & 0x0F);
  487. SDL_bool dpad_up = SDL_FALSE;
  488. SDL_bool dpad_down = SDL_FALSE;
  489. SDL_bool dpad_left = SDL_FALSE;
  490. SDL_bool dpad_right = SDL_FALSE;
  491. switch (data) {
  492. case 0:
  493. dpad_up = SDL_TRUE;
  494. break;
  495. case 1:
  496. dpad_up = SDL_TRUE;
  497. dpad_right = SDL_TRUE;
  498. break;
  499. case 2:
  500. dpad_right = SDL_TRUE;
  501. break;
  502. case 3:
  503. dpad_right = SDL_TRUE;
  504. dpad_down = SDL_TRUE;
  505. break;
  506. case 4:
  507. dpad_down = SDL_TRUE;
  508. break;
  509. case 5:
  510. dpad_left = SDL_TRUE;
  511. dpad_down = SDL_TRUE;
  512. break;
  513. case 6:
  514. dpad_left = SDL_TRUE;
  515. break;
  516. case 7:
  517. dpad_up = SDL_TRUE;
  518. dpad_left = SDL_TRUE;
  519. break;
  520. default:
  521. break;
  522. }
  523. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, dpad_down);
  524. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, dpad_up);
  525. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, dpad_right);
  526. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left);
  527. }
  528. }
  529. if (ctx->last_state.simple.rgucButtonsHatAndCounter[1] != packet->rgucButtonsHatAndCounter[1]) {
  530. Uint8 data = packet->rgucButtonsHatAndCounter[1];
  531. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
  532. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
  533. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
  534. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
  535. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
  536. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED);
  537. }
  538. if (ctx->last_state.simple.rgucButtonsHatAndCounter[2] != packet->rgucButtonsHatAndCounter[2]) {
  539. Uint8 data = (packet->rgucButtonsHatAndCounter[2] & 0x03);
  540. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
  541. SDL_PrivateJoystickButton(joystick, 15, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
  542. }
  543. axis = ((int)packet->ucTriggerLeft * 257) - 32768;
  544. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
  545. axis = ((int)packet->ucTriggerRight * 257) - 32768;
  546. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
  547. axis = ((int)packet->ucLeftJoystickX * 257) - 32768;
  548. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
  549. axis = ((int)packet->ucLeftJoystickY * 257) - 32768;
  550. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
  551. axis = ((int)packet->ucRightJoystickX * 257) - 32768;
  552. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
  553. axis = ((int)packet->ucRightJoystickY * 257) - 32768;
  554. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
  555. SDL_memcpy(&ctx->last_state.simple, packet, sizeof(ctx->last_state.simple));
  556. }
  557. static void
  558. HIDAPI_DriverPS5_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS5_Context *ctx, PS5StatePacket_t *packet)
  559. {
  560. static const float TOUCHPAD_SCALEX = 1.0f / 1920;
  561. static const float TOUCHPAD_SCALEY = 1.0f / 1070;
  562. Sint16 axis;
  563. Uint8 touchpad_state;
  564. int touchpad_x, touchpad_y;
  565. if (ctx->last_state.state.rgucButtonsAndHat[0] != packet->rgucButtonsAndHat[0]) {
  566. {
  567. Uint8 data = (packet->rgucButtonsAndHat[0] >> 4);
  568. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
  569. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
  570. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
  571. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
  572. }
  573. {
  574. Uint8 data = (packet->rgucButtonsAndHat[0] & 0x0F);
  575. SDL_bool dpad_up = SDL_FALSE;
  576. SDL_bool dpad_down = SDL_FALSE;
  577. SDL_bool dpad_left = SDL_FALSE;
  578. SDL_bool dpad_right = SDL_FALSE;
  579. switch (data) {
  580. case 0:
  581. dpad_up = SDL_TRUE;
  582. break;
  583. case 1:
  584. dpad_up = SDL_TRUE;
  585. dpad_right = SDL_TRUE;
  586. break;
  587. case 2:
  588. dpad_right = SDL_TRUE;
  589. break;
  590. case 3:
  591. dpad_right = SDL_TRUE;
  592. dpad_down = SDL_TRUE;
  593. break;
  594. case 4:
  595. dpad_down = SDL_TRUE;
  596. break;
  597. case 5:
  598. dpad_left = SDL_TRUE;
  599. dpad_down = SDL_TRUE;
  600. break;
  601. case 6:
  602. dpad_left = SDL_TRUE;
  603. break;
  604. case 7:
  605. dpad_up = SDL_TRUE;
  606. dpad_left = SDL_TRUE;
  607. break;
  608. default:
  609. break;
  610. }
  611. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, dpad_down);
  612. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, dpad_up);
  613. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, dpad_right);
  614. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left);
  615. }
  616. }
  617. if (ctx->last_state.state.rgucButtonsAndHat[1] != packet->rgucButtonsAndHat[1]) {
  618. Uint8 data = packet->rgucButtonsAndHat[1];
  619. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
  620. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
  621. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
  622. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
  623. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
  624. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED);
  625. }
  626. if (ctx->last_state.state.rgucButtonsAndHat[2] != packet->rgucButtonsAndHat[2]) {
  627. Uint8 data = packet->rgucButtonsAndHat[2];
  628. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
  629. SDL_PrivateJoystickButton(joystick, 15, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
  630. SDL_PrivateJoystickButton(joystick, 16, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
  631. }
  632. axis = ((int)packet->ucTriggerLeft * 257) - 32768;
  633. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
  634. axis = ((int)packet->ucTriggerRight * 257) - 32768;
  635. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
  636. axis = ((int)packet->ucLeftJoystickX * 257) - 32768;
  637. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
  638. axis = ((int)packet->ucLeftJoystickY * 257) - 32768;
  639. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
  640. axis = ((int)packet->ucRightJoystickX * 257) - 32768;
  641. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
  642. axis = ((int)packet->ucRightJoystickY * 257) - 32768;
  643. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
  644. if (packet->ucBatteryLevel & 0x10) {
  645. /* 0x20 set means fully charged */
  646. joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
  647. } else {
  648. /* Battery level ranges from 0 to 10 */
  649. int level = (packet->ucBatteryLevel & 0xF);
  650. if (level == 0) {
  651. joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
  652. } else if (level <= 2) {
  653. joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
  654. } else if (level <= 7) {
  655. joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
  656. } else {
  657. joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
  658. }
  659. }
  660. touchpad_state = ((packet->ucTouchpadCounter1 & 0x80) == 0) ? SDL_PRESSED : SDL_RELEASED;
  661. touchpad_x = packet->rgucTouchpadData1[0] | (((int)packet->rgucTouchpadData1[1] & 0x0F) << 8);
  662. touchpad_y = (packet->rgucTouchpadData1[1] >> 4) | ((int)packet->rgucTouchpadData1[2] << 4);
  663. SDL_PrivateJoystickTouchpad(joystick, 0, 0, touchpad_state, touchpad_x * TOUCHPAD_SCALEX, touchpad_y * TOUCHPAD_SCALEY, touchpad_state ? 1.0f : 0.0f);
  664. touchpad_state = ((packet->ucTouchpadCounter2 & 0x80) == 0) ? SDL_PRESSED : SDL_RELEASED;
  665. touchpad_x = packet->rgucTouchpadData2[0] | (((int)packet->rgucTouchpadData2[1] & 0x0F) << 8);
  666. touchpad_y = (packet->rgucTouchpadData2[1] >> 4) | ((int)packet->rgucTouchpadData2[2] << 4);
  667. SDL_PrivateJoystickTouchpad(joystick, 0, 1, touchpad_state, touchpad_x * TOUCHPAD_SCALEX, touchpad_y * TOUCHPAD_SCALEY, touchpad_state ? 1.0f : 0.0f);
  668. if (ctx->report_sensors) {
  669. float data[3];
  670. data[0] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 0, LOAD16(packet->rgucGyroX[0], packet->rgucGyroX[1]));
  671. data[1] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 1, LOAD16(packet->rgucGyroY[0], packet->rgucGyroY[1]));
  672. data[2] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 2, LOAD16(packet->rgucGyroZ[0], packet->rgucGyroZ[1]));
  673. SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, data, 3);
  674. data[0] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 3, LOAD16(packet->rgucAccelX[0], packet->rgucAccelX[1]));
  675. data[1] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 4, LOAD16(packet->rgucAccelY[0], packet->rgucAccelY[1]));
  676. data[2] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 5, LOAD16(packet->rgucAccelZ[0], packet->rgucAccelZ[1]));
  677. SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, data, 3);
  678. }
  679. SDL_memcpy(&ctx->last_state.state, packet, sizeof(ctx->last_state.state));
  680. }
  681. static SDL_bool
  682. HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device)
  683. {
  684. SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
  685. SDL_Joystick *joystick = NULL;
  686. Uint8 data[USB_PACKET_LENGTH*2];
  687. int size;
  688. if (device->num_joysticks > 0) {
  689. joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
  690. }
  691. if (!joystick) {
  692. return SDL_FALSE;
  693. }
  694. while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
  695. #ifdef DEBUG_PS5_PROTOCOL
  696. HIDAPI_DumpPacket("PS5 packet: size = %d", data, size);
  697. #endif
  698. switch (data[0]) {
  699. case k_EPS5ReportIdState:
  700. if (size == 10) {
  701. HIDAPI_DriverPS5_SetBluetooth(device, SDL_TRUE); /* Simple state packet over Bluetooth */
  702. HIDAPI_DriverPS5_HandleSimpleStatePacket(joystick, device->dev, ctx, (PS5SimpleStatePacket_t *)&data[1]);
  703. } else {
  704. HIDAPI_DriverPS5_SetBluetooth(device, SDL_FALSE);
  705. HIDAPI_DriverPS5_HandleStatePacket(joystick, device->dev, ctx, (PS5StatePacket_t *)&data[1]);
  706. }
  707. break;
  708. case k_EPS5ReportIdBluetoothState:
  709. HIDAPI_DriverPS5_SetBluetooth(device, SDL_TRUE);
  710. HIDAPI_DriverPS5_HandleStatePacket(joystick, device->dev, ctx, (PS5StatePacket_t *)&data[2]);
  711. break;
  712. default:
  713. #ifdef DEBUG_JOYSTICK
  714. SDL_Log("Unknown PS5 packet: 0x%.2x\n", data[0]);
  715. #endif
  716. break;
  717. }
  718. }
  719. if (size < 0) {
  720. /* Read error, device is disconnected */
  721. HIDAPI_JoystickDisconnected(device, joystick->instance_id, SDL_FALSE);
  722. }
  723. return (size >= 0);
  724. }
  725. static void
  726. HIDAPI_DriverPS5_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
  727. {
  728. hid_close(device->dev);
  729. device->dev = NULL;
  730. SDL_free(device->context);
  731. device->context = NULL;
  732. }
  733. static void
  734. HIDAPI_DriverPS5_FreeDevice(SDL_HIDAPI_Device *device)
  735. {
  736. }
  737. SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS5 =
  738. {
  739. SDL_HINT_JOYSTICK_HIDAPI_PS5,
  740. SDL_TRUE,
  741. HIDAPI_DriverPS5_IsSupportedDevice,
  742. HIDAPI_DriverPS5_GetDeviceName,
  743. HIDAPI_DriverPS5_InitDevice,
  744. HIDAPI_DriverPS5_GetDevicePlayerIndex,
  745. HIDAPI_DriverPS5_SetDevicePlayerIndex,
  746. HIDAPI_DriverPS5_UpdateDevice,
  747. HIDAPI_DriverPS5_OpenJoystick,
  748. HIDAPI_DriverPS5_RumbleJoystick,
  749. HIDAPI_DriverPS5_RumbleJoystickTriggers,
  750. HIDAPI_DriverPS5_HasJoystickLED,
  751. HIDAPI_DriverPS5_SetJoystickLED,
  752. HIDAPI_DriverPS5_SetJoystickSensorsEnabled,
  753. HIDAPI_DriverPS5_CloseJoystick,
  754. HIDAPI_DriverPS5_FreeDevice,
  755. NULL
  756. };
  757. #endif /* SDL_JOYSTICK_HIDAPI_PS5 */
  758. #endif /* SDL_JOYSTICK_HIDAPI */
  759. /* vi: set ts=4 sw=4 expandtab: */