Skip to content

Commit 43693c0

Browse files
committed
Bug 1523353 - Part 2: DS4 gamepad multitouch and lightindicator support on Mac OS. r=baku
Differential Revision: https://phabricator.services.mozilla.com/D37463 --HG-- extra : moz-landing-system : lando
1 parent 3087968 commit 43693c0

File tree

4 files changed

+103
-14
lines changed

4 files changed

+103
-14
lines changed

dom/gamepad/GamepadRemapping.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,11 @@ class Dualshock4Remapper final : public GamepadRemapper {
403403
aReport[8] = aBlue;
404404
}
405405

406-
virtual void GetTouchData(uint32_t aIndex, void* aInput) override {
406+
virtual uint32_t GetMaxInputReportLength() const override {
407+
return MAX_INPUT_LEN;
408+
}
409+
410+
virtual void ProcessTouchData(uint32_t aIndex, void* aInput) override {
407411
nsTArray<GamepadTouchState> touches(TOUCH_EVENT_COUNT);
408412
touches.SetLength(TOUCH_EVENT_COUNT);
409413
uint8_t* rawData = (uint8_t*)aInput;
@@ -546,6 +550,7 @@ class Dualshock4Remapper final : public GamepadRemapper {
546550

547551
static const uint32_t LIGHT_INDICATOR_COUNT = 1;
548552
static const uint32_t TOUCH_EVENT_COUNT = 2;
553+
static const uint32_t MAX_INPUT_LEN = 68;
549554

550555
nsTArray<unsigned long> mLastTouchId;
551556
nsTArray<bool> mLastTouches;

dom/gamepad/GamepadRemapping.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,14 @@ class GamepadRemapper {
7878
virtual uint32_t GetTouchEventCount() const { return 0; }
7979
virtual void GetLightColorReport(uint8_t aRed, uint8_t aGreen, uint8_t aBlue,
8080
std::vector<uint8_t>& aReport) const {}
81+
virtual uint32_t GetMaxInputReportLength() const { return 0; }
8182

8283
virtual void SetAxisCount(uint32_t aButtonCount) {}
8384
virtual void SetButtonCount(uint32_t aButtonCount) {}
8485
virtual GamepadMappingType GetMappingType() const {
8586
return GamepadMappingType::Standard;
8687
}
87-
virtual void GetTouchData(uint32_t aIndex, void* aInput) {}
88+
virtual void ProcessTouchData(uint32_t aIndex, void* aInput) {}
8889
virtual void RemapAxisMoveEvent(uint32_t aIndex, uint32_t aAxis,
8990
double aValue) const = 0;
9091
virtual void RemapButtonEvent(uint32_t aIndex, uint32_t aButton,

dom/gamepad/cocoa/CocoaGamepad.cpp

Lines changed: 94 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ class Gamepad {
8383

8484
public:
8585
Gamepad() : mDevice(nullptr), mSuperIndex(-1) {}
86+
8687
bool operator==(IOHIDDeviceRef device) const { return mDevice == device; }
8788
bool empty() const { return mDevice == nullptr; }
8889
void clear() {
@@ -92,13 +93,12 @@ class Gamepad {
9293
mSuperIndex = -1;
9394
}
9495
void init(IOHIDDeviceRef device);
96+
void ReportChanged(uint8_t* report, CFIndex report_length);
97+
size_t WriteOutputReport(const std::vector<uint8_t>& aReport) const;
98+
9599
size_t numButtons() { return buttons.Length(); }
96100
size_t numAxes() { return axes.Length(); }
97101

98-
// Index given by our superclass.
99-
uint32_t mSuperIndex;
100-
RefPtr<GamepadRemapper> mRemapper;
101-
102102
Button* lookupButton(IOHIDElementRef element) {
103103
for (unsigned i = 0; i < buttons.Length(); i++) {
104104
if (buttons[i].element == element) return &buttons[i];
@@ -112,6 +112,11 @@ class Gamepad {
112112
}
113113
return nullptr;
114114
}
115+
116+
// Index given by our superclass.
117+
uint32_t mSuperIndex;
118+
RefPtr<GamepadRemapper> mRemapper;
119+
std::vector<uint8_t> mInputReport;
115120
};
116121

117122
void Gamepad::init(IOHIDDeviceRef device) {
@@ -192,8 +197,16 @@ class DarwinGamepadService {
192197
public:
193198
DarwinGamepadService();
194199
~DarwinGamepadService();
200+
201+
static void ReportChangedCallback(void* context, IOReturn result,
202+
void* sender, IOHIDReportType report_type,
203+
uint32_t report_id, uint8_t* report,
204+
CFIndex report_length);
205+
195206
void Startup();
196207
void Shutdown();
208+
void SetLightIndicatorColor(uint32_t aControllerIdx, uint32_t aLightIndex,
209+
uint8_t aRed, uint8_t aGreen, uint8_t aBlue);
197210
friend class DarwinGamepadServiceStartupRunnable;
198211
friend class DarwinGamepadServiceShutdownRunnable;
199212
};
@@ -284,13 +297,27 @@ void DarwinGamepadService::DeviceAdded(IOHIDDeviceRef device) {
284297
remapper->SetButtonCount(mGamepads[slot].numButtons());
285298

286299
uint32_t index = service->AddGamepad(
287-
buffer, remapper->GetMappingType(),
288-
mozilla::dom::GamepadHand::_empty, remapper->GetButtonCount(),
289-
remapper->GetAxisCount(), 0, 0,
290-
0); // TODO: Bug 680289, implement gamepad haptics for cocoa.
291-
// TODO: Bug 1523355, implement gamepad lighindicator and touch for cocoa.
300+
buffer, remapper->GetMappingType(), mozilla::dom::GamepadHand::_empty,
301+
remapper->GetButtonCount(), remapper->GetAxisCount(),
302+
0, // TODO: Bug 680289, implement gamepad haptics for cocoa.
303+
remapper->GetLightIndicatorCount(), remapper->GetTouchEventCount());
304+
305+
nsTArray<GamepadLightIndicatorType> lightTypes;
306+
remapper->GetLightIndicators(lightTypes);
307+
for (uint32_t i = 0; i < lightTypes.Length(); ++i) {
308+
if (lightTypes[i] != GamepadLightIndicator::DefaultType()) {
309+
service->NewLightIndicatorTypeEvent(index, i, lightTypes[i]);
310+
}
311+
}
312+
292313
mGamepads[slot].mSuperIndex = index;
314+
mGamepads[slot].mInputReport.resize(remapper->GetMaxInputReportLength());
293315
mGamepads[slot].mRemapper = remapper.forget();
316+
317+
IOHIDDeviceRegisterInputReportCallback(
318+
device, mGamepads[slot].mInputReport.data(),
319+
mGamepads[slot].mInputReport.size(), ReportChangedCallback,
320+
&mGamepads[slot]);
294321
}
295322

296323
void DarwinGamepadService::DeviceRemoved(IOHIDDeviceRef device) {
@@ -308,6 +335,29 @@ void DarwinGamepadService::DeviceRemoved(IOHIDDeviceRef device) {
308335
}
309336
}
310337

338+
// Replace context to be Gamepad.
339+
void DarwinGamepadService::ReportChangedCallback(
340+
void* context, IOReturn result, void* sender, IOHIDReportType report_type,
341+
uint32_t report_id, uint8_t* report, CFIndex report_length) {
342+
if (report_type == kIOHIDReportTypeInput) {
343+
reinterpret_cast<Gamepad*>(context)->ReportChanged(report, report_length);
344+
}
345+
}
346+
347+
void Gamepad::ReportChanged(uint8_t* report, CFIndex report_len) {
348+
MOZ_RELEASE_ASSERT(report_len <= mRemapper->GetMaxInputReportLength());
349+
mRemapper->ProcessTouchData(mSuperIndex, report);
350+
}
351+
352+
size_t Gamepad::WriteOutputReport(const std::vector<uint8_t>& aReport) const {
353+
IOReturn success =
354+
IOHIDDeviceSetReport(mDevice, kIOHIDReportTypeOutput, aReport[0],
355+
aReport.data(), aReport.size());
356+
357+
MOZ_ASSERT(success == kIOReturnSuccess);
358+
return (success == kIOReturnSuccess) ? aReport.size() : 0;
359+
}
360+
311361
void DarwinGamepadService::InputValueChanged(IOHIDValueRef value) {
312362
RefPtr<GamepadPlatformService> service =
313363
GamepadPlatformService::GetParentService();
@@ -507,6 +557,35 @@ void DarwinGamepadService::Shutdown() {
507557
mIsRunning = false;
508558
}
509559

560+
void DarwinGamepadService::SetLightIndicatorColor(uint32_t aControllerIdx,
561+
uint32_t aLightColorIndex,
562+
uint8_t aRed, uint8_t aGreen,
563+
uint8_t aBlue) {
564+
// We get aControllerIdx from GamepadPlatformService::AddGamepad(),
565+
// It begins from 1 and is stored at Gamepad.id.
566+
const Gamepad* gamepad = nullptr;
567+
for (const auto& pad : mGamepads) {
568+
if (pad.mSuperIndex == aControllerIdx) {
569+
gamepad = &pad;
570+
break;
571+
}
572+
}
573+
if (!gamepad) {
574+
MOZ_ASSERT(false);
575+
return;
576+
}
577+
578+
RefPtr<GamepadRemapper> remapper = gamepad->mRemapper;
579+
if (!remapper || remapper->GetLightIndicatorCount() <= aLightColorIndex) {
580+
MOZ_ASSERT(false);
581+
return;
582+
}
583+
584+
std::vector<uint8_t> report;
585+
remapper->GetLightColorReport(aRed, aGreen, aBlue, report);
586+
gamepad->WriteOutputReport(report);
587+
}
588+
510589
} // namespace
511590

512591
namespace mozilla {
@@ -535,8 +614,12 @@ void StopGamepadMonitoring() {
535614
void SetGamepadLightIndicatorColor(uint32_t aControllerIdx,
536615
uint32_t aLightColorIndex, uint8_t aRed,
537616
uint8_t aGreen, uint8_t aBlue) {
538-
// TODO: Bug 1523353.
539-
NS_WARNING("Mac OS doesn't support gamepad light indicator.");
617+
MOZ_ASSERT(gService);
618+
if (!gService) {
619+
return;
620+
}
621+
gService->SetLightIndicatorColor(aControllerIdx, aLightColorIndex, aRed,
622+
aGreen, aBlue);
540623
}
541624

542625
} // namespace dom

dom/gamepad/windows/WindowsGamepad.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,7 @@ bool WindowsGamepadService::HandleRawInput(HRAWINPUT handle) {
850850
}
851851

852852
BYTE* rawData = raw->data.hid.bRawData;
853-
gamepad->remapper->GetTouchData(gamepad->id, rawData);
853+
gamepad->remapper->ProcessTouchData(gamepad->id, rawData);
854854

855855
return true;
856856
}

0 commit comments

Comments
 (0)