1
+ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
+ /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
+ /* This Source Code Form is subject to the terms of the Mozilla Public
4
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
+
7
+ // Based on
8
+ // https://cs.chromium.org/chromium/src/device/gamepad/gamepad_standard_mappings.h
9
+
10
+ // Copyright (c) 2012 The Chromium Authors. All rights reserved.
11
+ // Use of this source code is governed by a BSD-style license that can be
12
+ // found in the LICENSE file.
13
+
14
+ #include " mozilla/dom/GamepadRemapping.h"
15
+
16
+ namespace mozilla {
17
+ namespace dom {
18
+
19
+ // Follow the canonical ordering recommendation for the "Standard Gamepad"
20
+ // from https://www.w3.org/TR/gamepad/#remapping.
21
+ enum CanonicalButtonIndex {
22
+ BUTTON_INDEX_PRIMARY,
23
+ BUTTON_INDEX_SECONDARY,
24
+ BUTTON_INDEX_TERTIARY,
25
+ BUTTON_INDEX_QUATERNARY,
26
+ BUTTON_INDEX_LEFT_SHOULDER,
27
+ BUTTON_INDEX_RIGHT_SHOULDER,
28
+ BUTTON_INDEX_LEFT_TRIGGER,
29
+ BUTTON_INDEX_RIGHT_TRIGGER,
30
+ BUTTON_INDEX_BACK_SELECT,
31
+ BUTTON_INDEX_START,
32
+ BUTTON_INDEX_LEFT_THUMBSTICK,
33
+ BUTTON_INDEX_RIGHT_THUMBSTICK,
34
+ BUTTON_INDEX_DPAD_UP,
35
+ BUTTON_INDEX_DPAD_DOWN,
36
+ BUTTON_INDEX_DPAD_LEFT,
37
+ BUTTON_INDEX_DPAD_RIGHT,
38
+ BUTTON_INDEX_META,
39
+ BUTTON_INDEX_COUNT
40
+ };
41
+
42
+ enum CanonicalAxisIndex {
43
+ AXIS_INDEX_LEFT_STICK_X,
44
+ AXIS_INDEX_LEFT_STICK_Y,
45
+ AXIS_INDEX_RIGHT_STICK_X,
46
+ AXIS_INDEX_RIGHT_STICK_Y,
47
+ AXIS_INDEX_COUNT
48
+ };
49
+
50
+ void FetchDpadFromAxis (uint32_t aIndex, double dir) {
51
+ bool up = false ;
52
+ bool right = false ;
53
+ bool down = false ;
54
+ bool left = false ;
55
+
56
+ // Dpad is mapped as a direction on one axis, where -1 is up and it
57
+ // increases clockwise to 1, which is up + left. It's set to a large (> 1.f)
58
+ // number when nothing is depressed, except on start up, sometimes it's 0.0
59
+ // for no data, rather than the large number.
60
+ if (dir != 0 .0f ) {
61
+ up = (dir >= -1 .f && dir < -0 .7f ) || (dir >= .95f && dir <= 1 .f );
62
+ right = dir >= -.75f && dir < -.1f ;
63
+ down = dir >= -.2f && dir < .45f ;
64
+ left = dir >= .4f && dir <= 1 .f ;
65
+ }
66
+
67
+ RefPtr<GamepadPlatformService> service =
68
+ GamepadPlatformService::GetParentService ();
69
+ if (!service) {
70
+ return ;
71
+ }
72
+
73
+ service->NewButtonEvent (aIndex, BUTTON_INDEX_DPAD_UP, up);
74
+ service->NewButtonEvent (aIndex, BUTTON_INDEX_DPAD_RIGHT, right);
75
+ service->NewButtonEvent (aIndex, BUTTON_INDEX_DPAD_DOWN, down);
76
+ service->NewButtonEvent (aIndex, BUTTON_INDEX_DPAD_LEFT, left);
77
+ }
78
+
79
+ class DefaultRemapper final : public GamepadRemapper {
80
+ public:
81
+ virtual uint32_t GetAxisCount () const override {
82
+ return numAxes;
83
+ }
84
+
85
+ virtual uint32_t GetButtonCount () const override {
86
+ return numButtons;
87
+ }
88
+
89
+ virtual void SetAxisCount (uint32_t aAxisCount) override {
90
+ numAxes = aAxisCount;
91
+ }
92
+
93
+ virtual void SetButtonCount (uint32_t aButtonCount) override {
94
+ numButtons = aButtonCount;
95
+ }
96
+
97
+ virtual void RemapAxisMoveEvent (uint32_t aIndex, uint32_t aAxis,
98
+ double aValue) const override {
99
+ RefPtr<GamepadPlatformService> service =
100
+ GamepadPlatformService::GetParentService ();
101
+ if (!service) {
102
+ return ;
103
+ }
104
+ service->NewAxisMoveEvent (aIndex, aAxis, aValue);
105
+ }
106
+
107
+ virtual void RemapButtonEvent (uint32_t aIndex, uint32_t aButton,
108
+ bool aPressed) const override {
109
+ RefPtr<GamepadPlatformService> service =
110
+ GamepadPlatformService::GetParentService ();
111
+ if (!service) {
112
+ return ;
113
+ }
114
+ service->NewButtonEvent (aIndex, aButton, aPressed);
115
+ }
116
+
117
+ private:
118
+ uint32_t numAxes;
119
+ uint32_t numButtons;
120
+ };
121
+
122
+ class Dualshock4Remapper final : public GamepadRemapper {
123
+ public:
124
+ virtual uint32_t GetAxisCount () const override { return AXIS_INDEX_COUNT; }
125
+
126
+ virtual uint32_t GetButtonCount () const override {
127
+ return DUALSHOCK_BUTTON_COUNT;
128
+ }
129
+
130
+ virtual GamepadMappingType GetMappingType () const override {
131
+ return GamepadMappingType::_empty;
132
+ }
133
+
134
+ virtual void RemapAxisMoveEvent (uint32_t aIndex, uint32_t aAxis,
135
+ double aValue) const override {
136
+ RefPtr<GamepadPlatformService> service =
137
+ GamepadPlatformService::GetParentService ();
138
+ if (!service) {
139
+ return ;
140
+ }
141
+
142
+ switch (aAxis) {
143
+ case 0 :
144
+ service->NewAxisMoveEvent (aIndex, AXIS_INDEX_LEFT_STICK_X, aValue);
145
+ break ;
146
+ case 1 :
147
+ service->NewAxisMoveEvent (aIndex, AXIS_INDEX_LEFT_STICK_Y, aValue);
148
+ break ;
149
+ case 2 :
150
+ service->NewAxisMoveEvent (aIndex, AXIS_INDEX_RIGHT_STICK_X, aValue);
151
+ break ;
152
+ case 3 :
153
+ service->NewButtonEvent (aIndex, BUTTON_INDEX_LEFT_TRIGGER,
154
+ aValue > 0 .1f );
155
+ break ;
156
+ case 4 :
157
+ service->NewButtonEvent (aIndex, BUTTON_INDEX_RIGHT_TRIGGER,
158
+ aValue > 0 .1f );
159
+ break ;
160
+ case 5 :
161
+ service->NewAxisMoveEvent (aIndex, AXIS_INDEX_RIGHT_STICK_Y, aValue);
162
+ break ;
163
+ case 9 :
164
+ FetchDpadFromAxis (aIndex, aValue);
165
+ break ;
166
+ default :
167
+ NS_WARNING (
168
+ nsPrintfCString (
169
+ " Axis idx '%d' doesn't support in Dualshock4Remapper()." , aAxis)
170
+ .get());
171
+ break ;
172
+ }
173
+ }
174
+
175
+ virtual void RemapButtonEvent (uint32_t aIndex, uint32_t aButton,
176
+ bool aPressed) const override {
177
+ RefPtr<GamepadPlatformService> service =
178
+ GamepadPlatformService::GetParentService ();
179
+ if (!service) {
180
+ return ;
181
+ }
182
+
183
+ const std::vector<uint32_t > buttonMapping = {
184
+ BUTTON_INDEX_TERTIARY,
185
+ BUTTON_INDEX_PRIMARY,
186
+ BUTTON_INDEX_SECONDARY,
187
+ BUTTON_INDEX_QUATERNARY,
188
+ BUTTON_INDEX_LEFT_SHOULDER,
189
+ BUTTON_INDEX_RIGHT_SHOULDER,
190
+ BUTTON_INDEX_LEFT_TRIGGER,
191
+ BUTTON_INDEX_RIGHT_TRIGGER,
192
+ BUTTON_INDEX_BACK_SELECT,
193
+ BUTTON_INDEX_START,
194
+ BUTTON_INDEX_LEFT_THUMBSTICK,
195
+ BUTTON_INDEX_RIGHT_THUMBSTICK,
196
+ BUTTON_INDEX_META,
197
+ DUALSHOCK_BUTTON_TOUCHPAD
198
+ };
199
+
200
+ if (buttonMapping.size () <= aIndex) {
201
+ NS_WARNING (
202
+ nsPrintfCString (
203
+ " Button idx '%d' doesn't support in Dualshock4Remapper()." ,
204
+ aButton)
205
+ .get());
206
+ return ;
207
+ }
208
+
209
+ service->NewButtonEvent (aIndex, buttonMapping[aButton], aPressed);
210
+ }
211
+
212
+ private:
213
+ enum Dualshock4Buttons {
214
+ DUALSHOCK_BUTTON_TOUCHPAD = BUTTON_INDEX_COUNT,
215
+ DUALSHOCK_BUTTON_COUNT
216
+ };
217
+ };
218
+
219
+ already_AddRefed<GamepadRemapper> GetGamepadRemapper (const uint16_t aVendorId,
220
+ const uint16_t aProductId) {
221
+ const std::vector<GamepadRemappingData> remappingRules = {
222
+ {GamepadId::kSonyDualshock4 , new Dualshock4Remapper ()},
223
+ {GamepadId::kSonyDualshock4Slim , new Dualshock4Remapper ()},
224
+ {GamepadId::kSonyDualshock4USBReceiver , new Dualshock4Remapper ()}
225
+ };
226
+ const GamepadId id = static_cast <GamepadId>((aVendorId << 16 ) | aProductId);
227
+
228
+ for (uint32_t i = 0 ; i < remappingRules.size (); ++i) {
229
+ if (id == remappingRules[i].id ) {
230
+ return do_AddRef (remappingRules[i].remapping .get ());
231
+ }
232
+ }
233
+
234
+ static RefPtr<GamepadRemapper> defaultRemapper = new DefaultRemapper ();
235
+ return do_AddRef (defaultRemapper.get ());
236
+ }
237
+
238
+ } // namespace dom
239
+ } // namespace mozilla
0 commit comments