|
@@ -9,6 +9,7 @@
|
|
|
#include "core/hle/kernel/k_readable_event.h"
|
|
#include "core/hle/kernel/k_readable_event.h"
|
|
|
#include "core/hle/kernel/k_shared_memory.h"
|
|
#include "core/hle/kernel/k_shared_memory.h"
|
|
|
#include "core/hle/kernel/k_transfer_memory.h"
|
|
#include "core/hle/kernel/k_transfer_memory.h"
|
|
|
|
|
+#include "core/hle/service/cmif_serialization.h"
|
|
|
#include "core/hle/service/hid/hidbus.h"
|
|
#include "core/hle/service/hid/hidbus.h"
|
|
|
#include "core/hle/service/ipc_helpers.h"
|
|
#include "core/hle/service/ipc_helpers.h"
|
|
|
#include "core/hle/service/service.h"
|
|
#include "core/hle/service/service.h"
|
|
@@ -22,25 +23,25 @@ namespace Service::HID {
|
|
|
// (15ms, 66Hz)
|
|
// (15ms, 66Hz)
|
|
|
constexpr auto hidbus_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000};
|
|
constexpr auto hidbus_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000};
|
|
|
|
|
|
|
|
-HidBus::HidBus(Core::System& system_)
|
|
|
|
|
|
|
+Hidbus::Hidbus(Core::System& system_)
|
|
|
: ServiceFramework{system_, "hidbus"}, service_context{system_, service_name} {
|
|
: ServiceFramework{system_, "hidbus"}, service_context{system_, service_name} {
|
|
|
|
|
|
|
|
// clang-format off
|
|
// clang-format off
|
|
|
static const FunctionInfo functions[] = {
|
|
static const FunctionInfo functions[] = {
|
|
|
- {1, &HidBus::GetBusHandle, "GetBusHandle"},
|
|
|
|
|
- {2, &HidBus::IsExternalDeviceConnected, "IsExternalDeviceConnected"},
|
|
|
|
|
- {3, &HidBus::Initialize, "Initialize"},
|
|
|
|
|
- {4, &HidBus::Finalize, "Finalize"},
|
|
|
|
|
- {5, &HidBus::EnableExternalDevice, "EnableExternalDevice"},
|
|
|
|
|
- {6, &HidBus::GetExternalDeviceId, "GetExternalDeviceId"},
|
|
|
|
|
- {7, &HidBus::SendCommandAsync, "SendCommandAsync"},
|
|
|
|
|
- {8, &HidBus::GetSendCommandAsynceResult, "GetSendCommandAsynceResult"},
|
|
|
|
|
- {9, &HidBus::SetEventForSendCommandAsycResult, "SetEventForSendCommandAsycResult"},
|
|
|
|
|
- {10, &HidBus::GetSharedMemoryHandle, "GetSharedMemoryHandle"},
|
|
|
|
|
- {11, &HidBus::EnableJoyPollingReceiveMode, "EnableJoyPollingReceiveMode"},
|
|
|
|
|
- {12, &HidBus::DisableJoyPollingReceiveMode, "DisableJoyPollingReceiveMode"},
|
|
|
|
|
|
|
+ {1, C<&Hidbus::GetBusHandle>, "GetBusHandle"},
|
|
|
|
|
+ {2, C<&Hidbus::IsExternalDeviceConnected>, "IsExternalDeviceConnected"},
|
|
|
|
|
+ {3, C<&Hidbus::Initialize>, "Initialize"},
|
|
|
|
|
+ {4, C<&Hidbus::Finalize>, "Finalize"},
|
|
|
|
|
+ {5, C<&Hidbus::EnableExternalDevice>, "EnableExternalDevice"},
|
|
|
|
|
+ {6, C<&Hidbus::GetExternalDeviceId>, "GetExternalDeviceId"},
|
|
|
|
|
+ {7, C<&Hidbus::SendCommandAsync>, "SendCommandAsync"},
|
|
|
|
|
+ {8, C<&Hidbus::GetSendCommandAsynceResult>, "GetSendCommandAsynceResult"},
|
|
|
|
|
+ {9, C<&Hidbus::SetEventForSendCommandAsycResult>, "SetEventForSendCommandAsycResult"},
|
|
|
|
|
+ {10, C<&Hidbus::GetSharedMemoryHandle>, "GetSharedMemoryHandle"},
|
|
|
|
|
+ {11, C<&Hidbus::EnableJoyPollingReceiveMode>, "EnableJoyPollingReceiveMode"},
|
|
|
|
|
+ {12, C<&Hidbus::DisableJoyPollingReceiveMode>, "DisableJoyPollingReceiveMode"},
|
|
|
{13, nullptr, "GetPollingData"},
|
|
{13, nullptr, "GetPollingData"},
|
|
|
- {14, &HidBus::SetStatusManagerType, "SetStatusManagerType"},
|
|
|
|
|
|
|
+ {14, C<&Hidbus::SetStatusManagerType>, "SetStatusManagerType"},
|
|
|
};
|
|
};
|
|
|
// clang-format on
|
|
// clang-format on
|
|
|
|
|
|
|
@@ -60,11 +61,11 @@ HidBus::HidBus(Core::System& system_)
|
|
|
hidbus_update_event);
|
|
hidbus_update_event);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-HidBus::~HidBus() {
|
|
|
|
|
|
|
+Hidbus::~Hidbus() {
|
|
|
system.CoreTiming().UnscheduleEvent(hidbus_update_event);
|
|
system.CoreTiming().UnscheduleEvent(hidbus_update_event);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void HidBus::UpdateHidbus(std::chrono::nanoseconds ns_late) {
|
|
|
|
|
|
|
+void Hidbus::UpdateHidbus(std::chrono::nanoseconds ns_late) {
|
|
|
if (is_hidbus_enabled) {
|
|
if (is_hidbus_enabled) {
|
|
|
for (std::size_t i = 0; i < devices.size(); ++i) {
|
|
for (std::size_t i = 0; i < devices.size(); ++i) {
|
|
|
if (!devices[i].is_device_initialized) {
|
|
if (!devices[i].is_device_initialized) {
|
|
@@ -84,7 +85,7 @@ void HidBus::UpdateHidbus(std::chrono::nanoseconds ns_late) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-std::optional<std::size_t> HidBus::GetDeviceIndexFromHandle(BusHandle handle) const {
|
|
|
|
|
|
|
+std::optional<std::size_t> Hidbus::GetDeviceIndexFromHandle(BusHandle handle) const {
|
|
|
for (std::size_t i = 0; i < devices.size(); ++i) {
|
|
for (std::size_t i = 0; i < devices.size(); ++i) {
|
|
|
const auto& device_handle = devices[i].handle;
|
|
const auto& device_handle = devices[i].handle;
|
|
|
if (handle.abstracted_pad_id == device_handle.abstracted_pad_id &&
|
|
if (handle.abstracted_pad_id == device_handle.abstracted_pad_id &&
|
|
@@ -98,20 +99,11 @@ std::optional<std::size_t> HidBus::GetDeviceIndexFromHandle(BusHandle handle) co
|
|
|
return std::nullopt;
|
|
return std::nullopt;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void HidBus::GetBusHandle(HLERequestContext& ctx) {
|
|
|
|
|
- IPC::RequestParser rp{ctx};
|
|
|
|
|
- struct Parameters {
|
|
|
|
|
- Core::HID::NpadIdType npad_id;
|
|
|
|
|
- INSERT_PADDING_WORDS_NOINIT(1);
|
|
|
|
|
- BusType bus_type;
|
|
|
|
|
- u64 applet_resource_user_id;
|
|
|
|
|
- };
|
|
|
|
|
- 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);
|
|
|
|
|
|
|
+Result Hidbus::GetBusHandle(Out<bool> out_is_valid, Out<BusHandle> out_bus_handle,
|
|
|
|
|
+ Core::HID::NpadIdType npad_id, BusType bus_type,
|
|
|
|
|
+ AppletResourceUserId aruid) {
|
|
|
|
|
+ LOG_INFO(Service_HID, "called, npad_id={}, bus_type={}, applet_resource_user_id={}", npad_id,
|
|
|
|
|
+ bus_type, aruid.pid);
|
|
|
|
|
|
|
|
bool is_handle_found = 0;
|
|
bool is_handle_found = 0;
|
|
|
std::size_t handle_index = 0;
|
|
std::size_t handle_index = 0;
|
|
@@ -121,8 +113,8 @@ void HidBus::GetBusHandle(HLERequestContext& ctx) {
|
|
|
if (!handle.is_valid) {
|
|
if (!handle.is_valid) {
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
- if (static_cast<Core::HID::NpadIdType>(handle.player_number) == parameters.npad_id &&
|
|
|
|
|
- handle.bus_type_id == static_cast<u8>(parameters.bus_type)) {
|
|
|
|
|
|
|
+ if (handle.player_number.As<Core::HID::NpadIdType>() == npad_id &&
|
|
|
|
|
+ handle.bus_type_id == static_cast<u8>(bus_type)) {
|
|
|
is_handle_found = true;
|
|
is_handle_found = true;
|
|
|
handle_index = i;
|
|
handle_index = i;
|
|
|
break;
|
|
break;
|
|
@@ -135,388 +127,231 @@ void HidBus::GetBusHandle(HLERequestContext& ctx) {
|
|
|
if (devices[i].handle.is_valid) {
|
|
if (devices[i].handle.is_valid) {
|
|
|
continue;
|
|
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,
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ devices[i].handle.raw = 0;
|
|
|
|
|
+ devices[i].handle.abstracted_pad_id.Assign(i);
|
|
|
|
|
+ devices[i].handle.internal_index.Assign(i);
|
|
|
|
|
+ devices[i].handle.player_number.Assign(static_cast<u8>(npad_id));
|
|
|
|
|
+ devices[i].handle.bus_type_id.Assign(static_cast<u8>(bus_type));
|
|
|
|
|
+ devices[i].handle.is_valid.Assign(true);
|
|
|
handle_index = i;
|
|
handle_index = i;
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- struct OutData {
|
|
|
|
|
- bool is_valid;
|
|
|
|
|
- INSERT_PADDING_BYTES(7);
|
|
|
|
|
- BusHandle handle;
|
|
|
|
|
- };
|
|
|
|
|
- static_assert(sizeof(OutData) == 0x10, "OutData has incorrect size.");
|
|
|
|
|
-
|
|
|
|
|
- const OutData out_data{
|
|
|
|
|
- .is_valid = true,
|
|
|
|
|
- .handle = devices[handle_index].handle,
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 6};
|
|
|
|
|
- rb.Push(ResultSuccess);
|
|
|
|
|
- rb.PushRaw(out_data);
|
|
|
|
|
|
|
+ *out_is_valid = true;
|
|
|
|
|
+ *out_bus_handle = devices[handle_index].handle;
|
|
|
|
|
+ R_SUCCEED();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void HidBus::IsExternalDeviceConnected(HLERequestContext& ctx) {
|
|
|
|
|
- IPC::RequestParser rp{ctx};
|
|
|
|
|
- const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
|
|
|
|
-
|
|
|
|
|
|
|
+Result Hidbus::IsExternalDeviceConnected(Out<bool> out_is_connected, BusHandle bus_handle) {
|
|
|
LOG_INFO(Service_HID,
|
|
LOG_INFO(Service_HID,
|
|
|
"Called, abstracted_pad_id={}, bus_type={}, internal_index={}, "
|
|
"Called, abstracted_pad_id={}, bus_type={}, internal_index={}, "
|
|
|
"player_number={}, is_valid={}",
|
|
"player_number={}, is_valid={}",
|
|
|
- bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
|
|
|
|
- bus_handle_.player_number, bus_handle_.is_valid);
|
|
|
|
|
|
|
+ bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
|
|
|
|
|
+ bus_handle.player_number, bus_handle.is_valid);
|
|
|
|
|
|
|
|
- const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
|
|
|
|
|
|
+ const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
|
|
|
|
|
|
|
- if (device_index) {
|
|
|
|
|
- const auto& device = devices[device_index.value()].device;
|
|
|
|
|
- const bool is_attached = device->IsDeviceActivated();
|
|
|
|
|
|
|
+ R_UNLESS(device_index.has_value(), ResultUnknown);
|
|
|
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 3};
|
|
|
|
|
- rb.Push(ResultSuccess);
|
|
|
|
|
- rb.Push(is_attached);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- LOG_ERROR(Service_HID, "Invalid handle");
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
|
- rb.Push(ResultUnknown);
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ *out_is_connected = devices[device_index.value()].device->IsDeviceActivated();
|
|
|
|
|
+ R_SUCCEED();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void HidBus::Initialize(HLERequestContext& ctx) {
|
|
|
|
|
- IPC::RequestParser rp{ctx};
|
|
|
|
|
- const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
|
|
|
|
- const auto applet_resource_user_id{rp.Pop<u64>()};
|
|
|
|
|
-
|
|
|
|
|
|
|
+Result Hidbus::Initialize(BusHandle bus_handle, AppletResourceUserId aruid) {
|
|
|
LOG_INFO(Service_HID,
|
|
LOG_INFO(Service_HID,
|
|
|
"called, abstracted_pad_id={} bus_type={} internal_index={} "
|
|
"called, abstracted_pad_id={} bus_type={} internal_index={} "
|
|
|
"player_number={} is_valid={}, applet_resource_user_id={}",
|
|
"player_number={} is_valid={}, applet_resource_user_id={}",
|
|
|
- bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
|
|
|
|
- bus_handle_.player_number, bus_handle_.is_valid, applet_resource_user_id);
|
|
|
|
|
|
|
+ bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
|
|
|
|
|
+ bus_handle.player_number, bus_handle.is_valid, aruid.pid);
|
|
|
|
|
|
|
|
is_hidbus_enabled = true;
|
|
is_hidbus_enabled = true;
|
|
|
|
|
|
|
|
- const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
|
|
|
|
-
|
|
|
|
|
- if (device_index) {
|
|
|
|
|
- const auto entry_index = devices[device_index.value()].handle.internal_index;
|
|
|
|
|
- auto& cur_entry = hidbus_status.entries[entry_index];
|
|
|
|
|
-
|
|
|
|
|
- if (bus_handle_.internal_index == 0 && Settings::values.enable_ring_controller) {
|
|
|
|
|
- MakeDevice<RingController>(bus_handle_);
|
|
|
|
|
- devices[device_index.value()].is_device_initialized = true;
|
|
|
|
|
- devices[device_index.value()].device->ActivateDevice();
|
|
|
|
|
- cur_entry.is_in_focus = true;
|
|
|
|
|
- cur_entry.is_connected = true;
|
|
|
|
|
- cur_entry.is_connected_result = ResultSuccess;
|
|
|
|
|
- cur_entry.is_enabled = false;
|
|
|
|
|
- cur_entry.is_polling_mode = false;
|
|
|
|
|
- } else {
|
|
|
|
|
- MakeDevice<HidbusStubbed>(bus_handle_);
|
|
|
|
|
- devices[device_index.value()].is_device_initialized = true;
|
|
|
|
|
- cur_entry.is_in_focus = true;
|
|
|
|
|
- cur_entry.is_connected = false;
|
|
|
|
|
- cur_entry.is_connected_result = ResultSuccess;
|
|
|
|
|
- cur_entry.is_enabled = false;
|
|
|
|
|
- cur_entry.is_polling_mode = false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status,
|
|
|
|
|
- sizeof(hidbus_status));
|
|
|
|
|
-
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
|
- rb.Push(ResultSuccess);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
|
|
|
|
|
|
|
- LOG_ERROR(Service_HID, "Invalid handle");
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
|
- rb.Push(ResultUnknown);
|
|
|
|
|
- return;
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ R_UNLESS(device_index.has_value(), ResultUnknown);
|
|
|
|
|
|
|
|
-void HidBus::Finalize(HLERequestContext& ctx) {
|
|
|
|
|
- IPC::RequestParser rp{ctx};
|
|
|
|
|
- const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
|
|
|
|
- const auto applet_resource_user_id{rp.Pop<u64>()};
|
|
|
|
|
-
|
|
|
|
|
- LOG_INFO(Service_HID,
|
|
|
|
|
- "called, abstracted_pad_id={}, bus_type={}, internal_index={}, "
|
|
|
|
|
- "player_number={}, is_valid={}, applet_resource_user_id={}",
|
|
|
|
|
- bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
|
|
|
|
- bus_handle_.player_number, bus_handle_.is_valid, applet_resource_user_id);
|
|
|
|
|
-
|
|
|
|
|
- const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
|
|
|
|
-
|
|
|
|
|
- if (device_index) {
|
|
|
|
|
- const auto entry_index = devices[device_index.value()].handle.internal_index;
|
|
|
|
|
- auto& cur_entry = hidbus_status.entries[entry_index];
|
|
|
|
|
- auto& device = devices[device_index.value()].device;
|
|
|
|
|
- devices[device_index.value()].is_device_initialized = false;
|
|
|
|
|
- device->DeactivateDevice();
|
|
|
|
|
|
|
+ const auto entry_index = devices[device_index.value()].handle.internal_index;
|
|
|
|
|
+ auto& cur_entry = hidbus_status.entries[entry_index];
|
|
|
|
|
|
|
|
|
|
+ if (bus_handle.internal_index == 0 && Settings::values.enable_ring_controller) {
|
|
|
|
|
+ MakeDevice<RingController>(bus_handle);
|
|
|
|
|
+ devices[device_index.value()].is_device_initialized = true;
|
|
|
|
|
+ devices[device_index.value()].device->ActivateDevice();
|
|
|
|
|
+ cur_entry.is_in_focus = true;
|
|
|
|
|
+ cur_entry.is_connected = true;
|
|
|
|
|
+ cur_entry.is_connected_result = ResultSuccess;
|
|
|
|
|
+ cur_entry.is_enabled = false;
|
|
|
|
|
+ cur_entry.is_polling_mode = false;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ MakeDevice<HidbusStubbed>(bus_handle);
|
|
|
|
|
+ devices[device_index.value()].is_device_initialized = true;
|
|
|
cur_entry.is_in_focus = true;
|
|
cur_entry.is_in_focus = true;
|
|
|
cur_entry.is_connected = false;
|
|
cur_entry.is_connected = false;
|
|
|
cur_entry.is_connected_result = ResultSuccess;
|
|
cur_entry.is_connected_result = ResultSuccess;
|
|
|
cur_entry.is_enabled = false;
|
|
cur_entry.is_enabled = false;
|
|
|
cur_entry.is_polling_mode = false;
|
|
cur_entry.is_polling_mode = false;
|
|
|
- std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status,
|
|
|
|
|
- sizeof(hidbus_status));
|
|
|
|
|
-
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
|
- rb.Push(ResultSuccess);
|
|
|
|
|
- return;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- LOG_ERROR(Service_HID, "Invalid handle");
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
|
- rb.Push(ResultUnknown);
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status,
|
|
|
|
|
+ sizeof(hidbus_status));
|
|
|
|
|
+ R_SUCCEED();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void HidBus::EnableExternalDevice(HLERequestContext& ctx) {
|
|
|
|
|
- IPC::RequestParser rp{ctx};
|
|
|
|
|
- struct Parameters {
|
|
|
|
|
- bool enable;
|
|
|
|
|
- INSERT_PADDING_BYTES_NOINIT(7);
|
|
|
|
|
- BusHandle bus_handle;
|
|
|
|
|
- u64 inval;
|
|
|
|
|
- u64 applet_resource_user_id;
|
|
|
|
|
- };
|
|
|
|
|
- static_assert(sizeof(Parameters) == 0x20, "Parameters has incorrect size.");
|
|
|
|
|
-
|
|
|
|
|
- const auto parameters{rp.PopRaw<Parameters>()};
|
|
|
|
|
|
|
+Result Hidbus::Finalize(BusHandle bus_handle, AppletResourceUserId aruid) {
|
|
|
|
|
+ LOG_INFO(Service_HID,
|
|
|
|
|
+ "called, abstracted_pad_id={}, bus_type={}, internal_index={}, "
|
|
|
|
|
+ "player_number={}, is_valid={}, applet_resource_user_id={}",
|
|
|
|
|
+ bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
|
|
|
|
|
+ bus_handle.player_number, bus_handle.is_valid, aruid.pid);
|
|
|
|
|
+
|
|
|
|
|
+ const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
|
|
|
|
+
|
|
|
|
|
+ R_UNLESS(device_index.has_value(), ResultUnknown);
|
|
|
|
|
+
|
|
|
|
|
+ const auto entry_index = devices[device_index.value()].handle.internal_index;
|
|
|
|
|
+ auto& cur_entry = hidbus_status.entries[entry_index];
|
|
|
|
|
+ auto& device = devices[device_index.value()].device;
|
|
|
|
|
+ devices[device_index.value()].is_device_initialized = false;
|
|
|
|
|
+ device->DeactivateDevice();
|
|
|
|
|
+
|
|
|
|
|
+ cur_entry.is_in_focus = true;
|
|
|
|
|
+ cur_entry.is_connected = false;
|
|
|
|
|
+ cur_entry.is_connected_result = ResultSuccess;
|
|
|
|
|
+ cur_entry.is_enabled = false;
|
|
|
|
|
+ cur_entry.is_polling_mode = false;
|
|
|
|
|
+ std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status,
|
|
|
|
|
+ sizeof(hidbus_status));
|
|
|
|
|
+ R_SUCCEED();
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
+Result Hidbus::EnableExternalDevice(bool is_enabled, BusHandle bus_handle, u64 inval,
|
|
|
|
|
+ AppletResourceUserId aruid) {
|
|
|
LOG_DEBUG(Service_HID,
|
|
LOG_DEBUG(Service_HID,
|
|
|
"called, enable={}, abstracted_pad_id={}, bus_type={}, internal_index={}, "
|
|
"called, enable={}, abstracted_pad_id={}, bus_type={}, internal_index={}, "
|
|
|
"player_number={}, is_valid={}, inval={}, applet_resource_user_id{}",
|
|
"player_number={}, is_valid={}, inval={}, applet_resource_user_id{}",
|
|
|
- parameters.enable, parameters.bus_handle.abstracted_pad_id,
|
|
|
|
|
- parameters.bus_handle.bus_type_id, parameters.bus_handle.internal_index,
|
|
|
|
|
- parameters.bus_handle.player_number, parameters.bus_handle.is_valid, parameters.inval,
|
|
|
|
|
- parameters.applet_resource_user_id);
|
|
|
|
|
-
|
|
|
|
|
- const auto device_index = GetDeviceIndexFromHandle(parameters.bus_handle);
|
|
|
|
|
-
|
|
|
|
|
- if (device_index) {
|
|
|
|
|
- auto& device = devices[device_index.value()].device;
|
|
|
|
|
- device->Enable(parameters.enable);
|
|
|
|
|
|
|
+ is_enabled, bus_handle.abstracted_pad_id, bus_handle.bus_type_id,
|
|
|
|
|
+ bus_handle.internal_index, bus_handle.player_number, bus_handle.is_valid, inval,
|
|
|
|
|
+ aruid.pid);
|
|
|
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
|
- rb.Push(ResultSuccess);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
|
|
|
|
|
|
|
- LOG_ERROR(Service_HID, "Invalid handle");
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
|
- rb.Push(ResultUnknown);
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ R_UNLESS(device_index.has_value(), ResultUnknown);
|
|
|
|
|
+ devices[device_index.value()].device->Enable(is_enabled);
|
|
|
|
|
+ R_SUCCEED();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void HidBus::GetExternalDeviceId(HLERequestContext& ctx) {
|
|
|
|
|
- IPC::RequestParser rp{ctx};
|
|
|
|
|
- const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
|
|
|
|
-
|
|
|
|
|
|
|
+Result Hidbus::GetExternalDeviceId(Out<u32> out_device_id, BusHandle bus_handle) {
|
|
|
LOG_DEBUG(Service_HID,
|
|
LOG_DEBUG(Service_HID,
|
|
|
"called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, "
|
|
"called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, "
|
|
|
"is_valid={}",
|
|
"is_valid={}",
|
|
|
- bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
|
|
|
|
- bus_handle_.player_number, bus_handle_.is_valid);
|
|
|
|
|
-
|
|
|
|
|
- const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
|
|
|
|
-
|
|
|
|
|
- if (device_index) {
|
|
|
|
|
- const auto& device = devices[device_index.value()].device;
|
|
|
|
|
- u32 device_id = device->GetDeviceId();
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 3};
|
|
|
|
|
- rb.Push(ResultSuccess);
|
|
|
|
|
- rb.Push<u32>(device_id);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
|
|
|
|
|
+ bus_handle.player_number, bus_handle.is_valid);
|
|
|
|
|
|
|
|
- LOG_ERROR(Service_HID, "Invalid handle");
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
|
- rb.Push(ResultUnknown);
|
|
|
|
|
- return;
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
|
|
|
|
|
|
|
-void HidBus::SendCommandAsync(HLERequestContext& ctx) {
|
|
|
|
|
- IPC::RequestParser rp{ctx};
|
|
|
|
|
- const auto data = ctx.ReadBuffer();
|
|
|
|
|
- const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
|
|
|
|
|
|
+ R_UNLESS(device_index.has_value(), ResultUnknown);
|
|
|
|
|
|
|
|
|
|
+ *out_device_id = devices[device_index.value()].device->GetDeviceId();
|
|
|
|
|
+ R_SUCCEED();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+Result Hidbus::SendCommandAsync(BusHandle bus_handle,
|
|
|
|
|
+ InBuffer<BufferAttr_HipcAutoSelect> buffer_data) {
|
|
|
LOG_DEBUG(Service_HID,
|
|
LOG_DEBUG(Service_HID,
|
|
|
"called, data_size={}, abstracted_pad_id={}, bus_type={}, internal_index={}, "
|
|
"called, data_size={}, abstracted_pad_id={}, bus_type={}, internal_index={}, "
|
|
|
"player_number={}, is_valid={}",
|
|
"player_number={}, is_valid={}",
|
|
|
- data.size(), bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id,
|
|
|
|
|
- bus_handle_.internal_index, bus_handle_.player_number, bus_handle_.is_valid);
|
|
|
|
|
|
|
+ buffer_data.size(), bus_handle.abstracted_pad_id, bus_handle.bus_type_id,
|
|
|
|
|
+ bus_handle.internal_index, bus_handle.player_number, bus_handle.is_valid);
|
|
|
|
|
|
|
|
- const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
|
|
|
|
|
|
+ const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
|
|
|
|
|
|
|
- if (device_index) {
|
|
|
|
|
- auto& device = devices[device_index.value()].device;
|
|
|
|
|
- device->SetCommand(data);
|
|
|
|
|
-
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
|
- rb.Push(ResultSuccess);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ R_UNLESS(device_index.has_value(), ResultUnknown);
|
|
|
|
|
|
|
|
- LOG_ERROR(Service_HID, "Invalid handle");
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
|
- rb.Push(ResultUnknown);
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ devices[device_index.value()].device->SetCommand(buffer_data);
|
|
|
|
|
+ R_SUCCEED();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-void HidBus::GetSendCommandAsynceResult(HLERequestContext& ctx) {
|
|
|
|
|
- IPC::RequestParser rp{ctx};
|
|
|
|
|
- const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
|
|
|
|
-
|
|
|
|
|
|
|
+Result Hidbus::GetSendCommandAsynceResult(Out<u64> out_data_size, BusHandle bus_handle,
|
|
|
|
|
+ OutBuffer<BufferAttr_HipcAutoSelect> out_buffer_data) {
|
|
|
LOG_DEBUG(Service_HID,
|
|
LOG_DEBUG(Service_HID,
|
|
|
"called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, "
|
|
"called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, "
|
|
|
"is_valid={}",
|
|
"is_valid={}",
|
|
|
- bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
|
|
|
|
- bus_handle_.player_number, bus_handle_.is_valid);
|
|
|
|
|
-
|
|
|
|
|
- const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
|
|
|
|
|
|
+ bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
|
|
|
|
|
+ bus_handle.player_number, bus_handle.is_valid);
|
|
|
|
|
|
|
|
- if (device_index) {
|
|
|
|
|
- const auto& device = devices[device_index.value()].device;
|
|
|
|
|
- const std::vector<u8> data = device->GetReply();
|
|
|
|
|
- const u64 data_size = ctx.WriteBuffer(data);
|
|
|
|
|
|
|
+ const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
|
|
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 4};
|
|
|
|
|
- rb.Push(ResultSuccess);
|
|
|
|
|
- rb.Push<u64>(data_size);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ R_UNLESS(device_index.has_value(), ResultUnknown);
|
|
|
|
|
|
|
|
- LOG_ERROR(Service_HID, "Invalid handle");
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
|
- rb.Push(ResultUnknown);
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ *out_data_size = devices[device_index.value()].device->GetReply(out_buffer_data);
|
|
|
|
|
+ R_SUCCEED();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-void HidBus::SetEventForSendCommandAsycResult(HLERequestContext& ctx) {
|
|
|
|
|
- IPC::RequestParser rp{ctx};
|
|
|
|
|
- const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
|
|
|
|
-
|
|
|
|
|
|
|
+Result Hidbus::SetEventForSendCommandAsycResult(OutCopyHandle<Kernel::KReadableEvent> out_event,
|
|
|
|
|
+ BusHandle bus_handle) {
|
|
|
LOG_INFO(Service_HID,
|
|
LOG_INFO(Service_HID,
|
|
|
"called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, "
|
|
"called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, "
|
|
|
"is_valid={}",
|
|
"is_valid={}",
|
|
|
- bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
|
|
|
|
- bus_handle_.player_number, bus_handle_.is_valid);
|
|
|
|
|
|
|
+ bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
|
|
|
|
|
+ bus_handle.player_number, bus_handle.is_valid);
|
|
|
|
|
|
|
|
- const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
|
|
|
|
|
|
+ const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
|
|
|
|
|
|
|
- if (device_index) {
|
|
|
|
|
- const auto& device = devices[device_index.value()].device;
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
|
|
|
- rb.Push(ResultSuccess);
|
|
|
|
|
- rb.PushCopyObjects(device->GetSendCommandAsycEvent());
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ R_UNLESS(device_index.has_value(), ResultUnknown);
|
|
|
|
|
|
|
|
- LOG_ERROR(Service_HID, "Invalid handle");
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
|
- rb.Push(ResultUnknown);
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ *out_event = &devices[device_index.value()].device->GetSendCommandAsycEvent();
|
|
|
|
|
+ R_SUCCEED();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-void HidBus::GetSharedMemoryHandle(HLERequestContext& ctx) {
|
|
|
|
|
|
|
+Result Hidbus::GetSharedMemoryHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory) {
|
|
|
LOG_DEBUG(Service_HID, "called");
|
|
LOG_DEBUG(Service_HID, "called");
|
|
|
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
|
|
|
- rb.Push(ResultSuccess);
|
|
|
|
|
- rb.PushCopyObjects(&system.Kernel().GetHidBusSharedMem());
|
|
|
|
|
|
|
+ *out_shared_memory = &system.Kernel().GetHidBusSharedMem();
|
|
|
|
|
+ R_SUCCEED();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void HidBus::EnableJoyPollingReceiveMode(HLERequestContext& ctx) {
|
|
|
|
|
- IPC::RequestParser rp{ctx};
|
|
|
|
|
- const auto t_mem_size{rp.Pop<u32>()};
|
|
|
|
|
- const auto t_mem_handle{ctx.GetCopyHandle(0)};
|
|
|
|
|
- const auto polling_mode_{rp.PopEnum<JoyPollingMode>()};
|
|
|
|
|
- const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
|
|
|
|
-
|
|
|
|
|
|
|
+Result Hidbus::EnableJoyPollingReceiveMode(u32 t_mem_size, JoyPollingMode polling_mode,
|
|
|
|
|
+ BusHandle bus_handle,
|
|
|
|
|
+ InCopyHandle<Kernel::KTransferMemory> t_mem) {
|
|
|
ASSERT_MSG(t_mem_size == 0x1000, "t_mem_size is not 0x1000 bytes");
|
|
ASSERT_MSG(t_mem_size == 0x1000, "t_mem_size is not 0x1000 bytes");
|
|
|
-
|
|
|
|
|
- auto t_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(t_mem_handle);
|
|
|
|
|
-
|
|
|
|
|
- if (t_mem.IsNull()) {
|
|
|
|
|
- LOG_ERROR(Service_HID, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle);
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
|
- rb.Push(ResultUnknown);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- ASSERT_MSG(t_mem->GetSize() == 0x1000, "t_mem has incorrect size");
|
|
|
|
|
|
|
+ ASSERT_MSG(t_mem->GetSize() == t_mem_size, "t_mem has incorrect size");
|
|
|
|
|
|
|
|
LOG_INFO(Service_HID,
|
|
LOG_INFO(Service_HID,
|
|
|
- "called, t_mem_handle=0x{:08X}, polling_mode={}, abstracted_pad_id={}, bus_type={}, "
|
|
|
|
|
|
|
+ "called, polling_mode={}, abstracted_pad_id={}, bus_type={}, "
|
|
|
"internal_index={}, player_number={}, is_valid={}",
|
|
"internal_index={}, player_number={}, is_valid={}",
|
|
|
- t_mem_handle, polling_mode_, bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id,
|
|
|
|
|
- bus_handle_.internal_index, bus_handle_.player_number, bus_handle_.is_valid);
|
|
|
|
|
|
|
+ polling_mode, bus_handle.abstracted_pad_id, bus_handle.bus_type_id,
|
|
|
|
|
+ bus_handle.internal_index, bus_handle.player_number, bus_handle.is_valid);
|
|
|
|
|
|
|
|
- const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
|
|
|
|
|
|
+ const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
|
|
|
|
|
|
|
- if (device_index) {
|
|
|
|
|
- auto& device = devices[device_index.value()].device;
|
|
|
|
|
- device->SetPollingMode(polling_mode_);
|
|
|
|
|
- device->SetTransferMemoryAddress(t_mem->GetSourceAddress());
|
|
|
|
|
|
|
+ R_UNLESS(device_index.has_value(), ResultUnknown);
|
|
|
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
|
- rb.Push(ResultSuccess);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- LOG_ERROR(Service_HID, "Invalid handle");
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
|
- rb.Push(ResultUnknown);
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ auto& device = devices[device_index.value()].device;
|
|
|
|
|
+ device->SetPollingMode(polling_mode);
|
|
|
|
|
+ device->SetTransferMemoryAddress(t_mem->GetSourceAddress());
|
|
|
|
|
+ R_SUCCEED();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void HidBus::DisableJoyPollingReceiveMode(HLERequestContext& ctx) {
|
|
|
|
|
- IPC::RequestParser rp{ctx};
|
|
|
|
|
- const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
|
|
|
|
-
|
|
|
|
|
|
|
+Result Hidbus::DisableJoyPollingReceiveMode(BusHandle bus_handle) {
|
|
|
LOG_INFO(Service_HID,
|
|
LOG_INFO(Service_HID,
|
|
|
"called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, "
|
|
"called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, "
|
|
|
"is_valid={}",
|
|
"is_valid={}",
|
|
|
- bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
|
|
|
|
- bus_handle_.player_number, bus_handle_.is_valid);
|
|
|
|
|
|
|
+ bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
|
|
|
|
|
+ bus_handle.player_number, bus_handle.is_valid);
|
|
|
|
|
|
|
|
- const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
|
|
|
|
|
|
+ const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
|
|
|
|
|
|
|
- if (device_index) {
|
|
|
|
|
- auto& device = devices[device_index.value()].device;
|
|
|
|
|
- device->DisablePollingMode();
|
|
|
|
|
-
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
|
- rb.Push(ResultSuccess);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ R_UNLESS(device_index.has_value(), ResultUnknown);
|
|
|
|
|
|
|
|
- LOG_ERROR(Service_HID, "Invalid handle");
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
|
- rb.Push(ResultUnknown);
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ auto& device = devices[device_index.value()].device;
|
|
|
|
|
+ device->DisablePollingMode();
|
|
|
|
|
+ R_SUCCEED();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void HidBus::SetStatusManagerType(HLERequestContext& ctx) {
|
|
|
|
|
- IPC::RequestParser rp{ctx};
|
|
|
|
|
- const auto manager_type{rp.PopEnum<StatusManagerType>()};
|
|
|
|
|
-
|
|
|
|
|
|
|
+Result Hidbus::SetStatusManagerType(StatusManagerType manager_type) {
|
|
|
LOG_WARNING(Service_HID, "(STUBBED) called, manager_type={}", manager_type);
|
|
LOG_WARNING(Service_HID, "(STUBBED) called, manager_type={}", manager_type);
|
|
|
-
|
|
|
|
|
- IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
|
- rb.Push(ResultSuccess);
|
|
|
|
|
|
|
+ R_SUCCEED();
|
|
|
};
|
|
};
|
|
|
|
|
+
|
|
|
} // namespace Service::HID
|
|
} // namespace Service::HID
|