mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-06-12 17:50:03 +00:00
792 lines
18 KiB
C++
792 lines
18 KiB
C++
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
// Based on dkms-hid-nintendo implementation, CTCaer joycon toolkit and dekuNukem reverse
|
|
// engineering https://github.com/nicman23/dkms-hid-nintendo/blob/master/src/hid-nintendo.c
|
|
// https://github.com/CTCaer/jc_toolkit
|
|
// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering
|
|
|
|
#pragma once
|
|
|
|
#include <array>
|
|
#include <functional>
|
|
#include <SDL_hidapi.h>
|
|
|
|
#include "common/bit_field.h"
|
|
#include "common/common_funcs.h"
|
|
#include "common/common_types.h"
|
|
|
|
namespace InputCommon::Joycon {
|
|
constexpr u32 MaxErrorCount = 50;
|
|
constexpr u32 MaxBufferSize = 368;
|
|
constexpr std::array<u8, 8> DefaultVibrationBuffer{0x0, 0x1, 0x40, 0x40, 0x0, 0x1, 0x40, 0x40};
|
|
|
|
using MacAddress = std::array<u8, 6>;
|
|
using SerialNumber = std::array<u8, 15>;
|
|
using TagUUID = std::array<u8, 7>;
|
|
using MifareUUID = std::array<u8, 4>;
|
|
|
|
enum class ControllerType : u8 {
|
|
None = 0x00,
|
|
Left = 0x01,
|
|
Right = 0x02,
|
|
Pro = 0x03,
|
|
Dual = 0x05, // TODO: Verify this id
|
|
LarkHvc1 = 0x07,
|
|
LarkHvc2 = 0x08,
|
|
LarkNesLeft = 0x09,
|
|
LarkNesRight = 0x0A,
|
|
Lucia = 0x0B,
|
|
Lagon = 0x0C,
|
|
Lager = 0x0D,
|
|
};
|
|
|
|
enum class PadAxes {
|
|
LeftStickX,
|
|
LeftStickY,
|
|
RightStickX,
|
|
RightStickY,
|
|
Undefined,
|
|
};
|
|
|
|
enum class PadMotion {
|
|
LeftMotion,
|
|
RightMotion,
|
|
Undefined,
|
|
};
|
|
|
|
enum class PadButton : u32 {
|
|
Down = 0x000001,
|
|
Up = 0x000002,
|
|
Right = 0x000004,
|
|
Left = 0x000008,
|
|
LeftSR = 0x000010,
|
|
LeftSL = 0x000020,
|
|
L = 0x000040,
|
|
ZL = 0x000080,
|
|
Y = 0x000100,
|
|
X = 0x000200,
|
|
B = 0x000400,
|
|
A = 0x000800,
|
|
RightSR = 0x001000,
|
|
RightSL = 0x002000,
|
|
R = 0x004000,
|
|
ZR = 0x008000,
|
|
Minus = 0x010000,
|
|
Plus = 0x020000,
|
|
StickR = 0x040000,
|
|
StickL = 0x080000,
|
|
Home = 0x100000,
|
|
Capture = 0x200000,
|
|
};
|
|
|
|
enum class PassivePadButton : u32 {
|
|
Down_A = 0x0001,
|
|
Right_X = 0x0002,
|
|
Left_B = 0x0004,
|
|
Up_Y = 0x0008,
|
|
SL = 0x0010,
|
|
SR = 0x0020,
|
|
Minus = 0x0100,
|
|
Plus = 0x0200,
|
|
StickL = 0x0400,
|
|
StickR = 0x0800,
|
|
Home = 0x1000,
|
|
Capture = 0x2000,
|
|
L_R = 0x4000,
|
|
ZL_ZR = 0x8000,
|
|
};
|
|
|
|
enum class PassivePadStick : u8 {
|
|
Right = 0x00,
|
|
RightDown = 0x01,
|
|
Down = 0x02,
|
|
DownLeft = 0x03,
|
|
Left = 0x04,
|
|
LeftUp = 0x05,
|
|
Up = 0x06,
|
|
UpRight = 0x07,
|
|
Neutral = 0x08,
|
|
};
|
|
|
|
enum class OutputReport : u8 {
|
|
RUMBLE_AND_SUBCMD = 0x01,
|
|
FW_UPDATE_PKT = 0x03,
|
|
RUMBLE_ONLY = 0x10,
|
|
MCU_DATA = 0x11,
|
|
USB_CMD = 0x80,
|
|
};
|
|
|
|
enum class FeatureReport : u8 {
|
|
Last_SUBCMD = 0x02,
|
|
OTA_GW_UPGRADE = 0x70,
|
|
SETUP_MEM_READ = 0x71,
|
|
MEM_READ = 0x72,
|
|
ERASE_MEM_SECTOR = 0x73,
|
|
MEM_WRITE = 0x74,
|
|
LAUNCH = 0x75,
|
|
};
|
|
|
|
enum class SubCommand : u8 {
|
|
STATE = 0x00,
|
|
MANUAL_BT_PAIRING = 0x01,
|
|
REQ_DEV_INFO = 0x02,
|
|
SET_REPORT_MODE = 0x03,
|
|
TRIGGERS_ELAPSED = 0x04,
|
|
GET_PAGE_LIST_STATE = 0x05,
|
|
SET_HCI_STATE = 0x06,
|
|
RESET_PAIRING_INFO = 0x07,
|
|
LOW_POWER_MODE = 0x08,
|
|
SPI_FLASH_READ = 0x10,
|
|
SPI_FLASH_WRITE = 0x11,
|
|
SPI_SECTOR_ERASE = 0x12,
|
|
RESET_MCU = 0x20,
|
|
SET_MCU_CONFIG = 0x21,
|
|
SET_MCU_STATE = 0x22,
|
|
SET_PLAYER_LIGHTS = 0x30,
|
|
GET_PLAYER_LIGHTS = 0x31,
|
|
SET_HOME_LIGHT = 0x38,
|
|
ENABLE_IMU = 0x40,
|
|
SET_IMU_SENSITIVITY = 0x41,
|
|
WRITE_IMU_REG = 0x42,
|
|
READ_IMU_REG = 0x43,
|
|
ENABLE_VIBRATION = 0x48,
|
|
GET_REGULATED_VOLTAGE = 0x50,
|
|
SET_EXTERNAL_CONFIG = 0x58,
|
|
GET_EXTERNAL_DEVICE_INFO = 0x59,
|
|
ENABLE_EXTERNAL_POLLING = 0x5A,
|
|
DISABLE_EXTERNAL_POLLING = 0x5B,
|
|
SET_EXTERNAL_FORMAT_CONFIG = 0x5C,
|
|
};
|
|
|
|
enum class UsbSubCommand : u8 {
|
|
CONN_STATUS = 0x01,
|
|
HADSHAKE = 0x02,
|
|
BAUDRATE_3M = 0x03,
|
|
NO_TIMEOUT = 0x04,
|
|
EN_TIMEOUT = 0x05,
|
|
RESET = 0x06,
|
|
PRE_HANDSHAKE = 0x91,
|
|
SEND_UART = 0x92,
|
|
};
|
|
|
|
enum class CalibrationMagic : u8 {
|
|
USR_MAGIC_0 = 0xB2,
|
|
USR_MAGIC_1 = 0xA1,
|
|
};
|
|
|
|
enum class SpiAddress : u16 {
|
|
MAGIC = 0x0000,
|
|
MAC_ADDRESS = 0x0015,
|
|
PAIRING_INFO = 0x2000,
|
|
SHIPMENT = 0x5000,
|
|
SERIAL_NUMBER = 0x6000,
|
|
DEVICE_TYPE = 0x6012,
|
|
FORMAT_VERSION = 0x601B,
|
|
FACT_IMU_DATA = 0x6020,
|
|
FACT_LEFT_DATA = 0x603d,
|
|
FACT_RIGHT_DATA = 0x6046,
|
|
COLOR_DATA = 0x6050,
|
|
DESIGN_VARIATION = 0x605C,
|
|
SENSOR_DATA = 0x6080,
|
|
USER_LEFT_MAGIC = 0x8010,
|
|
USER_LEFT_DATA = 0x8012,
|
|
USER_RIGHT_MAGIC = 0x801B,
|
|
USER_RIGHT_DATA = 0x801D,
|
|
USER_IMU_MAGIC = 0x8026,
|
|
USER_IMU_DATA = 0x8028,
|
|
};
|
|
|
|
enum class ReportMode : u8 {
|
|
ACTIVE_POLLING_NFC_IR_CAMERA_DATA = 0x00,
|
|
ACTIVE_POLLING_NFC_IR_CAMERA_CONFIGURATION = 0x01,
|
|
ACTIVE_POLLING_NFC_IR_CAMERA_DATA_CONFIGURATION = 0x02,
|
|
ACTIVE_POLLING_IR_CAMERA_DATA = 0x03,
|
|
SUBCMD_REPLY = 0x21,
|
|
MCU_UPDATE_STATE = 0x23,
|
|
STANDARD_FULL_60HZ = 0x30,
|
|
NFC_IR_MODE_60HZ = 0x31,
|
|
SIMPLE_HID_MODE = 0x3F,
|
|
INPUT_USB_RESPONSE = 0x81,
|
|
};
|
|
|
|
enum class GyroSensitivity : u8 {
|
|
DPS250,
|
|
DPS500,
|
|
DPS1000,
|
|
DPS2000, // Default
|
|
};
|
|
|
|
enum class AccelerometerSensitivity : u8 {
|
|
G8, // Default
|
|
G4,
|
|
G2,
|
|
G16,
|
|
};
|
|
|
|
enum class GyroPerformance : u8 {
|
|
HZ833,
|
|
HZ208, // Default
|
|
};
|
|
|
|
enum class AccelerometerPerformance : u8 {
|
|
HZ200,
|
|
HZ100, // Default
|
|
};
|
|
|
|
enum class MCUCommand : u8 {
|
|
ConfigureMCU = 0x21,
|
|
ConfigureIR = 0x23,
|
|
};
|
|
|
|
enum class MCUSubCommand : u8 {
|
|
SetMCUMode = 0x0,
|
|
SetDeviceMode = 0x1,
|
|
ReadDeviceMode = 0x02,
|
|
WriteDeviceRegisters = 0x4,
|
|
};
|
|
|
|
enum class MCUMode : u8 {
|
|
Suspend = 0,
|
|
Standby = 1,
|
|
Ringcon = 3,
|
|
NFC = 4,
|
|
IR = 5,
|
|
MaybeFWUpdate = 6,
|
|
};
|
|
|
|
enum class MCURequest : u8 {
|
|
GetMCUStatus = 1,
|
|
GetNFCData = 2,
|
|
GetIRData = 3,
|
|
};
|
|
|
|
enum class MCUReport : u8 {
|
|
Empty = 0x00,
|
|
StateReport = 0x01,
|
|
IRData = 0x03,
|
|
BusyInitializing = 0x0b,
|
|
IRStatus = 0x13,
|
|
IRRegisters = 0x1b,
|
|
NFCState = 0x2a,
|
|
NFCReadData = 0x3a,
|
|
EmptyAwaitingCmd = 0xff,
|
|
};
|
|
|
|
enum class MCUPacketFlag : u8 {
|
|
MorePacketsRemaining = 0x00,
|
|
LastCommandPacket = 0x08,
|
|
};
|
|
|
|
enum class NFCCommand : u8 {
|
|
CancelAll = 0x00,
|
|
StartPolling = 0x01,
|
|
StopPolling = 0x02,
|
|
StartWaitingReceive = 0x04,
|
|
ReadNtag = 0x06,
|
|
WriteNtag = 0x08,
|
|
Mifare = 0x0F,
|
|
};
|
|
|
|
enum class NFCTagType : u8 {
|
|
AllTags = 0x00,
|
|
Ntag215 = 0x01,
|
|
};
|
|
|
|
enum class NFCPages {
|
|
Block0 = 0,
|
|
Block3 = 3,
|
|
Block45 = 45,
|
|
Block135 = 135,
|
|
Block231 = 231,
|
|
};
|
|
|
|
enum class NFCStatus : u8 {
|
|
Ready = 0x00,
|
|
Polling = 0x01,
|
|
LastPackage = 0x04,
|
|
WriteDone = 0x05,
|
|
TagLost = 0x07,
|
|
WriteReady = 0x09,
|
|
MifareDone = 0x10,
|
|
};
|
|
|
|
enum class MifareCmd : u8 {
|
|
None = 0x00,
|
|
Read = 0x30,
|
|
AuthA = 0x60,
|
|
AuthB = 0x61,
|
|
Write = 0xA0,
|
|
Transfer = 0xB0,
|
|
Decrement = 0xC0,
|
|
Increment = 0xC1,
|
|
Store = 0xC2
|
|
};
|
|
|
|
enum class IrsMode : u8 {
|
|
None = 0x02,
|
|
Moment = 0x03,
|
|
Dpd = 0x04,
|
|
Clustering = 0x06,
|
|
ImageTransfer = 0x07,
|
|
Silhouette = 0x08,
|
|
TeraImage = 0x09,
|
|
SilhouetteTeraImage = 0x0A,
|
|
};
|
|
|
|
enum class IrsResolution {
|
|
Size320x240,
|
|
Size160x120,
|
|
Size80x60,
|
|
Size40x30,
|
|
Size20x15,
|
|
None,
|
|
};
|
|
|
|
enum class IrsResolutionCode : u8 {
|
|
Size320x240 = 0x00, // Full pixel array
|
|
Size160x120 = 0x50, // Sensor Binning [2 X 2]
|
|
Size80x60 = 0x64, // Sensor Binning [4 x 2] and Skipping [1 x 2]
|
|
Size40x30 = 0x69, // Sensor Binning [4 x 2] and Skipping [2 x 4]
|
|
Size20x15 = 0x6A, // Sensor Binning [4 x 2] and Skipping [4 x 4]
|
|
};
|
|
|
|
// Size of image divided by 300
|
|
enum class IrsFragments : u8 {
|
|
Size20x15 = 0x00,
|
|
Size40x30 = 0x03,
|
|
Size80x60 = 0x0f,
|
|
Size160x120 = 0x3f,
|
|
Size320x240 = 0xFF,
|
|
};
|
|
|
|
enum class IrLeds : u8 {
|
|
BrightAndDim = 0x00,
|
|
Bright = 0x20,
|
|
Dim = 0x10,
|
|
None = 0x30,
|
|
};
|
|
|
|
enum class IrExLedFilter : u8 {
|
|
Disabled = 0x00,
|
|
Enabled = 0x03,
|
|
};
|
|
|
|
enum class IrImageFlip : u8 {
|
|
Normal = 0x00,
|
|
Inverted = 0x02,
|
|
};
|
|
|
|
enum class IrRegistersAddress : u16 {
|
|
UpdateTime = 0x0400,
|
|
FinalizeConfig = 0x0700,
|
|
LedFilter = 0x0e00,
|
|
Leds = 0x1000,
|
|
LedIntensityMSB = 0x1100,
|
|
LedIntensityLSB = 0x1200,
|
|
ImageFlip = 0x2d00,
|
|
Resolution = 0x2e00,
|
|
DigitalGainLSB = 0x2e01,
|
|
DigitalGainMSB = 0x2f01,
|
|
ExposureLSB = 0x3001,
|
|
ExposureMSB = 0x3101,
|
|
ExposureTime = 0x3201,
|
|
WhitePixelThreshold = 0x4301,
|
|
DenoiseSmoothing = 0x6701,
|
|
DenoiseEdge = 0x6801,
|
|
DenoiseColor = 0x6901,
|
|
};
|
|
|
|
enum class ExternalDeviceId : u16 {
|
|
RingController = 0x2000,
|
|
Starlink = 0x2800,
|
|
};
|
|
|
|
struct MotionSensorCalibration {
|
|
s16 offset;
|
|
s16 scale;
|
|
};
|
|
|
|
struct MotionCalibration {
|
|
std::array<MotionSensorCalibration, 3> accelerometer;
|
|
std::array<MotionSensorCalibration, 3> gyro;
|
|
};
|
|
|
|
// Basic motion data containing data from the sensors and a timestamp in microseconds
|
|
struct MotionData {
|
|
float gyro_x{};
|
|
float gyro_y{};
|
|
float gyro_z{};
|
|
float accel_x{};
|
|
float accel_y{};
|
|
float accel_z{};
|
|
u64 delta_timestamp{};
|
|
};
|
|
|
|
// Output from SPI read command containing user calibration magic
|
|
struct MagicSpiCalibration {
|
|
CalibrationMagic first;
|
|
CalibrationMagic second;
|
|
};
|
|
static_assert(sizeof(MagicSpiCalibration) == 0x2, "MagicSpiCalibration is an invalid size");
|
|
|
|
// Output from SPI read command containing left joystick calibration
|
|
struct JoystickLeftSpiCalibration {
|
|
std::array<u8, 3> max;
|
|
std::array<u8, 3> center;
|
|
std::array<u8, 3> min;
|
|
};
|
|
static_assert(sizeof(JoystickLeftSpiCalibration) == 0x9,
|
|
"JoystickLeftSpiCalibration is an invalid size");
|
|
|
|
// Output from SPI read command containing right joystick calibration
|
|
struct JoystickRightSpiCalibration {
|
|
std::array<u8, 3> center;
|
|
std::array<u8, 3> min;
|
|
std::array<u8, 3> max;
|
|
};
|
|
static_assert(sizeof(JoystickRightSpiCalibration) == 0x9,
|
|
"JoystickRightSpiCalibration is an invalid size");
|
|
|
|
struct JoyStickAxisCalibration {
|
|
u16 max;
|
|
u16 min;
|
|
u16 center;
|
|
};
|
|
|
|
struct JoyStickCalibration {
|
|
JoyStickAxisCalibration x;
|
|
JoyStickAxisCalibration y;
|
|
};
|
|
|
|
struct ImuSpiCalibration {
|
|
std::array<s16, 3> accelerometer_offset;
|
|
std::array<s16, 3> accelerometer_scale;
|
|
std::array<s16, 3> gyroscope_offset;
|
|
std::array<s16, 3> gyroscope_scale;
|
|
};
|
|
static_assert(sizeof(ImuSpiCalibration) == 0x18, "ImuSpiCalibration is an invalid size");
|
|
|
|
struct RingCalibration {
|
|
s16 default_value;
|
|
s16 max_value;
|
|
s16 min_value;
|
|
};
|
|
|
|
struct Color {
|
|
u32 body;
|
|
u32 buttons;
|
|
u32 left_grip;
|
|
u32 right_grip;
|
|
};
|
|
|
|
struct Battery {
|
|
union {
|
|
u8 raw{};
|
|
|
|
BitField<0, 4, u8> unknown;
|
|
BitField<4, 1, u8> charging;
|
|
BitField<5, 3, u8> status;
|
|
};
|
|
};
|
|
|
|
struct VibrationValue {
|
|
f32 low_amplitude;
|
|
f32 low_frequency;
|
|
f32 high_amplitude;
|
|
f32 high_frequency;
|
|
};
|
|
|
|
struct JoyconHandle {
|
|
SDL_hid_device* handle = nullptr;
|
|
u8 packet_counter{};
|
|
};
|
|
|
|
struct MCUConfig {
|
|
MCUCommand command;
|
|
MCUSubCommand sub_command;
|
|
MCUMode mode;
|
|
INSERT_PADDING_BYTES(0x22);
|
|
u8 crc;
|
|
};
|
|
static_assert(sizeof(MCUConfig) == 0x26, "MCUConfig is an invalid size");
|
|
|
|
#pragma pack(push, 1)
|
|
struct InputReportPassive {
|
|
ReportMode report_mode;
|
|
u16 button_input;
|
|
u8 stick_state;
|
|
std::array<u8, 10> unknown_data;
|
|
};
|
|
static_assert(sizeof(InputReportPassive) == 0xE, "InputReportPassive is an invalid size");
|
|
|
|
struct InputReportActive {
|
|
ReportMode report_mode;
|
|
u8 packet_id;
|
|
Battery battery_status;
|
|
std::array<u8, 3> button_input;
|
|
std::array<u8, 3> left_stick_state;
|
|
std::array<u8, 3> right_stick_state;
|
|
u8 vibration_code;
|
|
std::array<s16, 6 * 2> motion_input;
|
|
INSERT_PADDING_BYTES(0x2);
|
|
s16 ring_input;
|
|
};
|
|
static_assert(sizeof(InputReportActive) == 0x29, "InputReportActive is an invalid size");
|
|
|
|
struct InputReportNfcIr {
|
|
ReportMode report_mode;
|
|
u8 packet_id;
|
|
Battery battery_status;
|
|
std::array<u8, 3> button_input;
|
|
std::array<u8, 3> left_stick_state;
|
|
std::array<u8, 3> right_stick_state;
|
|
u8 vibration_code;
|
|
std::array<s16, 6 * 2> motion_input;
|
|
INSERT_PADDING_BYTES(0x4);
|
|
};
|
|
static_assert(sizeof(InputReportNfcIr) == 0x29, "InputReportNfcIr is an invalid size");
|
|
#pragma pack(pop)
|
|
|
|
struct NFCReadBlock {
|
|
u8 start;
|
|
u8 end;
|
|
};
|
|
static_assert(sizeof(NFCReadBlock) == 0x2, "NFCReadBlock is an invalid size");
|
|
|
|
struct NFCReadBlockCommand {
|
|
u8 block_count{};
|
|
std::array<NFCReadBlock, 4> blocks{};
|
|
};
|
|
static_assert(sizeof(NFCReadBlockCommand) == 0x9, "NFCReadBlockCommand is an invalid size");
|
|
|
|
struct NFCReadCommandData {
|
|
u8 unknown;
|
|
u8 uuid_length;
|
|
TagUUID uid;
|
|
NFCTagType tag_type;
|
|
NFCReadBlockCommand read_block;
|
|
};
|
|
static_assert(sizeof(NFCReadCommandData) == 0x13, "NFCReadCommandData is an invalid size");
|
|
|
|
#pragma pack(push, 1)
|
|
struct NFCWriteCommandData {
|
|
u8 unknown;
|
|
u8 uuid_length;
|
|
TagUUID uid;
|
|
NFCTagType tag_type;
|
|
u8 unknown2;
|
|
u8 unknown3;
|
|
u8 unknown4;
|
|
u8 unknown5;
|
|
u8 unknown6;
|
|
u8 unknown7;
|
|
u8 unknown8;
|
|
u8 magic;
|
|
u16_be write_count;
|
|
u8 amiibo_version;
|
|
};
|
|
static_assert(sizeof(NFCWriteCommandData) == 0x15, "NFCWriteCommandData is an invalid size");
|
|
#pragma pack(pop)
|
|
|
|
struct MifareCommandData {
|
|
u8 unknown1;
|
|
u8 unknown2;
|
|
u8 number_of_short_bytes;
|
|
MifareUUID uid;
|
|
};
|
|
static_assert(sizeof(MifareCommandData) == 0x7, "MifareCommandData is an invalid size");
|
|
|
|
struct NFCPollingCommandData {
|
|
u8 enable_mifare;
|
|
u8 unknown_1;
|
|
u8 unknown_2;
|
|
u8 unknown_3;
|
|
u8 unknown_4;
|
|
};
|
|
static_assert(sizeof(NFCPollingCommandData) == 0x05, "NFCPollingCommandData is an invalid size");
|
|
|
|
struct NFCRequestState {
|
|
NFCCommand command_argument;
|
|
u8 block_id;
|
|
u8 packet_id;
|
|
MCUPacketFlag packet_flag;
|
|
u8 data_length;
|
|
union {
|
|
std::array<u8, 0x1F> raw_data;
|
|
NFCReadCommandData nfc_read;
|
|
NFCPollingCommandData nfc_polling;
|
|
};
|
|
u8 crc;
|
|
INSERT_PADDING_BYTES(0x1);
|
|
};
|
|
static_assert(sizeof(NFCRequestState) == 0x26, "NFCRequestState is an invalid size");
|
|
|
|
struct NFCDataChunk {
|
|
u8 nfc_page;
|
|
u8 data_size;
|
|
std::array<u8, 0xFF> data;
|
|
};
|
|
|
|
struct NFCWritePackage {
|
|
NFCWriteCommandData command_data;
|
|
u8 number_of_chunks;
|
|
std::array<NFCDataChunk, 4> data_chunks;
|
|
};
|
|
|
|
struct MifareReadChunk {
|
|
MifareCmd command;
|
|
std::array<u8, 0x6> sector_key;
|
|
u8 sector;
|
|
};
|
|
|
|
struct MifareWriteChunk {
|
|
MifareCmd command;
|
|
std::array<u8, 0x6> sector_key;
|
|
u8 sector;
|
|
std::array<u8, 0x10> data;
|
|
};
|
|
|
|
struct MifareReadData {
|
|
u8 sector;
|
|
std::array<u8, 0x10> data;
|
|
};
|
|
|
|
struct MifareReadPackage {
|
|
MifareCommandData command_data;
|
|
std::array<MifareReadChunk, 0x10> data_chunks;
|
|
};
|
|
|
|
struct MifareWritePackage {
|
|
MifareCommandData command_data;
|
|
std::array<MifareWriteChunk, 0x10> data_chunks;
|
|
};
|
|
|
|
struct TagInfo {
|
|
u8 uuid_length;
|
|
u8 protocol;
|
|
u8 tag_type;
|
|
std::array<u8, 10> uuid;
|
|
};
|
|
|
|
struct IrsConfigure {
|
|
MCUCommand command;
|
|
MCUSubCommand sub_command;
|
|
IrsMode irs_mode;
|
|
IrsFragments number_of_fragments;
|
|
u16 mcu_major_version;
|
|
u16 mcu_minor_version;
|
|
INSERT_PADDING_BYTES(0x1D);
|
|
u8 crc;
|
|
};
|
|
static_assert(sizeof(IrsConfigure) == 0x26, "IrsConfigure is an invalid size");
|
|
|
|
#pragma pack(push, 1)
|
|
struct IrsRegister {
|
|
IrRegistersAddress address;
|
|
u8 value;
|
|
};
|
|
static_assert(sizeof(IrsRegister) == 0x3, "IrsRegister is an invalid size");
|
|
|
|
struct IrsWriteRegisters {
|
|
MCUCommand command;
|
|
MCUSubCommand sub_command;
|
|
u8 number_of_registers;
|
|
std::array<IrsRegister, 9> registers;
|
|
INSERT_PADDING_BYTES(0x7);
|
|
u8 crc;
|
|
};
|
|
static_assert(sizeof(IrsWriteRegisters) == 0x26, "IrsWriteRegisters is an invalid size");
|
|
#pragma pack(pop)
|
|
|
|
struct FirmwareVersion {
|
|
u8 major;
|
|
u8 minor;
|
|
};
|
|
static_assert(sizeof(FirmwareVersion) == 0x2, "FirmwareVersion is an invalid size");
|
|
|
|
struct DeviceInfo {
|
|
FirmwareVersion firmware;
|
|
std::array<u8, 2> unknown_1;
|
|
MacAddress mac_address;
|
|
std::array<u8, 2> unknown_2;
|
|
};
|
|
static_assert(sizeof(DeviceInfo) == 0xC, "DeviceInfo is an invalid size");
|
|
|
|
struct MotionStatus {
|
|
bool is_enabled;
|
|
u64 delta_time;
|
|
GyroSensitivity gyro_sensitivity;
|
|
AccelerometerSensitivity accelerometer_sensitivity;
|
|
};
|
|
|
|
struct RingStatus {
|
|
bool is_enabled;
|
|
s16 default_value;
|
|
s16 max_value;
|
|
s16 min_value;
|
|
};
|
|
|
|
struct VibrationPacket {
|
|
OutputReport output_report;
|
|
u8 packet_counter;
|
|
std::array<u8, 0x8> vibration_data;
|
|
};
|
|
static_assert(sizeof(VibrationPacket) == 0xA, "VibrationPacket is an invalid size");
|
|
|
|
struct SubCommandPacket {
|
|
OutputReport output_report;
|
|
u8 packet_counter;
|
|
INSERT_PADDING_BYTES(0x8); // This contains vibration data
|
|
union {
|
|
SubCommand sub_command;
|
|
MCUSubCommand mcu_sub_command;
|
|
};
|
|
std::array<u8, 0x26> command_data;
|
|
};
|
|
static_assert(sizeof(SubCommandPacket) == 0x31, "SubCommandPacket is an invalid size");
|
|
|
|
#pragma pack(push, 1)
|
|
struct ReadSpiPacket {
|
|
SpiAddress spi_address;
|
|
INSERT_PADDING_BYTES(0x2);
|
|
u8 size;
|
|
};
|
|
static_assert(sizeof(ReadSpiPacket) == 0x5, "ReadSpiPacket is an invalid size");
|
|
|
|
struct SubCommandResponse {
|
|
InputReportPassive input_report;
|
|
SubCommand sub_command;
|
|
union {
|
|
std::array<u8, 0x30> command_data;
|
|
SpiAddress spi_address; // Reply from SPI_FLASH_READ subcommand
|
|
ExternalDeviceId external_device_id; // Reply from GET_EXTERNAL_DEVICE_INFO subcommand
|
|
DeviceInfo device_info; // Reply from REQ_DEV_INFO subcommand
|
|
};
|
|
u8 crc; // This is never used
|
|
};
|
|
static_assert(sizeof(SubCommandResponse) == 0x40, "SubCommandResponse is an invalid size");
|
|
#pragma pack(pop)
|
|
|
|
struct MCUCommandResponse {
|
|
InputReportNfcIr input_report;
|
|
INSERT_PADDING_BYTES(0x8);
|
|
MCUReport mcu_report;
|
|
std::array<u8, 0x13D> mcu_data;
|
|
u8 crc;
|
|
};
|
|
static_assert(sizeof(MCUCommandResponse) == 0x170, "MCUCommandResponse is an invalid size");
|
|
|
|
struct JoyconCallbacks {
|
|
std::function<void(Battery)> on_battery_data;
|
|
std::function<void(Color)> on_color_data;
|
|
std::function<void(int, bool)> on_button_data;
|
|
std::function<void(int, f32)> on_stick_data;
|
|
std::function<void(int, const MotionData&)> on_motion_data;
|
|
std::function<void(f32)> on_ring_data;
|
|
std::function<void(const Joycon::TagInfo&)> on_amiibo_data;
|
|
std::function<void(const std::vector<u8>&, IrsResolution)> on_camera_data;
|
|
};
|
|
|
|
} // namespace InputCommon::Joycon
|