mode_hidgyro.cpp 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #include "mode_hidgyro.h"
  2. #include "triton.h"
  3. #include "gamepad_util.h"
  4. #include "config.h"
  5. #include "haptics.h"
  6. #include <Adafruit_TinyUSB.h>
  7. #include <Arduino.h>
  8. #include <string.h>
  9. HidGyroController g_hidGyroCtl;
  10. static const uint8_t GYRO_HID_DESC[]={
  11. 0x05,0x01,0x09,0x05,0xA1,0x01,0x85,0x01,0x09,0x30,0x09,0x31,0x09,0x32,0x09,0x35,
  12. 0x15,0x00,0x26,0xFF,0x00,0x75,0x08,0x95,0x04,0x81,0x02,0x09,0x39,0x15,0x00,0x25,
  13. 0x07,0x35,0x00,0x46,0x3B,0x01,0x65,0x14,0x75,0x04,0x95,0x01,0x81,0x42,0x65,0x00,
  14. 0x05,0x09,0x19,0x01,0x29,0x0E,0x15,0x00,0x25,0x01,0x75,0x01,0x95,0x0E,0x81,0x02,
  15. 0x06,0x00,0xFF,0x09,0x20,0x75,0x06,0x95,0x01,0x15,0x00,0x25,0x7F,0x81,0x02,0x05,
  16. 0x01,0x09,0x33,0x09,0x34,0x15,0x00,0x26,0xFF,0x00,0x75,0x08,0x95,0x02,0x81,0x02,
  17. 0x06,0x00,0xFF,0x09,0x21,0x95,0x36,0x81,0x02,0x85,0x05,0x09,0x22,0x95,0x1F,0x91,
  18. 0x02,0x85,0x04,0x09,0x23,0x95,0x24,0xB1,0x02,0x85,0x02,0x09,0x24,0x95,0x24,0xB1,
  19. 0x02,0xC0
  20. };
  21. #define DS4_TOUCH_H 942
  22. #define DS4_STATUS_USB 0x1B // cable + level 11 (full)
  23. static unsigned long g_gyroLastMs=0;
  24. static Adafruit_USBD_HID g_hidGyro;
  25. static void hidGyroSet(uint8_t rid, hid_report_type_t type, uint8_t const* b, uint16_t n){
  26. if(type!=HID_REPORT_TYPE_OUTPUT || n<1) return;
  27. uint8_t id; const uint8_t* p; uint16_t pn;
  28. if(rid==0){ id=b[0]; p=b+1; pn=(uint16_t)(n-1); }
  29. else { id=rid; p=b; pn=n; }
  30. // DS4 USB effects: report 0x05, magic at byte 0, effects block starts at byte 3.
  31. if(id!=0x05 || pn<5) return;
  32. hapticSteamRumble((uint16_t)p[4]*257u, (uint16_t)p[3]*257u); // DS4: left=low, right=high
  33. }
  34. static void hidGyroBuild(uint8_t out[63]){
  35. uint32_t b=psButtonsFromSteam(g_in.buttons);
  36. bool lTouch=(b&TB_LPADT)||(b&TB_LPADC), rTouch=(b&TB_RPADT)||(b&TB_RPADC);
  37. memset(out,0,63);
  38. out[0]=swStick(g_in.lx,false); out[1]=swStick(g_in.ly,true);
  39. out[2]=swStick(g_in.rx,false); out[3]=swStick(g_in.ry,true);
  40. out[4]=psHatNibble(b)|psFaceNibble(b);
  41. out[5]=psShouldersByte(b);
  42. static uint8_t ctr=0; out[6]=((ctr++&0x0F)<<4)|((b&TB_TOUCH||b&TB_LPADC||b&TB_RPADC)?0x02:0)|((b&TB_STEAM)?0x01:0);
  43. out[7]=g_in.lt; out[8]=g_in.rt;
  44. out[12]=g_in.gx&0xFF; out[13]=g_in.gx>>8;
  45. out[14]=g_in.gy&0xFF; out[15]=g_in.gy>>8;
  46. out[16]=(-g_in.gz)&0xFF; out[17]=(-g_in.gz)>>8;
  47. out[18]=g_in.ax&0xFF; out[19]=g_in.ax>>8;
  48. out[20]=g_in.ay&0xFF; out[21]=g_in.ay>>8;
  49. out[22]=g_in.az&0xFF; out[23]=g_in.az>>8;
  50. out[29]=DS4_STATUS_USB;
  51. if(lTouch || rTouch){
  52. uint16_t lx, ly, rx, ry;
  53. steamPadsToTouch(b, DS4_TOUCH_H, g_in.lpx, g_in.lpy, g_in.rpx, g_in.rpy, &lx, &ly, &rx, &ry);
  54. static uint8_t tstamp=0;
  55. out[32]=1; out[33]=tstamp++;
  56. touchPackPads(out+34, lTouch, rTouch, lx, ly, rx, ry);
  57. } else {
  58. out[32]=0;
  59. touchPackPads(out+34, false, false, 0, 0, 0, 0); // contact 0x80 -- memset(0) reads as touch @0,0
  60. }
  61. }
  62. void HidGyroController::begin(){
  63. USBDevice.setID(0x054C, 0x05C4);
  64. USBDevice.setDeviceVersion(0x0101); // bumped from 0x0100 for the added wake-mouse interface (Windows caches config by VID:PID:bcdDevice)
  65. USBDevice.setManufacturerDescriptor("Sony Computer Entertainment");
  66. USBDevice.setProductDescriptor("Wireless Controller");
  67. g_hidGyro.enableOutEndpoint(true);
  68. g_hidGyro.setReportCallback(NULL, hidGyroSet);
  69. g_hidGyro.setReportDescriptor(GYRO_HID_DESC, sizeof GYRO_HID_DESC);
  70. g_hidGyro.setPollInterval(4);
  71. g_hidGyro.begin();
  72. }
  73. void HidGyroController::task(){
  74. if(!g_hidGyro.ready()) return;
  75. if(millis()-g_gyroLastMs<USB_STREAM_MS) return; g_gyroLastMs=millis();
  76. uint8_t p[63]; hidGyroBuild(p);
  77. g_hidGyro.sendReport(0x01, p, sizeof p);
  78. }