mode_ps3.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. #include "mode_ps3.h"
  2. #include "triton.h"
  3. #include "gamepad_util.h"
  4. #include "config.h"
  5. #include "haptics.h"
  6. #include "bonds.h"
  7. #include "usb_tx.h"
  8. #include <Adafruit_TinyUSB.h>
  9. #include <Arduino.h>
  10. #include <string.h>
  11. Ps3Controller g_ps3Ctl;
  12. // ---------------------------------------------------------------------------------------------------------
  13. // Genuine Sony Sixaxis / DualShock 3 (054C:0268) HID report descriptor -- 148 bytes, captured verbatim from
  14. // real hardware (Nefarius "SIXAXIS native HID Report Descriptor"). The PS3 console does NOT parse this to
  15. // drive input -- it recognises the pad by VID/PID and the control-transfer handshake below -- but a faithful
  16. // descriptor (declaring input 0x01, output 0x01, and feature reports 0x01/0x02/0xEE/0xEF) keeps both the
  17. // console and PC HID stacks happy. Do not "tidy" it: this is the real firmware's (famously odd) descriptor.
  18. // ---------------------------------------------------------------------------------------------------------
  19. static const uint8_t DS3_HID_DESC[148] = {
  20. 0x05, 0x01, 0x09, 0x04, 0xA1, 0x01, 0xA1, 0x02, 0x85, 0x01, 0x75, 0x08,
  21. 0x95, 0x01, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x81, 0x03, 0x75, 0x01, 0x95,
  22. 0x13, 0x15, 0x00, 0x25, 0x01, 0x35, 0x00, 0x45, 0x01, 0x05, 0x09, 0x19,
  23. 0x01, 0x29, 0x13, 0x81, 0x02, 0x75, 0x01, 0x95, 0x0D, 0x06, 0x00, 0xFF,
  24. 0x81, 0x03, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x05, 0x01, 0x09, 0x01, 0xA1,
  25. 0x00, 0x75, 0x08, 0x95, 0x04, 0x35, 0x00, 0x46, 0xFF, 0x00, 0x09, 0x30,
  26. 0x09, 0x31, 0x09, 0x32, 0x09, 0x35, 0x81, 0x02, 0xC0, 0x05, 0x01, 0x75,
  27. 0x08, 0x95, 0x27, 0x09, 0x01, 0x81, 0x02, 0x75, 0x08, 0x95, 0x30, 0x09,
  28. 0x01, 0x91, 0x02, 0x75, 0x08, 0x95, 0x30, 0x09, 0x01, 0xB1, 0x02, 0xC0,
  29. 0xA1, 0x02, 0x85, 0x02, 0x75, 0x08, 0x95, 0x30, 0x09, 0x01, 0xB1, 0x02,
  30. 0xC0, 0xA1, 0x02, 0x85, 0xEE, 0x75, 0x08, 0x95, 0x30, 0x09, 0x01, 0xB1,
  31. 0x02, 0xC0, 0xA1, 0x02, 0x85, 0xEF, 0x75, 0x08, 0x95, 0x30, 0x09, 0x01,
  32. 0xB1, 0x02, 0xC0, 0xC0
  33. };
  34. // ---------------------------------------------------------------------------------------------------------
  35. // Magic GET_REPORT(Feature) responses. Lifted verbatim from GIMX-firmwares EMUPS3 (matlo) -- a LUFA-based DS3
  36. // emulator proven to enumerate on a real PS3. GIMX sends each 64-byte array RAW (Endpoint_Write_Control_-
  37. // Stream_LE), so the genuine wire byte 0 is the array's first byte -- which for a Sixaxis is NOT the report
  38. // id (e.g. GET 0xF5 returns 01 00.., GET 0xEF returns 00 EF..). See emitFeature() for how we reproduce that
  39. // despite TinyUSB force-prepending the report id. The PS3 enable handshake is:
  40. // GET 0x01 -> GET 0xF2 -> {SET 0xEF / GET 0xEF}x2 -> GET 0xF8 -> SET output 0x01 -> SET 0xF4(enable)
  41. // then input report 0x01 streams. (GIMX does not even handle 0xF4 and streams unconditionally; so do we.)
  42. // ---------------------------------------------------------------------------------------------------------
  43. static const uint8_t report_01[64] = {
  44. 0x00, 0x01, 0x04, 0x00, 0x07, 0x0c, 0x01, 0x02, 0x18, 0x18, 0x18,
  45. 0x18, 0x09, 0x0a, 0x10, 0x11, 0x12, 0x13, 0x00, 0x00, 0x00, 0x00,
  46. 0x04, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x04, 0x04,
  47. 0x04, 0x04, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x07, 0x00, 0x17,
  48. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  49. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  50. };
  51. // 0xF2 device info; bytes [4..9] = the controller's Bluetooth MAC (overlaid from g_ds3Mac at runtime).
  52. static const uint8_t report_f2[64] = {
  53. 0xf2, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x00,
  54. 0x03, 0x50, 0x81, 0xd8, 0x01, 0x8a, 0x13, 0x00, 0x00, 0x00, 0x00,
  55. 0x04, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x04, 0x04,
  56. 0x04, 0x04, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x07, 0x00, 0x17,
  57. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  58. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  59. };
  60. // 0xF5 host-pairing info; bytes [2..7] = master (host) BT MAC, overlaid once learned from a SET 0xF5.
  61. static const uint8_t report_f5[64] = {
  62. 0x01, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xf7, 0x00,
  63. 0x03, 0x50, 0x81, 0xd8, 0x01, 0x8a, 0x13, 0x00, 0x00, 0x00, 0x00,
  64. 0x04, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x04, 0x04,
  65. 0x04, 0x04, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x07, 0x00, 0x17,
  66. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  67. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  68. };
  69. // 0xEF / 0xF8 calibration; byte [7] echoes whatever the PS3 last wrote in SET 0xEF byte[6] (the "do you
  70. // remember" check the console performs during the 0xEF dance).
  71. static const uint8_t report_ef[64] = {
  72. 0x00, 0xef, 0x04, 0x00, 0x07, 0x03, 0x01, 0xb0, 0x00, 0x00, 0x00,
  73. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x6b, 0x02, 0x68, 0x00,
  74. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  75. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  76. 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  78. };
  79. static const uint8_t report_f8[64] = {
  80. 0x00, 0x01, 0x00, 0x00, 0x07, 0x03, 0x01, 0xb0, 0x00, 0x00, 0x00,
  81. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x6b, 0x02, 0x68, 0x00,
  82. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  83. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  84. 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  85. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  86. };
  87. static const uint8_t report_f7[64] = {
  88. 0x01, 0x04, 0xc4, 0x02, 0xd6, 0x01, 0xee, 0xff, 0x14, 0x13, 0x01,
  89. 0x02, 0xc4, 0x01, 0xd6, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x03,
  90. 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x62, 0x01, 0x02, 0x01, 0x5e,
  91. 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  92. 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  93. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  94. };
  95. // One HID slot -- a PS3 expects exactly one Sixaxis per USB port.
  96. static Adafruit_USBD_HID g_ds3;
  97. static unsigned long g_ds3LastMs = 0;
  98. // A slot counts as the live controller while it has replied within this window (matches usb_mount's CONN_UP_MS).
  99. #define DS3_CONN_MS 1200u
  100. // First bonded slot with a recent RF reply (the controller we present), or -1 if none is connected. Used for
  101. // both input streaming and rumble routing (this mode is static, so the dynamic g_usbToBond map isn't built).
  102. static int ds3ActiveSlot()
  103. {
  104. unsigned long now = millis();
  105. for (int s = 0; s < NSLOT; s++)
  106. if (g_slot[s].used && g_connReplyMs[s] &&
  107. (now - g_connReplyMs[s]) < DS3_CONN_MS)
  108. return s;
  109. return -1;
  110. }
  111. static uint8_t g_byte6ef =
  112. 0xb0; // last SET-0xEF byte[6]; echoed back in GET 0xEF/0xF8 byte[7]
  113. static uint8_t g_masterBd[6] = {
  114. 0, 0, 0, 0, 0, 0
  115. }; // host MAC learned via SET 0xF5
  116. static bool g_haveMaster = false;
  117. // Controller BT MAC. OUI 00:1B:DC matches the other PS modes here; last byte 0x80 keeps it distinct. Used
  118. // only for BT pairing identity -- irrelevant over USB, but the PS3 reads it via GET 0xF2.
  119. static uint8_t g_ds3Mac[6] = { 0x00, 0x1B, 0xDC, 0x4F, 0x55, 0x80 };
  120. // Reproduce a genuine 64-byte Sixaxis feature report on the wire. TinyUSB's HID GET_REPORT path force-writes
  121. // the requested report id as wire byte 0 and hands us the buffer PAST it (`buf` = ctrl[1]); a real Sixaxis
  122. // (and GIMX) instead puts the array's own first byte there. So we overwrite that prepended id via buf[-1]
  123. // (== ctrl[0], a valid writable byte for this control transfer) and copy bytes [1..] into buf. Returns the
  124. // payload length; the stack adds the 1 byte we placed -> total = min(64, wLength), exactly like GIMX's
  125. // Endpoint_Write_Control_Stream_LE(arr, wLength). reqlen is post-prepend (host wLength - 1); the PS3 always
  126. // reads these with wLength >= 8, so the prepend always happened and buf[-1] is in bounds.
  127. static uint16_t emitFeature(uint8_t *buf, uint16_t reqlen,
  128. const uint8_t arr[64])
  129. {
  130. // buf[-1] is only the prepended id (and writable) when the stack actually prepended -- which it does iff
  131. // the host's wLength was > 1. reqlen here is already post-decrement, so reqlen < 2 means either no prepend
  132. // (wLength <= 1) or a 2-byte request; bail in both cases so we never write out of bounds. The PS3 reads
  133. // these reports with wLength >= 8, so real requests are unaffected.
  134. if (reqlen < 2)
  135. return 0;
  136. buf[-1] = arr[0];
  137. uint16_t n = 63; // 64-byte report minus byte 0 (placed above)
  138. if (n > reqlen)
  139. n = reqlen;
  140. memcpy(buf, arr + 1, n);
  141. return n;
  142. }
  143. static uint16_t ds3GetReport(uint8_t rid, hid_report_type_t type, uint8_t *buf,
  144. uint16_t reqlen)
  145. {
  146. if (type != HID_REPORT_TYPE_FEATURE || !buf || reqlen == 0)
  147. return 0;
  148. uint8_t r[64];
  149. switch (rid) {
  150. case 0x01:
  151. return emitFeature(buf, reqlen, report_01);
  152. case 0xf2: // overlay our controller MAC at [4..9]
  153. memcpy(r, report_f2, 64);
  154. memcpy(r + 4, g_ds3Mac, 6);
  155. return emitFeature(buf, reqlen, r);
  156. case 0xf5: // overlay learned host MAC at [2..7] (else the dummy aa.. from the template)
  157. memcpy(r, report_f5, 64);
  158. if (g_haveMaster)
  159. memcpy(r + 2, g_masterBd, 6);
  160. return emitFeature(buf, reqlen, r);
  161. case 0xef: // echo the PS3's remembered byte at [7]
  162. memcpy(r, report_ef, 64);
  163. r[7] = g_byte6ef;
  164. return emitFeature(buf, reqlen, r);
  165. case 0xf8:
  166. memcpy(r, report_f8, 64);
  167. r[7] = g_byte6ef;
  168. return emitFeature(buf, reqlen, r);
  169. case 0xf7:
  170. return emitFeature(buf, reqlen, report_f7);
  171. default:
  172. return 0;
  173. }
  174. }
  175. static void ds3SetReport(uint8_t rid, hid_report_type_t type, uint8_t const *b,
  176. uint16_t n)
  177. {
  178. if (type == HID_REPORT_TYPE_FEATURE) {
  179. // 0xEF: remember byte[6] so the next GET 0xEF/0xF8 echoes it. 0xF5: learn the host's BT MAC.
  180. // 0xF4: the PS3's "set operational"/power command -- ACK silently (no gating needed; we stream
  181. // unconditionally like GIMX). b[1]==0x08 would be a power-off request; ignored here.
  182. if (rid == 0xef && n >= 7)
  183. g_byte6ef = b[6];
  184. else if (rid == 0xf5 && n >= 8) {
  185. memcpy(g_masterBd, b + 2, 6);
  186. g_haveMaster = true;
  187. }
  188. return;
  189. }
  190. if (type != HID_REPORT_TYPE_OUTPUT || n < 1)
  191. return;
  192. // DS3 output report 0x01 (rumble + LED). It reaches us two ways: on the OUT interrupt endpoint (rid=0,
  193. // report id 0x01 included as b[0]) or via control SET_REPORT(Output,0x01) (rid=0x01, id not in the data).
  194. // Normalise to `p` = the bytes AFTER the report id, where the full report is
  195. // [0]=id [1]=0x00 [2]=small(right/HFR) dur [3]=small power(on/off) [4]=large(left/LFR) dur [5]=large power.
  196. // So in p: p[2]=small power, p[4]=large power. Map large->lowFreq, small->highFreq;
  197. // 257 = 65535/255 scales 8-bit power to the 16-bit haptic range.
  198. const uint8_t *p;
  199. uint16_t pn;
  200. if (rid == 0) { // OUT endpoint: report id leads the transfer
  201. if (b[0] != 0x01)
  202. return;
  203. p = b + 1;
  204. pn = (uint16_t)(n - 1);
  205. } else if (rid ==
  206. 0x01) { // control SET_REPORT: id may or may not be echoed in the data
  207. if (b[0] == 0x01) {
  208. p = b + 1;
  209. pn = (uint16_t)(n - 1);
  210. } else {
  211. p = b;
  212. pn = n;
  213. }
  214. } else {
  215. return;
  216. }
  217. if (pn < 5)
  218. return;
  219. int slot = ds3ActiveSlot();
  220. if (slot < 0)
  221. return;
  222. hapticSteamRumble((uint16_t)p[4] * 257u, p[2] ? 0xFFFFu : 0u,
  223. (uint8_t)slot);
  224. }
  225. // SC2 IMU int16 (center 0) -> DS3 10-bit unsigned (center 511), little-endian on the wire (low byte first).
  226. // >>6 maps the full int16 swing onto roughly +/-512 around center; the PS3 applies its own calibration so
  227. // exact scale is not critical. Writes 2 bytes at out[0..1].
  228. static void ds3Imu(uint8_t *out, int16_t v)
  229. {
  230. int32_t e = 511 + ((int32_t)v >> 6);
  231. if (e < 0)
  232. e = 0;
  233. if (e > 1023)
  234. e = 1023;
  235. out[0] = (uint8_t)(e & 0xFF);
  236. out[1] = (uint8_t)((e >> 8) & 0xFF);
  237. }
  238. // Build the 48-byte input-report PAYLOAD (the stack prepends report id 0x01 -> 49-byte Sixaxis report).
  239. // Offsets are the genuine report's rd[] minus one (rd[0] is the prepended id).
  240. static void ds3Build(uint8_t slot, uint8_t out[48])
  241. {
  242. uint32_t b = psButtonsFromSteam(g_in[slot].buttons);
  243. bool l2 = (g_in[slot].lt > SW_TRIG_ON) || (b & TB_L2);
  244. bool r2 = (g_in[slot].rt > SW_TRIG_ON) || (b & TB_R2);
  245. memset(out, 0, 48);
  246. // out[0] reserved (rd[1]); if it were 0xFF the kernel/console would drop the report -- keep 0.
  247. // out[1] (rd[2]): Select(bit0) L3 R3 Start(bit3) Up Right Down Left.
  248. // SC2 View -> Start, Menu -> Select: matches the physical button positions on the puck/controller (the
  249. // opposite of the PS5/DS4 Create/Options convention, which read reversed on the DS3 in testing).
  250. out[1] = ((b & TB_MENU) ? 0x01 : 0) | ((b & TB_L3) ? 0x02 : 0) |
  251. ((b & TB_R3) ? 0x04 : 0) | ((b & TB_VIEW) ? 0x08 : 0) |
  252. ((b & TB_DUP) ? 0x10 : 0) | ((b & TB_DRT) ? 0x20 : 0) |
  253. ((b & TB_DDN) ? 0x40 : 0) | ((b & TB_DLF) ? 0x80 : 0);
  254. // out[2] (rd[3]): L2 R2 L1 R1 Triangle Circle Cross Square. g_abSwap swaps the A/B + X/Y face pair.
  255. uint8_t tri, cir, crs, sqr;
  256. if (g_abSwap) {
  257. tri = (b & TB_A) ? 0x10 : 0;
  258. cir = (b & TB_B) ? 0x20 : 0;
  259. crs = (b & TB_X) ? 0x40 : 0;
  260. sqr = (b & TB_Y) ? 0x80 : 0;
  261. } else {
  262. tri = (b & TB_Y) ? 0x10 : 0;
  263. cir = (b & TB_B) ? 0x20 : 0;
  264. crs = (b & TB_A) ? 0x40 : 0;
  265. sqr = (b & TB_X) ? 0x80 : 0;
  266. }
  267. out[2] = (l2 ? 0x01 : 0) | (r2 ? 0x02 : 0) | ((b & TB_LB) ? 0x04 : 0) |
  268. ((b & TB_RB) ? 0x08 : 0) | tri | cir | crs | sqr;
  269. // out[3] (rd[4]): PS button
  270. out[3] = (b & TB_STEAM) ? 0x01 : 0;
  271. // out[5..8] (rd[6..9]): LX LY RX RY, center 0x80
  272. int16_t lx, ly, rx, ry;
  273. slotSticks(slot, &lx, &ly, &rx, &ry);
  274. out[5] = swStick(lx, false);
  275. out[6] = swStick(ly, true);
  276. out[7] = swStick(rx, false);
  277. out[8] = swStick(ry, true);
  278. // out[13..24] (rd[14..25]): analog pressures, order Up Right Down Left L2 R2 L1 R1 Tri Cir Cross Square
  279. out[13] = (b & TB_DUP) ? 0xFF : 0;
  280. out[14] = (b & TB_DRT) ? 0xFF : 0;
  281. out[15] = (b & TB_DDN) ? 0xFF : 0;
  282. out[16] = (b & TB_DLF) ? 0xFF : 0;
  283. out[17] = g_in[slot].lt;
  284. out[18] = g_in[slot].rt;
  285. out[19] = (b & TB_LB) ? 0xFF : 0;
  286. out[20] = (b & TB_RB) ? 0xFF : 0;
  287. out[21] = tri ? 0xFF : 0;
  288. out[22] = cir ? 0xFF : 0;
  289. out[23] = crs ? 0xFF : 0;
  290. out[24] = sqr ? 0xFF : 0;
  291. // out[28..30] (rd[29..31]): genuine DS3 link/power state.
  292. // 0x02 = plugged, 0x05 = full power, 0x10 = wired + rumble capable.
  293. out[28] = 0x02;
  294. out[29] = 0x05;
  295. out[30] = 0x10;
  296. // out[40..47] (rd[41..48]): accel X, accel Z, accel Y, gyro Z -- each 10-bit LE, center 511.
  297. ds3Imu(out + 40, g_in[slot].ax);
  298. ds3Imu(out + 42, g_in[slot].az);
  299. ds3Imu(out + 44, g_in[slot].ay);
  300. ds3Imu(out + 46, g_in[slot].gz);
  301. }
  302. // Neutral input report: centered sticks + IMU, no buttons. Streamed when no controller is linked so the PS3
  303. // keeps the Sixaxis "alive" (and a games/XMB controller slot) instead of seeing a silent endpoint.
  304. static void ds3Neutral(uint8_t out[48])
  305. {
  306. memset(out, 0, 48);
  307. out[5] = out[6] = out[7] = out[8] = 0x80; // sticks centered
  308. // Keep neutral reports semantically identical to an attached wired DS3.
  309. out[28] = 0x02; // plugged
  310. out[29] = 0x05; // full power
  311. out[30] = 0x10; // wired + rumble capable
  312. ds3Imu(out + 40, 0);
  313. ds3Imu(out + 42, 0);
  314. ds3Imu(out + 44, 0);
  315. ds3Imu(out + 46, 0);
  316. }
  317. void Ps3Controller::usbIdentity()
  318. {
  319. // Genuine Sixaxis / DualShock 3 identity. The PS3 recognises the pad by exactly this VID/PID.
  320. USBDevice.setID(0x054C, 0x0268);
  321. USBDevice.setVersion(0x0200);
  322. USBDevice.setDeviceVersion(0x0100);
  323. USBDevice.setManufacturerDescriptor("Sony");
  324. USBDevice.setProductDescriptor("PLAYSTATION(R)3 Controller");
  325. }
  326. // Static mount: present the single DS3 interface permanently (the setup() static path calls begin() then
  327. // attaches; it does NOT call usbIdentity() or build a slot pool, so we set the identity and register the HID
  328. // here). g_ds3.begin() both adds the interface to the descriptor and locks its TinyUSB instance.
  329. void Ps3Controller::begin()
  330. {
  331. usbIdentity();
  332. g_ds3.enableOutEndpoint(
  333. true); // OUT endpoint for rumble/LED output reports
  334. g_ds3.setReportCallback(ds3GetReport, ds3SetReport);
  335. g_ds3.setReportDescriptor(DS3_HID_DESC, sizeof DS3_HID_DESC);
  336. g_ds3.setPollInterval(1); // 1 ms interrupt IN, like the genuine pad
  337. g_ds3.begin();
  338. }
  339. void Ps3Controller::task()
  340. {
  341. if (!g_ds3.ready())
  342. return;
  343. if (millis() - g_ds3LastMs < USB_STREAM_MS)
  344. return;
  345. g_ds3LastMs = millis();
  346. uint8_t p[48];
  347. int slot = ds3ActiveSlot();
  348. if (slot >= 0)
  349. ds3Build((uint8_t)slot, p);
  350. else
  351. ds3Neutral(p);
  352. usbTxHid(&g_ds3, 0x01, p, sizeof p);
  353. }