strat: use sf::NativeHandle for ipc templating

This commit is contained in:
Michael Scire
2021-10-05 00:11:36 -07:00
parent d97e97258e
commit 69777cf792
41 changed files with 447 additions and 454 deletions

View File

@@ -20,7 +20,7 @@
#include <stratosphere/sf.hpp>
#define AMS_LDR_I_PROCESS_MANAGER_INTERFACE_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, CreateProcess, (sf::OutMoveHandle proc_h, ldr::PinId id, u32 flags, sf::CopyHandle reslimit_h), (proc_h, id, flags, reslimit_h)) \
AMS_SF_METHOD_INFO(C, H, 0, Result, CreateProcess, (sf::OutMoveHandle proc_h, ldr::PinId id, u32 flags, sf::CopyHandle &&reslimit_h), (proc_h, id, flags, std::move(reslimit_h))) \
AMS_SF_METHOD_INFO(C, H, 1, Result, GetProgramInfo, (sf::Out<ldr::ProgramInfo> out_program_info, const ncm::ProgramLocation &loc), (out_program_info, loc)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, PinProgram, (sf::Out<ldr::PinId> out_id, const ncm::ProgramLocation &loc), (out_id, loc)) \
AMS_SF_METHOD_INFO(C, H, 3, Result, UnpinProgram, (ldr::PinId id), (id)) \

View File

@@ -46,9 +46,12 @@ namespace ams::pgl {
explicit EventObserverByCmif(ams::sf::SharedPointer<pgl::sf::IEventObserver> intf) : m_cmif_interface(intf) { /* ... */ }
public:
virtual Result GetSystemEvent(os::SystemEventType *out) override {
ams::sf::CopyHandle handle;
ams::sf::NativeHandle handle;
R_TRY(m_cmif_interface->GetProcessEventHandle(std::addressof(handle)));
os::AttachSystemEvent(out, handle.GetValue(), true, svc::InvalidHandle, false, os::EventClearMode_AutoClear);
os::AttachReadableHandleToSystemEvent(out, handle.GetOsHandle(), handle.IsManaged(), os::EventClearMode_AutoClear);
handle.Detach();
return ResultSuccess();
}
@@ -70,7 +73,7 @@ namespace ams::pgl {
virtual Result GetSystemEvent(os::SystemEventType *out) override {
ams::tipc::CopyHandle handle;
R_TRY(m_tipc_interface.GetProcessEventHandle(std::addressof(handle)));
os::AttachSystemEvent(out, handle.GetValue(), true, svc::InvalidHandle, false, os::EventClearMode_AutoClear);
os::AttachReadableHandleToSystemEvent(out, handle.GetValue(), true, os::EventClearMode_AutoClear);
return ResultSuccess();
}

View File

@@ -24,7 +24,7 @@
AMS_SF_METHOD_INFO(C, H, 1, Result, UnmapManualLoadModuleMemory, (const sf::ClientProcessId &client_pid, u64 nro_address), (client_pid, nro_address)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, RegisterModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size), (client_pid, nrr_address, nrr_size)) \
AMS_SF_METHOD_INFO(C, H, 3, Result, UnregisterModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address), (client_pid, nrr_address)) \
AMS_SF_METHOD_INFO(C, H, 4, Result, RegisterProcessHandle, (const sf::ClientProcessId &client_pid, sf::CopyHandle process_h), (client_pid, process_h)) \
AMS_SF_METHOD_INFO(C, H, 10, Result, RegisterProcessModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size, sf::CopyHandle process_h), (client_pid, nrr_address, nrr_size, process_h), hos::Version_7_0_0)
AMS_SF_METHOD_INFO(C, H, 4, Result, RegisterProcessHandle, (const sf::ClientProcessId &client_pid, sf::CopyHandle &&process_h), (client_pid, std::move(process_h))) \
AMS_SF_METHOD_INFO(C, H, 10, Result, RegisterProcessModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size, sf::CopyHandle &&process_h), (client_pid, nrr_address, nrr_size, std::move(process_h)), hos::Version_7_0_0)
AMS_SF_DEFINE_INTERFACE(ams::ro::impl, IRoInterface, AMS_RO_I_RO_INTERFACE_INTERFACE_INFO)

View File

