Add support for wired switch controllers from PowerA

This commit is contained in:
Phillip Stephens 2017-11-23 23:17:28 -08:00
parent e0cabf9e1c
commit 4aa662cd67
6 changed files with 142 additions and 1 deletions

View File

@ -244,6 +244,7 @@ add_library(boo
lib/inputdev/CafeProPad.cpp include/boo/inputdev/CafeProPad.hpp
lib/inputdev/RevolutionPad.cpp include/boo/inputdev/RevolutionPad.hpp
lib/inputdev/DolphinSmashAdapter.cpp include/boo/inputdev/DolphinSmashAdapter.hpp
lib/inputdev/NintendoPowerA.cpp include/boo/inputdev/NintendoPowerA.hpp
lib/inputdev/DualshockPad.cpp include/boo/inputdev/DualshockPad.hpp
include/boo/inputdev/XInputPad.hpp
lib/inputdev/GenericPad.cpp include/boo/inputdev/GenericPad.hpp

View File

@ -3,6 +3,7 @@
#include "boo/inputdev/DualshockPad.hpp"
#include "boo/inputdev/GenericPad.hpp"
#include "boo/inputdev/XInputPad.hpp"
#include "boo/inputdev/NintendoPowerA.hpp"
namespace boo
{
@ -12,6 +13,7 @@ const DeviceSignature BOO_DEVICE_SIGS[] =
DEVICE_SIG(DolphinSmashAdapter, 0x57e, 0x337, DeviceType::USB),
DEVICE_SIG(DualshockPad, 0x54c, 0x268, DeviceType::HID),
DEVICE_SIG(GenericPad, 0, 0, DeviceType::HID),
DEVICE_SIG(NintendoPowerA, 0x20D6, 0xA711, DeviceType::USB),
DEVICE_SIG(XInputPad, 0, 0, DeviceType::XInput),
DEVICE_SIG_SENTINEL()
};

View File

@ -7,6 +7,7 @@
#include "inputdev/DolphinSmashAdapter.hpp"
#include "inputdev/DualshockPad.hpp"
#include "inputdev/GenericPad.hpp"
#include "inputdev/NintendoPowerA.hpp"
#include "graphicsdev/IGraphicsCommandQueue.hpp"
#include "graphicsdev/IGraphicsDataFactory.hpp"
#include "DeferredWindowEvents.hpp"

View File

@ -0,0 +1,57 @@
#ifndef NINTENDOPOWERA_HPP
#define NINTENDOPOWERA_HPP
#include "DeviceBase.hpp"
#include "boo/System.hpp"
namespace boo
{
struct NintendoPowerAState
{
uint8_t y : 1;
uint8_t b : 1;
uint8_t a : 1;
uint8_t x : 1;
uint8_t l : 1;
uint8_t r : 1;
uint8_t zl : 1;
uint8_t zr : 1;
uint8_t minus : 1;
uint8_t plus : 1;
uint8_t stickL : 1;
uint8_t stickR : 1;
uint8_t home : 1;
uint8_t capture : 1;
uint8_t dPad;
uint8_t leftX;
uint8_t leftY;
uint8_t rightX;
uint8_t rightY;
bool operator==(const NintendoPowerAState& other);
bool operator!=(const NintendoPowerAState& other);
};
class NintendoPowerA;
struct INintendoPowerACallback
{
virtual void controllerDisconnected() {}
virtual void controllerUpdate(const NintendoPowerAState& state) {}
};
class NintendoPowerA final : public DeviceBase
{
INintendoPowerACallback* m_callback = nullptr;
NintendoPowerAState m_last;
void deviceDisconnected();
void initialCycle();
void transferCycle();
void finalCycle();
void receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message);
public:
NintendoPowerA(DeviceToken*);
~NintendoPowerA();
void setCallback(INintendoPowerACallback* cb) { m_callback = cb; }
};
}
#endif // NINTENDOPWERA_HPP

View File

@ -0,0 +1,53 @@
#include "boo/inputdev/NintendoPowerA.hpp"
#include <memory.h>
namespace boo
{
NintendoPowerA::NintendoPowerA(DeviceToken* token)
: DeviceBase(token)
{
}
NintendoPowerA::~NintendoPowerA()
{
}
void NintendoPowerA::deviceDisconnected()
{
if (m_callback)
m_callback->controllerDisconnected();
}
void NintendoPowerA::initialCycle() {}
void NintendoPowerA::transferCycle()
{
uint8_t payload[8];
size_t recvSz = receiveUSBInterruptTransfer(payload, sizeof(payload));
if (recvSz != 8)
return;
NintendoPowerAState state = *reinterpret_cast<NintendoPowerAState*>(&payload);
if (state != m_last && m_callback)
m_callback->controllerUpdate(state);
m_last = state;
}
void NintendoPowerA::finalCycle() {}
void NintendoPowerA::receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message)
{
}
bool NintendoPowerAState::operator==(const NintendoPowerAState &other)
{
return !memcmp(this, &other, sizeof(NintendoPowerAState));
}
bool NintendoPowerAState::operator!=(const NintendoPowerAState &other)
{
return memcmp(this, &other, sizeof(NintendoPowerAState));
}
}

View File

@ -105,17 +105,34 @@ class GenericPadCallback : public IGenericPadCallback
}
};
class NintendoPowerACallback : public INintendoPowerACallback
{
void controllerDisconnected()
{
fprintf(stderr, "CONTROLLER DISCONNECTED\n");
}
void controllerUpdate(const NintendoPowerAState& state)
{
fprintf(stderr, "%i %i\n"
"%i %i\n",
state.leftX, state.leftY,
state.rightX, state.rightY);
}
};
class TestDeviceFinder : public DeviceFinder
{
std::shared_ptr<DolphinSmashAdapter> m_smashAdapter;
std::shared_ptr<NintendoPowerA> m_nintendoPowerA;
std::shared_ptr<DualshockPad> m_ds3;
std::shared_ptr<GenericPad> m_generic;
DolphinSmashAdapterCallback m_cb;
NintendoPowerACallback m_nintendoPowerACb;
DualshockPadCallback m_ds3CB;
GenericPadCallback m_genericCb;
public:
TestDeviceFinder()
: DeviceFinder({typeid(DolphinSmashAdapter), typeid(GenericPad)})
: DeviceFinder({typeid(DolphinSmashAdapter), typeid(NintendoPowerA), typeid(GenericPad)})
{}
void deviceConnected(DeviceToken& tok)
{
@ -126,16 +143,24 @@ public:
m_smashAdapter->startRumble(0);
return;
}
m_nintendoPowerA = std::dynamic_pointer_cast<NintendoPowerA>(tok.openAndGetDevice());
if (m_nintendoPowerA)
{
m_nintendoPowerA->setCallback(&m_nintendoPowerACb);
return;
}
m_ds3 = std::dynamic_pointer_cast<DualshockPad>(tok.openAndGetDevice());
if (m_ds3)
{
m_ds3->setCallback(&m_ds3CB);
m_ds3->setLED(EDualshockLED::LED_1);
return;
}
m_generic = std::dynamic_pointer_cast<GenericPad>(tok.openAndGetDevice());
if (m_generic)
{
m_generic->setCallback(&m_genericCb);
return;
}
}
void deviceDisconnected(DeviceToken&, DeviceBase* device)
@ -146,6 +171,8 @@ public:
m_ds3.reset();
if (m_generic.get() == device)
m_generic.reset();
if (m_nintendoPowerA.get() == device)
m_nintendoPowerA.reset();
}
};