mirror of
https://github.com/ndeadly/MissionControl
synced 2025-02-16 21:28:25 +00:00
Stop tracking old code directories
This commit is contained in:
parent
15c8d7630c
commit
165d2e87b3
38 changed files with 0 additions and 3057 deletions
|
@ -1,26 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
inline uint16_t __bswap_16(uint16_t val) {
|
||||
return (val << 8) | (val >> 8 );
|
||||
}
|
||||
|
||||
inline uint32_t __bswap_32(uint32_t val) {
|
||||
val = ((val << 8) & 0xFF00FF00 ) | ((val >> 8) & 0xFF00FF );
|
||||
return (val << 16) | (val >> 16);
|
||||
}
|
||||
|
||||
inline uint64_t __bswap_64(uint64_t val) {
|
||||
val = ((val << 8) & 0xFF00FF00FF00FF00ULL ) | ((val >> 8) & 0x00FF00FF00FF00FFULL );
|
||||
val = ((val << 16) & 0xFFFF0000FFFF0000ULL ) | ((val >> 16) & 0x0000FFFF0000FFFFULL );
|
||||
return (val << 32) | (val >> 32);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,25 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
namespace mc::log {
|
||||
|
||||
//const constexpr char *app = "sdmc:/missioncontrol-applet.log";
|
||||
//const constexpr char *sys = "sdmc:/missioncontrol-sysmodule.log";
|
||||
|
||||
//void Write(const char *location, const char *fmt, ...);
|
||||
//void WriteData(const char *location, void *data, size_t size);
|
||||
|
||||
class Logger {
|
||||
|
||||
public:
|
||||
Logger(const char *location);
|
||||
|
||||
void write(const char *fmt, ...);
|
||||
void writeData(void *data, size_t size);
|
||||
|
||||
private:
|
||||
Mutex m_logMutex;
|
||||
const char *m_location;
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <switch.h>
|
||||
|
||||
#define BTM_COD_MAJOR_PERIPHERAL 0x05
|
||||
#define BTM_COD_MINOR_GAMEPAD 0x08
|
||||
#define BTM_COD_MINOR_JOYSTICK 0x04
|
||||
|
||||
inline bool bdcmp(const BluetoothAddress *addr1, const BluetoothAddress *addr2) {
|
||||
//return (*(uint64_t *)addr1 & 0xffffffffffff0000) == (*(uint64_t *)addr2 & 0xffffffffffff0000);
|
||||
return std::memcmp(addr1, addr2, sizeof(BluetoothAddress)) == 0;
|
||||
}
|
||||
|
||||
inline bool isController(const BluetoothDeviceClass *cod) {
|
||||
return ( (((uint8_t *)cod)[1] & 0x0f) == BTM_COD_MAJOR_PERIPHERAL ) &&
|
||||
( ((((uint8_t *)cod)[2] & 0x0f) == BTM_COD_MINOR_GAMEPAD) ||
|
||||
((((uint8_t *)cod)[2] & 0x0f) == BTM_COD_MINOR_JOYSTICK) );
|
||||
}
|
|
@ -1,149 +0,0 @@
|
|||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <ctype.h>
|
||||
#include <switch.h>
|
||||
#include "logger.hpp"
|
||||
|
||||
namespace mc::log {
|
||||
|
||||
/*
|
||||
namespace {
|
||||
|
||||
Mutex logMutex;
|
||||
|
||||
}
|
||||
|
||||
void Write(const char *location, const char *fmt, ...) {
|
||||
mutexLock(&logMutex);
|
||||
|
||||
FILE *fp = std::fopen(location, "a");
|
||||
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
std::vfprintf(fp, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
std::fprintf(fp, "\n");
|
||||
std::fclose(fp);
|
||||
|
||||
mutexUnlock(&logMutex);
|
||||
}
|
||||
|
||||
void WriteData(const char *location, void *data, size_t size) {
|
||||
mutexLock(&logMutex);
|
||||
|
||||
FILE *fp = std::fopen(location, "a");
|
||||
|
||||
unsigned int i = 0;
|
||||
while (i < size) {
|
||||
// Print offset
|
||||
std::fprintf(fp, " %04x", i);
|
||||
std::fprintf(fp, " |");
|
||||
|
||||
// Print line of hex
|
||||
unsigned int j;
|
||||
for (j = 0; j < 16; ++j) {
|
||||
if (i + j < size) {
|
||||
std::fprintf(fp, " %02x", ((char *)data)[i+j]);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Print separator
|
||||
for (unsigned int k = 0; k < 16-j; ++k)
|
||||
{
|
||||
fprintf(fp, " ");
|
||||
}
|
||||
fprintf(fp, " | ");
|
||||
|
||||
// Print line of ascii
|
||||
for (unsigned int j = 0; j < 16; ++j) {
|
||||
if (i + j < size) {
|
||||
char c = ((char *)data)[i+j];
|
||||
std::fprintf(fp, "%c", isprint(c) ? c: 0x2e);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::fprintf(fp, "\n");
|
||||
i += 16;
|
||||
}
|
||||
std::fclose(fp);
|
||||
|
||||
mutexUnlock(&logMutex);
|
||||
}
|
||||
*/
|
||||
|
||||
Logger::Logger(const char *location) : m_location(location) {
|
||||
mutexInit(&m_logMutex);
|
||||
};
|
||||
|
||||
void Logger::write(const char *fmt, ...) {
|
||||
mutexLock(&m_logMutex);
|
||||
|
||||
FILE *fp = std::fopen(m_location, "a");
|
||||
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
std::vfprintf(fp, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
std::fprintf(fp, "\n");
|
||||
std::fclose(fp);
|
||||
|
||||
mutexUnlock(&m_logMutex);
|
||||
}
|
||||
|
||||
void Logger::writeData(void *data, size_t size) {
|
||||
mutexLock(&m_logMutex);
|
||||
|
||||
FILE *fp = std::fopen(m_location, "a");
|
||||
|
||||
unsigned int i = 0;
|
||||
while (i < size) {
|
||||
// Print offset
|
||||
std::fprintf(fp, " %04x", i);
|
||||
std::fprintf(fp, " |");
|
||||
|
||||
// Print line of hex
|
||||
unsigned int j;
|
||||
for (j = 0; j < 16; ++j) {
|
||||
if (i + j < size) {
|
||||
std::fprintf(fp, " %02x", ((char *)data)[i+j]);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Print separator
|
||||
for (unsigned int k = 0; k < 16-j; ++k)
|
||||
{
|
||||
fprintf(fp, " ");
|
||||
}
|
||||
fprintf(fp, " | ");
|
||||
|
||||
// Print line of ascii
|
||||
for (unsigned int j = 0; j < 16; ++j) {
|
||||
if (i + j < size) {
|
||||
char c = ((char *)data)[i+j];
|
||||
std::fprintf(fp, "%c", isprint(c) ? c: 0x2e);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::fprintf(fp, "\n");
|
||||
i += 16;
|
||||
}
|
||||
std::fclose(fp);
|
||||
|
||||
mutexUnlock(&m_logMutex);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,222 +0,0 @@
|
|||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITPRO)),)
|
||||
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITPRO)/libnx/switch_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
# ROMFS is the directory containing data to be added to RomFS, relative to the Makefile (Optional)
|
||||
#
|
||||
# NO_ICON: if set to anything, do not use icon.
|
||||
# NO_NACP: if set to anything, no .nacp file is generated.
|
||||
# APP_TITLE is the name of the app stored in the .nacp file (Optional)
|
||||
# APP_AUTHOR is the author of the app stored in the .nacp file (Optional)
|
||||
# APP_VERSION is the version of the app stored in the .nacp file (Optional)
|
||||
# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional)
|
||||
# ICON is the filename of the icon (.jpg), relative to the project folder.
|
||||
# If not set, it attempts to use one of the following (in this order):
|
||||
# - <Project name>.jpg
|
||||
# - icon.jpg
|
||||
# - <libnx folder>/default_icon.jpg
|
||||
#
|
||||
# CONFIG_JSON is the filename of the NPDM config file (.json), relative to the project folder.
|
||||
# If not set, it attempts to use one of the following (in this order):
|
||||
# - <Project name>.json
|
||||
# - config.json
|
||||
# If a JSON file is provided or autodetected, an ExeFS PFS0 (.nsp) is built instead
|
||||
# of a homebrew executable (.nro). This is intended to be used for sysmodules.
|
||||
# NACP building is skipped as well.
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := source source/bluetooth source/gamepad source/gamepad/controllers
|
||||
DATA := data
|
||||
INCLUDES := include ../common/include
|
||||
#ROMFS := romfs
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
|
||||
|
||||
CFLAGS := -g -Wall -O2 -ffunction-sections \
|
||||
$(ARCH) $(DEFINES)
|
||||
|
||||
CFLAGS += $(INCLUDE) -D__SWITCH__
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
LIBS := -lnx
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(PORTLIBS) $(LIBNX)
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
ifeq ($(strip $(CONFIG_JSON)),)
|
||||
jsons := $(wildcard *.json)
|
||||
ifneq (,$(findstring $(TARGET).json,$(jsons)))
|
||||
export APP_JSON := $(TOPDIR)/$(TARGET).json
|
||||
else
|
||||
ifneq (,$(findstring config.json,$(jsons)))
|
||||
export APP_JSON := $(TOPDIR)/config.json
|
||||
endif
|
||||
endif
|
||||
else
|
||||
export APP_JSON := $(TOPDIR)/$(CONFIG_JSON)
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(ICON)),)
|
||||
icons := $(wildcard *.jpg)
|
||||
ifneq (,$(findstring $(TARGET).jpg,$(icons)))
|
||||
export APP_ICON := $(TOPDIR)/$(TARGET).jpg
|
||||
else
|
||||
ifneq (,$(findstring icon.jpg,$(icons)))
|
||||
export APP_ICON := $(TOPDIR)/icon.jpg
|
||||
endif
|
||||
endif
|
||||
else
|
||||
export APP_ICON := $(TOPDIR)/$(ICON)
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(NO_ICON)),)
|
||||
export NROFLAGS += --icon=$(APP_ICON)
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(NO_NACP)),)
|
||||
export NROFLAGS += --nacp=$(CURDIR)/$(TARGET).nacp
|
||||
endif
|
||||
|
||||
ifneq ($(APP_TITLEID),)
|
||||
export NACPFLAGS += --titleid=$(APP_TITLEID)
|
||||
endif
|
||||
|
||||
ifneq ($(ROMFS),)
|
||||
export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS)
|
||||
endif
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
ifeq ($(strip $(APP_JSON)),)
|
||||
@rm -fr $(BUILD) $(TARGET).nro $(TARGET).nacp $(TARGET).elf
|
||||
else
|
||||
@rm -fr $(BUILD) $(TARGET).nsp $(TARGET).nso $(TARGET).npdm $(TARGET).elf
|
||||
endif
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
.PHONY: all
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(APP_JSON)),)
|
||||
|
||||
all : $(OUTPUT).nro
|
||||
|
||||
ifeq ($(strip $(NO_NACP)),)
|
||||
$(OUTPUT).nro : $(OUTPUT).elf $(OUTPUT).nacp
|
||||
else
|
||||
$(OUTPUT).nro : $(OUTPUT).elf
|
||||
endif
|
||||
|
||||
else
|
||||
|
||||
all : $(OUTPUT).nsp
|
||||
|
||||
$(OUTPUT).nsp : $(OUTPUT).nso $(OUTPUT).npdm
|
||||
|
||||
$(OUTPUT).nso : $(OUTPUT).elf
|
||||
|
||||
endif
|
||||
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
$(OFILES_SRC) : $(HFILES_BIN)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o %_bin.h : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
|
@ -1,19 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
namespace mc::bluetooth::hid {
|
||||
|
||||
const constexpr size_t event_buffer_size = 0x480;
|
||||
const constexpr size_t thread_stack_size = 0x4000;
|
||||
|
||||
extern std::atomic<bool> exitFlag;
|
||||
|
||||
void Initialise(void);
|
||||
void Cleanup(void);
|
||||
void PrepareForSleep(void);
|
||||
void PrepareForWake(void);
|
||||
void OnWake(void);
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
#include <switch.h>
|
||||
#include "gamepad/virtualcontroller.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
class AbstractedPadVirtualController : public VirtualController {
|
||||
|
||||
public:
|
||||
AbstractedPadVirtualController();
|
||||
~AbstractedPadVirtualController();
|
||||
|
||||
Result connect(void);
|
||||
Result disconnect(void);
|
||||
Result setState(const SwitchProGamepadState* state);
|
||||
|
||||
private:
|
||||
uint8_t m_uniqueId;
|
||||
HiddbgAbstractedPadState m_state;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
class BluetoothDatabase {
|
||||
|
||||
public:
|
||||
static const uint8_t max_devices = 10;
|
||||
static constexpr const char * default_location = "sdmc:/config/MissionControl/bluetooth.db";
|
||||
|
||||
BluetoothDatabase();
|
||||
BluetoothDatabase(const char *location);
|
||||
|
||||
Result reload(void);
|
||||
|
||||
Result addDevice(const BluetoothDevice *device);
|
||||
Result removeDevice(const BluetoothAddress *address);
|
||||
|
||||
const BluetoothDevice *search(const BluetoothAddress *address);
|
||||
const BluetoothDevice *operator[](uint8_t index);
|
||||
const BluetoothDevice *deviceAt(uint8_t index);
|
||||
uint8_t indexOf(const BluetoothAddress *address);
|
||||
|
||||
uint8_t size(void);
|
||||
|
||||
private:
|
||||
Result loadDatabase(void);
|
||||
Result storeDatabase(void);
|
||||
|
||||
struct {
|
||||
uint8_t size;
|
||||
BluetoothDevice devices[BluetoothDatabase::max_devices];
|
||||
} m_database;
|
||||
|
||||
const char * m_location;
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <switch.h>
|
||||
#include "gamepad/hidinterface.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
class BluetoothInterface : public HidInterface {
|
||||
|
||||
public:
|
||||
BluetoothInterface() : HidInterface(HidInterfaceType_Bluetooth) {};
|
||||
|
||||
Result connect(void);
|
||||
Result disconnect(void);
|
||||
Result wake(void);
|
||||
Result sendData(const uint8_t *buffer, uint16_t length);
|
||||
|
||||
const BluetoothAddress& address(void) const;
|
||||
void setAddress(const BluetoothAddress *address);
|
||||
|
||||
private:
|
||||
BluetoothAddress m_address;
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <switch.h>
|
||||
#include "gamepad/bluetoothdatabase.hpp"
|
||||
#include "gamepad/controllers.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
class ControllerManager {
|
||||
|
||||
public:
|
||||
ControllerManager();
|
||||
~ControllerManager();
|
||||
|
||||
static ControllerType identify(uint16_t vid, uint16_t pid);
|
||||
static ControllerType identify(const HardwareID *hwId);
|
||||
static ControllerType identify(const BluetoothDevice *device);
|
||||
|
||||
Result registerBluetoothControllers(void);
|
||||
Result attachBluetoothController(const BluetoothAddress *address);
|
||||
Result removeBluetoothController(const BluetoothAddress *address);
|
||||
Result receiveBluetoothReport(const BluetoothAddress *address, const HidReport *report);
|
||||
|
||||
//Result attachUsbController();
|
||||
//Result removeUsbController();
|
||||
//Result receiveUsbReport(, const HidReport *report);
|
||||
|
||||
void removeControllers(void);
|
||||
|
||||
private:
|
||||
std::unique_ptr<BluetoothDatabase> m_database;
|
||||
std::vector<std::unique_ptr<HidGamepad>> m_controllers;
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "gamepad/controllers/joycon.hpp"
|
||||
#include "gamepad/controllers/switchpro.hpp"
|
||||
#include "gamepad/controllers/wiimote.hpp"
|
||||
#include "gamepad/controllers/wiiupro.hpp"
|
||||
#include "gamepad/controllers/dualshock4.hpp"
|
||||
#include "gamepad/controllers/xboxone.hpp"
|
|
@ -1,119 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <switch.h>
|
||||
#include "gamepad/hidgamepad.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
enum Dualshock4ControllerVariant {
|
||||
Dualshock4ControllerVariant_V1,
|
||||
Dualshock4ControllerVariant_V2,
|
||||
Dualshock4ControllerVariant_Unknown
|
||||
};
|
||||
|
||||
enum Dualshock4DPadDirection {
|
||||
Dualshock4DPad_N,
|
||||
Dualshock4DPad_NE,
|
||||
Dualshock4DPad_E,
|
||||
Dualshock4DPad_SE,
|
||||
Dualshock4DPad_S,
|
||||
Dualshock4DPad_SW,
|
||||
Dualshock4DPad_W,
|
||||
Dualshock4DPad_NW,
|
||||
Dualshock4DPad_Released
|
||||
};
|
||||
|
||||
struct Dualshock4StickData {
|
||||
uint8_t x;
|
||||
uint8_t y;
|
||||
};
|
||||
|
||||
struct Dualshock4ButtonData {
|
||||
uint8_t dpad : 4;
|
||||
uint8_t square : 1;
|
||||
uint8_t cross : 1;
|
||||
uint8_t circle : 1;
|
||||
uint8_t triangle : 1;
|
||||
|
||||
uint8_t L1 : 1;
|
||||
uint8_t R1 : 1;
|
||||
uint8_t L2 : 1;
|
||||
uint8_t R2 : 1;
|
||||
uint8_t share : 1;
|
||||
uint8_t options : 1;
|
||||
uint8_t L3 : 1;
|
||||
uint8_t R3 : 1;
|
||||
|
||||
uint8_t ps : 1;
|
||||
uint8_t tpad : 1;
|
||||
uint8_t counter : 6;
|
||||
};
|
||||
|
||||
struct Dualshock4OutputReport0x11 {
|
||||
struct {
|
||||
uint8_t data[75];
|
||||
};
|
||||
uint32_t crc;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct Dualshock4InputReport0x01 {
|
||||
Dualshock4StickData left_stick;
|
||||
Dualshock4StickData right_stick;
|
||||
Dualshock4ButtonData buttons;
|
||||
uint8_t left_trigger;
|
||||
uint8_t right_trigger;
|
||||
};
|
||||
|
||||
/* This report is sent once the GET REPORT FEATURE 0x02 is received */
|
||||
struct Dualshock4InputReport0x11 {
|
||||
uint8_t _unk[2];
|
||||
Dualshock4StickData left_stick;
|
||||
Dualshock4StickData right_stick;
|
||||
Dualshock4ButtonData buttons;
|
||||
uint8_t left_trigger;
|
||||
uint8_t right_trigger;
|
||||
uint16_t timestamp;
|
||||
uint8_t battery;
|
||||
uint16_t vel_x;
|
||||
uint16_t vel_y;
|
||||
uint16_t vel_z;
|
||||
uint16_t acc_x;
|
||||
uint16_t acc_y;
|
||||
uint16_t acc_z;
|
||||
uint32_t _unk0;
|
||||
|
||||
uint8_t battery_level : 4;
|
||||
uint8_t usb : 1;
|
||||
uint8_t mic : 1;
|
||||
uint8_t phone : 1;
|
||||
uint8_t : 0;
|
||||
|
||||
uint16_t _unk2;
|
||||
uint8_t tpad_packets;
|
||||
uint8_t packet_counter;
|
||||
};
|
||||
|
||||
union Dualshock4ReportData {
|
||||
Dualshock4InputReport0x01 report0x01;
|
||||
Dualshock4InputReport0x11 report0x11;
|
||||
};
|
||||
|
||||
class Dualshock4Controller : public HidGamepad {
|
||||
|
||||
public:
|
||||
static constexpr const HardwareID hardwareIds[] = {
|
||||
{0x054c, 0x05c4}, // Official Dualshock4 v1
|
||||
{0x054c, 0x09cc} // Official Dualshock4 v2
|
||||
};
|
||||
|
||||
Dualshock4Controller(HidInterfaceType iface);
|
||||
|
||||
Result receiveReport(const HidReport *report);
|
||||
|
||||
private:
|
||||
void mapStickValues(JoystickPosition *dst, const Dualshock4StickData *src);
|
||||
void handleInputReport0x01(const Dualshock4ReportData *data);
|
||||
void handleInputReport0x11(const Dualshock4ReportData *data);
|
||||
};
|
||||
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <switch.h>
|
||||
#include "gamepad/hidgamepad.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
union JoyconStickData {
|
||||
struct __attribute__ ((__packed__)) {
|
||||
uint16_t x : 12;
|
||||
uint16_t : 0;
|
||||
uint8_t : 8;
|
||||
};
|
||||
|
||||
struct __attribute__ ((__packed__)) {
|
||||
uint8_t : 8;
|
||||
uint16_t : 4;
|
||||
uint16_t y : 12;
|
||||
};
|
||||
};
|
||||
|
||||
struct JoyconButtonData {
|
||||
uint8_t Y : 1;
|
||||
uint8_t X : 1;
|
||||
uint8_t B : 1;
|
||||
uint8_t A : 1;
|
||||
uint8_t : 2; // SR, SL (Right Joy)
|
||||
uint8_t R : 1;
|
||||
uint8_t ZR : 1;
|
||||
|
||||
uint8_t minus : 1;
|
||||
uint8_t plus : 1;
|
||||
uint8_t rstick_press : 1;
|
||||
uint8_t lstick_press : 1;
|
||||
uint8_t home : 1;
|
||||
uint8_t capture : 1;
|
||||
uint8_t : 0;
|
||||
|
||||
uint8_t dpad_down : 1;
|
||||
uint8_t dpad_up : 1;
|
||||
uint8_t dpad_right : 1;
|
||||
uint8_t dpad_left : 1;
|
||||
uint8_t : 2; // SR, SL (Left Joy)
|
||||
uint8_t L : 1;
|
||||
uint8_t ZL : 1;
|
||||
};
|
||||
|
||||
union JoyconReportData {
|
||||
struct {
|
||||
uint8_t conn_info : 4;
|
||||
uint8_t battery : 4;
|
||||
uint8_t timer;
|
||||
JoyconButtonData buttons;
|
||||
JoyconStickData left_stick;
|
||||
JoyconStickData right_stick;
|
||||
} report0x30;
|
||||
};
|
||||
|
||||
class JoyconController : public HidGamepad {
|
||||
|
||||
public:
|
||||
static constexpr const HardwareID hardwareIds[] = {
|
||||
{0x057e, 2006}, // Official Joycon(L) Controller
|
||||
{0x057e, 2007}, // Official Joycon(R) Controller
|
||||
};
|
||||
|
||||
JoyconController(HidInterfaceType iface) : HidGamepad(iface) {};
|
||||
|
||||
Result receiveReport(const HidReport *report);
|
||||
|
||||
private:
|
||||
void mapStickValues(JoystickPosition *dst, const JoyconStickData *src);
|
||||
void handleInputReport0x30(const JoyconReportData *data);
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <switch.h>
|
||||
#include "gamepad/hidgamepad.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
union SwitchProStickData {
|
||||
struct __attribute__ ((__packed__)) {
|
||||
uint16_t x : 12;
|
||||
uint16_t : 0;
|
||||
uint8_t : 8;
|
||||
};
|
||||
|
||||
struct __attribute__ ((__packed__)) {
|
||||
uint8_t : 8;
|
||||
uint16_t : 4;
|
||||
uint16_t y : 12;
|
||||
};
|
||||
};
|
||||
|
||||
struct SwitchProButtonData {
|
||||
uint8_t Y : 1;
|
||||
uint8_t X : 1;
|
||||
uint8_t B : 1;
|
||||
uint8_t A : 1;
|
||||
uint8_t : 2; // SR, SL (Right Joy)
|
||||
uint8_t R : 1;
|
||||
uint8_t ZR : 1;
|
||||
|
||||
uint8_t minus : 1;
|
||||
uint8_t plus : 1;
|
||||
uint8_t rstick_press : 1;
|
||||
uint8_t lstick_press : 1;
|
||||
uint8_t home : 1;
|
||||
uint8_t capture : 1;
|
||||
uint8_t : 0;
|
||||
|
||||
uint8_t dpad_down : 1;
|
||||
uint8_t dpad_up : 1;
|
||||
uint8_t dpad_right : 1;
|
||||
uint8_t dpad_left : 1;
|
||||
uint8_t : 2; // SR, SL (Left Joy)
|
||||
uint8_t L : 1;
|
||||
uint8_t ZL : 1;
|
||||
};
|
||||
|
||||
union SwitchProReportData {
|
||||
struct {
|
||||
uint8_t conn_info : 4;
|
||||
uint8_t battery : 4;
|
||||
uint8_t timer;
|
||||
SwitchProButtonData buttons;
|
||||
SwitchProStickData left_stick;
|
||||
SwitchProStickData right_stick;
|
||||
} report0x30;
|
||||
};
|
||||
|
||||
class SwitchProController : public HidGamepad {
|
||||
|
||||
public:
|
||||
static constexpr const HardwareID hardwareIds[] = {
|
||||
{0x057e, 0x2009} // Official Switch Pro Controller
|
||||
};
|
||||
|
||||
SwitchProController(HidInterfaceType iface) : HidGamepad(iface) {};
|
||||
|
||||
Result receiveReport(const HidReport *report);
|
||||
|
||||
private:
|
||||
void mapStickValues(JoystickPosition *dst, const SwitchProStickData *src);
|
||||
void handleInputReport0x30(const SwitchProReportData *data);
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <switch.h>
|
||||
#include "gamepad/hidgamepad.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
enum WiimoteLEDs {
|
||||
WiimoteLEDs_P1 = 0x10,
|
||||
WiimoteLEDs_P2 = 0x20,
|
||||
WiimoteLEDs_P3 = 0x40,
|
||||
WiimoteLEDs_P4 = 0x80,
|
||||
};
|
||||
|
||||
struct WiimoteButtonData {
|
||||
uint8_t dpad_left : 1;
|
||||
uint8_t dpad_right : 1;
|
||||
uint8_t dpad_down : 1;
|
||||
uint8_t dpad_up : 1;
|
||||
uint8_t plus : 1;
|
||||
uint8_t : 0;
|
||||
|
||||
uint8_t two : 1;
|
||||
uint8_t one : 1;
|
||||
uint8_t B : 1;
|
||||
uint8_t A : 1;
|
||||
uint8_t minus : 1;
|
||||
uint8_t : 2;
|
||||
uint8_t home : 1;
|
||||
};
|
||||
|
||||
union WiimoteReportData {
|
||||
struct {
|
||||
WiimoteButtonData buttons;
|
||||
uint8_t _unk;
|
||||
} report0x30;
|
||||
};
|
||||
|
||||
Result write_wiimote_memory(const BluetoothAddress *bd_addr, uint32_t address, const uint8_t *data, uint8_t length);
|
||||
|
||||
class WiimoteController : public HidGamepad {
|
||||
|
||||
public:
|
||||
static constexpr const HardwareID hardwareIds[] = {
|
||||
{0x057e, 0x0306}, // Official wiimote
|
||||
};
|
||||
|
||||
WiimoteController(HidInterfaceType iface);
|
||||
|
||||
Result receiveReport(const HidReport *report);
|
||||
|
||||
private:
|
||||
void handleInputReport0x30(const WiimoteReportData *data);
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <switch.h>
|
||||
#include "gamepad/controllers/wiimote.hpp"
|
||||
#include "gamepad/hidgamepad.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
struct WiiUProButtonData {
|
||||
uint8_t : 1;
|
||||
uint8_t R : 1;
|
||||
uint8_t plus : 1;
|
||||
uint8_t home : 1;
|
||||
uint8_t minus : 1;
|
||||
uint8_t L : 1;
|
||||
uint8_t dpad_down : 1;
|
||||
uint8_t dpad_right : 1;
|
||||
|
||||
uint8_t dpad_up : 1;
|
||||
uint8_t dpad_left : 1;
|
||||
uint8_t ZR : 1;
|
||||
uint8_t X : 1;
|
||||
uint8_t A : 1;
|
||||
uint8_t Y : 1;
|
||||
uint8_t B : 1;
|
||||
uint8_t ZL : 1;
|
||||
|
||||
uint8_t rstick_press : 1;
|
||||
uint8_t lstick_press : 1;
|
||||
uint8_t : 0;
|
||||
};
|
||||
|
||||
union WiiUProReportData {
|
||||
struct {
|
||||
WiimoteButtonData core_buttons;
|
||||
|
||||
/*
|
||||
uint8_t left_stick_x : 6;
|
||||
uint8_t right_stick_x2 : 2;
|
||||
|
||||
uint8_t left_stick_y : 6;
|
||||
uint8_t right_stick_x1 : 2;
|
||||
|
||||
uint8_t right_stick_x0 : 1;
|
||||
uint8_t left_trigger_1 : 2;
|
||||
uint8_t right_stick_y : 5;
|
||||
|
||||
uint8_t left_trigger_0 : 3;
|
||||
uint8_t right_trigger : 5;
|
||||
*/
|
||||
uint16_t left_stick_x;
|
||||
uint16_t right_stick_x;
|
||||
uint16_t left_stick_y;
|
||||
uint16_t right_stick_y;
|
||||
WiiUProButtonData buttons;
|
||||
} report0x34;
|
||||
};
|
||||
|
||||
class WiiUProController : public HidGamepad {
|
||||
|
||||
public:
|
||||
static constexpr const HardwareID hardwareIds[] = {
|
||||
{0x057e, 0x0330}, // Official Wii U Pro Controller
|
||||
};
|
||||
|
||||
WiiUProController(HidInterfaceType iface);
|
||||
|
||||
Result receiveReport(const HidReport *report);
|
||||
|
||||
private:
|
||||
void mapStickValues(JoystickPosition *dst, uint16_t x, uint16_t y);
|
||||
void handleInputReport0x20(const WiiUProReportData *data);
|
||||
void handleInputReport0x34(const WiiUProReportData *data);
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <switch.h>
|
||||
#include "gamepad/hidgamepad.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
enum XboxOneDPadDirection {
|
||||
XboxOneDPad_Released,
|
||||
XboxOneDPad_N,
|
||||
XboxOneDPad_NE,
|
||||
XboxOneDPad_E,
|
||||
XboxOneDPad_SE,
|
||||
XboxOneDPad_S,
|
||||
XboxOneDPad_SW,
|
||||
XboxOneDPad_W,
|
||||
XboxOneDPad_NW
|
||||
};
|
||||
|
||||
struct XboxOneStickData {
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
};
|
||||
|
||||
struct XboxOneButtonData {
|
||||
uint8_t dpad;
|
||||
|
||||
uint8_t A : 1;
|
||||
uint8_t B : 1;
|
||||
uint8_t X : 1;
|
||||
uint8_t Y : 1;
|
||||
uint8_t LB : 1;
|
||||
uint8_t RB : 1;
|
||||
uint8_t view : 1;
|
||||
uint8_t menu : 1;
|
||||
|
||||
uint8_t lstick_press : 1;
|
||||
uint8_t rstick_press : 1;
|
||||
uint8_t : 0;
|
||||
};
|
||||
|
||||
union XboxOneReportData {
|
||||
struct {
|
||||
XboxOneStickData left_stick;
|
||||
XboxOneStickData right_stick;
|
||||
uint16_t left_trigger;
|
||||
uint16_t right_trigger;
|
||||
XboxOneButtonData buttons;
|
||||
} report0x01;
|
||||
|
||||
struct {
|
||||
uint8_t guide : 1;
|
||||
} report0x02;
|
||||
};
|
||||
|
||||
class XboxOneController : public HidGamepad {
|
||||
|
||||
public:
|
||||
static constexpr const HardwareID hardwareIds[] = {
|
||||
{0x045e, 0x02e0}, // Official Xbox One S Controller (old FW?)
|
||||
{0x045e, 0x02fd} // Official Xbox One S Controller
|
||||
};
|
||||
|
||||
XboxOneController(HidInterfaceType iface);
|
||||
|
||||
Result receiveReport(const HidReport *report);
|
||||
|
||||
private:
|
||||
void mapStickValues(JoystickPosition *dst, const XboxOneStickData *src);
|
||||
void handleInputReport0x01(const XboxOneReportData *data);
|
||||
void handleInputReport0x02(const XboxOneReportData *data);
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <switch.h>
|
||||
#include "gamepad/virtualcontroller.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
class HdlsVirtualController : public VirtualController {
|
||||
|
||||
public:
|
||||
HdlsVirtualController();
|
||||
~HdlsVirtualController();
|
||||
|
||||
Result connect(void);
|
||||
Result disconnect(void);
|
||||
Result setState(const SwitchProGamepadState* state);
|
||||
|
||||
private:
|
||||
uint64_t m_handle;
|
||||
HiddbgHdlsDeviceInfo m_device;
|
||||
HiddbgHdlsState m_state;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <cmath>
|
||||
#include <switch.h>
|
||||
|
||||
#include "gamepad/bluetoothinterface.hpp"
|
||||
#include "gamepad/abstractedpad.hpp"
|
||||
#include "gamepad/hdls.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
enum ControllerType {
|
||||
ControllerType_Joycon,
|
||||
ControllerType_SwitchPro,
|
||||
ControllerType_WiiUPro,
|
||||
ControllerType_Wiimote,
|
||||
ControllerType_Dualshock4,
|
||||
ControllerType_XboxOne,
|
||||
ControllerType_Unknown
|
||||
};
|
||||
|
||||
struct HardwareID {
|
||||
uint16_t vid;
|
||||
uint16_t pid;
|
||||
};
|
||||
|
||||
/* Convert an unsigned joystick value of arbitrary precision to int32 used by libnx */
|
||||
inline int32_t unsigned_to_signed(uint32_t x, uint8_t nbits) {
|
||||
return x * UINT16_MAX / (powf(2, nbits) - 1) + INT16_MIN;
|
||||
}
|
||||
|
||||
class HidGamepad {
|
||||
|
||||
public:
|
||||
friend class ControllerManager;
|
||||
|
||||
HidGamepad(HidInterfaceType type);
|
||||
virtual ~HidGamepad() {};
|
||||
|
||||
//HidInterfaceType interfaceType(void) { return m_interface->type(); }
|
||||
|
||||
virtual Result receiveReport(const HidReport *report) = 0;
|
||||
|
||||
void setInnerDeadzone(float percentage);
|
||||
void setOuterDeadzone(float percentage);
|
||||
|
||||
protected:
|
||||
uint16_t m_innerDeadzone;
|
||||
uint16_t m_outerDeadzone;
|
||||
|
||||
std::unique_ptr<BluetoothInterface> m_btInterface;
|
||||
std::unique_ptr<VirtualController> m_virtual;
|
||||
|
||||
SwitchProGamepadState m_state;
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
enum HidInterfaceType {
|
||||
HidInterfaceType_Bluetooth,
|
||||
HidInterfaceType_Usb
|
||||
};
|
||||
|
||||
class HidInterface {
|
||||
|
||||
public:
|
||||
HidInterface(HidInterfaceType type) : m_type(type) {};
|
||||
|
||||
HidInterfaceType type(void) { return m_type; }
|
||||
|
||||
virtual Result connect(void) = 0;
|
||||
virtual Result disconnect(void) = 0;
|
||||
|
||||
private:
|
||||
HidInterfaceType m_type;
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
struct SwitchProGamepadState {
|
||||
|
||||
uint8_t Y : 1;
|
||||
uint8_t X : 1;
|
||||
uint8_t B : 1;
|
||||
uint8_t A : 1;
|
||||
uint8_t : 2; // SR, SL (Right Joy)
|
||||
uint8_t R : 1;
|
||||
uint8_t ZR : 1;
|
||||
|
||||
uint8_t minus : 1;
|
||||
uint8_t plus : 1;
|
||||
uint8_t rstick_press : 1;
|
||||
uint8_t lstick_press : 1;
|
||||
uint8_t home : 1;
|
||||
uint8_t capture : 1;
|
||||
uint8_t : 0;
|
||||
|
||||
uint8_t dpad_down : 1;
|
||||
uint8_t dpad_up : 1;
|
||||
uint8_t dpad_right : 1;
|
||||
uint8_t dpad_left : 1;
|
||||
uint8_t : 2; // SR, SL (Left Joy)
|
||||
uint8_t L : 1;
|
||||
uint8_t ZL : 1;
|
||||
|
||||
JoystickPosition left_stick;
|
||||
JoystickPosition right_stick;
|
||||
};
|
||||
|
||||
class VirtualController {
|
||||
|
||||
public:
|
||||
virtual ~VirtualController() {};
|
||||
|
||||
virtual Result connect(void) = 0;
|
||||
virtual Result disconnect(void) = 0;
|
||||
virtual Result setState(const SwitchProGamepadState* state) = 0;
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
||||
namespace mc::log {
|
||||
|
||||
void Write(const char *fmt, ...);
|
||||
void WriteData(void *data, size_t size);
|
||||
|
||||
}
|
|
@ -1,225 +0,0 @@
|
|||
#include <cstring>
|
||||
#include "bluetooth/hid.hpp"
|
||||
#include "gamepad/controllermanager.hpp"
|
||||
|
||||
#include "log.hpp"
|
||||
|
||||
namespace mc::bluetooth::hid {
|
||||
|
||||
std::atomic<bool> exitFlag(false);
|
||||
|
||||
namespace {
|
||||
|
||||
static Event btmDeviceInfoEvent = {};
|
||||
static Event btmDeviceConditionEvent = {};
|
||||
static Thread btmDeviceEventThread;
|
||||
static BtmDeviceCondition connectedDevices = {};
|
||||
|
||||
static Event hidEvent = {};
|
||||
static Thread hidEventThread;
|
||||
static uint8_t hidEventBuffer[event_buffer_size] = {};
|
||||
|
||||
static Event hidReportEvent = {};
|
||||
static Thread hidReportEventThread;
|
||||
static uint8_t hidReportEventBuffer[event_buffer_size] = {};
|
||||
|
||||
std::unique_ptr<mc::controller::ControllerManager> controllerManager;
|
||||
|
||||
void handleConnectionStateEvent(const HidEventData *eventData) {
|
||||
//mc::log::Write("Hid Connection State: %d", eventData->connectionState.state);
|
||||
|
||||
switch(eventData->connectionState.state) {
|
||||
case HidConnectionState_Connected:
|
||||
controllerManager->attachBluetoothController(&eventData->connectionState.address);
|
||||
break;
|
||||
|
||||
case HidConnectionState_Disconnected:
|
||||
controllerManager->removeBluetoothController(&eventData->connectionState.address);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void hidEventThreadFunc(void* arg) {
|
||||
Result rc;
|
||||
HidEventType eventType;
|
||||
HidEventData *eventData = reinterpret_cast<HidEventData *>(hidEventBuffer);
|
||||
|
||||
while (!exitFlag) {
|
||||
if (R_SUCCEEDED(eventWait(&hidEvent, 1e9))) {
|
||||
|
||||
rc = btdrvGetHidEventInfo(&eventType, hidEventBuffer, sizeof(hidEventBuffer));
|
||||
if R_FAILED(rc)
|
||||
fatalThrow(rc);
|
||||
eventClear(&hidEvent);
|
||||
|
||||
switch (eventType) {
|
||||
case HidEvent_ConnectionState:
|
||||
handleConnectionStateEvent(eventData);
|
||||
break;
|
||||
|
||||
default:
|
||||
//mc::log::Write("Unexpected Hid event: %d", eventType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hidReportEventThreadFunc(void* arg) {
|
||||
Result rc;
|
||||
HidEventType eventType;
|
||||
HidEventData *eventData = reinterpret_cast<HidEventData *>(hidReportEventBuffer);
|
||||
|
||||
while (!exitFlag) {
|
||||
if (R_SUCCEEDED(eventWait(&hidReportEvent, 1e9))) {
|
||||
|
||||
rc = btdrvGetHidReportEventInfo(&eventType, hidReportEventBuffer, sizeof(hidReportEventBuffer));
|
||||
if R_FAILED(rc)
|
||||
fatalThrow(rc);
|
||||
|
||||
switch (eventType) {
|
||||
case HidEvent_GetReport:
|
||||
if (eventData->getReport.status == HidStatus_Ok) {
|
||||
//mc::log::WriteData(&eventData->getReport.report_data.report, eventData->getReport.report_data.size);
|
||||
controllerManager->receiveBluetoothReport(&eventData->getReport.address, &eventData->getReport.report_data.report);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
mc::log::Write("Unexpected Hid report event: %d", eventType);
|
||||
mc::log::WriteData(&eventData->getReport.report_data.report, eventData->getReport.report_data.size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void btmDeviceEventThreadFunc(void* arg) {
|
||||
Result rc;
|
||||
BtmDeviceCondition devices;
|
||||
|
||||
while (!exitFlag) {
|
||||
if (R_SUCCEEDED(eventWait(&btmDeviceConditionEvent, 1e9))) {
|
||||
|
||||
rc = btmGetDeviceCondition(&devices);
|
||||
if R_FAILED(rc)
|
||||
fatalThrow(rc);
|
||||
eventClear(&btmDeviceConditionEvent);
|
||||
|
||||
mc::log::Write("Device condition event");
|
||||
for (int i = 0; i < devices.connected_count; ++i) {
|
||||
mc::log::WriteData(&devices.devices[i], sizeof(BtmConnectedDevice));
|
||||
}
|
||||
|
||||
|
||||
int i;
|
||||
if (devices.connected_count > connectedDevices.connected_count) {
|
||||
i = devices.connected_count - 1;
|
||||
controllerManager->attachBluetoothController(&devices.devices[i].address);
|
||||
}
|
||||
else if (devices.connected_count < connectedDevices.connected_count) {
|
||||
/*
|
||||
for (i = 0; i < ) {
|
||||
|
||||
}
|
||||
controllerManager->removeBluetoothController();
|
||||
*/
|
||||
}
|
||||
|
||||
std::memcpy(&connectedDevices, &devices, sizeof(BtmDeviceCondition));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Initialise(void) {
|
||||
Result rc;
|
||||
|
||||
/* Init HID events */
|
||||
rc = btdrvInitializeHid(&hidEvent, 1);
|
||||
if R_FAILED(rc)
|
||||
fatalThrow(rc);
|
||||
|
||||
uint8_t flags;
|
||||
rc = btmAcquireDeviceConditionEvent(&btmDeviceConditionEvent, &flags);
|
||||
if R_FAILED(rc)
|
||||
fatalThrow(rc);
|
||||
|
||||
rc = btdrvRegisterHidReportEvent(&hidReportEvent);
|
||||
if R_FAILED(rc)
|
||||
fatalThrow(rc);
|
||||
|
||||
|
||||
/* Init threads */
|
||||
rc = threadCreate(&hidEventThread, hidEventThreadFunc, nullptr, nullptr, thread_stack_size, 0x2C, -2);
|
||||
if R_FAILED(rc)
|
||||
fatalThrow(rc);
|
||||
|
||||
rc = threadCreate(&hidReportEventThread, hidReportEventThreadFunc, nullptr, nullptr, thread_stack_size, 0x2C, -2);
|
||||
if R_FAILED(rc)
|
||||
fatalThrow(rc);
|
||||
|
||||
rc = threadCreate(&btmDeviceEventThread, btmDeviceEventThreadFunc, nullptr, nullptr, thread_stack_size, 0x2C, -2);
|
||||
if R_FAILED(rc)
|
||||
fatalThrow(rc);
|
||||
|
||||
/* Init controller manager */
|
||||
controllerManager = std::make_unique<mc::controller::ControllerManager>();
|
||||
//controllerManager->registerBluetoothControllers();
|
||||
|
||||
/* Start threads */
|
||||
rc = threadStart(&hidEventThread);
|
||||
if R_FAILED(rc)
|
||||
fatalThrow(rc);
|
||||
|
||||
rc = threadStart(&hidReportEventThread);
|
||||
if R_FAILED(rc)
|
||||
fatalThrow(rc);
|
||||
|
||||
/*
|
||||
rc = threadStart(&btmDeviceEventThread);
|
||||
if R_FAILED(rc)
|
||||
fatalThrow(rc);
|
||||
*/
|
||||
}
|
||||
|
||||
void Cleanup(void) {
|
||||
/* Wait for all threads to finish */
|
||||
threadWaitForExit(&btmDeviceEventThread);
|
||||
threadWaitForExit(&hidReportEventThread);
|
||||
threadWaitForExit(&hidEventThread);
|
||||
|
||||
/* Cleanup threads */
|
||||
threadClose(&btmDeviceEventThread);
|
||||
threadClose(&hidReportEventThread);
|
||||
threadClose(&hidEventThread);
|
||||
|
||||
/* Cleanup events */
|
||||
eventClose(&btmDeviceConditionEvent);
|
||||
eventClose(&hidReportEvent);
|
||||
eventClose(&hidEvent);
|
||||
|
||||
/* Cleanup Bluetooth HID interface */
|
||||
//btdrvFinalizeHid();
|
||||
}
|
||||
|
||||
void PrepareForSleep(void) {
|
||||
mc::log::Write("Console preparing for sleep");
|
||||
controllerManager->removeControllers();
|
||||
}
|
||||
|
||||
void PrepareForWake(void) {
|
||||
//controllerManager->registerBluetoothControllers();
|
||||
mc::log::Write("Console preparing for wake");
|
||||
}
|
||||
|
||||
void OnWake(void) {
|
||||
mc::log::Write("Console awake");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
#include <cstring>
|
||||
#include "gamepad/abstractedpad.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
AbstractedPadVirtualController::AbstractedPadVirtualController() {
|
||||
std::memset(&m_state, 0, sizeof(HiddbgAbstractedPadState));
|
||||
m_state.type = BIT(0); //maybe equivalent to HidDeviceTypeBits_FullKey
|
||||
m_state.npadInterfaceType = NpadInterfaceType_Bluetooth;
|
||||
m_state.flags = 0xff; //Don't know if needs to be this value
|
||||
m_state.state.batteryCharge = 4;
|
||||
m_state.singleColorBody = RGBA8_MAXALPHA(45, 45, 45);
|
||||
m_state.singleColorButtons = RGBA8_MAXALPHA(230, 230, 230);
|
||||
|
||||
/* Todo: keep track of assigned ids and set this properly */
|
||||
m_uniqueId = 0;
|
||||
}
|
||||
|
||||
AbstractedPadVirtualController::~AbstractedPadVirtualController() {
|
||||
this->disconnect();
|
||||
}
|
||||
|
||||
Result AbstractedPadVirtualController::connect(void) {
|
||||
return hiddbgSetAutoPilotVirtualPadState(m_uniqueId, &m_state);
|
||||
}
|
||||
|
||||
Result AbstractedPadVirtualController::disconnect(void) {
|
||||
return hiddbgUnsetAutoPilotVirtualPadState(m_uniqueId);
|
||||
}
|
||||
|
||||
Result AbstractedPadVirtualController::setState(const SwitchProGamepadState* state) {
|
||||
m_state.state.buttons = 0;
|
||||
|
||||
m_state.state.buttons |= state->A ? KEY_A : 0;
|
||||
m_state.state.buttons |= state->B ? KEY_B : 0;
|
||||
m_state.state.buttons |= state->X ? KEY_X : 0;
|
||||
m_state.state.buttons |= state->Y ? KEY_Y : 0;
|
||||
|
||||
m_state.state.buttons |= state->dpad_down ? KEY_DDOWN : 0;
|
||||
m_state.state.buttons |= state->dpad_up ? KEY_DUP : 0;
|
||||
m_state.state.buttons |= state->dpad_right ? KEY_DRIGHT : 0;
|
||||
m_state.state.buttons |= state->dpad_left ? KEY_DLEFT : 0;
|
||||
|
||||
m_state.state.buttons |= state->L ? KEY_L : 0;
|
||||
m_state.state.buttons |= state->ZL ? KEY_ZL : 0;
|
||||
m_state.state.buttons |= state->lstick_press ? KEY_LSTICK : 0;
|
||||
|
||||
m_state.state.buttons |= state->R ? KEY_R : 0;
|
||||
m_state.state.buttons |= state->ZR ? KEY_ZR : 0;
|
||||
m_state.state.buttons |= state->rstick_press ? KEY_RSTICK : 0;
|
||||
|
||||
m_state.state.buttons |= state->minus ? KEY_MINUS : 0;
|
||||
m_state.state.buttons |= state->plus ? KEY_PLUS : 0;
|
||||
m_state.state.buttons |= state->capture ? KEY_CAPTURE : 0;
|
||||
m_state.state.buttons |= state->home ? KEY_HOME : 0;
|
||||
|
||||
m_state.state.joysticks[JOYSTICK_LEFT].dx = state->left_stick.dx;
|
||||
m_state.state.joysticks[JOYSTICK_LEFT].dy = state->left_stick.dy;
|
||||
|
||||
m_state.state.joysticks[JOYSTICK_RIGHT].dx = state->right_stick.dx;
|
||||
m_state.state.joysticks[JOYSTICK_RIGHT].dy = state->right_stick.dy;
|
||||
|
||||
return hiddbgSetAutoPilotVirtualPadState(m_uniqueId, &m_state);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include "gamepad/bluetoothdatabase.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
#include "logger.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
BluetoothDatabase::BluetoothDatabase() : m_location(BluetoothDatabase::default_location) {
|
||||
this->loadDatabase();
|
||||
}
|
||||
|
||||
BluetoothDatabase::BluetoothDatabase(const char *location) : m_location(location) {
|
||||
this->loadDatabase();
|
||||
}
|
||||
|
||||
Result BluetoothDatabase::loadDatabase(void) {
|
||||
FILE *fp = std::fopen(m_location, "rb");
|
||||
if (fp == nullptr) {
|
||||
//mc::log::Write("Error opening bluetooth database");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//mc::log::Write("Reading bluetooth database...");
|
||||
std::fread(&m_database, sizeof(m_database), 1, fp);
|
||||
std::fclose(fp);
|
||||
|
||||
if (std::ferror(fp)) {
|
||||
//mc::log::Write("Error loading bluetooth database");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result BluetoothDatabase::storeDatabase(void) {
|
||||
FILE *fp = std::fopen(m_location, "wb");
|
||||
if (fp == nullptr) {
|
||||
//mc::log::Write("Error opening bluetooth database");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//mc::log::Write("Writing bluetooth database...");
|
||||
std::fwrite(&m_database, sizeof(m_database), 1, fp);
|
||||
std::fclose(fp);
|
||||
|
||||
if (std::ferror(fp)) {
|
||||
//mc::log::Write("Error writing bluetooth database");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result BluetoothDatabase::reload(void) {
|
||||
return this->loadDatabase();
|
||||
}
|
||||
|
||||
Result BluetoothDatabase::addDevice(const BluetoothDevice *device) {
|
||||
if (device == nullptr) {
|
||||
//mc::log::Write("BluetoothDatabase::addDevice: device is nullptr");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check if device is already in database */
|
||||
const BluetoothDevice *existing = this->search(&device->address);
|
||||
|
||||
if (existing) {
|
||||
//mc::log::Write("Copying over exiting database entry...");
|
||||
/* Overwrite existing database entry */
|
||||
std::memcpy(const_cast<BluetoothDevice *>(existing), device, sizeof(BluetoothDevice));
|
||||
}
|
||||
else if (m_database.size < BluetoothDatabase::max_devices) {
|
||||
//mc::log::Write("Adding new device to bluetooth database...");
|
||||
/* Add new device to the database */
|
||||
std::memcpy(&m_database.devices[m_database.size++], device, sizeof(BluetoothDevice));
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return this->storeDatabase();
|
||||
}
|
||||
|
||||
Result BluetoothDatabase::removeDevice(const BluetoothAddress *address) {
|
||||
/* Locate index of device in database */
|
||||
uint8_t index = this->indexOf(address);
|
||||
if (index >= 0) {
|
||||
/* remove device from database and shift remaining devices down */
|
||||
std::memcpy(&m_database.devices[index], &m_database.devices[index+1], (m_database.size-index-1) * sizeof(BluetoothDevice));
|
||||
std::memset(&m_database.devices[--m_database.size], 0, sizeof(BluetoothDevice));
|
||||
}
|
||||
|
||||
return this->storeDatabase();
|
||||
}
|
||||
|
||||
const BluetoothDevice *BluetoothDatabase::search(const BluetoothAddress *address) {
|
||||
for (uint8_t i = 0; i < m_database.size; ++i) {
|
||||
if (bdcmp(address, &m_database.devices[i].address)) {
|
||||
return &m_database.devices[i];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const BluetoothDevice *BluetoothDatabase::operator[](uint8_t index) {
|
||||
return this->deviceAt(index);
|
||||
}
|
||||
|
||||
const BluetoothDevice *BluetoothDatabase::deviceAt(uint8_t index) {
|
||||
if (index < m_database.size) {
|
||||
return &m_database.devices[index];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint8_t BluetoothDatabase::indexOf(const BluetoothAddress *address) {
|
||||
for (uint8_t i = 0; i < m_database.size; ++i) {
|
||||
if (bdcmp(address, &m_database.devices[i].address)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t BluetoothDatabase::size(void) {
|
||||
return m_database.size;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
#include <cstring>
|
||||
#include "gamepad/bluetoothinterface.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
Result BluetoothInterface::connect(void) {
|
||||
return btdrvOpenHidConnection(&m_address);
|
||||
}
|
||||
|
||||
Result BluetoothInterface::disconnect(void) {
|
||||
return btdrvCloseHidConnection(&m_address);
|
||||
}
|
||||
|
||||
Result BluetoothInterface::wake(void) {
|
||||
return btdrvTriggerConnection(&m_address, 0);
|
||||
}
|
||||
|
||||
Result BluetoothInterface::sendData(const uint8_t *buffer, uint16_t length) {
|
||||
return btdrvWriteHidData2(&m_address, buffer, length);
|
||||
}
|
||||
|
||||
const BluetoothAddress& BluetoothInterface::address(void) const {
|
||||
return m_address;
|
||||
}
|
||||
|
||||
void BluetoothInterface::setAddress(const BluetoothAddress *address) {
|
||||
std::memcpy(&m_address, address, sizeof(BluetoothAddress));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,226 +0,0 @@
|
|||
#include <algorithm>
|
||||
#include "gamepad/controllermanager.hpp"
|
||||
#include "gamepad/bluetoothinterface.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
#include "log.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
ControllerManager::ControllerManager() {
|
||||
|
||||
if (hosversionAtLeast(7, 0, 0)) {
|
||||
Result rc = hiddbgAttachHdlsWorkBuffer();
|
||||
if R_FAILED(rc)
|
||||
fatalThrow(rc);
|
||||
}
|
||||
|
||||
m_database = std::make_unique<BluetoothDatabase>();
|
||||
}
|
||||
|
||||
ControllerManager::~ControllerManager() {
|
||||
|
||||
if (hosversionAtLeast(7, 0, 0)) {
|
||||
Result rc = hiddbgReleaseHdlsWorkBuffer();
|
||||
if R_FAILED(rc)
|
||||
fatalThrow(rc);
|
||||
}
|
||||
}
|
||||
|
||||
ControllerType ControllerManager::identify(uint16_t vid, uint16_t pid) {
|
||||
for (HardwareID hwId : JoyconController::hardwareIds) {
|
||||
if ( (vid == hwId.vid) && (pid == hwId.pid) ) {
|
||||
return ControllerType_Joycon;
|
||||
}
|
||||
}
|
||||
|
||||
for (HardwareID hwId : SwitchProController::hardwareIds) {
|
||||
if ( (vid == hwId.vid) && (pid == hwId.pid) ) {
|
||||
return ControllerType_SwitchPro;
|
||||
}
|
||||
}
|
||||
|
||||
for (HardwareID hwId : WiiUProController::hardwareIds) {
|
||||
if ( (vid == hwId.vid) && (pid == hwId.pid) ) {
|
||||
return ControllerType_WiiUPro;
|
||||
}
|
||||
}
|
||||
|
||||
for (HardwareID hwId : WiimoteController::hardwareIds) {
|
||||
if ( (vid == hwId.vid) && (pid == hwId.pid) ) {
|
||||
return ControllerType_Wiimote;
|
||||
}
|
||||
}
|
||||
|
||||
for (HardwareID hwId : Dualshock4Controller::hardwareIds) {
|
||||
if ( (vid == hwId.vid) && (pid == hwId.pid) ) {
|
||||
return ControllerType_Dualshock4;
|
||||
}
|
||||
}
|
||||
|
||||
for (HardwareID hwId : XboxOneController::hardwareIds) {
|
||||
if ( (vid == hwId.vid) && (pid == hwId.pid) ) {
|
||||
return ControllerType_XboxOne;
|
||||
}
|
||||
}
|
||||
|
||||
return ControllerType_Unknown;
|
||||
}
|
||||
|
||||
ControllerType ControllerManager::identify(const HardwareID *hwId) {
|
||||
return ControllerManager::identify(hwId->vid, hwId->pid);
|
||||
}
|
||||
|
||||
ControllerType ControllerManager::identify(const BluetoothDevice *device) {
|
||||
return ControllerManager::identify(device->vid, device->pid);
|
||||
}
|
||||
|
||||
Result ControllerManager::registerBluetoothControllers(void) {
|
||||
Result rc;
|
||||
|
||||
/* Register database entries with bluetooth module */
|
||||
for (uint8_t i = 0; i < m_database->size(); ++i) {
|
||||
rc = btdrvAddPairedDeviceInfo(m_database->deviceAt(i));
|
||||
if R_FAILED(rc)
|
||||
fatalThrow(rc);
|
||||
}
|
||||
|
||||
//mc::log::Write("Registered pairing database with bluetooth module");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result ControllerManager::attachBluetoothController(const BluetoothAddress *address) {
|
||||
|
||||
const BluetoothDevice *device = m_database->search(address);
|
||||
if (device) {
|
||||
switch (this->identify(device)) {
|
||||
case ControllerType_SwitchPro:
|
||||
m_controllers.push_back(std::make_unique<SwitchProController>(HidInterfaceType_Bluetooth));
|
||||
break;
|
||||
|
||||
case ControllerType_WiiUPro:
|
||||
m_controllers.push_back(std::make_unique<WiiUProController>(HidInterfaceType_Bluetooth));
|
||||
break;
|
||||
|
||||
case ControllerType_Wiimote:
|
||||
m_controllers.push_back(std::make_unique<WiimoteController>(HidInterfaceType_Bluetooth));
|
||||
break;
|
||||
|
||||
case ControllerType_Dualshock4:
|
||||
{
|
||||
m_controllers.push_back(std::make_unique<Dualshock4Controller>(HidInterfaceType_Bluetooth));
|
||||
|
||||
/*
|
||||
// This definitely doesn't belong here
|
||||
uint8_t r = 0xff;
|
||||
uint8_t g = 0x00;
|
||||
uint8_t b = 0x00;
|
||||
|
||||
Dualshock4OutputReport0x11 report = {0xa2, 0x11, 0xc0, 0x20, 0xf3, 0x04, 0x00, 0x00, 0x00, r, g, b};
|
||||
report.crc = crc32Calculate(report.data, sizeof(report.data));
|
||||
|
||||
BluetoothHidData hidData = {};
|
||||
hidData.length = sizeof(report) - 1;
|
||||
std::memcpy(&hidData.data, &report.data[1], hidData.length);
|
||||
|
||||
Result rc = btdrvHidSetReport(address, HidReportType_OutputReport, &hidData);
|
||||
*/
|
||||
}
|
||||
break;
|
||||
|
||||
case ControllerType_XboxOne:
|
||||
m_controllers.push_back(std::make_unique<XboxOneController>(HidInterfaceType_Bluetooth));
|
||||
break;
|
||||
|
||||
default:
|
||||
//mc::log::Write("Unrecognised device: <%04x:%04x>", device->vid, device->pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Pretty filthy hack until I work out how to structure this better
|
||||
m_controllers.back()->m_btInterface->setAddress(address);
|
||||
|
||||
/*
|
||||
mc::log::Write("ControllerManager::attachBluetoothController: Attached bluetooth controller [%02x:%02x:%02x:%02x:%02x:%02x]",
|
||||
((uint8_t *)address)[0],
|
||||
((uint8_t *)address)[1],
|
||||
((uint8_t *)address)[2],
|
||||
((uint8_t *)address)[3],
|
||||
((uint8_t *)address)[4],
|
||||
((uint8_t *)address)[5]
|
||||
);
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
Result ControllerManager::removeBluetoothController(const BluetoothAddress *address) {
|
||||
|
||||
for (auto it = m_controllers.begin(); it < m_controllers.end(); ++it) {
|
||||
if ((*it)->m_btInterface != nullptr) {
|
||||
if (bdcmp(&(*it)->m_btInterface->address(), address)) {
|
||||
m_controllers.erase(it);
|
||||
|
||||
/*
|
||||
mc::log::Write("ControllerManager::removeBluetoothController: Removed bluetooth controller [%02x:%02x:%02x:%02x:%02x:%02x]",
|
||||
((uint8_t *)address)[0],
|
||||
((uint8_t *)address)[1],
|
||||
((uint8_t *)address)[2],
|
||||
((uint8_t *)address)[3],
|
||||
((uint8_t *)address)[4],
|
||||
((uint8_t *)address)[5]
|
||||
);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
mc::log::Write("ControllerManager::removeBluetoothController: Couldn't located controller [%02x:%02x:%02x:%02x:%02x:%02x]",
|
||||
((uint8_t *)address)[0],
|
||||
((uint8_t *)address)[1],
|
||||
((uint8_t *)address)[2],
|
||||
((uint8_t *)address)[3],
|
||||
((uint8_t *)address)[4],
|
||||
((uint8_t *)address)[5]
|
||||
);
|
||||
*/
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ControllerManager::removeControllers(void) {
|
||||
//mc::log::Write("Removing all controllers");
|
||||
m_controllers.clear();
|
||||
}
|
||||
|
||||
Result ControllerManager::receiveBluetoothReport(const BluetoothAddress *address, const HidReport *report) {
|
||||
|
||||
for (auto it = m_controllers.begin(); it < m_controllers.end(); ++it) {
|
||||
if ((*it)->m_btInterface != nullptr) {
|
||||
if (bdcmp(&(*it)->m_btInterface->address(), address)) {
|
||||
(*it)->receiveReport(report);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
mc::log::Write("ControllerManager::receiveBluetoothReport: Controller not found [%02x:%02x:%02x:%02x:%02x:%02x] ",
|
||||
((uint8_t *)address)[0],
|
||||
((uint8_t *)address)[1],
|
||||
((uint8_t *)address)[2],
|
||||
((uint8_t *)address)[3],
|
||||
((uint8_t *)address)[4],
|
||||
((uint8_t *)address)[5]
|
||||
);
|
||||
*/
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include "gamepad/controllers/dualshock4.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
namespace {
|
||||
|
||||
const constexpr uint8_t dualshock4_joystick_nbits = 8;
|
||||
|
||||
}
|
||||
|
||||
Dualshock4Controller::Dualshock4Controller(HidInterfaceType iface) : HidGamepad(iface) {
|
||||
this->setInnerDeadzone(0.1);
|
||||
}
|
||||
|
||||
void Dualshock4Controller::mapStickValues(JoystickPosition *dst, const Dualshock4StickData *src) {
|
||||
dst->dx = unsigned_to_signed(src->x, dualshock4_joystick_nbits);
|
||||
dst->dy = -unsigned_to_signed(src->y, dualshock4_joystick_nbits);
|
||||
|
||||
float angle = atan2(dst->dy, dst->dx);
|
||||
float magnitude = hypot(dst->dx, dst->dy);
|
||||
|
||||
if (magnitude < m_innerDeadzone) {
|
||||
dst->dx = 0;
|
||||
dst->dy = 0;
|
||||
}
|
||||
else if (magnitude > m_outerDeadzone) {
|
||||
dst->dx = JOYSTICK_MAX * cos(angle);
|
||||
dst->dy = JOYSTICK_MAX * sin(angle);
|
||||
}
|
||||
}
|
||||
|
||||
Result Dualshock4Controller::receiveReport(const HidReport *report) {
|
||||
|
||||
const Dualshock4ReportData *reportData = reinterpret_cast<const Dualshock4ReportData *>(&report->data);
|
||||
|
||||
switch(report->id) {
|
||||
case 0x01:
|
||||
handleInputReport0x01(reportData);
|
||||
break;
|
||||
|
||||
case 0x11:
|
||||
handleInputReport0x11(reportData);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Dualshock4Controller::handleInputReport0x01(const Dualshock4ReportData *data) {
|
||||
std::memset(&m_state, 0, sizeof(m_state));
|
||||
|
||||
this->mapStickValues(&m_state.left_stick, &data->report0x01.left_stick);
|
||||
this->mapStickValues(&m_state.right_stick, &data->report0x01.right_stick);
|
||||
|
||||
m_state.dpad_left = (data->report0x01.buttons.dpad == Dualshock4DPad_W) ||
|
||||
(data->report0x01.buttons.dpad == Dualshock4DPad_NW) ||
|
||||
(data->report0x01.buttons.dpad == Dualshock4DPad_SW);
|
||||
m_state.dpad_up = (data->report0x01.buttons.dpad == Dualshock4DPad_N) ||
|
||||
(data->report0x01.buttons.dpad == Dualshock4DPad_NE) ||
|
||||
(data->report0x01.buttons.dpad == Dualshock4DPad_NW);
|
||||
m_state.dpad_right = (data->report0x01.buttons.dpad == Dualshock4DPad_E) ||
|
||||
(data->report0x01.buttons.dpad == Dualshock4DPad_NE) ||
|
||||
(data->report0x01.buttons.dpad == Dualshock4DPad_SE);
|
||||
m_state.dpad_down = (data->report0x01.buttons.dpad == Dualshock4DPad_S) ||
|
||||
(data->report0x01.buttons.dpad == Dualshock4DPad_SE) ||
|
||||
(data->report0x01.buttons.dpad == Dualshock4DPad_SW);
|
||||
|
||||
m_state.Y = data->report0x01.buttons.square;
|
||||
m_state.X = data->report0x01.buttons.triangle;
|
||||
m_state.B = data->report0x01.buttons.cross;
|
||||
m_state.A = data->report0x01.buttons.circle;
|
||||
|
||||
m_state.L = data->report0x01.buttons.L1;
|
||||
m_state.ZL = data->report0x01.buttons.L2;
|
||||
m_state.lstick_press = data->report0x01.buttons.L3;
|
||||
|
||||
m_state.R = data->report0x01.buttons.R1;
|
||||
m_state.ZR = data->report0x01.buttons.R2;
|
||||
m_state.rstick_press = data->report0x01.buttons.R3;
|
||||
|
||||
m_state.minus = data->report0x01.buttons.share;
|
||||
m_state.plus = data->report0x01.buttons.options;
|
||||
m_state.capture = data->report0x01.buttons.tpad;
|
||||
m_state.home = data->report0x01.buttons.ps;
|
||||
|
||||
m_virtual->setState(&m_state);
|
||||
}
|
||||
|
||||
void Dualshock4Controller::handleInputReport0x11(const Dualshock4ReportData *data) {
|
||||
std::memset(&m_state, 0, sizeof(m_state));
|
||||
|
||||
this->mapStickValues(&m_state.left_stick, &data->report0x11.left_stick);
|
||||
this->mapStickValues(&m_state.right_stick, &data->report0x11.right_stick);
|
||||
|
||||
m_state.dpad_left = (data->report0x11.buttons.dpad == Dualshock4DPad_W) ||
|
||||
(data->report0x11.buttons.dpad == Dualshock4DPad_NW) ||
|
||||
(data->report0x11.buttons.dpad == Dualshock4DPad_SW);
|
||||
m_state.dpad_up = (data->report0x11.buttons.dpad == Dualshock4DPad_N) ||
|
||||
(data->report0x11.buttons.dpad == Dualshock4DPad_NE) ||
|
||||
(data->report0x11.buttons.dpad == Dualshock4DPad_NW);
|
||||
m_state.dpad_right = (data->report0x11.buttons.dpad == Dualshock4DPad_E) ||
|
||||
(data->report0x11.buttons.dpad == Dualshock4DPad_NE) ||
|
||||
(data->report0x11.buttons.dpad == Dualshock4DPad_SE);
|
||||
m_state.dpad_down = (data->report0x11.buttons.dpad == Dualshock4DPad_S) ||
|
||||
(data->report0x11.buttons.dpad == Dualshock4DPad_SE) ||
|
||||
(data->report0x11.buttons.dpad == Dualshock4DPad_SW);
|
||||
|
||||
m_state.Y = data->report0x11.buttons.square;
|
||||
m_state.X = data->report0x11.buttons.triangle;
|
||||
m_state.B = data->report0x11.buttons.cross;
|
||||
m_state.A = data->report0x11.buttons.circle;
|
||||
|
||||
m_state.L = data->report0x11.buttons.L1;
|
||||
m_state.ZL = data->report0x11.buttons.L2;
|
||||
m_state.lstick_press = data->report0x11.buttons.L3;
|
||||
|
||||
m_state.R = data->report0x11.buttons.R1;
|
||||
m_state.ZR = data->report0x11.buttons.R2;
|
||||
m_state.rstick_press = data->report0x11.buttons.R3;
|
||||
|
||||
m_state.minus = data->report0x11.buttons.share;
|
||||
m_state.plus = data->report0x11.buttons.options;
|
||||
m_state.capture = data->report0x11.buttons.tpad;
|
||||
m_state.home = data->report0x11.buttons.ps;
|
||||
|
||||
m_virtual->setState(&m_state);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include "gamepad/controllers/joycon.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
namespace {
|
||||
|
||||
const constexpr uint8_t joycon_joystick_nbits = 12;
|
||||
|
||||
}
|
||||
|
||||
void JoyconController::mapStickValues(JoystickPosition *dst, const JoyconStickData *src) {
|
||||
dst->dx = unsigned_to_signed(src->x, joycon_joystick_nbits);
|
||||
dst->dy = -unsigned_to_signed(src->y, joycon_joystick_nbits);
|
||||
|
||||
float angle = atan2(dst->dy, dst->dx);
|
||||
float magnitude = hypot(dst->dx, dst->dy);
|
||||
|
||||
if (magnitude < m_innerDeadzone) {
|
||||
dst->dx = 0;
|
||||
dst->dy = 0;
|
||||
}
|
||||
else if (magnitude > m_outerDeadzone) {
|
||||
dst->dx = JOYSTICK_MAX * cos(angle);
|
||||
dst->dy = JOYSTICK_MAX * sin(angle);
|
||||
}
|
||||
}
|
||||
|
||||
Result JoyconController::receiveReport(const HidReport *report) {
|
||||
|
||||
const JoyconReportData *reportData = reinterpret_cast<const JoyconReportData *>(&report->data);
|
||||
|
||||
switch(report->id) {
|
||||
case 0x30:
|
||||
handleInputReport0x30(reportData);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void JoyconController::handleInputReport0x30(const JoyconReportData *data) {
|
||||
std::memset(&m_state, 0, sizeof(m_state));
|
||||
|
||||
this->mapStickValues(&m_state.left_stick, &data->report0x30.left_stick);
|
||||
this->mapStickValues(&m_state.right_stick, &data->report0x30.right_stick);
|
||||
|
||||
m_state.dpad_left = data->report0x30.buttons.dpad_left;
|
||||
m_state.dpad_up = data->report0x30.buttons.dpad_up;
|
||||
m_state.dpad_right = data->report0x30.buttons.dpad_right;
|
||||
m_state.dpad_down = data->report0x30.buttons.dpad_down;
|
||||
|
||||
m_state.A = data->report0x30.buttons.A;
|
||||
m_state.B = data->report0x30.buttons.B;
|
||||
m_state.X = data->report0x30.buttons.X;
|
||||
m_state.Y = data->report0x30.buttons.Y;
|
||||
|
||||
m_state.L = data->report0x30.buttons.L;
|
||||
m_state.ZL = data->report0x30.buttons.ZL;
|
||||
m_state.lstick_press = data->report0x30.buttons.lstick_press;
|
||||
|
||||
m_state.R = data->report0x30.buttons.R;
|
||||
m_state.ZR = data->report0x30.buttons.ZR;
|
||||
m_state.rstick_press = data->report0x30.buttons.rstick_press;
|
||||
|
||||
m_state.minus = data->report0x30.buttons.minus;
|
||||
m_state.plus = data->report0x30.buttons.plus;
|
||||
m_state.capture = data->report0x30.buttons.capture;
|
||||
m_state.home = data->report0x30.buttons.home;
|
||||
|
||||
m_virtual->setState(&m_state);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include "gamepad/controllers/switchpro.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
namespace {
|
||||
|
||||
const constexpr uint8_t switchpro_joystick_nbits = 12;
|
||||
|
||||
}
|
||||
|
||||
void SwitchProController::mapStickValues(JoystickPosition *dst, const SwitchProStickData *src) {
|
||||
dst->dx = unsigned_to_signed(src->x, switchpro_joystick_nbits);
|
||||
dst->dy = -unsigned_to_signed(src->y, switchpro_joystick_nbits);
|
||||
|
||||
float angle = atan2(dst->dy, dst->dx);
|
||||
float magnitude = hypot(dst->dx, dst->dy);
|
||||
|
||||
if (magnitude < m_innerDeadzone) {
|
||||
dst->dx = 0;
|
||||
dst->dy = 0;
|
||||
}
|
||||
else if (magnitude > m_outerDeadzone) {
|
||||
dst->dx = JOYSTICK_MAX * cos(angle);
|
||||
dst->dy = JOYSTICK_MAX * sin(angle);
|
||||
}
|
||||
}
|
||||
|
||||
Result SwitchProController::receiveReport(const HidReport *report) {
|
||||
|
||||
const SwitchProReportData *reportData = reinterpret_cast<const SwitchProReportData *>(&report->data);
|
||||
|
||||
switch(report->id) {
|
||||
case 0x30:
|
||||
handleInputReport0x30(reportData);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SwitchProController::handleInputReport0x30(const SwitchProReportData *data) {
|
||||
std::memset(&m_state, 0, sizeof(m_state));
|
||||
|
||||
this->mapStickValues(&m_state.left_stick, &data->report0x30.left_stick);
|
||||
this->mapStickValues(&m_state.right_stick, &data->report0x30.right_stick);
|
||||
|
||||
m_state.dpad_left = data->report0x30.buttons.dpad_left;
|
||||
m_state.dpad_up = data->report0x30.buttons.dpad_up;
|
||||
m_state.dpad_right = data->report0x30.buttons.dpad_right;
|
||||
m_state.dpad_down = data->report0x30.buttons.dpad_down;
|
||||
|
||||
m_state.A = data->report0x30.buttons.A;
|
||||
m_state.B = data->report0x30.buttons.B;
|
||||
m_state.X = data->report0x30.buttons.X;
|
||||
m_state.Y = data->report0x30.buttons.Y;
|
||||
|
||||
m_state.L = data->report0x30.buttons.L;
|
||||
m_state.ZL = data->report0x30.buttons.ZL;
|
||||
m_state.lstick_press = data->report0x30.buttons.lstick_press;
|
||||
|
||||
m_state.R = data->report0x30.buttons.R;
|
||||
m_state.ZR = data->report0x30.buttons.ZR;
|
||||
m_state.rstick_press = data->report0x30.buttons.rstick_press;
|
||||
|
||||
m_state.minus = data->report0x30.buttons.minus;
|
||||
m_state.plus = data->report0x30.buttons.plus;
|
||||
m_state.capture = data->report0x30.buttons.capture;
|
||||
m_state.home = data->report0x30.buttons.home;
|
||||
|
||||
m_virtual->setState(&m_state);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
#include <cstring>
|
||||
#include "gamepad/controllers/wiimote.hpp"
|
||||
#include "byteswap.h"
|
||||
|
||||
#include "log.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
WiimoteController::WiimoteController(HidInterfaceType iface) : HidGamepad(iface) {
|
||||
//this->setInnerDeadzone(0.1);
|
||||
|
||||
/*
|
||||
uint8_t reportdata[] = {0x11, 0x10}; // set player led
|
||||
|
||||
BluetoothHidData hidData = {};
|
||||
hidData.length = sizeof(reportdata);
|
||||
std::memcpy(&hidData.data, &reportdata, sizeof(reportdata));
|
||||
|
||||
btdrvHidSetReport(&address, HidReportType_OutputReport, &hidData);
|
||||
*/
|
||||
}
|
||||
|
||||
Result write_wiimote_memory(const BluetoothAddress *bd_addr, uint32_t address, const uint8_t *data, uint8_t length) {
|
||||
const struct {
|
||||
uint8_t id;
|
||||
uint32_t address;
|
||||
uint8_t length;
|
||||
uint8_t data[0x10];
|
||||
} __attribute__((packed)) report = {0x16, __bswap_32(address), length, *data};
|
||||
//std::memcpy(report.data, data, length);
|
||||
|
||||
BluetoothHidData hidData = {};
|
||||
hidData.length = sizeof(report);
|
||||
std::memcpy(&hidData.data, &report, sizeof(report));
|
||||
|
||||
mc::log::Write("Writing to wii remote control registers");
|
||||
mc::log::WriteData(&hidData.data, hidData.length);
|
||||
|
||||
return btdrvWriteHidData(bd_addr, &hidData);
|
||||
}
|
||||
|
||||
|
||||
Result WiimoteController::receiveReport(const HidReport *report) {
|
||||
|
||||
const WiimoteReportData *reportData = reinterpret_cast<const WiimoteReportData *>(&report->data);
|
||||
|
||||
switch(report->id) {
|
||||
case 0x30:
|
||||
handleInputReport0x30(reportData);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WiimoteController::handleInputReport0x30(const WiimoteReportData *data) {
|
||||
std::memset(&m_state, 0, sizeof(m_state));
|
||||
|
||||
m_state.dpad_left = data->report0x30.buttons.dpad_up;
|
||||
m_state.dpad_up = data->report0x30.buttons.dpad_right;
|
||||
m_state.dpad_right = data->report0x30.buttons.dpad_down;
|
||||
m_state.dpad_down = data->report0x30.buttons.dpad_left;
|
||||
|
||||
m_state.A = data->report0x30.buttons.two;
|
||||
m_state.B = data->report0x30.buttons.one;
|
||||
|
||||
m_state.L = data->report0x30.buttons.B;
|
||||
m_state.R = data->report0x30.buttons.A;
|
||||
|
||||
m_state.plus = data->report0x30.buttons.plus;
|
||||
m_state.minus = data->report0x30.buttons.minus;
|
||||
m_state.home = data->report0x30.buttons.home;
|
||||
|
||||
m_virtual->setState(&m_state);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
#include <cstring>
|
||||
#include "gamepad/controllers/wiiupro.hpp"
|
||||
|
||||
#include "log.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
namespace {
|
||||
|
||||
const constexpr uint8_t wiiupro_joystick_nbits = 12;
|
||||
|
||||
Result send_init_1(const BluetoothAddress *address) {
|
||||
const uint8_t data[] = {0x55};
|
||||
return write_wiimote_memory(address, 0x04a400f0, data, sizeof(data));
|
||||
}
|
||||
|
||||
Result send_init_2(const BluetoothAddress *address) {
|
||||
const uint8_t data[] = {0x00};
|
||||
return write_wiimote_memory(address, 0x04a400fb, data, sizeof(data));
|
||||
}
|
||||
|
||||
Result set_report_mode(const BluetoothAddress *address, uint8_t mode) {
|
||||
uint8_t data[] = {0x12, 0x00, mode};
|
||||
BluetoothHidData hidData = {};
|
||||
hidData.length = sizeof(data);
|
||||
std::memcpy(&hidData.data, data, sizeof(data));
|
||||
return btdrvWriteHidData(address, &hidData);
|
||||
}
|
||||
|
||||
Result set_player_leds(const BluetoothAddress *address, uint8_t mask) {
|
||||
uint8_t data[] = {0x11, mask}; // set player led
|
||||
BluetoothHidData hidData = {};
|
||||
hidData.length = sizeof(data);
|
||||
std::memcpy(&hidData.data, data, sizeof(data));
|
||||
return btdrvWriteHidData(address, &hidData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
WiiUProController::WiiUProController(HidInterfaceType iface) : HidGamepad(iface) {
|
||||
this->setInnerDeadzone(0.15);
|
||||
}
|
||||
|
||||
void WiiUProController::mapStickValues(JoystickPosition *dst, uint16_t x, uint16_t y) {
|
||||
dst->dx = 2*unsigned_to_signed(x, wiiupro_joystick_nbits);
|
||||
dst->dy = 2*unsigned_to_signed(y, wiiupro_joystick_nbits);
|
||||
|
||||
float angle = atan2(dst->dy, dst->dx);
|
||||
float magnitude = hypot(dst->dx, dst->dy);
|
||||
|
||||
if (magnitude < m_innerDeadzone) {
|
||||
dst->dx = 0;
|
||||
dst->dy = 0;
|
||||
}
|
||||
else if (magnitude > m_outerDeadzone) {
|
||||
dst->dx = JOYSTICK_MAX * cos(angle);
|
||||
dst->dy = JOYSTICK_MAX * sin(angle);
|
||||
}
|
||||
}
|
||||
|
||||
Result WiiUProController::receiveReport(const HidReport *report) {
|
||||
|
||||
const WiiUProReportData *reportData = reinterpret_cast<const WiiUProReportData *>(&report->data);
|
||||
|
||||
switch(report->id) {
|
||||
case 0x20: //extension connected
|
||||
handleInputReport0x20(reportData);
|
||||
break;
|
||||
|
||||
case 0x22: // Acknowledgement
|
||||
break;
|
||||
|
||||
case 0x32: // Buttons + Ext bytes
|
||||
break;
|
||||
|
||||
case 0x34: // Buttons + Ext bytes
|
||||
handleInputReport0x34(reportData);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WiiUProController::handleInputReport0x20(const WiiUProReportData *data) {
|
||||
Result rc;
|
||||
const BluetoothAddress address = this->m_btInterface->address();
|
||||
|
||||
rc = set_player_leds(&address, WiimoteLEDs_P1);
|
||||
rc = send_init_1(&address);
|
||||
rc = send_init_2(&address);
|
||||
rc = set_report_mode(&address, 0x34);
|
||||
|
||||
}
|
||||
|
||||
void WiiUProController::handleInputReport0x34(const WiiUProReportData *data) {
|
||||
std::memset(&m_state, 0, sizeof(m_state));
|
||||
|
||||
/*
|
||||
this->mapStickValues(&m_state.left_stick, data->report0x34.left_stick_x, data->report0x34.left_stick_y, 6);
|
||||
this->mapStickValues(&m_state.right_stick,
|
||||
data->report0x34.right_stick_x0 | (data->report0x34.right_stick_x1 << 1) | (data->report0x34.right_stick_x2 << 3),
|
||||
data->report0x34.right_stick_y, 5);
|
||||
*/
|
||||
this->mapStickValues(&m_state.left_stick, data->report0x34.left_stick_x, data->report0x34.left_stick_y);
|
||||
this->mapStickValues(&m_state.right_stick, data->report0x34.right_stick_x, data->report0x34.right_stick_y);
|
||||
|
||||
m_state.dpad_left = !data->report0x34.buttons.dpad_left;
|
||||
m_state.dpad_up = !data->report0x34.buttons.dpad_up;
|
||||
m_state.dpad_right = !data->report0x34.buttons.dpad_right;
|
||||
m_state.dpad_down = !data->report0x34.buttons.dpad_down;
|
||||
|
||||
m_state.A = !data->report0x34.buttons.A;
|
||||
m_state.B = !data->report0x34.buttons.B;
|
||||
m_state.X = !data->report0x34.buttons.X;
|
||||
m_state.Y = !data->report0x34.buttons.Y;
|
||||
|
||||
m_state.L = !data->report0x34.buttons.L;
|
||||
m_state.ZL = !data->report0x34.buttons.ZL;
|
||||
m_state.lstick_press = !data->report0x34.buttons.lstick_press;
|
||||
|
||||
m_state.R = !data->report0x34.buttons.R;
|
||||
m_state.ZR = !data->report0x34.buttons.ZR;
|
||||
m_state.rstick_press = !data->report0x34.buttons.rstick_press;
|
||||
|
||||
m_state.plus = !data->report0x34.buttons.plus;
|
||||
m_state.minus = !data->report0x34.buttons.minus;
|
||||
m_state.home = !data->report0x34.buttons.home;
|
||||
|
||||
m_virtual->setState(&m_state);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include "gamepad/controllers/xboxone.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
namespace {
|
||||
|
||||
const constexpr uint8_t xboxone_joystick_nbits = 16;
|
||||
|
||||
}
|
||||
|
||||
XboxOneController::XboxOneController(HidInterfaceType iface) : HidGamepad(iface) {
|
||||
this->setInnerDeadzone(0.1);
|
||||
}
|
||||
|
||||
void XboxOneController::mapStickValues(JoystickPosition *dst, const XboxOneStickData *src) {
|
||||
dst->dx = unsigned_to_signed(src->x, xboxone_joystick_nbits);
|
||||
dst->dy = -unsigned_to_signed(src->y, xboxone_joystick_nbits);
|
||||
|
||||
float angle = atan2(dst->dy, dst->dx);
|
||||
float magnitude = hypot(dst->dx, dst->dy);
|
||||
|
||||
if (magnitude < m_innerDeadzone) {
|
||||
dst->dx = 0;
|
||||
dst->dy = 0;
|
||||
}
|
||||
else if (magnitude > m_outerDeadzone) {
|
||||
dst->dx = JOYSTICK_MAX * cos(angle);
|
||||
dst->dy = JOYSTICK_MAX * sin(angle);
|
||||
}
|
||||
}
|
||||
|
||||
Result XboxOneController::receiveReport(const HidReport *report) {
|
||||
|
||||
const XboxOneReportData *reportData = reinterpret_cast<const XboxOneReportData *>(&report->data);
|
||||
|
||||
switch(report->id) {
|
||||
case 0x01:
|
||||
handleInputReport0x01(reportData);
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
handleInputReport0x02(reportData);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void XboxOneController::handleInputReport0x01(const XboxOneReportData *data) {
|
||||
std::memset(&m_state, 0, sizeof(m_state));
|
||||
|
||||
this->mapStickValues(&m_state.left_stick, &data->report0x01.left_stick);
|
||||
this->mapStickValues(&m_state.right_stick, &data->report0x01.right_stick);
|
||||
|
||||
m_state.dpad_left = (data->report0x01.buttons.dpad == XboxOneDPad_W) ||
|
||||
(data->report0x01.buttons.dpad == XboxOneDPad_NW) ||
|
||||
(data->report0x01.buttons.dpad == XboxOneDPad_SW);
|
||||
m_state.dpad_up = (data->report0x01.buttons.dpad == XboxOneDPad_N) ||
|
||||
(data->report0x01.buttons.dpad == XboxOneDPad_NE) ||
|
||||
(data->report0x01.buttons.dpad == XboxOneDPad_NW);
|
||||
m_state.dpad_right = (data->report0x01.buttons.dpad == XboxOneDPad_E) ||
|
||||
(data->report0x01.buttons.dpad == XboxOneDPad_NE) ||
|
||||
(data->report0x01.buttons.dpad == XboxOneDPad_SE);
|
||||
m_state.dpad_down = (data->report0x01.buttons.dpad == XboxOneDPad_S) ||
|
||||
(data->report0x01.buttons.dpad == XboxOneDPad_SE) ||
|
||||
(data->report0x01.buttons.dpad == XboxOneDPad_SW);
|
||||
|
||||
m_state.A = data->report0x01.buttons.B;
|
||||
m_state.B = data->report0x01.buttons.A;
|
||||
m_state.X = data->report0x01.buttons.Y;
|
||||
m_state.Y = data->report0x01.buttons.X;
|
||||
|
||||
m_state.L = data->report0x01.buttons.LB;
|
||||
m_state.ZL = data->report0x01.left_trigger > 0;
|
||||
m_state.lstick_press = data->report0x01.buttons.lstick_press;
|
||||
|
||||
m_state.R = data->report0x01.buttons.RB;
|
||||
m_state.ZR = data->report0x01.right_trigger > 0;
|
||||
m_state.rstick_press = data->report0x01.buttons.rstick_press;
|
||||
|
||||
m_state.minus = data->report0x01.buttons.view;
|
||||
m_state.plus = data->report0x01.buttons.menu;
|
||||
//m_state.capture = ;
|
||||
//m_state.home = ;
|
||||
|
||||
m_virtual->setState(&m_state);
|
||||
}
|
||||
|
||||
void XboxOneController::handleInputReport0x02(const XboxOneReportData *data) {
|
||||
std::memset(&m_state, 0, sizeof(m_state));
|
||||
|
||||
m_state.home = data->report0x02.guide;
|
||||
|
||||
m_virtual->setState(&m_state);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
#include <cstring>
|
||||
#include "gamepad/hdls.hpp"
|
||||
|
||||
#include "logger.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
HdlsVirtualController::HdlsVirtualController() {
|
||||
m_handle = INVALID_HANDLE;
|
||||
|
||||
std::memset(&m_device, 0, sizeof(HiddbgHdlsDeviceInfo));
|
||||
m_device.deviceType = HidDeviceType_FullKey3;
|
||||
m_device.npadInterfaceType = NpadInterfaceType_Bluetooth;
|
||||
// Set official pro controller colours
|
||||
m_device.singleColorBody = RGBA8_MAXALPHA(45, 45, 45);
|
||||
m_device.singleColorButtons = RGBA8_MAXALPHA(230, 230, 230);
|
||||
m_device.colorLeftGrip = RGBA8_MAXALPHA(70, 70, 70);
|
||||
m_device.colorRightGrip = RGBA8_MAXALPHA(70, 70, 70);
|
||||
|
||||
std::memset(&m_state, 0, sizeof(HiddbgHdlsState));
|
||||
m_state.batteryCharge = 4;
|
||||
}
|
||||
|
||||
HdlsVirtualController::~HdlsVirtualController() {
|
||||
//mc::log::Write("~HdlsVirtualController() called");
|
||||
this->disconnect();
|
||||
}
|
||||
|
||||
Result HdlsVirtualController::connect(void) {
|
||||
//mc::log::Write("Connecting Hdls virtual device");
|
||||
return hiddbgAttachHdlsVirtualDevice(&m_handle, &m_device);
|
||||
}
|
||||
|
||||
Result HdlsVirtualController::disconnect(void) {
|
||||
//mc::log::Write("Disconnecting Hdls virtual device");
|
||||
return hiddbgDetachHdlsVirtualDevice(m_handle);
|
||||
}
|
||||
|
||||
Result HdlsVirtualController::setState(const SwitchProGamepadState* state) {
|
||||
if (m_handle != INVALID_HANDLE) {
|
||||
m_state.buttons = 0;
|
||||
|
||||
m_state.buttons |= state->A ? KEY_A : 0;
|
||||
m_state.buttons |= state->B ? KEY_B : 0;
|
||||
m_state.buttons |= state->X ? KEY_X : 0;
|
||||
m_state.buttons |= state->Y ? KEY_Y : 0;
|
||||
|
||||
m_state.buttons |= state->dpad_down ? KEY_DDOWN : 0;
|
||||
m_state.buttons |= state->dpad_up ? KEY_DUP : 0;
|
||||
m_state.buttons |= state->dpad_right ? KEY_DRIGHT : 0;
|
||||
m_state.buttons |= state->dpad_left ? KEY_DLEFT : 0;
|
||||
|
||||
m_state.buttons |= state->L ? KEY_L : 0;
|
||||
m_state.buttons |= state->ZL ? KEY_ZL : 0;
|
||||
m_state.buttons |= state->lstick_press ? KEY_LSTICK : 0;
|
||||
|
||||
m_state.buttons |= state->R ? KEY_R : 0;
|
||||
m_state.buttons |= state->ZR ? KEY_ZR : 0;
|
||||
m_state.buttons |= state->rstick_press ? KEY_RSTICK : 0;
|
||||
|
||||
m_state.buttons |= state->minus ? KEY_MINUS : 0;
|
||||
m_state.buttons |= state->plus ? KEY_PLUS : 0;
|
||||
m_state.buttons |= state->capture ? KEY_CAPTURE : 0;
|
||||
m_state.buttons |= state->home ? KEY_HOME : 0;
|
||||
|
||||
m_state.joysticks[JOYSTICK_LEFT].dx = state->left_stick.dx;
|
||||
m_state.joysticks[JOYSTICK_LEFT].dy = state->left_stick.dy;
|
||||
|
||||
m_state.joysticks[JOYSTICK_RIGHT].dx = state->right_stick.dx;
|
||||
m_state.joysticks[JOYSTICK_RIGHT].dy = state->right_stick.dy;
|
||||
|
||||
return hiddbgSetHdlsState(m_handle, &m_state);
|
||||
}
|
||||
|
||||
//mc::log::Write("HdlsVirtualController::setState: handle is invalid");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
#include "gamepad/hidgamepad.hpp"
|
||||
#include "gamepad/bluetoothinterface.hpp"
|
||||
|
||||
namespace mc::controller {
|
||||
|
||||
namespace {
|
||||
|
||||
const constexpr int default_deadzone_percent = 0.05;
|
||||
|
||||
}
|
||||
|
||||
HidGamepad::HidGamepad(HidInterfaceType iface) {
|
||||
/* Assign HIDinterface */
|
||||
switch (iface) {
|
||||
case HidInterfaceType_Bluetooth:
|
||||
m_btInterface = std::make_unique<BluetoothInterface>();
|
||||
break;
|
||||
case HidInterfaceType_Usb: // Not yet implemented
|
||||
m_btInterface = nullptr;
|
||||
break;
|
||||
default:
|
||||
fatalThrow(-1);
|
||||
}
|
||||
|
||||
/* Assign virtual controller */
|
||||
if (hosversionAtLeast(7, 0, 0)) {
|
||||
m_virtual = std::make_unique<HdlsVirtualController>();
|
||||
} else if (hosversionAtLeast(5, 0, 0)) {
|
||||
m_virtual = std::make_unique<AbstractedPadVirtualController>();
|
||||
} else {
|
||||
fatalThrow(-1);
|
||||
}
|
||||
|
||||
this->setInnerDeadzone(default_deadzone_percent);
|
||||
this->setOuterDeadzone(default_deadzone_percent);
|
||||
|
||||
m_virtual->connect();
|
||||
}
|
||||
|
||||
void HidGamepad::setInnerDeadzone(float percentage) {
|
||||
m_innerDeadzone = JOYSTICK_MAX * percentage;
|
||||
}
|
||||
|
||||
void HidGamepad::setOuterDeadzone(float percentage) {
|
||||
m_outerDeadzone = JOYSTICK_MAX * (1.0 - percentage);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
#include "log.hpp"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <switch.h>
|
||||
|
||||
namespace mc::log {
|
||||
|
||||
namespace {
|
||||
|
||||
Mutex logMutex;
|
||||
const constexpr char *location = "sdmc:/missioncontrol-sysmodule.log";
|
||||
|
||||
}
|
||||
|
||||
void Write(const char *fmt, ...) {
|
||||
mutexLock(&logMutex);
|
||||
|
||||
FILE *fp = std::fopen(location, "a");
|
||||
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
std::vfprintf(fp, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
std::fprintf(fp, "\n");
|
||||
std::fclose(fp);
|
||||
|
||||
mutexUnlock(&logMutex);
|
||||
}
|
||||
|
||||
void WriteData(void *data, size_t size) {
|
||||
mutexLock(&logMutex);
|
||||
|
||||
FILE *fp = std::fopen(location, "a");
|
||||
|
||||
unsigned int i = 0;
|
||||
while (i < size) {
|
||||
// Print offset
|
||||
std::fprintf(fp, " %04x", i);
|
||||
std::fprintf(fp, " |");
|
||||
|
||||
// Print line of hex
|
||||
unsigned int j;
|
||||
for (j = 0; j < 16; ++j) {
|
||||
if (i + j < size) {
|
||||
std::fprintf(fp, " %02x", ((char *)data)[i+j]);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Print separator
|
||||
for (unsigned int k = 0; k < 16-j; ++k)
|
||||
{
|
||||
fprintf(fp, " ");
|
||||
}
|
||||
fprintf(fp, " | ");
|
||||
|
||||
// Print line of ascii
|
||||
for (unsigned int j = 0; j < 16; ++j) {
|
||||
if (i + j < size) {
|
||||
char c = ((char *)data)[i+j];
|
||||
std::fprintf(fp, "%c", isprint(c) ? c: 0x2e);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::fprintf(fp, "\n");
|
||||
i += 16;
|
||||
}
|
||||
std::fclose(fp);
|
||||
|
||||
mutexUnlock(&logMutex);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,144 +0,0 @@
|
|||
#include <switch.h>
|
||||
#include "bluetooth/hid.hpp"
|
||||
|
||||
#include "log.hpp"
|
||||
|
||||
// Adjust size as needed.
|
||||
#define INNER_HEAP_SIZE 0x40000
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
// Newlib
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __appInit(void) {
|
||||
Result rc;
|
||||
|
||||
rc = smInitialize();
|
||||
if (R_FAILED(rc))
|
||||
fatalThrow(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM));
|
||||
|
||||
// Ensure system firmware version has been set before we start doing IPC that relies on it
|
||||
if (hosversionGet() == 0) {
|
||||
rc = setsysInitialize();
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
SetSysFirmwareVersion fw;
|
||||
rc = setsysGetFirmwareVersion(&fw);
|
||||
if (R_SUCCEEDED(rc))
|
||||
hosversionSet(MAKEHOSVERSION(fw.major, fw.minor, fw.micro));
|
||||
setsysExit();
|
||||
}
|
||||
}
|
||||
|
||||
rc = fsInitialize();
|
||||
if (R_FAILED(rc))
|
||||
fatalThrow(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS));
|
||||
|
||||
fsdevMountSdmc();
|
||||
|
||||
rc = pscmInitialize();
|
||||
if R_FAILED(rc)
|
||||
fatalThrow(rc);
|
||||
|
||||
rc = btdrvInitialize();
|
||||
if (R_FAILED(rc))
|
||||
fatalThrow(rc);
|
||||
|
||||
rc = btmInitialize();
|
||||
if (R_FAILED(rc))
|
||||
fatalThrow(rc);
|
||||
|
||||
rc = hiddbgInitialize();
|
||||
if R_FAILED(rc)
|
||||
fatalThrow(rc);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) userAppExit(void);
|
||||
|
||||
void __attribute__((weak)) __appExit(void) {
|
||||
hiddbgExit();
|
||||
btmExit();
|
||||
btdrvExit();
|
||||
pscmExit();
|
||||
fsdevUnmountAll();
|
||||
fsExit();
|
||||
smExit();
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
Result rc;
|
||||
PscPmModule pmModule = {};
|
||||
PscPmState pmState;
|
||||
uint32_t pmFlags;
|
||||
|
||||
/* Init power management */
|
||||
PscPmModuleId pmModuleId = static_cast<PscPmModuleId>(0xbd);
|
||||
const uint16_t deps[] = { PscPmModuleId_Bluetooth }; //PscPmModuleId_Bluetooth, PscPmModuleId_Btm, PscPmModuleId_Hid ??
|
||||
rc = pscmGetPmModule(&pmModule, pmModuleId, deps, sizeof(deps) / sizeof(u16), true);
|
||||
if (R_FAILED(rc))
|
||||
fatalThrow(rc);
|
||||
|
||||
/* Init bluetooth HID */
|
||||
mc::bluetooth::hid::Initialise();
|
||||
mc::log::Write("HID initialised");
|
||||
|
||||
while (!mc::bluetooth::hid::exitFlag) {
|
||||
|
||||
/* Check power management events */
|
||||
if (R_SUCCEEDED(eventWait(&pmModule.event, UINT64_MAX))) {
|
||||
|
||||
rc = pscPmModuleGetRequest(&pmModule, &pmState, &pmFlags);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
switch(pmState) {
|
||||
case PscPmState_Awake:
|
||||
mc::bluetooth::hid::OnWake();
|
||||
break;
|
||||
case PscPmState_ReadyAwaken:
|
||||
mc::bluetooth::hid::PrepareForWake();
|
||||
break;
|
||||
case PscPmState_ReadySleep:
|
||||
mc::bluetooth::hid::PrepareForSleep();
|
||||
break;
|
||||
case PscPmState_ReadyShutdown:
|
||||
case PscPmState_ReadyAwakenCritical:
|
||||
case PscPmState_ReadySleepCritical:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
rc = pscPmModuleAcknowledge(&pmModule, pmState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Cleanup bluetooth HID */
|
||||
mc::bluetooth::hid::Cleanup();
|
||||
|
||||
/* Cleanup power management */
|
||||
eventClose(&pmModule.event);
|
||||
pscPmModuleFinalize(&pmModule);
|
||||
pscPmModuleClose(&pmModule);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
{
|
||||
"name": "bdsm",
|
||||
"title_id": "0x010000000000b100",
|
||||
"title_id_range_min": "0x010000000000b100",
|
||||
"title_id_range_max": "0x010000000000b100",
|
||||
"main_thread_stack_size": "0x00004000",
|
||||
"main_thread_priority": 18,
|
||||
"default_cpu_id": 3,
|
||||
"process_category": 0,
|
||||
"is_retail": true,
|
||||
"pool_partition": 2,
|
||||
"is_64_bit": true,
|
||||
"address_space_type": 1,
|
||||
"filesystem_access": {
|
||||
"permissions": "0xffffffffffffffff"
|
||||
},
|
||||
"service_access": ["*"],
|
||||
"service_host": ["*"],
|
||||
"kernel_capabilities": [{
|
||||
"type": "kernel_flags",
|
||||
"value": {
|
||||
"highest_thread_priority": 63,
|
||||
"lowest_thread_priority": 12,
|
||||
"lowest_cpu_id": 3,
|
||||
"highest_cpu_id": 3
|
||||
}
|
||||
}, {
|
||||
"type": "syscalls",
|
||||
"value": {
|
||||
"svcUnknown": "0x00",
|
||||
"svcSetHeapSize": "0x01",
|
||||
"svcSetMemoryPermission": "0x02",
|
||||
"svcSetMemoryAttribute": "0x03",
|
||||
"svcMapMemory": "0x04",
|
||||
"svcUnmapMemory": "0x05",
|
||||
"svcQueryMemory": "0x06",
|
||||
"svcExitProcess": "0x07",
|
||||
"svcCreateThread": "0x08",
|
||||
"svcStartThread": "0x09",
|
||||
"svcExitThread": "0x0a",
|
||||
"svcSleepThread": "0x0b",
|
||||
"svcGetThreadPriority": "0x0c",
|
||||
"svcSetThreadPriority": "0x0d",
|
||||
"svcGetThreadCoreMask": "0x0e",
|
||||
"svcSetThreadCoreMask": "0x0f",
|
||||
"svcGetCurrentProcessorNumber": "0x10",
|
||||
"svcSignalEvent": "0x11",
|
||||
"svcClearEvent": "0x12",
|
||||
"svcMapSharedMemory": "0x13",
|
||||
"svcUnmapSharedMemory": "0x14",
|
||||
"svcCreateTransferMemory": "0x15",
|
||||
"svcCloseHandle": "0x16",
|
||||
"svcResetSignal": "0x17",
|
||||
"svcWaitSynchronization": "0x18",
|
||||
"svcCancelSynchronization": "0x19",
|
||||
"svcArbitrateLock": "0x1a",
|
||||
"svcArbitrateUnlock": "0x1b",
|
||||
"svcWaitProcessWideKeyAtomic": "0x1c",
|
||||
"svcSignalProcessWideKey": "0x1d",
|
||||
"svcGetSystemTick": "0x1e",
|
||||
"svcConnectToNamedPort": "0x1f",
|
||||
"svcSendSyncRequestLight": "0x20",
|
||||
"svcSendSyncRequest": "0x21",
|
||||
"svcSendSyncRequestWithUserBuffer": "0x22",
|
||||
"svcSendAsyncRequestWithUserBuffer": "0x23",
|
||||
"svcGetProcessId": "0x24",
|
||||
"svcGetThreadId": "0x25",
|
||||
"svcBreak": "0x26",
|
||||
"svcOutputDebugString": "0x27",
|
||||
"svcReturnFromException": "0x28",
|
||||
"svcGetInfo": "0x29",
|
||||
"svcFlushEntireDataCache": "0x2a",
|
||||
"svcFlushDataCache": "0x2b",
|
||||
"svcMapPhysicalMemory": "0x2c",
|
||||
"svcUnmapPhysicalMemory": "0x2d",
|
||||
"svcGetFutureThreadInfo": "0x2e",
|
||||
"svcGetLastThreadInfo": "0x2f",
|
||||
"svcGetResourceLimitLimitValue": "0x30",
|
||||
"svcGetResourceLimitCurrentValue": "0x31",
|
||||
"svcSetThreadActivity": "0x32",
|
||||
"svcGetThreadContext3": "0x33",
|
||||
"svcWaitForAddress": "0x34",
|
||||
"svcSignalToAddress": "0x35",
|
||||
"svcUnknown": "0x36",
|
||||
"svcUnknown": "0x37",
|
||||
"svcUnknown": "0x38",
|
||||
"svcUnknown": "0x39",
|
||||
"svcUnknown": "0x3a",
|
||||
"svcUnknown": "0x3b",
|
||||
"svcDumpInfo": "0x3c",
|
||||
"svcDumpInfoNew": "0x3d",
|
||||
"svcUnknown": "0x3e",
|
||||
"svcUnknown": "0x3f",
|
||||
"svcCreateSession": "0x40",
|
||||
"svcAcceptSession": "0x41",
|
||||
"svcReplyAndReceiveLight": "0x42",
|
||||
"svcReplyAndReceive": "0x43",
|
||||
"svcReplyAndReceiveWithUserBuffer": "0x44",
|
||||
"svcCreateEvent": "0x45",
|
||||
"svcUnknown": "0x46",
|
||||
"svcUnknown": "0x47",
|
||||
"svcMapPhysicalMemoryUnsafe": "0x48",
|
||||
"svcUnmapPhysicalMemoryUnsafe": "0x49",
|
||||
"svcSetUnsafeLimit": "0x4a",
|
||||
"svcCreateCodeMemory": "0x4b",
|
||||
"svcControlCodeMemory": "0x4c",
|
||||
"svcSleepSystem": "0x4d",
|
||||
"svcReadWriteRegister": "0x4e",
|
||||
"svcSetProcessActivity": "0x4f",
|
||||
"svcCreateSharedMemory": "0x50",
|
||||
"svcMapTransferMemory": "0x51",
|
||||
"svcUnmapTransferMemory": "0x52",
|
||||
"svcCreateInterruptEvent": "0x53",
|
||||
"svcQueryPhysicalAddress": "0x54",
|
||||
"svcQueryIoMapping": "0x55",
|
||||
"svcCreateDeviceAddressSpace": "0x56",
|
||||
"svcAttachDeviceAddressSpace": "0x57",
|
||||
"svcDetachDeviceAddressSpace": "0x58",
|
||||
"svcMapDeviceAddressSpaceByForce": "0x59",
|
||||
"svcMapDeviceAddressSpaceAligned": "0x5a",
|
||||
"svcMapDeviceAddressSpace": "0x5b",
|
||||
"svcUnmapDeviceAddressSpace": "0x5c",
|
||||
"svcInvalidateProcessDataCache": "0x5d",
|
||||
"svcStoreProcessDataCache": "0x5e",
|
||||
"svcFlushProcessDataCache": "0x5f",
|
||||
"svcDebugActiveProcess": "0x60",
|
||||
"svcBreakDebugProcess": "0x61",
|
||||
"svcTerminateDebugProcess": "0x62",
|
||||
"svcGetDebugEvent": "0x63",
|
||||
"svcContinueDebugEvent": "0x64",
|
||||
"svcGetProcessList": "0x65",
|
||||
"svcGetThreadList": "0x66",
|
||||
"svcGetDebugThreadContext": "0x67",
|
||||
"svcSetDebugThreadContext": "0x68",
|
||||
"svcQueryDebugProcessMemory": "0x69",
|
||||
"svcReadDebugProcessMemory": "0x6a",
|
||||
"svcWriteDebugProcessMemory": "0x6b",
|
||||
"svcSetHardwareBreakPoint": "0x6c",
|
||||
"svcGetDebugThreadParam": "0x6d",
|
||||
"svcUnknown": "0x6e",
|
||||
"svcGetSystemInfo": "0x6f",
|
||||
"svcCreatePort": "0x70",
|
||||
"svcManageNamedPort": "0x71",
|
||||
"svcConnectToPort": "0x72",
|
||||
"svcSetProcessMemoryPermission": "0x73",
|
||||
"svcMapProcessMemory": "0x74",
|
||||
"svcUnmapProcessMemory": "0x75",
|
||||
"svcQueryProcessMemory": "0x76",
|
||||
"svcMapProcessCodeMemory": "0x77",
|
||||
"svcUnmapProcessCodeMemory": "0x78",
|
||||
"svcCreateProcess": "0x79",
|
||||
"svcStartProcess": "0x7a",
|
||||
"svcTerminateProcess": "0x7b",
|
||||
"svcGetProcessInfo": "0x7c",
|
||||
"svcCreateResourceLimit": "0x7d",
|
||||
"svcSetResourceLimitLimitValue": "0x7e",
|
||||
"svcCallSecureMonitor": "0x7f"
|
||||
}
|
||||
}, {
|
||||
"type": "min_kernel_version",
|
||||
"value": "0x0030"
|
||||
}, {
|
||||
"type": "handle_table_size",
|
||||
"value": 1023
|
||||
}, {
|
||||
"type": "debug_flags",
|
||||
"value": {
|
||||
"allow_debug": false,
|
||||
"force_debug": true
|
||||
}
|
||||
}]
|
||||
}
|
Loading…
Add table
Reference in a new issue