/* * 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 . */ #pragma once #include #include "impl/sm_service_manager.hpp" namespace ams::sm { /* Service definition. */ class UserService : public tipc::DeferrableBase { private: os::ProcessId m_process_id; bool m_initialized; public: UserService() : m_process_id{os::InvalidProcessId}, m_initialized{false} { /* ... */ } ~UserService() { if (m_initialized) { impl::OnClientDisconnected(m_process_id); } } public: /* Official commands. */ Result RegisterClient(const tipc::ClientProcessId client_process_id) { m_process_id = client_process_id.value; m_initialized = true; R_SUCCEED(); } Result GetServiceHandle(tipc::OutMoveHandle out_h, ServiceName service) { R_UNLESS(m_initialized, sm::ResultInvalidClient()); TIPC_REGISTER_RETRY_ON_RESULT_REQUEST_DEFERRED(service); R_RETURN(impl::GetServiceHandle(out_h.GetPointer(), m_process_id, service)); } Result RegisterService(tipc::OutMoveHandle out_h, ServiceName service, u32 max_sessions, bool is_light) { R_UNLESS(m_initialized, sm::ResultInvalidClient()); R_RETURN(impl::RegisterService(out_h.GetPointer(), m_process_id, service, max_sessions, is_light)); } Result UnregisterService(ServiceName service) { R_UNLESS(m_initialized, sm::ResultInvalidClient()); R_RETURN(impl::UnregisterService(m_process_id, service)); } Result DetachClient(const tipc::ClientProcessId client_process_id) { AMS_UNUSED(client_process_id); m_initialized = false; R_SUCCEED(); } /* Atmosphere commands. */ Result AtmosphereInstallMitm(tipc::OutMoveHandle srv_h, tipc::OutMoveHandle qry_h, ServiceName service) { R_UNLESS(m_initialized, sm::ResultInvalidClient()); TIPC_REGISTER_RETRY_ON_RESULT_REQUEST_DEFERRED(service); R_RETURN(impl::InstallMitm(srv_h.GetPointer(), qry_h.GetPointer(), m_process_id, service)); } Result AtmosphereUninstallMitm(ServiceName service) { R_UNLESS(m_initialized, sm::ResultInvalidClient()); R_RETURN(impl::UninstallMitm(m_process_id, service)); } Result AtmosphereAcknowledgeMitmSession(tipc::Out client_info, tipc::OutMoveHandle fwd_h, ServiceName service) { R_UNLESS(m_initialized, sm::ResultInvalidClient()); R_RETURN(impl::AcknowledgeMitmSession(client_info.GetPointer(), fwd_h.GetPointer(), m_process_id, service)); } Result AtmosphereHasMitm(tipc::Out out, ServiceName service) { R_UNLESS(m_initialized, sm::ResultInvalidClient()); R_RETURN(impl::HasMitm(out.GetPointer(), service)); } Result AtmosphereWaitMitm(ServiceName service) { R_UNLESS(m_initialized, sm::ResultInvalidClient()); TIPC_REGISTER_RETRY_ON_RESULT_REQUEST_DEFERRED(service); R_RETURN(impl::WaitMitm(service)); } Result AtmosphereDeclareFutureMitm(ServiceName service) { R_UNLESS(m_initialized, sm::ResultInvalidClient()); R_RETURN(impl::DeclareFutureMitm(m_process_id, service)); } Result AtmosphereClearFutureMitm(ServiceName service) { R_UNLESS(m_initialized, sm::ResultInvalidClient()); R_RETURN(impl::ClearFutureMitm(m_process_id, service)); } Result AtmosphereHasService(tipc::Out out, ServiceName service) { R_UNLESS(m_initialized, sm::ResultInvalidClient()); R_RETURN(impl::HasService(out.GetPointer(), service)); } Result AtmosphereWaitService(ServiceName service) { R_UNLESS(m_initialized, sm::ResultInvalidClient()); TIPC_REGISTER_RETRY_ON_RESULT_REQUEST_DEFERRED(service); R_RETURN(impl::WaitService(service)); } public: /* Backwards compatibility layer for cmif. */ Result ProcessDefaultServiceCommand(const svc::ipc::MessageBuffer &message_buffer); }; static_assert(sm::impl::IsIUserInterface); static_assert(tipc::IsDeferrable); /* TODO: static assert that this is a tipc interface with default prototyping. */ }