gamepad_util.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // gamepad_util.h -- shared helpers for building host USB gamepad reports from g_in.
  2. //
  3. // These are reused across the DualSense / DS4 / Switch personalities: analog-stick rescaling, Steam-trackpad
  4. // -> absolute-touch mapping, and the PlayStation-layout button/hat/face/shoulder packers. Per-target button
  5. // code maps (codeToXB / codeToSwitch / codeToJc) live with their own controllers; only the cross-mode pieces
  6. // are here.
  7. #pragma once
  8. #include <stdint.h>
  9. #include "triton.h"
  10. // int16 stick (center 0) -> uint8 (center 0x80), optional axis invert (HID Y is down-positive).
  11. uint8_t swStick(int16_t v, bool invert);
  12. // Write a signed 16-bit value little-endian.
  13. static inline void le16(uint8_t *p, int16_t v)
  14. {
  15. p[0] = (uint8_t)(v & 0xFF);
  16. p[1] = (uint8_t)((v >> 8) & 0xFF);
  17. }
  18. // Fill a DS4/DualSense motion-calibration feature report PAYLOAD. The TinyUSB GET_REPORT path already wrote the
  19. // report id and hands us the buffer PAST it, so our offsets = the kernel's buf[] index minus one (bias at 0..5,
  20. // stays zero from the caller's memset). Zero bias + symmetric non-zero ranges so hid-playstation's/hid-sony's
  21. // divisor (|plus-bias|+|minus-bias|, and gyro speed_plus+speed_minus) is never zero. Shared by report 0x02 (DS4)
  22. // and 0x05 (DualSense) -- identical layout; the caller returns size-1 and leaves trailing bytes zero.
  23. void psNeutralCalib(uint8_t *buf);
  24. // Steam trackpad s16 coords -> absolute touch surface. TOUCH_PAD_W is split into left/right halves so both
  25. // pads can co-exist as two contacts on a single DualSense/DS4 touchpad.
  26. #define TOUCH_PAD_W 1920u
  27. uint16_t padNormU16(int16_t v, uint16_t maxv);
  28. uint16_t touchHalfX(int16_t v, bool rightHalf);
  29. uint16_t touchYInv(int16_t v, uint16_t height);
  30. void touchPackPoint(uint8_t *base, int finger, bool touch, uint16_t x,
  31. uint16_t y);
  32. // DualSense / DS4: many hosts only honor contact slot 0 -- put a lone pad in slot 0, both pads in 0+1.
  33. void touchPackPads(uint8_t *pts, bool lTouch, bool rTouch, uint16_t lx,
  34. uint16_t ly, uint16_t rx, uint16_t ry);
  35. void steamPadsToTouch(uint32_t b, uint16_t touchH, int16_t lpx, int16_t lpy,
  36. int16_t rpx, int16_t rpy, uint16_t *lx, uint16_t *ly,
  37. uint16_t *rx, uint16_t *ry);
  38. // Trackpad -> analog stick blend (WebUI "map trackpad to joystick", g_padStick). A pad mapped to a stick
  39. // BLENDS with it rather than replacing it: while the pad is touched each axis reports whichever of the two
  40. // sources is deflected further from center (signed), so pad and stick stay usable at the same time. An
  41. // untouched pad contributes nothing and the physical stick passes through unchanged -- which also means a
  42. // release can never leave a stale pad value stuck on the axis. b = raw TB_* buttons (touch bits); the
  43. // sticks are updated in place.
  44. void padStickBlend(uint32_t b, int16_t lpx, int16_t lpy, int16_t rpx,
  45. int16_t rpy, int16_t *lx, int16_t *ly, int16_t *rx,
  46. int16_t *ry);
  47. // g_in[slot] sticks with padStickBlend applied -- what every emulated mode should send to the host.
  48. void slotSticks(uint8_t slot, int16_t *lx, int16_t *ly, int16_t *rx,
  49. int16_t *ry);
  50. // Convert configurable button code -> TB_* flag (shared across modes).
  51. static inline uint32_t tritonFromCode(uint8_t c)
  52. {
  53. switch (c) {
  54. case 1:
  55. return TB_A;
  56. case 2:
  57. return TB_B;
  58. case 3:
  59. return TB_X;
  60. case 4:
  61. return TB_Y;
  62. case 5:
  63. return TB_LB;
  64. case 6:
  65. return TB_RB;
  66. case 7:
  67. return TB_L3;
  68. case 8:
  69. return TB_R3;
  70. case 9:
  71. return TB_VIEW;
  72. case 10:
  73. return TB_QAM;
  74. case 11:
  75. return TB_STEAM;
  76. case 12:
  77. return TB_DUP;
  78. case 13:
  79. return TB_DDN;
  80. case 14:
  81. return TB_DLF;
  82. case 15:
  83. return TB_DRT;
  84. case 16:
  85. return TB_TOUCH;
  86. case 17:
  87. return TB_MUTE;
  88. case 19:
  89. return TB_L2; // left trigger (LT / L2 / ZL)
  90. case 20:
  91. return TB_R2; // right trigger (RT / R2 / ZR)
  92. default:
  93. return 0;
  94. }
  95. }
  96. // PlayStation-layout button packing (shared by mode_ps5 + mode_hidgyro).
  97. uint32_t psButtonsFromSteam(
  98. uint32_t raw); // apply back-paddle + chord-guard + QAM remapping
  99. // L1..R3 + Create/Options byte. lt/rt are the per-slot analog trigger values so the digital ZL/ZR trip
  100. // doesn't leak across slots when several slots are active.
  101. uint8_t psShouldersByte(uint32_t b, uint8_t lt, uint8_t rt);
  102. uint8_t psHatNibble(uint32_t b); // d-pad -> 8-way hat (8 = neutral)
  103. uint8_t psFaceNibble(uint32_t b); // face buttons (with A/B + X/Y swap)