USB Host Shield 2.0
PS5Parser.h
Go to the documentation of this file.
1 /* Copyright (C) 2021 Kristian Sloth Lauszus. All rights reserved.
2 
3  This software may be distributed and modified under the terms of the GNU
4  General Public License version 2 (GPL2) as published by the Free Software
5  Foundation and appearing in the file GPL2.TXT included in the packaging of
6  this file. Please note that GPL2 Section 2[b] requires that all works based
7  on this software must also be made publicly available under the terms of
8  the GPL2 ("Copyleft").
9 
10  Contact information
11  -------------------
12 
13  Kristian Sloth Lauszus
14  Web : https://lauszus.com
15  e-mail : lauszus@gmail.com
16 
17  Thanks to Joseph Duchesne for the initial code.
18  Based on Ludwig Füchsl's https://github.com/Ohjurot/DualSense-Windows PS5 port
19  and the series of patches found here: https://patchwork.kernel.org/project/linux-input/cover/20201219062336.72568-1-roderick@gaikai.com/
20  */
21 
22 #ifndef _ps5parser_h_
23 #define _ps5parser_h_
24 
25 #include "Usb.h"
26 #include "controllerEnums.h"
27 #include "PS5Trigger.h"
28 
30 const uint8_t PS5_BUTTONS[] PROGMEM = {
31  UP, // UP
32  RIGHT, // RIGHT
33  DOWN, // DOWN
34  LEFT, // LEFT
35 
36  0x0C, // CREATE
37  0x0D, // OPTIONS
38  0x0E, // L3
39  0x0F, // R3
40 
41  0x0A, // L2
42  0x0B, // R2
43  0x08, // L1
44  0x09, // R1
45 
46  0x07, // TRIANGLE
47  0x06, // CIRCLE
48  0x05, // CROSS
49  0x04, // SQUARE
50 
51  0x10, // PS
52  0x11, // TOUCHPAD
53  0x12, // MICROPHONE
54 };
55 
56 union PS5Buttons {
57  struct {
58  uint8_t dpad : 4;
59  uint8_t square : 1;
60  uint8_t cross : 1;
61  uint8_t circle : 1;
62  uint8_t triangle : 1;
63 
64  uint8_t l1 : 1;
65  uint8_t r1 : 1;
66  uint8_t l2 : 1;
67  uint8_t r2 : 1;
68  uint8_t create : 1;
69  uint8_t menu : 1;
70  uint8_t l3 : 1;
71  uint8_t r3 : 1;
72 
73  uint8_t ps : 1;
74  uint8_t touchpad : 1;
75  uint8_t mic : 1;
76  uint8_t dummy : 5;
77  } __attribute__((packed));
78  uint32_t val : 24;
79 } __attribute__((packed));
80 
81 struct ps5TouchpadXY {
82  struct {
83  uint8_t counter : 7; // Increments every time a finger is touching the touchpad
84  uint8_t touching : 1; // The top bit is cleared if the finger is touching the touchpad
85  uint16_t x : 12;
86  uint16_t y : 12;
87  } __attribute__((packed)) finger[2]; // 0 = first finger, 1 = second finger
88 } __attribute__((packed));
89 
90 union PS5Status {
91  struct {
92  // first byte
93  uint8_t headphone : 1;
94  uint8_t dummy : 2; // Seems to change when a jack is plugged in. First bit stays on when a mic is plugged in.
95  uint8_t usb : 1; // charging
96  uint8_t dummy2: 4;
97 
98  // second byte
99  uint8_t mic : 1;
100  uint8_t dummy3 : 3;
101  } __attribute__((packed));
102  uint16_t val;
103 } __attribute__((packed));
104 
105 struct PS5Data {
106  /* Button and joystick values */
107  uint8_t hatValue[4]; // 0-3 bytes
108  uint8_t trigger[2]; // 4-5
109 
110  uint8_t sequence_number; // 6
111 
112  PS5Buttons btn; // 7-9
113 
114  uint8_t reserved[5]; // 0xA-0xD
115 
116  /* Gyro and accelerometer values */
117  int16_t gyroX, gyroZ, gyroY; // 0x0F - 0x14
118  int16_t accX, accZ, accY; // 0x15-0x1A
120 
121  uint8_t reserved2;
122 
123  // 0x20 - 0x23 touchpad point 1
124  // 0x24 - 0x27 touchpad point 2
126 
127 #if 0 // The status byte depends on if it's sent via USB or Bluetooth, so is not parsed for now
128  uint8_t reserved3; // 0x28
129 
130  uint8_t rightTriggerFeedback; // 0x29
131  uint8_t leftTriggerFeedback; // 0x2A
132  uint8_t reserved4[10]; // 0x2B - 0x34
133 
134  // status bytes 0x35-0x36
135  PS5Status status;
136 #endif
137 } __attribute__((packed));
138 
139 struct PS5Output {
140  uint8_t bigRumble, smallRumble; // Rumble
141  uint8_t microphoneLed;
142  uint8_t disableLeds;
143  uint8_t playerLeds;
144  uint8_t r, g, b; // RGB for lightbar
145  bool reportChanged; // The data is send when data is received from the controller
146 } __attribute__((packed));
147 
149 class PS5Parser {
150 public:
153  Reset();
154  };
155 
158 
170  bool getButtonPress(ButtonEnum b);
171  bool getButtonClick(ButtonEnum b);
181  uint8_t getAnalogButton(ButtonEnum b);
182 
188  uint8_t getAnalogHat(AnalogHatEnum a);
189 
194  uint16_t getX(uint8_t finger = 0) {
195  return ps5Data.xy.finger[finger].x;
196  };
197 
203  uint16_t getY(uint8_t finger = 0) {
204  return ps5Data.xy.finger[finger].y;
205  };
206 
212  bool isTouching(uint8_t finger = 0) {
213  return !(ps5Data.xy.finger[finger].touching); // The bit is cleared when a finger is touching the touchpad
214  };
215 
221  uint8_t getTouchCounter(uint8_t finger = 0) {
222  return ps5Data.xy.finger[finger].counter;
223  };
224 
230  float getAngle(AngleEnum a) {
231  if (a == Pitch)
232  return (atan2f(-ps5Data.accY, -ps5Data.accZ) + PI) * RAD_TO_DEG;
233  else
234  return (atan2f(ps5Data.accX, -ps5Data.accZ) + PI) * RAD_TO_DEG;
235  };
236 
242  int16_t getSensor(SensorEnum s) {
243  switch(s) {
244  case gX:
245  return ps5Data.gyroX;
246  case gY:
247  return ps5Data.gyroY;
248  case gZ:
249  return ps5Data.gyroZ;
250  case aX:
251  return ps5Data.accX;
252  case aY:
253  return ps5Data.accY;
254  case aZ:
255  return ps5Data.accZ;
256  default:
257  return 0;
258  }
259  };
260 
261 #if 0 // Seems to only be available via Bluetooth, so have been disabled for now
266  uint8_t getBatteryLevel() {
267  return ps5Data.status.battery;
268  };
269 #endif
270 
271 #if 0 // These are only valid via USB, so have been commented out for now
276  bool getUsbStatus() {
277  return ps5Data.status.usb;
278  };
279 
284  bool getAudioStatus() {
285  return ps5Data.status.headphone;
286  };
287 
292  bool getMicStatus() {
293  return ps5Data.status.mic;
294  };
295 #endif
296 
298  void setAllOff() {
299  setRumbleOff();
300  setLedOff();
301  };
302 
304  void setRumbleOff() {
305  setRumbleOn(0, 0);
306  };
307 
312  void setRumbleOn(RumbleEnum mode) {
313  if (mode == RumbleLow)
314  setRumbleOn(0x00, 0xFF);
315  else
316  setRumbleOn(0xFF, 0x00);
317  };
318 
324  void setRumbleOn(uint8_t bigRumble, uint8_t smallRumble) {
325  ps5Output.bigRumble = bigRumble;
326  ps5Output.smallRumble = smallRumble;
327  ps5Output.reportChanged = true;
328  };
329 
331  void setLedOff() {
332  setLed(0, 0, 0);
333  };
334 
339  void setLed(uint8_t r, uint8_t g, uint8_t b) {
340  ps5Output.r = r;
341  ps5Output.g = g;
342  ps5Output.b = b;
343  ps5Output.reportChanged = true;
344  };
345 
350  void setLed(ColorsEnum color) {
351  setLed((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
352  };
353 
356  setPlayerLed(0);
357  }
358 
363  void setPlayerLed(uint8_t mask) {
364  ps5Output.playerLeds = mask;
365  ps5Output.reportChanged = true;
366  }
367 
369  void setMicLedOff() {
370  setMicLed(0);
371  }
372 
377  void setMicLed(bool on) {
378  ps5Output.microphoneLed = on ? 1 : 0;
379  ps5Output.reportChanged = true;
380  }
381 
383  uint16_t getMessageCounter(){
384  return message_counter;
385  }
386 
387 protected:
393  void Parse(uint8_t len, uint8_t *buf);
394 
396  void Reset();
397 
402  virtual void sendOutputReport(PS5Output *output) = 0;
403 
404 
405 private:
406  static int8_t getButtonIndexPS5(ButtonEnum b);
407  bool checkDpad(ButtonEnum b); // Used to check PS5 DPAD buttons
408 
409  PS5Data ps5Data;
410  PS5Buttons oldButtonState, buttonClickState;
411  PS5Output ps5Output;
412  uint8_t oldDpad;
413  uint16_t message_counter = 0;
414 };
415 #endif
const uint8_t PS5_BUTTONS[]
Definition: PS5Parser.h:30
Based on Ludwig Füchsl's DualSense Windows driver https://github.com/Ohjurot/DualSense-Windows.
void setLed(uint8_t r, uint8_t g, uint8_t b)
Definition: PS5Parser.h:339
void Reset()
Definition: PS5Parser.cpp:149
uint16_t getY(uint8_t finger=0)
Definition: PS5Parser.h:203
void setMicLed(bool on)
Definition: PS5Parser.h:377
void setLedOff()
Definition: PS5Parser.h:331
PS5Trigger rightTrigger
Definition: PS5Parser.h:157
void setAllOff()
Definition: PS5Parser.h:298
bool getButtonPress(ButtonEnum b)
Definition: PS5Parser.cpp:60
void setPlayerLedOff()
Definition: PS5Parser.h:355
bool getButtonClick(ButtonEnum b)
Definition: PS5Parser.cpp:68
int16_t getSensor(SensorEnum s)
Definition: PS5Parser.h:242
uint8_t getAnalogHat(AnalogHatEnum a)
Definition: PS5Parser.cpp:85
PS5Trigger leftTrigger
Definition: PS5Parser.h:154
void setMicLedOff()
Definition: PS5Parser.h:369
void setPlayerLed(uint8_t mask)
Definition: PS5Parser.h:363
uint16_t getMessageCounter()
Definition: PS5Parser.h:383
void setLed(ColorsEnum color)
Definition: PS5Parser.h:350
void setRumbleOn(RumbleEnum mode)
Definition: PS5Parser.h:312
float getAngle(AngleEnum a)
Definition: PS5Parser.h:230
void setRumbleOff()
Definition: PS5Parser.h:304
bool isTouching(uint8_t finger=0)
Definition: PS5Parser.h:212
virtual void sendOutputReport(PS5Output *output)=0
uint8_t getTouchCounter(uint8_t finger=0)
Definition: PS5Parser.h:221
uint8_t getAnalogButton(ButtonEnum b)
Definition: PS5Parser.cpp:76
void setRumbleOn(uint8_t bigRumble, uint8_t smallRumble)
Definition: PS5Parser.h:324
uint16_t getX(uint8_t finger=0)
Definition: PS5Parser.h:194
SensorEnum
@ gY
@ gX
@ aX
@ aZ
@ gZ
@ aY
AnalogHatEnum
AngleEnum
@ Pitch
ButtonEnum
@ DOWN
@ UP
@ LEFT
@ RIGHT
ColorsEnum
RumbleEnum
@ RumbleLow
PS5Buttons btn
Definition: PS5Parser.h:112
uint8_t hatValue[4]
Definition: PS5Parser.h:107
int16_t accY
Definition: PS5Parser.h:118
uint8_t trigger[2]
Definition: PS5Parser.h:108
int16_t gyroY
Definition: PS5Parser.h:117
int16_t accZ
Definition: PS5Parser.h:118
int16_t gyroZ
Definition: PS5Parser.h:117
int16_t gyroX
Definition: PS5Parser.h:117
uint8_t reserved[5]
Definition: PS5Parser.h:114
int16_t accX
Definition: PS5Parser.h:118
uint8_t reserved2
Definition: PS5Parser.h:121
uint8_t sequence_number
Definition: PS5Parser.h:110
int32_t sensor_timestamp
Definition: PS5Parser.h:119
ps5TouchpadXY xy
Definition: PS5Parser.h:125
uint8_t smallRumble
Definition: PS5Parser.h:140
uint8_t b
Definition: PS5Parser.h:144
uint8_t microphoneLed
Definition: PS5Parser.h:141
uint8_t r
Definition: PS5Parser.h:144
bool reportChanged
Definition: PS5Parser.h:145
uint8_t playerLeds
Definition: PS5Parser.h:143
uint8_t disableLeds
Definition: PS5Parser.h:142
uint8_t bigRumble
Definition: PS5Parser.h:140
uint8_t g
Definition: PS5Parser.h:144
uint16_t y
Definition: PS5Parser.h:86
struct ps5TouchpadXY::@31 finger[2]
uint8_t counter
Definition: PS5Parser.h:83
uint16_t x
Definition: PS5Parser.h:85
uint8_t touching
Definition: PS5Parser.h:84
uint8_t touchpad
Definition: PS5Parser.h:74
uint8_t ps
Definition: PS5Parser.h:73
uint8_t r1
Definition: PS5Parser.h:65
uint8_t l3
Definition: PS5Parser.h:70
uint8_t dpad
Definition: PS5Parser.h:58
uint8_t r3
Definition: PS5Parser.h:71
uint8_t create
Definition: PS5Parser.h:68
uint8_t circle
Definition: PS5Parser.h:61
uint8_t dummy
Definition: PS5Parser.h:76
uint8_t square
Definition: PS5Parser.h:59
uint8_t l2
Definition: PS5Parser.h:66
uint8_t cross
Definition: PS5Parser.h:60
uint8_t l1
Definition: PS5Parser.h:64
uint8_t r2
Definition: PS5Parser.h:67
uint8_t mic
Definition: PS5Parser.h:75
uint8_t menu
Definition: PS5Parser.h:69
uint32_t val
Definition: PS5Parser.h:78
uint8_t triangle
Definition: PS5Parser.h:62
uint8_t dummy3
Definition: PS5Parser.h:100
uint8_t dummy
Definition: PS5Parser.h:94
uint8_t headphone
Definition: PS5Parser.h:93
uint8_t usb
Definition: PS5Parser.h:95
uint8_t mic
Definition: PS5Parser.h:99
uint16_t val
Definition: PS5Parser.h:102
uint8_t dummy2
Definition: PS5Parser.h:96