Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
german77 | 34a85b5a1e | |
german77 | 21a98b3fc7 |
|
@ -14,11 +14,21 @@ constexpr Result VibrationInvalidStyleIndex{ErrorModule::HID, 122};
|
|||
constexpr Result VibrationInvalidNpadId{ErrorModule::HID, 123};
|
||||
constexpr Result VibrationDeviceIndexOutOfRange{ErrorModule::HID, 124};
|
||||
constexpr Result InvalidSixAxisFusionRange{ErrorModule::HID, 423};
|
||||
|
||||
constexpr Result ResultMcuInvalidHandle{ErrorModule::HID, 541};
|
||||
constexpr Result ResultMcuNotEnabled{ErrorModule::HID, 542};
|
||||
constexpr Result ResultMcuNoDeviceConnected{ErrorModule::HID, 543};
|
||||
constexpr Result ResultMcuUnknown544{ErrorModule::HID, 544};
|
||||
constexpr Result ResultMcuUnknown546{ErrorModule::HID, 546};
|
||||
constexpr Result ResultMcuUnknown548{ErrorModule::HID, 548};
|
||||
|
||||
constexpr Result NpadIsDualJoycon{ErrorModule::HID, 601};
|
||||
constexpr Result NpadIsSameType{ErrorModule::HID, 602};
|
||||
constexpr Result InvalidNpadId{ErrorModule::HID, 709};
|
||||
constexpr Result NpadNotConnected{ErrorModule::HID, 710};
|
||||
constexpr Result InvalidArraySize{ErrorModule::HID, 715};
|
||||
|
||||
constexpr Result ResultControllerUpdateFailed{ErrorModule::HID, 3201};
|
||||
constexpr Result InvalidPalmaHandle{ErrorModule::HID, 3302};
|
||||
|
||||
} // namespace Service::HID
|
||||
|
@ -29,3 +39,17 @@ constexpr Result InvalidProcessorState{ErrorModule::Irsensor, 78};
|
|||
constexpr Result InvalidIrCameraHandle{ErrorModule::Irsensor, 204};
|
||||
|
||||
} // namespace Service::IRS
|
||||
|
||||
namespace Service::HIDBUS {
|
||||
|
||||
constexpr Result ResultNotEnabled{ErrorModule::HIDBUS, 1};
|
||||
constexpr Result ResultControllerUpdateFailed{ErrorModule::HIDBUS, 3};
|
||||
constexpr Result ResultInvalidBusHandle{ErrorModule::HIDBUS, 4};
|
||||
constexpr Result ResultNoDeviceConnected{ErrorModule::HIDBUS, 5};
|
||||
constexpr Result ResultUknown6{ErrorModule::HIDBUS, 6};
|
||||
constexpr Result ResultPollingRecieveDataNotAvailable{ErrorModule::HIDBUS, 7};
|
||||
constexpr Result ResultDeviceEnabledNotSet{ErrorModule::HIDBUS, 8};
|
||||
constexpr Result ResultBusHandleAlreadyInitialized{ErrorModule::HIDBUS, 10};
|
||||
constexpr Result ResultInvalidBusType{ErrorModule::HIDBUS, 11};
|
||||
|
||||
} // namespace Service::HIDBUS
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "core/hle/kernel/k_readable_event.h"
|
||||
#include "core/hle/kernel/k_shared_memory.h"
|
||||
#include "core/hle/kernel/k_transfer_memory.h"
|
||||
#include "core/hle/service/hid/controllers/npad.h"
|
||||
#include "core/hle/service/hid/errors.h"
|
||||
#include "core/hle/service/hid/hidbus.h"
|
||||
#include "core/hle/service/hid/hidbus/ringcon.h"
|
||||
#include "core/hle/service/hid/hidbus/starlink.h"
|
||||
|
@ -64,25 +66,7 @@ HidBus::~HidBus() {
|
|||
system.CoreTiming().UnscheduleEvent(hidbus_update_event, 0);
|
||||
}
|
||||
|
||||
void HidBus::UpdateHidbus(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
|
||||
if (is_hidbus_enabled) {
|
||||
for (std::size_t i = 0; i < devices.size(); ++i) {
|
||||
if (!devices[i].is_device_initializated) {
|
||||
continue;
|
||||
}
|
||||
auto& device = devices[i].device;
|
||||
device->OnUpdate();
|
||||
auto& cur_entry = hidbus_status.entries[devices[i].handle.internal_index];
|
||||
cur_entry.is_polling_mode = device->IsPollingMode();
|
||||
cur_entry.polling_mode = device->GetPollingMode();
|
||||
cur_entry.is_enabled = device->IsEnabled();
|
||||
|
||||
u8* shared_memory = system.Kernel().GetHidBusSharedMem().GetPointer();
|
||||
std::memcpy(shared_memory + (i * sizeof(HidbusStatusManagerEntry)), &hidbus_status,
|
||||
sizeof(HidbusStatusManagerEntry));
|
||||
}
|
||||
}
|
||||
}
|
||||
void HidBus::UpdateHidbus(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {}
|
||||
|
||||
std::optional<std::size_t> HidBus::GetDeviceIndexFromHandle(BusHandle handle) const {
|
||||
for (std::size_t i = 0; i < devices.size(); ++i) {
|
||||
|
@ -108,45 +92,6 @@ void HidBus::GetBusHandle(HLERequestContext& ctx) {
|
|||
};
|
||||
static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
|
||||
|
||||
const auto parameters{rp.PopRaw<Parameters>()};
|
||||
|
||||
LOG_INFO(Service_HID, "called, npad_id={}, bus_type={}, applet_resource_user_id={}",
|
||||
parameters.npad_id, parameters.bus_type, parameters.applet_resource_user_id);
|
||||
|
||||
bool is_handle_found = 0;
|
||||
std::size_t handle_index = 0;
|
||||
|
||||
for (std::size_t i = 0; i < devices.size(); i++) {
|
||||
const auto& handle = devices[i].handle;
|
||||
if (!handle.is_valid) {
|
||||
continue;
|
||||
}
|
||||
if (static_cast<Core::HID::NpadIdType>(handle.player_number) == parameters.npad_id &&
|
||||
handle.bus_type_id == static_cast<u8>(parameters.bus_type)) {
|
||||
is_handle_found = true;
|
||||
handle_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle not found. Create a new one
|
||||
if (!is_handle_found) {
|
||||
for (std::size_t i = 0; i < devices.size(); i++) {
|
||||
if (devices[i].handle.is_valid) {
|
||||
continue;
|
||||
}
|
||||
devices[i].handle = {
|
||||
.abstracted_pad_id = static_cast<u8>(i),
|
||||
.internal_index = static_cast<u8>(i),
|
||||
.player_number = static_cast<u8>(parameters.npad_id),
|
||||
.bus_type_id = static_cast<u8>(parameters.bus_type),
|
||||
.is_valid = true,
|
||||
};
|
||||
handle_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct OutData {
|
||||
bool is_valid;
|
||||
INSERT_PADDING_BYTES(7);
|
||||
|
@ -154,16 +99,158 @@ void HidBus::GetBusHandle(HLERequestContext& ctx) {
|
|||
};
|
||||
static_assert(sizeof(OutData) == 0x10, "OutData has incorrect size.");
|
||||
|
||||
const OutData out_data{
|
||||
.is_valid = true,
|
||||
.handle = devices[handle_index].handle,
|
||||
};
|
||||
const auto parameters{rp.PopRaw<Parameters>()};
|
||||
|
||||
LOG_INFO(Service_HID, "called, npad_id={}, bus_type={}, applet_resource_user_id={}",
|
||||
parameters.npad_id, parameters.bus_type, parameters.applet_resource_user_id);
|
||||
|
||||
if (parameters.bus_type >= BusType::MaxBusType) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(HIDBUS::ResultInvalidBusType);
|
||||
return;
|
||||
}
|
||||
|
||||
OutData out_data{};
|
||||
out_data.is_valid = GetBusHandleImpl(out_data.handle, parameters.npad_id, parameters.bus_type);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 6};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(out_data);
|
||||
}
|
||||
|
||||
bool HidBus::GetBusHandleImpl(BusHandle& handle, Core::HID::NpadIdType npad_id,
|
||||
BusType bus_type) const {
|
||||
if (!Controller_NPad::IsNpadIdValid(npad_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (MakeBusHandle(handle, npad_id, bus_type).IsError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bus_type == BusType::LeftJoyRail || bus_type == BusType::RightJoyRail) {
|
||||
// TODO: IsBusHandleValid(*npad_id,bus_type)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (bus_type == BusType::InternalBus) {
|
||||
// TODO: IsBusHandleValid(*npad_id,BusType::RightJoyRail)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Result HidBus::MakeBusHandle(BusHandle& handle, Core::HID::NpadIdType npad_id,
|
||||
BusType bus_type) const {
|
||||
u32 abstracted_pad_id{};
|
||||
const Result result = GetAbstractedHidbusPadId(abstracted_pad_id, npad_id, bus_type);
|
||||
|
||||
if (result.IsError()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
u8 internal_index = static_cast<u8>(npad_id);
|
||||
if (bus_type < BusType::MaxBusType) {
|
||||
internal_index = internal_index << 1 | 1;
|
||||
}
|
||||
if (bus_type == BusType::LeftJoyRail) {
|
||||
internal_index = internal_index << 1;
|
||||
}
|
||||
if (npad_id == Core::HID::NpadIdType::Handheld) {
|
||||
switch (bus_type) {
|
||||
case BusType::LeftJoyRail:
|
||||
internal_index = 0x10;
|
||||
break;
|
||||
case BusType::InternalBus:
|
||||
internal_index = 0;
|
||||
break;
|
||||
default:
|
||||
internal_index = 0x11;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handle = {
|
||||
.abstracted_pad_id = abstracted_pad_id,
|
||||
.internal_index = internal_index,
|
||||
.player_number = static_cast<u8>(npad_id) && 0xff,
|
||||
.bus_type_id = static_cast<u8>(bus_type) && 0xff,
|
||||
.is_valid = true, // This is hardcoded on the sysmodule
|
||||
};
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result HidBus::GetAbstractedHidbusPadId(u32& abstracted_pad_id, Core::HID::NpadIdType npad_id,
|
||||
BusType bus_type) const {
|
||||
// This struct is unknown
|
||||
struct LeftData {
|
||||
std::array<u8, 4> data;
|
||||
};
|
||||
|
||||
struct ControllerData {
|
||||
u32 data_1;
|
||||
u32 data_2;
|
||||
u32 is_connected; // ((d + 0x8) >> 1 & 1)
|
||||
u32 abstracted_pad_id;
|
||||
u32 data_5;
|
||||
u32 data_6;
|
||||
u32 data_7;
|
||||
u32 data_8;
|
||||
LeftData left_data;
|
||||
u32 right_data;
|
||||
u32 data_11;
|
||||
u32 data_12;
|
||||
u32 data_13;
|
||||
u32 has_battery; // ((d + 0x3a) & 6) ((d + 0x38) & 0x60000)
|
||||
u32 data_15;
|
||||
u32 data_16;
|
||||
};
|
||||
static_assert(sizeof(ControllerData) == 0x40, "ControllerData has incorrect size.");
|
||||
|
||||
// auto& controller = GetControllerFromNpadIdType(npad_id);
|
||||
const std::array<ControllerData, 5> data_pointer{}; // controller->GetControllerData(5);
|
||||
|
||||
if (data_pointer.size() == 0) {
|
||||
return ResultMcuInvalidHandle;
|
||||
}
|
||||
|
||||
for (const ControllerData& data : data_pointer) {
|
||||
bool is_valid = false;
|
||||
switch (bus_type) {
|
||||
case BusType::LeftJoyRail:
|
||||
if ((data.left_data.data[3] >> 1 & 1) != 0) {
|
||||
is_valid = true;
|
||||
}
|
||||
break;
|
||||
case BusType::RightJoyRail: {
|
||||
if (((data.right_data >> 9 & 1) == 0) && ((data.right_data >> 10 & 1) != 0)) {
|
||||
is_valid = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BusType::InternalBus:
|
||||
if ((data.right_data & 0xe00) == 0x800) {
|
||||
is_valid = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_valid) {
|
||||
abstracted_pad_id = data.abstracted_pad_id;
|
||||
return ResultSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
// STUB this function for now
|
||||
abstracted_pad_id = static_cast<u32>(npad_id);
|
||||
return ResultSuccess;
|
||||
|
||||
return ResultMcuInvalidHandle;
|
||||
}
|
||||
|
||||
void HidBus::IsExternalDeviceConnected(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
||||
|
|
|
@ -95,6 +95,10 @@ private:
|
|||
};
|
||||
|
||||
void GetBusHandle(HLERequestContext& ctx);
|
||||
bool GetBusHandleImpl(BusHandle& handle, Core::HID::NpadIdType npad_id, BusType bus_type) const;
|
||||
Result MakeBusHandle(BusHandle& handle, Core::HID::NpadIdType npad_id, BusType bus_type) const;
|
||||
Result GetAbstractedHidbusPadId(u32& abstracted_pad_id, Core::HID::NpadIdType npad_id,
|
||||
BusType bus_type) const;
|
||||
void IsExternalDeviceConnected(HLERequestContext& ctx);
|
||||
void Initialize(HLERequestContext& ctx);
|
||||
void Finalize(HLERequestContext& ctx);
|
||||
|
|
|
@ -74,7 +74,7 @@ Common::Input::DriverResult JoyconDriver::InitializeDevice() {
|
|||
passive_enabled = false;
|
||||
irs_enabled = false;
|
||||
input_only_device = false;
|
||||
gyro_sensitivity = Joycon::GyroSensitivity::DPS2000;
|
||||
gyro_sensitivity = Joycon::GyroSensitivity::DPS250;
|
||||
gyro_performance = Joycon::GyroPerformance::HZ833;
|
||||
accelerometer_sensitivity = Joycon::AccelerometerSensitivity::G8;
|
||||
accelerometer_performance = Joycon::AccelerometerPerformance::HZ100;
|
||||
|
@ -173,6 +173,12 @@ void JoyconDriver::InputThread(std::stop_token stop_token) {
|
|||
|
||||
void JoyconDriver::OnNewData(std::span<u8> buffer) {
|
||||
const auto report_mode = static_cast<ReportMode>(buffer[0]);
|
||||
std::string str = "";
|
||||
for (u8 dat : buffer) {
|
||||
str += fmt::format("{:02x} ", dat);
|
||||
}
|
||||
|
||||
LOG_CRITICAL(Input, "{}", str);
|
||||
|
||||
// Packages can be a little bit inconsistent. Average the delta time to provide a smoother
|
||||
// motion experience
|
||||
|
@ -203,7 +209,7 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) {
|
|||
if (ring_connected && report_mode == ReportMode::STANDARD_FULL_60HZ) {
|
||||
InputReportActive data{};
|
||||
memcpy(&data, buffer.data(), sizeof(InputReportActive));
|
||||
calibration_protocol->GetRingCalibration(ring_calibration, data.ring_input);
|
||||
//calibration_protocol->GetRingCalibration(ring_calibration, data.ring_input);
|
||||
}
|
||||
|
||||
const RingStatus ring_status{
|
||||
|
@ -264,8 +270,8 @@ Common::Input::DriverResult JoyconDriver::SetPollingMode() {
|
|||
|
||||
if (motion_enabled && supported_features.motion) {
|
||||
generic_protocol->EnableImu(true);
|
||||
generic_protocol->SetImuConfig(gyro_sensitivity, gyro_performance,
|
||||
accelerometer_sensitivity, accelerometer_performance);
|
||||
//generic_protocol->SetImuConfig(gyro_sensitivity, gyro_performance,
|
||||
// accelerometer_sensitivity, accelerometer_performance);
|
||||
} else {
|
||||
generic_protocol->EnableImu(false);
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ Common::Input::DriverResult GenericProtocol::GetControllerType(ControllerType& c
|
|||
|
||||
Common::Input::DriverResult GenericProtocol::EnableImu(bool enable) {
|
||||
ScopedSetBlocking sb(this);
|
||||
const std::array<u8, 1> buffer{static_cast<u8>(enable ? 1 : 0)};
|
||||
const std::array<u8, 1> buffer{static_cast<u8>(enable ? 3 : 0)};
|
||||
return SendSubCommand(SubCommand::ENABLE_IMU, buffer);
|
||||
}
|
||||
|
||||
|
|
|
@ -528,11 +528,9 @@ struct InputReportActive {
|
|||
std::array<u8, 3> left_stick_state;
|
||||
std::array<u8, 3> right_stick_state;
|
||||
u8 vibration_code;
|
||||
std::array<s16, 6 * 2> motion_input;
|
||||
INSERT_PADDING_BYTES(0x2);
|
||||
s16 ring_input;
|
||||
std::array<s16, 6 * 3> motion_input;
|
||||
};
|
||||
static_assert(sizeof(InputReportActive) == 0x29, "InputReportActive is an invalid size");
|
||||
static_assert(sizeof(InputReportActive) > 0x29, "InputReportActive is an invalid size");
|
||||
|
||||
struct InputReportNfcIr {
|
||||
ReportMode report_mode;
|
||||
|
|
|
@ -36,7 +36,7 @@ void JoyconPoller::ReadActiveMode(std::span<u8> buffer, const MotionStatus& moti
|
|||
}
|
||||
|
||||
if (ring_status.is_enabled) {
|
||||
UpdateRing(data.ring_input, ring_status);
|
||||
// UpdateRing(data.ring_input, ring_status);
|
||||
}
|
||||
|
||||
callbacks.on_battery_data(data.battery_status);
|
||||
|
@ -347,14 +347,18 @@ s16 JoyconPoller::GetRawIMUValues(std::size_t sensor, size_t axis,
|
|||
MotionData JoyconPoller::GetMotionInput(const InputReportActive& input,
|
||||
const MotionStatus& motion_status) const {
|
||||
MotionData motion{};
|
||||
for (int i = 0; i < 1; i++) {
|
||||
const auto& accel_cal = motion_calibration.accelerometer;
|
||||
const auto& gyro_cal = motion_calibration.gyro;
|
||||
const s16 raw_accel_x = input.motion_input[1];
|
||||
const s16 raw_accel_y = input.motion_input[0];
|
||||
const s16 raw_accel_z = input.motion_input[2];
|
||||
const s16 raw_gyro_x = input.motion_input[4];
|
||||
const s16 raw_gyro_y = input.motion_input[3];
|
||||
const s16 raw_gyro_z = input.motion_input[5];
|
||||
const s16 raw_accel_x = input.motion_input[1 + (i*6)];
|
||||
const s16 raw_accel_y = input.motion_input[0 + (i * 6)];
|
||||
const s16 raw_accel_z = input.motion_input[2 + (i * 6)];
|
||||
const s16 raw_gyro_x = input.motion_input[4 + (i * 6)];
|
||||
const s16 raw_gyro_y = input.motion_input[3 + (i * 6)];
|
||||
const s16 raw_gyro_z = input.motion_input[5 + (i * 6)];
|
||||
|
||||
LOG_WARNING(Input, "raw sample{}, accel ({},{},{}), gyro ({},{},{})", i, raw_accel_x, raw_accel_y, raw_accel_z,
|
||||
raw_gyro_x, raw_gyro_y, raw_gyro_z);
|
||||
|
||||
motion.delta_timestamp = motion_status.delta_time;
|
||||
motion.accel_x =
|
||||
|
@ -367,6 +371,10 @@ MotionData JoyconPoller::GetMotionInput(const InputReportActive& input,
|
|||
motion.gyro_y = GetGyroValue(raw_gyro_y, gyro_cal[0], motion_status.gyro_sensitivity);
|
||||
motion.gyro_z = GetGyroValue(raw_gyro_z, gyro_cal[2], motion_status.gyro_sensitivity);
|
||||
|
||||
|
||||
LOG_ERROR(Input, "calibrated samples{}, accel ({},{},{}), gyro ({},{},{})", i, motion.accel_x, motion.accel_y,
|
||||
motion.accel_z, motion.gyro_x, motion.gyro_y, motion.gyro_z);
|
||||
}
|
||||
// TODO(German77): Return all three samples data
|
||||
return motion;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue