USB Host Shield 2.0
Loading...
Searching...
No Matches
PS5Parser.cpp
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#include "PS5Parser.h"
23
35
36// To enable serial debugging see "settings.h"
37//#define PRINTREPORT // Uncomment to print the report send by the PS5 Controller
38
39int8_t PS5Parser::getButtonIndexPS5(ButtonEnum b) {
40 const int8_t index = ButtonIndex(b);
41 if ((uint8_t) index >= (sizeof(PS5_BUTTONS) / sizeof(PS5_BUTTONS[0]))) return -1;
42 return index;
43}
44
45bool PS5Parser::checkDpad(ButtonEnum b) {
46 switch (b) {
47 case UP:
48 return ps5Data.btn.dpad == DPAD_LEFT_UP || ps5Data.btn.dpad == DPAD_UP || ps5Data.btn.dpad == DPAD_UP_RIGHT;
49 case RIGHT:
50 return ps5Data.btn.dpad == DPAD_UP_RIGHT || ps5Data.btn.dpad == DPAD_RIGHT || ps5Data.btn.dpad == DPAD_RIGHT_DOWN;
51 case DOWN:
52 return ps5Data.btn.dpad == DPAD_RIGHT_DOWN || ps5Data.btn.dpad == DPAD_DOWN || ps5Data.btn.dpad == DPAD_DOWN_LEFT;
53 case LEFT:
54 return ps5Data.btn.dpad == DPAD_DOWN_LEFT || ps5Data.btn.dpad == DPAD_LEFT || ps5Data.btn.dpad == DPAD_LEFT_UP;
55 default:
56 return false;
57 }
58}
59
61 const int8_t index = getButtonIndexPS5(b); if (index < 0) return 0;
62 if (index <= LEFT) // Dpad
63 return checkDpad(b);
64 else
65 return ps5Data.btn.val & (1UL << pgm_read_byte(&PS5_BUTTONS[index]));
66}
67
69 const int8_t index = getButtonIndexPS5(b); if (index < 0) return 0;
70 uint32_t mask = 1UL << pgm_read_byte(&PS5_BUTTONS[index]);
71 bool click = buttonClickState.val & mask;
72 buttonClickState.val &= ~mask; // Clear "click" event
73 return click;
74}
75
77 const int8_t index = getButtonIndexPS5(b); if (index < 0) return 0;
78 if (index == ButtonIndex(L2)) // These are the only analog buttons on the controller
79 return ps5Data.trigger[0];
80 else if (index == ButtonIndex(R2))
81 return ps5Data.trigger[1];
82 return 0;
83}
84
88
90 if (len > 1 && buf) {
91#ifdef PRINTREPORT
92 Notify(PSTR("\r\nLen: "), 0x80); Notify(len, 0x80);
93 Notify(PSTR(", data: "), 0x80);
94 for (uint8_t i = 0; i < len; i++) {
95 D_PrintHex<uint8_t > (buf[i], 0x80);
96 Notify(PSTR(" "), 0x80);
97 }
98#endif
99
100 if (buf[0] == 0x01) // Check report ID
101 memcpy(&ps5Data, buf + 1, min((uint8_t)(len - 1), MFK_CASTUINT8T sizeof(ps5Data)));
102 else if (buf[0] == 0x31) { // This report is send via Bluetooth, it has an offset of 1 compared to the USB data
103 if (len < 3) {
104#ifdef DEBUG_USB_HOST
105 Notify(PSTR("\r\nReport is too short: "), 0x80);
107#endif
108 return;
109 }
110 memcpy(&ps5Data, buf + 2, min((uint8_t)(len - 2), MFK_CASTUINT8T sizeof(ps5Data)));
111 } else {
112#ifdef DEBUG_USB_HOST
113 Notify(PSTR("\r\nUnknown report id: "), 0x80);
114 D_PrintHex<uint8_t > (buf[0], 0x80);
115 Notify(PSTR(", len: "), 0x80);
117#endif
118 return;
119 }
120
121 if (ps5Data.btn.val != oldButtonState.val) { // Check if anything has changed
122 buttonClickState.val = ps5Data.btn.val & ~oldButtonState.val; // Update click state variable
123 oldButtonState.val = ps5Data.btn.val;
124
125 // The DPAD buttons does not set the different bits, but set a value corresponding to the buttons pressed, we will simply set the bits ourself
126 uint8_t newDpad = 0;
127 if (checkDpad(UP))
128 newDpad |= 1 << UP;
129 if (checkDpad(RIGHT))
130 newDpad |= 1 << RIGHT;
131 if (checkDpad(DOWN))
132 newDpad |= 1 << DOWN;
133 if (checkDpad(LEFT))
134 newDpad |= 1 << LEFT;
135 if (newDpad != oldDpad) {
136 buttonClickState.dpad = newDpad & ~oldDpad; // Override values
137 oldDpad = newDpad;
138 }
139 }
140
141 message_counter++;
142 }
143
145 sendOutputReport(&ps5Output); // Send output report
146}
147
148
150 uint8_t i;
151 for (i = 0; i < sizeof(ps5Data.hatValue); i++)
152 ps5Data.hatValue[i] = 127; // Center value
153 ps5Data.btn.val = 0;
154 oldButtonState.val = 0;
155 for (i = 0; i < sizeof(ps5Data.trigger); i++)
156 ps5Data.trigger[i] = 0;
157 for (i = 0; i < sizeof(ps5Data.xy.finger)/sizeof(ps5Data.xy.finger[0]); i++)
158 ps5Data.xy.finger[i].touching = 1; // The bit is cleared if the finger is touching the touchpad
159
160 ps5Data.btn.dpad = DPAD_OFF;
161 oldButtonState.dpad = DPAD_OFF;
162 buttonClickState.dpad = 0;
163 oldDpad = 0;
164
167
168 ps5Output.bigRumble = ps5Output.smallRumble = 0;
169 ps5Output.microphoneLed = 0;
170 ps5Output.disableLeds = 0;
171 ps5Output.playerLeds = 0;
172 ps5Output.r = ps5Output.g = ps5Output.b = 0;
173 ps5Output.reportChanged = false;
174};
DPADEnum
Definition PS4Parser.cpp:20
@ DPAD_DOWN_LEFT
Definition PS4Parser.cpp:26
@ DPAD_RIGHT_DOWN
Definition PS4Parser.cpp:24
@ DPAD_UP
Definition PS4Parser.cpp:21
@ DPAD_DOWN
Definition PS4Parser.cpp:25
@ DPAD_UP_RIGHT
Definition PS4Parser.cpp:22
@ DPAD_LEFT_UP
Definition PS4Parser.cpp:28
@ DPAD_OFF
Definition PS4Parser.cpp:29
@ DPAD_RIGHT
Definition PS4Parser.cpp:23
@ DPAD_LEFT
Definition PS4Parser.cpp:27
@ DPAD_DOWN_LEFT
Definition PS5Parser.cpp:30
@ DPAD_RIGHT_DOWN
Definition PS5Parser.cpp:28
@ DPAD_UP
Definition PS5Parser.cpp:25
@ DPAD_DOWN
Definition PS5Parser.cpp:29
@ DPAD_UP_RIGHT
Definition PS5Parser.cpp:26
@ DPAD_LEFT_UP
Definition PS5Parser.cpp:32
@ DPAD_OFF
Definition PS5Parser.cpp:33
@ DPAD_RIGHT
Definition PS5Parser.cpp:27
@ DPAD_LEFT
Definition PS5Parser.cpp:31
const uint8_t PS5_BUTTONS[]
Definition PS5Parser.h:30
void Reset()
void Parse(uint8_t len, uint8_t *buf)
Definition PS5Parser.cpp:89
PS5Trigger rightTrigger
Definition PS5Parser.h:157
bool getButtonPress(ButtonEnum b)
Definition PS5Parser.cpp:60
bool getButtonClick(ButtonEnum b)
Definition PS5Parser.cpp:68
uint8_t getAnalogHat(AnalogHatEnum a)
Definition PS5Parser.cpp:85
PS5Trigger leftTrigger
Definition PS5Parser.h:157
virtual void sendOutputReport(PS5Output *output)=0
uint8_t getAnalogButton(ButtonEnum b)
Definition PS5Parser.cpp:76
void Reset()
Definition PS5Trigger.h:100
bool reportChanged
Definition PS5Trigger.h:88
constexpr int8_t ButtonIndex(ButtonEnum key)
AnalogHatEnum
ButtonEnum
@ DOWN
@ UP
@ LEFT
@ RIGHT
#define Notify(...)
Definition message.h:51
#define MFK_CASTUINT8T
Definition settings.h:200
PS5Buttons btn
Definition PS5Parser.h:112
uint8_t hatValue[4]
Definition PS5Parser.h:107
uint8_t trigger[2]
Definition PS5Parser.h:108
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
struct ps5TouchpadXY::@31 finger[2]
uint8_t dpad
Definition PS5Parser.h:58
uint32_t val
Definition PS5Parser.h:78
#define pgm_read_byte(addr)
#define PSTR(str)