From 10255f7f5161ebe84b1a14725308b92b8d4cb862 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 10 Feb 2021 18:54:40 -0800 Subject: [PATCH] htc: skeleton HtcsManagerImpl, implement HtcsMonitor --- .../htclow/htclow_module_types.hpp | 32 ++++++ .../include/stratosphere/htcs.hpp | 2 + .../htcs/impl/htcs_channel_ids.hpp | 24 ++++ .../htcs/impl/htcs_manager_holder.hpp | 33 ++++++ .../htc/server/driver/htc_driver_manager.hpp | 2 + .../source/htc/server/htc_htcmisc_impl.cpp | 12 +- .../source/htc/server/htc_observer.cpp | 10 +- .../htc/server/rpc/htc_htcmisc_rpc_server.cpp | 2 +- .../htc/server/rpc/htc_htcmisc_rpc_server.hpp | 2 +- .../source/htc/server/rpc/htc_rpc_client.cpp | 49 ++++++++- .../source/htc/server/rpc/htc_rpc_client.hpp | 4 +- .../source/htcs/impl/htcs_manager.cpp | 39 +++++++ .../source/htcs/impl/htcs_manager.hpp | 37 +++++++ .../source/htcs/impl/htcs_manager_holder.cpp | 79 ++++++++++++++ .../source/htcs/impl/htcs_manager_impl.cpp | 49 +++++++++ .../source/htcs/impl/htcs_manager_impl.hpp | 46 ++++++++ .../source/htcs/impl/htcs_monitor.cpp | 103 ++++++++++++++++++ .../source/htcs/impl/htcs_monitor.hpp | 73 +++++++++++++ .../source/htcs/impl/htcs_service.hpp | 37 +++++++ .../impl/rpc/htcs_data_channel_manager.hpp | 34 ++++++ 20 files changed, 652 insertions(+), 17 deletions(-) create mode 100644 libraries/libstratosphere/include/stratosphere/htcs/impl/htcs_channel_ids.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/htcs/impl/htcs_manager_holder.hpp create mode 100644 libraries/libstratosphere/source/htcs/impl/htcs_manager.cpp create mode 100644 libraries/libstratosphere/source/htcs/impl/htcs_manager.hpp create mode 100644 libraries/libstratosphere/source/htcs/impl/htcs_manager_holder.cpp create mode 100644 libraries/libstratosphere/source/htcs/impl/htcs_manager_impl.cpp create mode 100644 libraries/libstratosphere/source/htcs/impl/htcs_manager_impl.hpp create mode 100644 libraries/libstratosphere/source/htcs/impl/htcs_monitor.cpp create mode 100644 libraries/libstratosphere/source/htcs/impl/htcs_monitor.hpp create mode 100644 libraries/libstratosphere/source/htcs/impl/htcs_service.hpp create mode 100644 libraries/libstratosphere/source/htcs/impl/rpc/htcs_data_channel_manager.hpp diff --git a/libraries/libstratosphere/include/stratosphere/htclow/htclow_module_types.hpp b/libraries/libstratosphere/include/stratosphere/htclow/htclow_module_types.hpp index 178c61dfa..3f039d153 100644 --- a/libraries/libstratosphere/include/stratosphere/htclow/htclow_module_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/htclow/htclow_module_types.hpp @@ -20,6 +20,8 @@ namespace ams::htclow { enum class ModuleId : u8 { + Unknown = 0, + Htcfs = 1, Htcmisc = 3, @@ -31,4 +33,34 @@ namespace ams::htclow { ModuleId _id; }; + constexpr void InitializeModule(ModuleType *out, ModuleId id) { + *out = { + ._is_initialized = true, + ._id = id, + }; + } + + constexpr void FinalizeModule(ModuleType *out) { + *out = { + ._is_initialized = false, + ._id = ModuleId::Unknown, + }; + } + + class Module final { + private: + ModuleType m_impl; + public: + constexpr explicit Module(ModuleId id) : m_impl() { + InitializeModule(std::addressof(m_impl), id); + } + + constexpr ~Module() { + FinalizeModule(std::addressof(m_impl)); + } + + ModuleType *GetBase() { return std::addressof(m_impl); } + const ModuleType *GetBase() const { return std::addressof(m_impl); } + }; + } diff --git a/libraries/libstratosphere/include/stratosphere/htcs.hpp b/libraries/libstratosphere/include/stratosphere/htcs.hpp index 345d42c5d..59881a770 100644 --- a/libraries/libstratosphere/include/stratosphere/htcs.hpp +++ b/libraries/libstratosphere/include/stratosphere/htcs.hpp @@ -16,3 +16,5 @@ #pragma once #include +#include +#include diff --git a/libraries/libstratosphere/include/stratosphere/htcs/impl/htcs_channel_ids.hpp b/libraries/libstratosphere/include/stratosphere/htcs/impl/htcs_channel_ids.hpp new file mode 100644 index 000000000..7406484ce --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/htcs/impl/htcs_channel_ids.hpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018-2020 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 + +namespace ams::htcs::impl { + + constexpr inline htclow::ChannelId HtcsClientChannelId = 0; + +} diff --git a/libraries/libstratosphere/include/stratosphere/htcs/impl/htcs_manager_holder.hpp b/libraries/libstratosphere/include/stratosphere/htcs/impl/htcs_manager_holder.hpp new file mode 100644 index 000000000..b9868254c --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/htcs/impl/htcs_manager_holder.hpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018-2020 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 + +namespace ams::htcs::impl { + + class HtcsManager; + + namespace HtcsManagerHolder { + + void AddReference(); + void Release(); + + HtcsManager *GetHtcsManager(); + + } + +} diff --git a/libraries/libstratosphere/source/htc/server/driver/htc_driver_manager.hpp b/libraries/libstratosphere/source/htc/server/driver/htc_driver_manager.hpp index 35757d778..072d30c9e 100644 --- a/libraries/libstratosphere/source/htc/server/driver/htc_driver_manager.hpp +++ b/libraries/libstratosphere/source/htc/server/driver/htc_driver_manager.hpp @@ -24,6 +24,8 @@ namespace ams::htc::server::driver { IDriver *m_driver; public: DriverManager(IDriver *driver) : m_driver(driver) { /* ... */ } + + IDriver *GetDriver() { return m_driver; } }; } diff --git a/libraries/libstratosphere/source/htc/server/htc_htcmisc_impl.cpp b/libraries/libstratosphere/source/htc/server/htc_htcmisc_impl.cpp index 5bd78d167..632c0e446 100644 --- a/libraries/libstratosphere/source/htc/server/htc_htcmisc_impl.cpp +++ b/libraries/libstratosphere/source/htc/server/htc_htcmisc_impl.cpp @@ -104,6 +104,7 @@ namespace ams::htc::server { m_rpc_client.Close(); m_rpc_client.Cancel(); m_rpc_client.Wait(); + this->SetClientConnectionEvent(false); }; /* Wait to become disconnected. */ @@ -111,12 +112,7 @@ namespace ams::htc::server { break; } - /* Set ourselves as disconnected. */ - this->SetClientConnectionEvent(false); } - - /* Set ourselves as disconnected. */ - this->SetClientConnectionEvent(false); } void HtcmiscImpl::ServerThread() { @@ -147,6 +143,7 @@ namespace ams::htc::server { m_rpc_server.Close(); m_rpc_server.Cancel(); m_rpc_server.Wait(); + this->SetServerConnectionEvent(false); }; /* Wait to become disconnected. */ @@ -154,12 +151,7 @@ namespace ams::htc::server { break; } - /* Set ourselves as disconnected. */ - this->SetServerConnectionEvent(false); } - - /* Set ourselves as disconnected. */ - this->SetServerConnectionEvent(false); } void HtcmiscImpl::SetClientConnectionEvent(bool en) { diff --git a/libraries/libstratosphere/source/htc/server/htc_observer.cpp b/libraries/libstratosphere/source/htc/server/htc_observer.cpp index 58fc965bb..c3f6fda84 100644 --- a/libraries/libstratosphere/source/htc/server/htc_observer.cpp +++ b/libraries/libstratosphere/source/htc/server/htc_observer.cpp @@ -15,6 +15,7 @@ */ #include #include "htc_observer.hpp" +#include "../../htcs/impl/htcs_manager.hpp" namespace ams::htc::server { @@ -29,7 +30,7 @@ namespace ams::htc::server { m_is_service_available(false) { /* Initialize htcs library. */ - /* TODO: AMS_ABORT("htcs::impl::HtcsManagerHolder::AddReference();"); */ + htcs::impl::HtcsManagerHolder::AddReference(); /* Update our event state. */ this->UpdateEvent(); @@ -76,10 +77,13 @@ namespace ams::htc::server { this->UpdateEvent(); }; + /* Get the htcs manager. */ + auto * const htcs_manager = htcs::impl::HtcsManagerHolder::GetHtcsManager(); + /* Get the events we're waiting on. */ os::EventType * const stop_event = m_stop_event.GetBase(); os::EventType * const conn_event = m_misc_impl.GetConnectionEvent(); - os::EventType * const htcs_event = nullptr /* TODO: htcs::impl::HtcsManagerHolder::GetHtcsManager()->GetServiceAvailabilityEvent() */; + os::EventType * const htcs_event = htcs_manager->GetServiceAvailabilityEvent(); /* Loop until we're asked to stop. */ while (!m_stopped) { @@ -98,7 +102,7 @@ namespace ams::htc::server { case 2: /* Htcs event, update our service status. */ os::ClearEvent(htcs_event); - m_is_service_available = false /* TODO: htcs::impl::HtcsManagerHolder::GetHtcsManager()->IsServiceAvailable() */; + m_is_service_available = htcs_manager->IsServiceAvailable(); break; AMS_UNREACHABLE_DEFAULT_CASE(); } diff --git a/libraries/libstratosphere/source/htc/server/rpc/htc_htcmisc_rpc_server.cpp b/libraries/libstratosphere/source/htc/server/rpc/htc_htcmisc_rpc_server.cpp index 5e28c1255..d0bd22eff 100644 --- a/libraries/libstratosphere/source/htc/server/rpc/htc_htcmisc_rpc_server.cpp +++ b/libraries/libstratosphere/source/htc/server/rpc/htc_htcmisc_rpc_server.cpp @@ -27,7 +27,7 @@ namespace ams::htc::server::rpc { } HtcmiscRpcServer::HtcmiscRpcServer(driver::IDriver *driver, htclow::ChannelId channel) - : m_00(0), + : m_allocator(nullptr), m_driver(driver), m_channel_id(channel), m_receive_thread_stack(g_receive_thread_stack), diff --git a/libraries/libstratosphere/source/htc/server/rpc/htc_htcmisc_rpc_server.hpp b/libraries/libstratosphere/source/htc/server/rpc/htc_htcmisc_rpc_server.hpp index 598559afe..e26679f32 100644 --- a/libraries/libstratosphere/source/htc/server/rpc/htc_htcmisc_rpc_server.hpp +++ b/libraries/libstratosphere/source/htc/server/rpc/htc_htcmisc_rpc_server.hpp @@ -25,7 +25,7 @@ namespace ams::htc::server::rpc { /* TODO: where is this value coming from, again? */ static constexpr size_t BufferSize = 1_KB; private: - u64 m_00; + mem::StandardAllocator *m_allocator; driver::IDriver *m_driver; htclow::ChannelId m_channel_id; void *m_receive_thread_stack; diff --git a/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_client.cpp b/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_client.cpp index 12c91ee74..00cb9b352 100644 --- a/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_client.cpp +++ b/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_client.cpp @@ -33,7 +33,7 @@ namespace ams::htc::server::rpc { } RpcClient::RpcClient(driver::IDriver *driver, htclow::ChannelId channel) - : m_00(0), + : m_allocator(nullptr), m_driver(driver), m_channel_id(channel), m_receive_thread_stack(g_receive_thread_stack), @@ -53,6 +53,53 @@ namespace ams::htc::server::rpc { } } + RpcClient::RpcClient(mem::StandardAllocator *allocator, driver::IDriver *driver, htclow::ChannelId channel) + : m_allocator(allocator), + m_driver(driver), + m_channel_id(channel), + m_receive_thread_stack(m_allocator->Allocate(ThreadStackSize, os::ThreadStackAlignment)), + m_send_thread_stack(m_allocator->Allocate(ThreadStackSize, os::ThreadStackAlignment)), + m_mutex(g_rpc_mutex), + m_task_id_free_list(g_task_id_free_list), + m_task_table(g_task_table), + m_task_active(), + m_task_queue(), + m_cancelled(false), + m_thread_running(false) + { + /* Initialize all events. */ + for (size_t i = 0; i < MaxRpcCount; ++i) { + os::InitializeEvent(std::addressof(m_receive_buffer_available_events[i]), false, os::EventClearMode_AutoClear); + os::InitializeEvent(std::addressof(m_send_buffer_available_events[i]), false, os::EventClearMode_AutoClear); + } + } + + RpcClient::~RpcClient() { + /* Finalize all events. */ + for (size_t i = 0; i < MaxRpcCount; ++i) { + os::FinalizeEvent(std::addressof(m_receive_buffer_available_events[i])); + os::FinalizeEvent(std::addressof(m_send_buffer_available_events[i])); + } + + /* Free the thread stacks. */ + if (m_allocator != nullptr) { + m_allocator->Free(m_receive_thread_stack); + m_allocator->Free(m_send_thread_stack); + } + m_receive_thread_stack = nullptr; + m_send_thread_stack = nullptr; + + /* Free all tasks. */ + for (u32 i = 0; i < MaxRpcCount; ++i) { + if (m_task_active[i]) { + std::scoped_lock lk(m_mutex); + + m_task_table.Delete(i); + m_task_id_free_list.Free(i); + } + } + } + void RpcClient::Open() { R_ABORT_UNLESS(m_driver->Open(m_channel_id)); } diff --git a/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_client.hpp b/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_client.hpp index 5b7369b11..1d8bf9fa3 100644 --- a/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_client.hpp +++ b/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_client.hpp @@ -27,7 +27,7 @@ namespace ams::htc::server::rpc { /* TODO: where is this value coming from, again? */ static constexpr size_t BufferSize = 0xE400; private: - u64 m_00; + mem::StandardAllocator *m_allocator; driver::IDriver *m_driver; htclow::ChannelId m_channel_id; void *m_receive_thread_stack; @@ -53,6 +53,8 @@ namespace ams::htc::server::rpc { Result SendThread(); public: RpcClient(driver::IDriver *driver, htclow::ChannelId channel); + RpcClient(mem::StandardAllocator *allocator, driver::IDriver *driver, htclow::ChannelId channel); + ~RpcClient(); public: void Open(); void Close(); diff --git a/libraries/libstratosphere/source/htcs/impl/htcs_manager.cpp b/libraries/libstratosphere/source/htcs/impl/htcs_manager.cpp new file mode 100644 index 000000000..d6c6360ea --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/htcs_manager.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018-2020 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 . + */ +#include +#include "htcs_manager.hpp" +#include "htcs_manager_impl.hpp" + +namespace ams::htcs::impl { + + HtcsManager::HtcsManager(mem::StandardAllocator *allocator, htclow::HtclowManager *htclow_manager) : m_allocator(allocator), m_impl(static_cast(allocator->Allocate(sizeof(HtcsManagerImpl), alignof(HtcsManagerImpl)))) { + std::construct_at(m_impl, m_allocator, htclow_manager); + } + + HtcsManager::~HtcsManager() { + std::destroy_at(m_impl); + m_allocator->Free(m_impl); + } + + os::EventType *HtcsManager::GetServiceAvailabilityEvent() { + return m_impl->GetServiceAvailabilityEvent(); + } + + bool HtcsManager::IsServiceAvailable() { + return m_impl->IsServiceAvailable(); + } + +} diff --git a/libraries/libstratosphere/source/htcs/impl/htcs_manager.hpp b/libraries/libstratosphere/source/htcs/impl/htcs_manager.hpp new file mode 100644 index 000000000..433fc8b7f --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/htcs_manager.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018-2020 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 "../../htclow/htclow_manager.hpp" + +namespace ams::htcs::impl { + + class HtcsManagerImpl; + + class HtcsManager { + private: + mem::StandardAllocator *m_allocator; + HtcsManagerImpl *m_impl; + public: + HtcsManager(mem::StandardAllocator *allocator, htclow::HtclowManager *htclow_manager); + ~HtcsManager(); + public: + os::EventType *GetServiceAvailabilityEvent(); + + bool IsServiceAvailable(); + }; + +} diff --git a/libraries/libstratosphere/source/htcs/impl/htcs_manager_holder.cpp b/libraries/libstratosphere/source/htcs/impl/htcs_manager_holder.cpp new file mode 100644 index 000000000..1091e3288 --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/htcs_manager_holder.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018-2020 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 . + */ +#include +#include "htcs_manager.hpp" + +namespace ams::htcs::impl::HtcsManagerHolder { + + namespace { + + constinit os::SdkMutex g_holder_mutex; + constinit int g_holder_reference_count = 0; + + mem::StandardAllocator g_allocator; + + constinit HtcsManager *g_manager = nullptr; + + alignas(os::MemoryPageSize) u8 g_heap_buffer[416_KB]; + + } + + void AddReference() { + std::scoped_lock lk(g_holder_mutex); + + if ((g_holder_reference_count++) == 0) { + /* Add reference to the htclow manager. */ + htclow::HtclowManagerHolder::AddReference(); + + /* Initialize the allocator for the manager. */ + g_allocator.Initialize(g_heap_buffer, sizeof(g_heap_buffer)); + + /* Allocate the manager. */ + g_manager = static_cast(g_allocator.Allocate(sizeof(HtcsManager), alignof(HtcsManager))); + + /* Construct the manager. */ + std::construct_at(g_manager, std::addressof(g_allocator), htclow::HtclowManagerHolder::GetHtclowManager()); + } + + AMS_ASSERT(g_holder_reference_count > 0); + } + + void Release() { + std::scoped_lock lk(g_holder_mutex); + + AMS_ASSERT(g_holder_reference_count > 0); + + if ((--g_holder_reference_count) == 0) { + /* Destroy the manager. */ + std::destroy_at(g_manager); + g_allocator.Free(g_manager); + g_manager = nullptr; + + /* Finalize the allocator. */ + g_allocator.Finalize(); + + /* Release reference to the htclow manager. */ + htclow::HtclowManagerHolder::Release(); + } + } + + HtcsManager *GetHtcsManager() { + std::scoped_lock lk(g_holder_mutex); + + return g_manager; + } + +} diff --git a/libraries/libstratosphere/source/htcs/impl/htcs_manager_impl.cpp b/libraries/libstratosphere/source/htcs/impl/htcs_manager_impl.cpp new file mode 100644 index 000000000..d6c71fb20 --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/htcs_manager_impl.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018-2020 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 . + */ +#include +#include "htcs_manager.hpp" +#include "htcs_manager_impl.hpp" + +namespace ams::htcs::impl { + + HtcsManagerImpl::HtcsManagerImpl(mem::StandardAllocator *allocator, htclow::HtclowManager *htclow_manager) + : m_allocator(allocator), + m_driver(htclow_manager, htclow::ModuleId::Htcs), + m_driver_manager(std::addressof(m_driver)), + m_rpc_client(m_allocator, std::addressof(m_driver), HtcsClientChannelId), + m_data_channel_manager(std::addressof(m_rpc_client), htclow_manager), + m_service(m_allocator, m_driver_manager.GetDriver(), std::addressof(m_rpc_client), std::addressof(m_data_channel_manager)), + m_monitor(m_allocator, m_driver_manager.GetDriver(), std::addressof(m_rpc_client), std::addressof(m_service)) + { + /* Start the monitor. */ + m_monitor.Start(); + } + + HtcsManagerImpl::~HtcsManagerImpl() { + /* Cancel our monitor. */ + m_monitor.Cancel(); + m_monitor.Wait(); + } + + os::EventType *HtcsManagerImpl::GetServiceAvailabilityEvent() { + return m_monitor.GetServiceAvailabilityEvent(); + } + + bool HtcsManagerImpl::IsServiceAvailable() { + return m_monitor.IsServiceAvailable(); + } + +} diff --git a/libraries/libstratosphere/source/htcs/impl/htcs_manager_impl.hpp b/libraries/libstratosphere/source/htcs/impl/htcs_manager_impl.hpp new file mode 100644 index 000000000..38c0916ec --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/htcs_manager_impl.hpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018-2020 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 "../../htclow/htclow_manager.hpp" +#include "../../htc/server/driver/htc_htclow_driver.hpp" +#include "../../htc/server/driver/htc_driver_manager.hpp" +#include "../../htc/server/rpc/htc_rpc_client.hpp" +#include "rpc/htcs_data_channel_manager.hpp" +#include "htcs_service.hpp" +#include "htcs_monitor.hpp" + +namespace ams::htcs::impl { + + class HtcsManagerImpl { + private: + mem::StandardAllocator *m_allocator; + htc::server::driver::HtclowDriver m_driver; + htc::server::driver::DriverManager m_driver_manager; + htc::server::rpc::RpcClient m_rpc_client; + rpc::DataChannelManager m_data_channel_manager; + HtcsService m_service; + HtcsMonitor m_monitor; + public: + HtcsManagerImpl(mem::StandardAllocator *allocator, htclow::HtclowManager *htclow_manager); + ~HtcsManagerImpl(); + public: + os::EventType *GetServiceAvailabilityEvent(); + + bool IsServiceAvailable(); + }; + +} diff --git a/libraries/libstratosphere/source/htcs/impl/htcs_monitor.cpp b/libraries/libstratosphere/source/htcs/impl/htcs_monitor.cpp new file mode 100644 index 000000000..cd949983b --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/htcs_monitor.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2018-2020 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 . + */ +#include +#include "htcs_manager.hpp" +#include "htcs_manager_impl.hpp" + +namespace ams::htcs::impl { + + HtcsMonitor::HtcsMonitor(mem::StandardAllocator *allocator, htc::server::driver::IDriver *drv, htc::server::rpc::RpcClient *rc, HtcsService *srv) + : m_allocator(allocator), + m_driver(drv), + m_rpc_client(rc), + m_service(srv), + m_monitor_thread_stack(m_allocator->Allocate(os::MemoryPageSize, os::ThreadStackAlignment)), + m_mutex(), + m_cancel_event(os::EventClearMode_ManualClear), + m_service_availability_event(os::EventClearMode_ManualClear), + m_cancelled(false), + m_is_service_available(false) + { + /* ... */ + } + + HtcsMonitor::~HtcsMonitor() { + /* Free thread stack. */ + m_allocator->Free(m_monitor_thread_stack); + } + + void HtcsMonitor::Start() { + /* Create the monitor thread. */ + R_ABORT_UNLESS(os::CreateThread(std::addressof(m_monitor_thread), ThreadEntry, this, m_monitor_thread_stack, os::MemoryPageSize, AMS_GET_SYSTEM_THREAD_PRIORITY(htc, HtcsMonitor))); + + /* Set thread name. */ + os::SetThreadNamePointer(std::addressof(m_monitor_thread), AMS_GET_SYSTEM_THREAD_NAME(htc, HtcsMonitor)); + + /* Start the monitor thread. */ + os::StartThread(std::addressof(m_monitor_thread)); + } + + void HtcsMonitor::Cancel() { + /* Cancel, and signal. */ + m_cancelled = true; + m_cancel_event.Signal(); + } + + void HtcsMonitor::Wait() { + /* Wait for the thread. */ + os::WaitThread(std::addressof(m_monitor_thread)); + os::DestroyThread(std::addressof(m_monitor_thread)); + } + + void HtcsMonitor::ThreadBody() { + /* Loop so long as we're not cancelled. */ + while (!m_cancelled) { + /* Open the rpc client. */ + m_rpc_client->Open(); + + /* Ensure we close, if something goes wrong. */ + auto client_guard = SCOPE_GUARD { m_rpc_client->Close(); }; + + /* Wait for the rpc server. */ + if (m_rpc_client->WaitAny(htclow::ChannelState_Connectable, m_cancel_event.GetBase()) != 0) { + break; + } + + /* Start the rpc client. */ + if (R_FAILED(m_rpc_client->Start())) { + continue; + } + + /* We're available! */ + this->SetServiceAvailability(true); + client_guard.Cancel(); + + /* We're available, so we want to cleanup when we're done. */ + ON_SCOPE_EXIT { + m_rpc_client->Close(); + m_rpc_client->Cancel(); + m_rpc_client->Wait(); + this->SetServiceAvailability(false); + }; + + /* Wait to become disconnected. */ + if (m_rpc_client->WaitAny(htclow::ChannelState_Disconnected, m_cancel_event.GetBase()) != 0) { + break; + } + } + } + +} diff --git a/libraries/libstratosphere/source/htcs/impl/htcs_monitor.hpp b/libraries/libstratosphere/source/htcs/impl/htcs_monitor.hpp new file mode 100644 index 000000000..be215e5e2 --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/htcs_monitor.hpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018-2020 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 "../../htc/server/driver/htc_i_driver.hpp" +#include "../../htc/server/rpc/htc_rpc_client.hpp" +#include "htcs_service.hpp" + +namespace ams::htcs::impl { + + class HtcsMonitor { + private: + mem::StandardAllocator *m_allocator; + htc::server::driver::IDriver *m_driver; + htc::server::rpc::RpcClient *m_rpc_client; + HtcsService *m_service; + void *m_monitor_thread_stack; + os::ThreadType m_monitor_thread; + os::SdkMutex m_mutex; + os::Event m_cancel_event; + os::Event m_service_availability_event; + bool m_cancelled; + bool m_is_service_available; + private: + static void ThreadEntry(void *arg) { + static_cast(arg)->ThreadBody(); + } + + void ThreadBody(); + public: + HtcsMonitor(mem::StandardAllocator *allocator, htc::server::driver::IDriver *drv, htc::server::rpc::RpcClient *rc, HtcsService *srv); + ~HtcsMonitor(); + public: + void Start(); + void Cancel(); + void Wait(); + + os::EventType *GetServiceAvailabilityEvent() { return m_service_availability_event.GetBase(); } + + bool IsServiceAvailable() { + /* Lock ourselves. */ + std::scoped_lock lk(m_mutex); + + /* Get availability. */ + return m_is_service_available; + } + private: + void SetServiceAvailability(bool available) { + /* Lock ourselves. */ + std::scoped_lock lk(m_mutex); + + /* Set availability. */ + m_is_service_available = available; + + /* Signal availability change. */ + m_service_availability_event.Signal(); + } + }; + +} diff --git a/libraries/libstratosphere/source/htcs/impl/htcs_service.hpp b/libraries/libstratosphere/source/htcs/impl/htcs_service.hpp new file mode 100644 index 000000000..9968b81ec --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/htcs_service.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018-2020 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 "../../htc/server/driver/htc_i_driver.hpp" +#include "../../htc/server/rpc/htc_rpc_client.hpp" +#include "rpc/htcs_data_channel_manager.hpp" + +namespace ams::htcs::impl { + + class HtcsService { + private: + mem::StandardAllocator *m_allocator; + htc::server::driver::IDriver *m_driver; + htc::server::rpc::RpcClient *m_rpc_client; + rpc::DataChannelManager *m_data_channel_manager; + public: + HtcsService(mem::StandardAllocator *allocator, htc::server::driver::IDriver *drv, htc::server::rpc::RpcClient *rc, rpc::DataChannelManager *dcm) + : m_allocator(allocator), m_driver(drv), m_rpc_client(rc), m_data_channel_manager(dcm) { /* ... */ } + public: + /* TODO */ + }; + +} diff --git a/libraries/libstratosphere/source/htcs/impl/rpc/htcs_data_channel_manager.hpp b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_data_channel_manager.hpp new file mode 100644 index 000000000..7d683e523 --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_data_channel_manager.hpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018-2020 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 "../../../htclow/htclow_manager.hpp" +#include "../../../htc/server/rpc/htc_rpc_client.hpp" + +namespace ams::htcs::impl::rpc { + + class DataChannelManager { + private: + htc::server::rpc::RpcClient* m_rpc_client; + htclow::HtclowManager *m_htclow_manager; + htclow::Module m_module; + public: + DataChannelManager(htc::server::rpc::RpcClient *client, htclow::HtclowManager *htclow_manager) : m_rpc_client(client), m_htclow_manager(htclow_manager), m_module(htclow::ModuleId::Htcs) { /* ... */ } + public: + /* TODO */ + }; + +}