@@ -19,7 +19,7 @@
#include <stratosphere/sf/sf_service_object.hpp>
#include <stratosphere/sf/sf_out.hpp>
#include <stratosphere/sf/sf_buffers.hpp>
#include <stratosphere/sf/sf_handles.hpp>
#include <stratosphere/sf/sf_native_handle.hpp>
#include <stratosphere/sf/cmif/sf_cmif_pointer_and_size.hpp>
#include <stratosphere/sf/cmif/sf_cmif_service_dispatch.hpp>
#include <stratosphere/sf/cmif/sf_cmif_service_object_holder.hpp>
@@ -199,15 +199,18 @@ namespace ams::sf::impl {
template<typename T>
constexpr inline ArgumentType GetArgumentType = [] {
static_assert(!std::same_as<T, sf::NativeHandle>);
static_assert(!std::same_as<T, sf::Out<sf::NativeHandle>>);
if constexpr (sf::IsBuffer<T>) {
return ArgumentType::Buffer;
} else if constexpr (IsInObject<T>::value) {
return ArgumentType::InObject;
} else if constexpr (std::is_base_of<sf::impl::OutObjectTag, T>::value) {
return ArgumentType::OutObject;
} else if constexpr (std::is_base_of<sf::impl::InHandleTag, T>::value) {
} else if constexpr (std::same_as<T, sf::CopyHandle> || std::same_as<T, sf::MoveHandle>) {
return ArgumentType::InHandle;
} else if constexpr (std::is_base_of<sf::impl::OutHandleTag, T>::value) {
} else if constexpr (std::same_as<T, sf::OutCopyHandle> || std::same_as<T, sf::OutMoveHandle>) {
return ArgumentType::OutHandle;
} else if constexpr (std::is_base_of<sf::impl::OutBaseTag, T>::value) {
return ArgumentType::OutData;
@@ -413,7 +416,7 @@ namespace ams::sf::impl {
};
template<typename T>
using DecayForCommandMetaArguments = typename std::conditional<sf::IsLargeData<typename std::decay<T>::type> && !std::is_base_of<impl::OutBaseTag, typename std::decay<T>::type>::value, T, typename std::decay<T>::type>::type;
using DecayForCommandMetaArguments = typename std::conditional<(sf::IsLargeData<typename std::decay<T>::type> && !std::is_base_of<impl::OutBaseTag, typename std::decay<T>::type>::value), T, typename std::conditional<(std::same_as<T, sf::MoveHandle &&> || std::same_as<T, sf::CopyHandle &&>), typename std::decay<T>::type &, typename std::decay<T>::type>::type>::type;
template<typename... Arguments>
struct CommandMetaInfo {
@@ -625,38 +628,57 @@ namespace ams::sf::impl {
};
template<size_t _NumMove, size_t _NumCopy>
class OutHandleHolder {
class InHandleHolder {
public:
static constexpr size_t NumMove = _NumMove;
static constexpr size_t NumCopy = _NumCopy;
private:
MoveHandle move_handles[NumMove];
CopyHandle copy_handles[NumCopy];
bool copy_managed[NumCopy];
public:
constexpr OutHandleHolder() : move_handles(), copy_handles(), copy_managed() { /* ... */ }
constexpr InHandleHolder() : move_handles(), copy_handles() { /* ... */ }
template<size_t Index>
constexpr inline MoveHandle *GetMoveHandlePointer() {
constexpr inline MoveHandle &SetMoveHandle(os::NativeHandle os_handle) {
static_assert(Index < NumMove);
move_handles[Index] = sf::NativeHandle(os_handle, true);
return move_handles[Index];
}
template<size_t Index>
constexpr inline CopyHandle &SetCopyHandle(os::NativeHandle os_handle) {
static_assert(Index < NumCopy);
copy_handles[Index] = sf::NativeHandle(os_handle, true);
return copy_handles[Index];
}
};
template<size_t _NumMove, size_t _NumCopy>
class OutHandleHolder {
public:
static constexpr size_t NumMove = _NumMove;
static constexpr size_t NumCopy = _NumCopy;
private:
NativeHandle move_handles[NumMove];
NativeHandle copy_handles[NumCopy];
public:
constexpr OutHandleHolder() : move_handles(), copy_handles() { /* ... */ }
template<size_t Index>
constexpr inline NativeHandle *GetMoveHandlePointer() {
static_assert(Index < NumMove, "Index < NumMove");
return &move_handles[Index];
return move_handles + Index;
}
template<size_t Index>
constexpr inline CopyHandle *GetCopyHandlePointer() {
constexpr inline NativeHandle *GetCopyHandlePointer() {
static_assert(Index < NumCopy, "Index < NumCopy");
return &copy_handles[Index];
}
template<size_t Index>
constexpr inline bool *GetCopyHandleManagedPointer() {
static_assert(Index < NumCopy, "Index < NumCopy");
return &copy_managed[Index];
return copy_handles + Index;
}
constexpr inline void CopyTo(const cmif::ServiceDispatchContext &ctx, const HipcRequest &response, const size_t num_out_object_handles) {
ctx.handles_to_close->num_handles = 0;
#define _SF_OUT_HANDLE_HOLDER_WRITE_COPY_HANDLE(n) do { if constexpr (NumCopy > n) { const auto handle = copy_handles[n].GetValue(); response.copy_handles[n] = handle; if (copy_managed[n]) { ctx.handles_to_close->handles[ctx.handles_to_close->num_handles++] = handle; } } } while (0)
#define _SF_OUT_HANDLE_HOLDER_WRITE_COPY_HANDLE(n) do { if constexpr (NumCopy > n) { const auto handle = copy_handles[n].GetOsHandle(); response.copy_handles[n] = handle; if (copy_handles[n].IsManaged()) { ctx.handles_to_close->handles[ctx.handles_to_close->num_handles++] = handle; } copy_handles[n].Detach(); } } while (0)
_SF_OUT_HANDLE_HOLDER_WRITE_COPY_HANDLE(0);
_SF_OUT_HANDLE_HOLDER_WRITE_COPY_HANDLE(1);
_SF_OUT_HANDLE_HOLDER_WRITE_COPY_HANDLE(2);
@@ -666,7 +688,7 @@ namespace ams::sf::impl {
_SF_OUT_HANDLE_HOLDER_WRITE_COPY_HANDLE(6);
_SF_OUT_HANDLE_HOLDER_WRITE_COPY_HANDLE(7);
#undef _SF_OUT_HANDLE_HOLDER_WRITE_COPY_HANDLE
#define _SF_OUT_HANDLE_HOLDER_WRITE_MOVE_HANDLE(n) do { if constexpr (NumMove > n) { response.move_handles[n + num_out_object_handles] = move_handles[n].GetValue(); } } while (0)
#define _SF_OUT_HANDLE_HOLDER_WRITE_MOVE_HANDLE(n) do { if constexpr (NumMove > n) { response.move_handles[n + num_out_object_handles] = move_handles[n].GetOsHandle(); move_handles[n].Detach(); } } while (0)
_SF_OUT_HANDLE_HOLDER_WRITE_MOVE_HANDLE(0);
_SF_OUT_HANDLE_HOLDER_WRITE_MOVE_HANDLE(1);
_SF_OUT_HANDLE_HOLDER_WRITE_MOVE_HANDLE(2);
@@ -830,6 +852,7 @@ namespace ams::sf::impl {
using ArgsType = typename CommandMeta::ArgsType;
using BufferArrayType = std::array<cmif::PointerAndSize, CommandMeta::NumBuffers>;
using OutRawHolderType = OutRawHolder<CommandMeta::OutDataSize, CommandMeta::OutDataAlign>;
using InHandleHolderType = InHandleHolder<CommandMeta::NumInMoveHandles, CommandMeta::NumInCopyHandles>;
using OutHandleHolderType = OutHandleHolder<CommandMeta::NumOutMoveHandles, CommandMeta::NumOutCopyHandles>;
using InOutObjectHolderType = InOutObjectHolder<CommandMeta::NumInObjects, CommandMeta::NumOutObjects>;
@@ -1014,7 +1037,7 @@ namespace ams::sf::impl {
/* Argument deserialization. */
private:
template<size_t Index, typename T = typename std::tuple_element<Index, ArgsType>::type>
NX_CONSTEXPR typename std::tuple_element<Index, ArgsTypeForInvoke>::type DeserializeArgumentImpl(const cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, const OutRawHolderType &out_raw_holder, const BufferArrayType &buffers, OutHandleHolderType &out_handles_holder, InOutObjectHolderType &in_out_objects_holder) {
NX_CONSTEXPR typename std::tuple_element<Index, ArgsTypeForInvoke>::type DeserializeArgumentImpl(const cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, const OutRawHolderType &out_raw_holder, const BufferArrayType &buffers, InHandleHolderType &in_handles_holder, OutHandleHolderType &out_handles_holder, InOutObjectHolderType &in_out_objects_holder) {
constexpr auto Info = CommandMeta::ArgumentSerializationInfos[Index];
if constexpr (Info.arg_type == ArgumentType::InData) {
/* New in rawdata. */
@@ -1031,19 +1054,22 @@ namespace ams::sf::impl {
return T(out_raw_holder.template GetAddress<Offset, T::TypeSize>());
} else if constexpr (Info.arg_type == ArgumentType::InHandle) {
/* New InHandle. */
using InvokeType = typename std::tuple_element<Index, ArgsTypeForInvoke>::type;
if constexpr (std::is_same<T, sf::MoveHandle>::value) {
return T(ctx.request.data.move_handles[Info.in_move_handle_index]);
static_assert(std::same_as<InvokeType, sf::MoveHandle &>);
return in_handles_holder.template SetMoveHandle<Info.in_move_handle_index>(ctx.request.data.move_handles[Info.in_move_handle_index]);
} else if constexpr (std::is_same<T, sf::CopyHandle>::value) {
return T(ctx.request.data.copy_handles[Info.in_copy_handle_index]);
static_assert(std::same_as<InvokeType, sf::CopyHandle &>);
return in_handles_holder.template SetCopyHandle<Info.in_copy_handle_index>(ctx.request.data.copy_handles[Info.in_copy_handle_index]);
} else {
static_assert(!std::is_same<T, T>::value, "Invalid InHandle kind");
}
} else if constexpr (Info.arg_type == ArgumentType::OutHandle) {
/* New OutHandle. */
if constexpr (std::is_same<T, sf::Out<sf::MoveHandle>>::value) {
if constexpr (std::is_same<T, sf::OutMoveHandle>::value) {
return T(out_handles_holder.template GetMoveHandlePointer<Info.out_move_handle_index>());
} else if constexpr (std::is_same<T, sf::Out<sf::CopyHandle>>::value) {
return T(out_handles_holder.template GetCopyHandlePointer<Info.out_copy_handle_index>(), out_handles_holder.template GetCopyHandleManagedPointer<Info.out_copy_handle_index>());
} else if constexpr (std::is_same<T, sf::OutCopyHandle>::value) {
return T(out_handles_holder.template GetCopyHandlePointer<Info.out_copy_handle_index>());
} else {
static_assert(!std::is_same<T, T>::value, "Invalid OutHandle kind");
}
@@ -1078,12 +1104,12 @@ namespace ams::sf::impl {
}
template<size_t... Is>
NX_CONSTEXPR ArgsTypeForInvoke DeserializeArgumentsImpl(const cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, const OutRawHolderType &out_raw_holder, const BufferArrayType &buffers, OutHandleHolderType &out_handles_holder, InOutObjectHolderType &in_out_objects_holder, std::index_sequence<Is...>) {
return ArgsTypeForInvoke { DeserializeArgumentImpl<Is>(ctx, in_raw_data, out_raw_holder, buffers, out_handles_holder, in_out_objects_holder)..., };
NX_CONSTEXPR ArgsTypeForInvoke DeserializeArgumentsImpl(const cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, const OutRawHolderType &out_raw_holder, const BufferArrayType &buffers, InHandleHolderType &in_handles_holder, OutHandleHolderType &out_handles_holder, InOutObjectHolderType &in_out_objects_holder, std::index_sequence<Is...>) {
return ArgsTypeForInvoke { DeserializeArgumentImpl<Is>(ctx, in_raw_data, out_raw_holder, buffers, in_handles_holder, out_handles_holder, in_out_objects_holder)..., };
}
public:
NX_CONSTEXPR ArgsTypeForInvoke DeserializeArguments(const cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, const OutRawHolderType &out_raw_holder, const BufferArrayType &buffers, OutHandleHolderType &out_handles_holder, InOutObjectHolderType &in_out_objects_holder) {
return DeserializeArgumentsImpl(ctx, in_raw_data, out_raw_holder, buffers, out_handles_holder, in_out_objects_holder, std::make_index_sequence<std::tuple_size<ArgsTypeForInvoke>::value>{});
NX_CONSTEXPR ArgsTypeForInvoke DeserializeArguments(const cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, const OutRawHolderType &out_raw_holder, const BufferArrayType &buffers, InHandleHolderType &in_handles_holder, OutHandleHolderType &out_handles_holder, InOutObjectHolderType &in_out_objects_holder) {
return DeserializeArgumentsImpl(ctx, in_raw_data, out_raw_holder, buffers, in_handles_holder, out_handles_holder, in_out_objects_holder, std::make_index_sequence<std::tuple_size<ArgsTypeForInvoke>::value>{});
}
};
@@ -1099,6 +1125,7 @@ namespace ams::sf::impl {
constexpr Result InvokeServiceCommandImplCommon(CmifOutHeader **out_header_ptr, cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, Result (*invoke_impl)(sf::IServiceObject *, Arguments &&...)) {
using ImplProcessorType = HipcCommandProcessor<CommandMeta>;
using BufferArrayType = std::array<cmif::PointerAndSize, CommandMeta::NumBuffers>;
using InHandleHolderType = InHandleHolder<CommandMeta::NumInMoveHandles, CommandMeta::NumInCopyHandles>;
using OutHandleHolderType = OutHandleHolder<CommandMeta::NumOutMoveHandles, CommandMeta::NumOutCopyHandles>;
using OutRawHolderType = OutRawHolder<CommandMeta::OutDataSize, CommandMeta::OutDataAlign>;
using InOutObjectHolderType = InOutObjectHolder<CommandMeta::NumInObjects, CommandMeta::NumOutObjects>;
@@ -1133,39 +1160,43 @@ namespace ams::sf::impl {
/* Decoding/Invocation. */
{
typename CommandMeta::ArgsTypeForInvoke args_tuple = ImplProcessorType::DeserializeArguments(ctx, in_raw_data, out_raw_holder, buffers, out_handles_holder, in_out_objects_holder);
Result command_result;
{
InHandleHolderType in_handles_holder;
typename CommandMeta::ArgsTypeForInvoke args_tuple = ImplProcessorType::DeserializeArguments(ctx, in_raw_data, out_raw_holder, buffers, in_handles_holder, out_handles_holder, in_out_objects_holder);
/* Handle in process ID holder if relevant. */
if constexpr (CommandMeta::HasInProcessIdHolder) {
/* TODO: More precise value than 32? */
static_assert(std::tuple_size<typename CommandMeta::ArgsTypeForInvoke>::value <= 32, "Commands must have <= 32 arguments");
os::ProcessId process_id{ctx.request.pid};
#define _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(n) do { \
using ArgsTypeForInvoke = typename CommandMeta::ArgsTypeForInvoke; \
if constexpr (n < std::tuple_size<ArgsTypeForInvoke>::value) { \
if constexpr (CommandMeta::template IsInProcessIdHolderIndex<n>) { \
R_TRY(MarshalProcessId(std::get<n>(args_tuple), process_id)); \
} \
} \
} while (0)
_SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x00); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x01); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x02); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x03);
_SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x04); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x05); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x06); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x07);
_SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x08); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x09); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x0a); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x0b);
_SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x0c); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x0d); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x0e); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x0f);
_SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x10); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x11); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x12); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x13);
_SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x14); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x15); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x16); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x17);
_SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x18); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x19); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x1a); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x1b);
_SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x1c); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x1d); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x1e); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x1f);
#undef _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID
/* Handle in process ID holder if relevant. */
if constexpr (CommandMeta::HasInProcessIdHolder) {
/* TODO: More precise value than 32? */
static_assert(std::tuple_size<typename CommandMeta::ArgsTypeForInvoke>::value <= 32, "Commands must have <= 32 arguments");
const os::ProcessId process_id{ctx.request.pid};
#define _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(n) do { \
using ArgsTypeForInvoke = typename CommandMeta::ArgsTypeForInvoke; \
if constexpr (n < std::tuple_size<ArgsTypeForInvoke>::value) { \
if constexpr (CommandMeta::template IsInProcessIdHolderIndex<n>) { \
R_TRY(MarshalProcessId(std::get<n>(args_tuple), process_id)); \
} \
} \
} while (0)
_SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x00); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x01); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x02); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x03);
_SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x04); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x05); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x06); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x07);
_SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x08); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x09); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x0a); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x0b);
_SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x0c); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x0d); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x0e); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x0f);
_SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x10); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x11); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x12); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x13);
_SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x14); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x15); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x16); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x17);
_SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x18); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x19); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x1a); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x1b);
_SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x1c); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x1d); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x1e); _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID(0x1f);
#undef _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID
}
using TrueArgumentsTuple = std::tuple<Arguments...>;
sf::IServiceObject * const this_ptr = ctx.srv_obj;
command_result = [this_ptr, invoke_impl, &args_tuple]<size_t ...Ix>(std::index_sequence<Ix...>) ALWAYS_INLINE_LAMBDA {
return invoke_impl(this_ptr, std::forward<typename std::tuple_element<Ix, TrueArgumentsTuple>::type>(std::get<Ix>(args_tuple))...);
}(std::make_index_sequence<std::tuple_size<typename CommandMeta::ArgsTypeForInvoke>::value>());
}
using TrueArgumentsTuple = std::tuple<Arguments...>;
sf::IServiceObject * const this_ptr = ctx.srv_obj;
const auto command_result = [this_ptr, invoke_impl, &args_tuple]<size_t ...Ix>(std::index_sequence<Ix...>) ALWAYS_INLINE_LAMBDA {
return invoke_impl(this_ptr, std::forward<typename std::tuple_element<Ix, TrueArgumentsTuple>::type>(std::get<Ix>(args_tuple))...);
}(std::make_index_sequence<std::tuple_size<typename CommandMeta::ArgsTypeForInvoke>::value>());
if (R_FAILED(command_result)) {
cmif::PointerAndSize out_raw_data;
ctx.processor->PrepareForErrorReply(ctx, out_raw_data, runtime_metadata);

View File

@@ -1,179 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere/sf/sf_common.hpp>
#include <stratosphere/sf/sf_out.hpp>
#include <stratosphere/sf/cmif/sf_cmif_pointer_and_size.hpp>
namespace ams::sf {
namespace impl {
struct InHandleTag{};
struct OutHandleTag{};
template<u32 Attribute>
struct InHandle : public InHandleTag {
os::NativeHandle handle;
constexpr InHandle() : handle(os::InvalidNativeHandle) { /* ... */ }
constexpr InHandle(os::NativeHandle h) : handle(h) { /* ... */ }
constexpr InHandle(const InHandle &o) : handle(o.handle) { /* ... */ }
constexpr void operator=(const os::NativeHandle &h) { this->handle = h; }
constexpr void operator=(const InHandle &o) { this->handle = o.handle; }
constexpr /* TODO: explicit? */ operator os::NativeHandle() const { return this->handle; }
constexpr os::NativeHandle GetValue() const { return this->handle; }
};
template<typename T>
class OutHandleImpl : public OutHandleTag {
static_assert(std::is_base_of<InHandleTag, T>::value, "OutHandleImpl requires InHandle base");
private:
T *ptr;
public:
constexpr OutHandleImpl(T *p) : ptr(p) { /* ... */ }
constexpr void SetValue(const os::NativeHandle &value) {
*this->ptr = value;
}
constexpr void SetValue(const T &value) {
*this->ptr = value;
}
constexpr const T &GetValue() const {
return *this->ptr;
}
constexpr T *GetPointer() const {
return this->ptr;
}
constexpr os::NativeHandle *GetHandlePointer() const {
return &this->ptr->handle;
}
constexpr T &operator *() const {
return *this->ptr;
}
constexpr T *operator ->() const {
return this->ptr;
}
};
}
using MoveHandle = typename impl::InHandle<SfOutHandleAttr_HipcMove>;
using CopyHandle = typename impl::InHandle<SfOutHandleAttr_HipcCopy>;
static_assert(sizeof(MoveHandle) == sizeof(os::NativeHandle), "sizeof(MoveHandle)");
static_assert(sizeof(CopyHandle) == sizeof(os::NativeHandle), "sizeof(CopyHandle)");
template<>
class IsOutForceEnabled<MoveHandle> : public std::true_type{};
template<>
class IsOutForceEnabled<CopyHandle> : public std::true_type{};
template<>
class Out<MoveHandle> : public impl::OutHandleImpl<MoveHandle> {
private:
using T = MoveHandle;
using Base = impl::OutHandleImpl<T>;
public:
constexpr Out<T>(T *p) : Base(p) { /* ... */ }
constexpr void SetValue(const os::NativeHandle &value) {
Base::SetValue(value);
}
constexpr void SetValue(const T &value) {
Base::SetValue(value);
}
constexpr const T &GetValue() const {
return Base::GetValue();
}
constexpr T *GetPointer() const {
return Base::GetPointer();
}
constexpr os::NativeHandle *GetHandlePointer() const {
return Base::GetHandlePointer();
}
constexpr T &operator *() const {
return Base::operator*();
}
constexpr T *operator ->() const {
return Base::operator->();
}
};
template<>
class Out<CopyHandle> : public impl::OutHandleImpl<CopyHandle> {
private:
using T = CopyHandle;
using Base = impl::OutHandleImpl<T>;
private:
bool *m_managed;
public:
constexpr Out<T>(T *p) : Base(p), m_managed(nullptr) { /* ... */ }
constexpr Out<T>(T *p, bool *m) : Base(p), m_managed(m) { /* ... */ }
constexpr void SetValue(const os::NativeHandle &value) {
Base::SetValue(value);
}
constexpr void SetValue(const T &value) {
Base::SetValue(value);
}
constexpr void SetManaged(bool m) {
AMS_ASSERT(m_managed != nullptr);
*m_managed = m;
}
constexpr const T &GetValue() const {
return Base::GetValue();
}
constexpr T *GetPointer() const {
return Base::GetPointer();
}
constexpr os::NativeHandle *GetHandlePointer() const {
return Base::GetHandlePointer();
}
constexpr T &operator *() const {
return Base::operator*();
}
constexpr T *operator ->() const {
return Base::operator->();
}
};
using OutMoveHandle = sf::Out<sf::MoveHandle>;
using OutCopyHandle = sf::Out<sf::CopyHandle>;
}

View File

@@ -21,7 +21,8 @@
namespace ams::sf {
class NativeHandle {
NON_COPYABLE(NativeHandle);
protected:
NON_COPYABLE(NativeHandle);
private:
os::NativeHandle m_handle;
bool m_managed;
@@ -77,12 +78,24 @@ namespace ams::sf {
}
};
ALWAYS_INLINE void swap(NativeHandle &lhs, NativeHandle &rhs) {
class CopyHandle : public NativeHandle {
public:
using NativeHandle::NativeHandle;
using NativeHandle::operator=;
};
class MoveHandle : public NativeHandle {
public:
using NativeHandle::NativeHandle;
using NativeHandle::operator=;
};
constexpr ALWAYS_INLINE void swap(NativeHandle &lhs, NativeHandle &rhs) {
lhs.swap(rhs);
}
template<>
class Out<NativeHandle> {
class Out<CopyHandle> {
private:
NativeHandle *m_ptr;
public:
@@ -92,9 +105,36 @@ namespace ams::sf {
*m_ptr = std::move(v);
}
ALWAYS_INLINE void SetValue(os::NativeHandle os_handle, bool managed) const {
return this->SetValue(NativeHandle(os_handle, managed));
}
NativeHandle &operator*() const {
return *m_ptr;
}
};
template<>
class Out<MoveHandle> {
private:
NativeHandle *m_ptr;
public:
Out(NativeHandle *p) : m_ptr(p) { /* ... */ }
void SetValue(NativeHandle v) const {
*m_ptr = std::move(v);
}
ALWAYS_INLINE void SetValue(os::NativeHandle os_handle, bool managed) const {
return this->SetValue(NativeHandle(os_handle, managed));
}
NativeHandle &operator*() const {
return *m_ptr;
}
};
using OutCopyHandle = Out<CopyHandle>;
using OutMoveHandle = Out<MoveHandle>;
}

View File

@@ -20,31 +20,31 @@
#include <stratosphere/tma/tma_i_socket.hpp>
/* NOTE: Minimum firmware version not enforced for any commands. */
#define AMS_TMA_I_SOCKET_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, Close, (sf::Out<s32> out_err, sf::Out<s32> out_res), (out_err, out_res)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, Connect, (sf::Out<s32> out_err, sf::Out<s32> out_res, const htcs::SockAddrHtcs &address), (out_err, out_res, address)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, Bind, (sf::Out<s32> out_err, sf::Out<s32> out_res, const htcs::SockAddrHtcs &address), (out_err, out_res, address)) \
AMS_SF_METHOD_INFO(C, H, 3, Result, Listen, (sf::Out<s32> out_err, sf::Out<s32> out_res, s32 backlog_count), (out_err, out_res, backlog_count)) \
AMS_SF_METHOD_INFO(C, H, 4, Result, Accept, (sf::Out<s32> out_err, sf::Out<sf::SharedPointer<tma::ISocket>> out, sf::Out<htcs::SockAddrHtcs> out_address), (out_err, out, out_address)) \
AMS_SF_METHOD_INFO(C, H, 5, Result, Recv, (sf::Out<s32> out_err, sf::Out<s64> out_size, const sf::OutAutoSelectBuffer &buffer, s32 flags), (out_err, out_size, buffer, flags)) \
AMS_SF_METHOD_INFO(C, H, 6, Result, Send, (sf::Out<s32> out_err, sf::Out<s64> out_size, const sf::InAutoSelectBuffer &buffer, s32 flags), (out_err, out_size, buffer, flags)) \
AMS_SF_METHOD_INFO(C, H, 7, Result, Shutdown, (sf::Out<s32> out_err, sf::Out<s32> out_res, s32 how), (out_err, out_res, how)) \
AMS_SF_METHOD_INFO(C, H, 8, Result, Fcntl, (sf::Out<s32> out_err, sf::Out<s32> out_res, s32 command, s32 value), (out_err, out_res, command, value)) \
AMS_SF_METHOD_INFO(C, H, 9, Result, AcceptStart, (sf::Out<u32> out_task_id, sf::OutCopyHandle out_event), (out_task_id, out_event)) \
AMS_SF_METHOD_INFO(C, H, 10, Result, AcceptResults, (sf::Out<s32> out_err, sf::Out<sf::SharedPointer<tma::ISocket>> out, sf::Out<htcs::SockAddrHtcs> out_address, u32 task_id), (out_err, out, out_address, task_id)) \
AMS_SF_METHOD_INFO(C, H, 11, Result, RecvStart, (sf::Out<u32> out_task_id, sf::OutCopyHandle out_event, s32 mem_size, s32 flags), (out_task_id, out_event, mem_size, flags)) \
AMS_SF_METHOD_INFO(C, H, 12, Result, RecvResults, (sf::Out<s32> out_err, sf::Out<s64> out_size, const sf::OutAutoSelectBuffer &buffer, u32 task_id), (out_err, out_size, buffer, task_id)) \
AMS_SF_METHOD_INFO(C, H, 13, Result, RecvLargeStart, (sf::Out<u32> out_task_id, sf::OutCopyHandle out_event, s32 unaligned_size_start, s32 unaligned_size_end, s64 aligned_size, sf::CopyHandle mem_handle, s32 flags), (out_task_id, out_event, unaligned_size_start, unaligned_size_end, aligned_size, mem_handle, flags)) \
AMS_SF_METHOD_INFO(C, H, 14, Result, SendStartOld, (sf::Out<u32> out_task_id, sf::OutCopyHandle out_event, const sf::InAutoSelectBuffer &buffer, s32 flags), (out_task_id, out_event, buffer, flags)) \
AMS_SF_METHOD_INFO(C, H, 15, Result, SendLargeStart, (sf::Out<u32> out_task_id, sf::OutCopyHandle out_event, const sf::InAutoSelectBuffer &start_buffer, const sf::InAutoSelectBuffer &end_buffer, sf::CopyHandle mem_handle, s64 aligned_size, s32 flags), (out_task_id, out_event, start_buffer, end_buffer, mem_handle, aligned_size, flags)) \
AMS_SF_METHOD_INFO(C, H, 16, Result, SendResults, (sf::Out<s32> out_err, sf::Out<s64> out_size, u32 task_id), (out_err, out_size, task_id)) \
AMS_SF_METHOD_INFO(C, H, 17, Result, StartSend, (sf::Out<u32> out_task_id, sf::OutCopyHandle out_event, sf::Out<s64> out_max_size, s64 size, s32 flags), (out_task_id, out_event, out_max_size, size, flags)) \
AMS_SF_METHOD_INFO(C, H, 18, Result, ContinueSendOld, (sf::Out<s64> out_size, sf::Out<bool> out_wait, const sf::InAutoSelectBuffer &buffer, u32 task_id), (out_size, out_wait, buffer, task_id)) \
AMS_SF_METHOD_INFO(C, H, 19, Result, EndSend, (sf::Out<s32> out_err, sf::Out<s64> out_size, u32 task_id), (out_err, out_size, task_id)) \
AMS_SF_METHOD_INFO(C, H, 20, Result, StartRecv, (sf::Out<u32> out_task_id, sf::OutCopyHandle out_event, s64 size, s32 flags), (out_task_id, out_event, size, flags)) \
AMS_SF_METHOD_INFO(C, H, 21, Result, EndRecv, (sf::Out<s32> out_err, sf::Out<s64> out_size, const sf::OutAutoSelectBuffer &buffer, u32 task_id), (out_err, out_size, buffer, task_id)) \
AMS_SF_METHOD_INFO(C, H, 22, Result, SendStart, (sf::Out<u32> out_task_id, sf::OutCopyHandle out_event, const sf::InNonSecureAutoSelectBuffer &buffer, s32 flags), (out_task_id, out_event, buffer, flags)) \
AMS_SF_METHOD_INFO(C, H, 23, Result, ContinueSend, (sf::Out<s64> out_size, sf::Out<bool> out_wait, const sf::InNonSecureAutoSelectBuffer &buffer, u32 task_id), (out_size, out_wait, buffer, task_id)) \
#define AMS_TMA_I_SOCKET_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, Close, (sf::Out<s32> out_err, sf::Out<s32> out_res), (out_err, out_res)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, Connect, (sf::Out<s32> out_err, sf::Out<s32> out_res, const htcs::SockAddrHtcs &address), (out_err, out_res, address)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, Bind, (sf::Out<s32> out_err, sf::Out<s32> out_res, const htcs::SockAddrHtcs &address), (out_err, out_res, address)) \
AMS_SF_METHOD_INFO(C, H, 3, Result, Listen, (sf::Out<s32> out_err, sf::Out<s32> out_res, s32 backlog_count), (out_err, out_res, backlog_count)) \
AMS_SF_METHOD_INFO(C, H, 4, Result, Accept, (sf::Out<s32> out_err, sf::Out<sf::SharedPointer<tma::ISocket>> out, sf::Out<htcs::SockAddrHtcs> out_address), (out_err, out, out_address)) \
AMS_SF_METHOD_INFO(C, H, 5, Result, Recv, (sf::Out<s32> out_err, sf::Out<s64> out_size, const sf::OutAutoSelectBuffer &buffer, s32 flags), (out_err, out_size, buffer, flags)) \
AMS_SF_METHOD_INFO(C, H, 6, Result, Send, (sf::Out<s32> out_err, sf::Out<s64> out_size, const sf::InAutoSelectBuffer &buffer, s32 flags), (out_err, out_size, buffer, flags)) \
AMS_SF_METHOD_INFO(C, H, 7, Result, Shutdown, (sf::Out<s32> out_err, sf::Out<s32> out_res, s32 how), (out_err, out_res, how)) \
AMS_SF_METHOD_INFO(C, H, 8, Result, Fcntl, (sf::Out<s32> out_err, sf::Out<s32> out_res, s32 command, s32 value), (out_err, out_res, command, value)) \
AMS_SF_METHOD_INFO(C, H, 9, Result, AcceptStart, (sf::Out<u32> out_task_id, sf::OutCopyHandle out_event), (out_task_id, out_event)) \
AMS_SF_METHOD_INFO(C, H, 10, Result, AcceptResults, (sf::Out<s32> out_err, sf::Out<sf::SharedPointer<tma::ISocket>> out, sf::Out<htcs::SockAddrHtcs> out_address, u32 task_id), (out_err, out, out_address, task_id)) \
AMS_SF_METHOD_INFO(C, H, 11, Result, RecvStart, (sf::Out<u32> out_task_id, sf::OutCopyHandle out_event, s32 mem_size, s32 flags), (out_task_id, out_event, mem_size, flags)) \
AMS_SF_METHOD_INFO(C, H, 12, Result, RecvResults, (sf::Out<s32> out_err, sf::Out<s64> out_size, const sf::OutAutoSelectBuffer &buffer, u32 task_id), (out_err, out_size, buffer, task_id)) \
AMS_SF_METHOD_INFO(C, H, 13, Result, RecvLargeStart, (sf::Out<u32> out_task_id, sf::OutCopyHandle out_event, s32 unaligned_size_start, s32 unaligned_size_end, s64 aligned_size, sf::CopyHandle &&mem_handle, s32 flags), (out_task_id, out_event, unaligned_size_start, unaligned_size_end, aligned_size, std::move(mem_handle), flags)) \
AMS_SF_METHOD_INFO(C, H, 14, Result, SendStartOld, (sf::Out<u32> out_task_id, sf::OutCopyHandle out_event, const sf::InAutoSelectBuffer &buffer, s32 flags), (out_task_id, out_event, buffer, flags)) \
AMS_SF_METHOD_INFO(C, H, 15, Result, SendLargeStart, (sf::Out<u32> out_task_id, sf::OutCopyHandle out_event, const sf::InAutoSelectBuffer &start_buffer, const sf::InAutoSelectBuffer &end_buffer, sf::CopyHandle &&mem_handle, s64 aligned_size, s32 flags), (out_task_id, out_event, start_buffer, end_buffer, std::move(mem_handle), aligned_size, flags)) \
AMS_SF_METHOD_INFO(C, H, 16, Result, SendResults, (sf::Out<s32> out_err, sf::Out<s64> out_size, u32 task_id), (out_err, out_size, task_id)) \
AMS_SF_METHOD_INFO(C, H, 17, Result, StartSend, (sf::Out<u32> out_task_id, sf::OutCopyHandle out_event, sf::Out<s64> out_max_size, s64 size, s32 flags), (out_task_id, out_event, out_max_size, size, flags)) \
AMS_SF_METHOD_INFO(C, H, 18, Result, ContinueSendOld, (sf::Out<s64> out_size, sf::Out<bool> out_wait, const sf::InAutoSelectBuffer &buffer, u32 task_id), (out_size, out_wait, buffer, task_id)) \
AMS_SF_METHOD_INFO(C, H, 19, Result, EndSend, (sf::Out<s32> out_err, sf::Out<s64> out_size, u32 task_id), (out_err, out_size, task_id)) \
AMS_SF_METHOD_INFO(C, H, 20, Result, StartRecv, (sf::Out<u32> out_task_id, sf::OutCopyHandle out_event, s64 size, s32 flags), (out_task_id, out_event, size, flags)) \
AMS_SF_METHOD_INFO(C, H, 21, Result, EndRecv, (sf::Out<s32> out_err, sf::Out<s64> out_size, const sf::OutAutoSelectBuffer &buffer, u32 task_id), (out_err, out_size, buffer, task_id)) \
AMS_SF_METHOD_INFO(C, H, 22, Result, SendStart, (sf::Out<u32> out_task_id, sf::OutCopyHandle out_event, const sf::InNonSecureAutoSelectBuffer &buffer, s32 flags), (out_task_id, out_event, buffer, flags)) \
AMS_SF_METHOD_INFO(C, H, 23, Result, ContinueSend, (sf::Out<s64> out_size, sf::Out<bool> out_wait, const sf::InNonSecureAutoSelectBuffer &buffer, u32 task_id), (out_size, out_wait, buffer, task_id)) \
AMS_SF_METHOD_INFO(C, H, 130, Result, GetPrimitive, (sf::Out<s32> out), (out))
AMS_SF_DEFINE_INTERFACE(ams::tma, ISocket, AMS_TMA_I_SOCKET_INTERFACE_INFO)

View File

@@ -20,17 +20,17 @@
#include <stratosphere/usb/usb_device_types.hpp>
#include <stratosphere/usb/ds/usb_i_ds_interface.hpp>
#define AMS_USB_I_DS_SERVICE_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, Bind, (usb::ComplexId complex_id, sf::CopyHandle process_h), (complex_id, process_h)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, RegisterInterface, (sf::Out<sf::SharedPointer<usb::ds::IDsInterface>> out, u8 bInterfaceNumber), (out, bInterfaceNumber)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, GetStateChangeEvent, (sf::OutCopyHandle out), (out)) \
AMS_SF_METHOD_INFO(C, H, 3, Result, GetState, (sf::Out<usb::UsbState> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 4, Result, ClearDeviceData, (), ()) \
AMS_SF_METHOD_INFO(C, H, 5, Result, AddUsbStringDescriptor, (sf::Out<u8> out, const sf::InBuffer &desc), (out, desc)) \
AMS_SF_METHOD_INFO(C, H, 6, Result, DeleteUsbStringDescriptor, (u8 index), (index)) \
AMS_SF_METHOD_INFO(C, H, 7, Result, SetUsbDeviceDescriptor, (const sf::InBuffer &desc, usb::UsbDeviceSpeed speed), (desc, speed)) \
AMS_SF_METHOD_INFO(C, H, 8, Result, SetBinaryObjectStore, (const sf::InBuffer &bos), (bos)) \
AMS_SF_METHOD_INFO(C, H, 9, Result, Enable, (), ()) \
#define AMS_USB_I_DS_SERVICE_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, Bind, (usb::ComplexId complex_id, sf::CopyHandle &&process_h), (complex_id, std::move(process_h))) \
AMS_SF_METHOD_INFO(C, H, 1, Result, RegisterInterface, (sf::Out<sf::SharedPointer<usb::ds::IDsInterface>> out, u8 bInterfaceNumber), (out, bInterfaceNumber)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, GetStateChangeEvent, (sf::OutCopyHandle out), (out)) \
AMS_SF_METHOD_INFO(C, H, 3, Result, GetState, (sf::Out<usb::UsbState> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 4, Result, ClearDeviceData, (), ()) \
AMS_SF_METHOD_INFO(C, H, 5, Result, AddUsbStringDescriptor, (sf::Out<u8> out, const sf::InBuffer &desc), (out, desc)) \
AMS_SF_METHOD_INFO(C, H, 6, Result, DeleteUsbStringDescriptor, (u8 index), (index)) \
AMS_SF_METHOD_INFO(C, H, 7, Result, SetUsbDeviceDescriptor, (const sf::InBuffer &desc, usb::UsbDeviceSpeed speed), (desc, speed)) \
AMS_SF_METHOD_INFO(C, H, 8, Result, SetBinaryObjectStore, (const sf::InBuffer &bos), (bos)) \
AMS_SF_METHOD_INFO(C, H, 9, Result, Enable, (), ()) \
AMS_SF_METHOD_INFO(C, H, 10, Result, Disable, (), ())
/* TODO: Deprecated interface? */