skyline/app/src/main/cpp/skyline/input/npad_device.h
PixelyIon fe5061a8e0 Address CR Comments (#132) + Change Core Migration API
This addresses all CR comments including more codebase-wide changes arising from certain review comments like proper usage of its/it's and consistent contraction of it is into it's. 

An overhaul was made to the presentation and formatting of `KThread.h` and `LoadBalance` works has been superseded by `GetOptimalCoreForThread` which can be used alongside `InsertThread` or `MigrateToCore`. It makes the API far more atomic and neater. This was a major point of contention for the design prior, it's simplified some code and potentially improved performance.
2021-03-05 14:55:34 +05:30

186 lines
6.6 KiB
C++

// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#pragma once
#include <kernel/types/KEvent.h>
#include "shared_mem.h"
namespace skyline::constant {
constexpr jlong MsInSecond{1000}; //!< The amount of milliseconds in a single second of time
constexpr jint AmplitudeMax{std::numeric_limits<u8>::max()}; //!< The maximum amplitude for Android Vibration APIs
constexpr i8 NullIndex{-1}; //!< The placeholder index value when there is no device present
}
namespace skyline::input {
/**
* @brief The orientations the Joy-Con(s) can be held in
*/
enum class NpadJoyOrientation : i64 {
Vertical = 0,
Horizontal = 1,
};
/**
* @url https://switchbrew.org/wiki/HID_services#NpadStyleTag
*/
union NpadStyleSet {
u32 raw;
struct {
bool proController : 1; //!< Pro Controller
bool joyconHandheld : 1; //!< Joy-Cons in handheld mode
bool joyconDual : 1; //!< Joy-Cons in a pair
bool joyconLeft : 1; //!< Left Joy-Con only
bool joyconRight : 1; //!< Right Joy-Con only
bool gamecube : 1; //!< GameCube controller
bool palma : 1; //!< Poké Ball Plus controller
bool nes : 1; //!< NES controller
bool nesHandheld : 1; //!< NES controller in handheld mode
bool snes : 1; //!< SNES controller
};
};
static_assert(sizeof(NpadStyleSet) == 0x4);
enum class NpadAxisId {
LX, //!< Left Stick X
LY, //!< Left Stick Y
RX, //!< Right Stick X
RY, //!< Right Stick Y
};
/**
* @url https://switchbrew.org/wiki/HID_services#NpadIdType
*/
enum class NpadId : u32 {
Player1 = 0x0,
Player2 = 0x1,
Player3 = 0x2,
Player4 = 0x3,
Player5 = 0x4,
Player6 = 0x5,
Player7 = 0x6,
Player8 = 0x7,
Unknown = 0x10,
Handheld = 0x20,
};
/**
* @brief A handle to a specific device addressed by its ID and type
* @note This is used by both Six-Axis and Vibration
*/
union __attribute__((__packed__)) NpadDeviceHandle {
u32 raw;
struct {
u8 type;
NpadId id : 8;
bool isRight : 1; //!< If this is a right Joy-Con (Both) or right LRA in the Pro-Controller (Vibration)
bool isSixAxisSingle : 1; //!< If the Six-Axis device is a single unit, either Handheld or Pro-Controller
};
constexpr NpadControllerType GetType() const {
switch (type) {
case 3:
return NpadControllerType::ProController;
case 4:
return NpadControllerType::Handheld;
case 5:
return NpadControllerType::JoyconDual;
case 6:
return NpadControllerType::JoyconLeft;
case 7:
return NpadControllerType::JoyconRight;
}
return NpadControllerType::None;
}
};
/**
* @brief The parameters to produce a vibration using an LRA
* @note The vibration is broken into a frequency band with the lower and high range supplied
* @note Amplitude is in arbitrary units from 0f to 1f
* @note Frequency is in Hertz
*/
struct NpadVibrationValue {
float amplitudeLow;
float frequencyLow;
float amplitudeHigh;
float frequencyHigh;
constexpr bool operator==(const NpadVibrationValue &) const = default;
};
static_assert(sizeof(NpadVibrationValue) == 0x10);
class NpadManager;
/**
* @brief An easy to use interface for a NPad which abstracts away the complicated details
*/
class NpadDevice {
private:
NpadManager &manager; //!< The manager responsible for managing this NpadDevice
NpadSection &section; //!< The section in HID shared memory for this controller
NpadControllerInfo *controllerInfo; //!< The NpadControllerInfo for this controller's type
u64 globalTimestamp{}; //!< An incrementing timestamp that's common across all sections
/**
* @brief Updates the headers and creates a new entry in HID Shared Memory
* @param info The controller info of the NPad that needs to be updated
* @return The next entry that has been created with values from the last entry
*/
NpadControllerState &GetNextEntry(NpadControllerInfo &info);
/**
* @return The NpadControllerInfo for this controller based on its type
*/
NpadControllerInfo &GetControllerInfo();
public:
NpadId id;
i8 index{constant::NullIndex}; //!< The index of the device assigned to this player
i8 partnerIndex{constant::NullIndex}; //!< The index of a partner device, if present
NpadVibrationValue vibrationLeft; //!< Vibration for the left Joy-Con (Handheld/Pair), left LRA in a Pro-Controller or individual Joy-Cons
std::optional<NpadVibrationValue> vibrationRight; //!< Vibration for the right Joy-Con (Handheld/Pair) or right LRA in a Pro-Controller
NpadControllerType type{};
NpadConnectionState connectionState{};
std::shared_ptr<kernel::type::KEvent> updateEvent; //!< This event is triggered on the controller's style changing
NpadDevice(NpadManager &manager, NpadSection &section, NpadId id);
inline void SetAssignment(NpadJoyAssignment assignment) {
section.header.assignment = assignment;
}
inline NpadJoyAssignment GetAssignment() {
return section.header.assignment;
}
/**
* @brief Connects this controller to the guest
*/
void Connect(NpadControllerType newType);
/**
* @brief Disconnects this controller from the guest
*/
void Disconnect();
/**
* @brief Changes the state of buttons to the specified state
* @param mask A bit-field mask of all the buttons to change
* @param pressed If the buttons were pressed or released
*/
void SetButtonState(NpadButton mask, bool pressed);
/**
* @brief Sets the value of an axis to the specified value
* @param axis The axis to set the value of
* @param value The value to set
*/
void SetAxisValue(NpadAxisId axis, i32 value);
void Vibrate(bool isRight, const NpadVibrationValue &value);
void Vibrate(const NpadVibrationValue &left, const NpadVibrationValue &right);
};
}