htc: skeleton constructors for htcmisc

This commit is contained in:
Michael Scire 2021-02-09 20:43:40 -08:00 committed by SciresM
parent b925344c3b
commit 1f03b11dbc
12 changed files with 310 additions and 6 deletions

View file

@ -140,6 +140,7 @@ namespace ams::impl {
AMS_DEFINE_SYSTEM_THREAD(10, htc, Htcmisc); AMS_DEFINE_SYSTEM_THREAD(10, htc, Htcmisc);
AMS_DEFINE_SYSTEM_THREAD(10, htc, HtcmiscReceive); AMS_DEFINE_SYSTEM_THREAD(10, htc, HtcmiscReceive);
AMS_DEFINE_SYSTEM_THREAD(10, htc, HtcmiscSend); AMS_DEFINE_SYSTEM_THREAD(10, htc, HtcmiscSend);
AMS_DEFINE_SYSTEM_THREAD(10, htc, HtcObserver);
AMS_DEFINE_SYSTEM_THREAD(10, tma, BridgePcieDriver); AMS_DEFINE_SYSTEM_THREAD(10, tma, BridgePcieDriver);

View file

@ -0,0 +1,87 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "htc_htcmisc_impl.hpp"
namespace ams::htc::server {
namespace {
alignas(os::ThreadStackAlignment) u8 g_client_thread_stack[os::MemoryPageSize];
alignas(os::ThreadStackAlignment) u8 g_server_thread_stack[os::MemoryPageSize];
}
HtcmiscImpl::HtcmiscImpl(htclow::HtclowManager *htclow_manager)
: m_htclow_driver(htclow_manager, htclow::ModuleId::Htcmisc),
m_driver_manager(std::addressof(m_htclow_driver)),
m_rpc_client(std::addressof(m_htclow_driver), HtcmiscClientChannelId),
m_rpc_server(std::addressof(m_htclow_driver), HtcmiscServerChannelId),
m_cancel_event(os::EventClearMode_ManualClear),
m_cancelled(false),
m_connection_event(os::EventClearMode_ManualClear),
m_client_connected(false),
m_server_connected(false),
m_connected(false),
m_connection_mutex()
{
/* Create the client thread. */
R_ABORT_UNLESS(os::CreateThread(std::addressof(m_client_thread), ClientThreadEntry, this, g_client_thread_stack, sizeof(g_client_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(htc, Htcmisc)));
/* Set the client thread name. */
os::SetThreadNamePointer(std::addressof(m_client_thread), AMS_GET_SYSTEM_THREAD_NAME(htc, Htcmisc));
/* Start the client thread. */
os::StartThread(std::addressof(m_client_thread));
/* Create the server thread. */
R_ABORT_UNLESS(os::CreateThread(std::addressof(m_server_thread), ServerThreadEntry, this, g_server_thread_stack, sizeof(g_server_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(htc, Htcmisc)));
/* Set the server thread name. */
os::SetThreadNamePointer(std::addressof(m_server_thread), AMS_GET_SYSTEM_THREAD_NAME(htc, Htcmisc));
/* Start the server thread. */
os::StartThread(std::addressof(m_server_thread));
}
HtcmiscImpl::~HtcmiscImpl() {
/* Cancel ourselves. */
this->Cancel();
/* Wait for our threads to be done, and destroy them. */
os::WaitThread(std::addressof(m_client_thread));
os::DestroyThread(std::addressof(m_client_thread));
os::WaitThread(std::addressof(m_server_thread));
os::DestroyThread(std::addressof(m_server_thread));
}
void HtcmiscImpl::Cancel() {
/* Set ourselves as cancelled. */
m_cancelled = true;
/* Signal our cancel event. */
m_cancel_event.Signal();
}
void HtcmiscImpl::ClientThread() {
AMS_ABORT("HtcmiscImpl::ClientThread");
}
void HtcmiscImpl::ServerThread() {
AMS_ABORT("HtcmiscImpl::ServerThread");
}
}

View file

@ -31,16 +31,24 @@ namespace ams::htc::server {
rpc::HtcmiscRpcServer m_rpc_server; rpc::HtcmiscRpcServer m_rpc_server;
os::ThreadType m_client_thread; os::ThreadType m_client_thread;
os::ThreadType m_server_thread; os::ThreadType m_server_thread;
os::Event m_event_61200; os::Event m_cancel_event;
u8 m_61228; bool m_cancelled;
os::Event m_event_61230; os::Event m_connection_event;
bool m_client_connected; bool m_client_connected;
bool m_server_connected; bool m_server_connected;
u8 m_6125A; bool m_connected;
os::SdkMutex m_connection_mutex; os::SdkMutex m_connection_mutex;
private:
static void ClientThreadEntry(void *arg) { static_cast<HtcmiscImpl *>(arg)->ClientThread(); }
static void ServerThreadEntry(void *arg) { static_cast<HtcmiscImpl *>(arg)->ServerThread(); }
void ClientThread();
void ServerThread();
public: public:
HtcmiscImpl(htclow::HtclowManager *htclow_manager); HtcmiscImpl(htclow::HtclowManager *htclow_manager);
~HtcmiscImpl();
public: public:
void Cancel();
/* TODO */ /* TODO */
}; };

View file

@ -0,0 +1,75 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "htc_observer.hpp"
namespace ams::htc::server {
Observer::Observer(const HtcmiscImpl &misc_impl)
: m_connect_event(os::EventClearMode_ManualClear, true),
m_disconnect_event(os::EventClearMode_ManualClear, true),
m_stop_event(os::EventClearMode_ManualClear),
m_misc_impl(misc_impl),
m_thread_running(false),
m_stopped(false),
m_connected(false),
m_is_service_available(false)
{
/* Initialize htcs library. */
AMS_ABORT("htcs::impl::HtcsManagerHolder::AddReference();");
/* Update our event state. */
this->UpdateEvent();
/* Start. */
R_ABORT_UNLESS(this->Start());
}
Result Observer::Start() {
/* Check that we're not already running. */
AMS_ASSERT(!m_thread_running);
/* Create the thread. */
R_TRY(os::CreateThread(std::addressof(m_observer_thread), ObserverThreadEntry, this, m_observer_thread_stack, sizeof(m_observer_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(htc, HtcObserver)));
/* Set the thread name pointer. */
os::SetThreadNamePointer(std::addressof(m_observer_thread), AMS_GET_SYSTEM_THREAD_NAME(htc, HtcObserver));
/* Mark our thread as running. */
m_thread_running = true;
m_stopped = false;
/* Start our thread. */
os::StartThread(std::addressof(m_observer_thread));
return ResultSuccess();
}
void Observer::UpdateEvent() {
if (m_connected && m_is_service_available) {
m_disconnect_event.Clear();
m_connect_event.Signal();
} else {
m_connect_event.Clear();
m_disconnect_event.Signal();
}
}
void Observer::ObserverThreadBody() {
AMS_ABORT("Observer::ObserverThreadBody");
}
}

View file

@ -23,15 +23,24 @@ namespace ams::htc::server {
private: private:
os::SystemEvent m_connect_event; os::SystemEvent m_connect_event;
os::SystemEvent m_disconnect_event; os::SystemEvent m_disconnect_event;
os::Event m_event_60; os::Event m_stop_event;
os::ThreadType m_observer_thread; os::ThreadType m_observer_thread;
const HtcmiscImpl &m_misc_impl; const HtcmiscImpl &m_misc_impl;
bool m_thread_running; bool m_thread_running;
bool m_stopped; bool m_stopped;
bool m_connected; bool m_connected;
bool m_is_service_available; bool m_is_service_available;
alignas(os::ThreadStackAlignment) u8 m_observer_thread_stack[os::MemoryPageSize];
public: public:
Observer(const HtcmiscImpl &misc_impl); Observer(const HtcmiscImpl &misc_impl);
private:
static void ObserverThreadEntry(void *arg) { static_cast<Observer *>(arg)->ObserverThreadBody(); }
void ObserverThreadBody();
private:
Result Start();
void UpdateEvent();
}; };
} }

View file

@ -0,0 +1,40 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "htc_htcmisc_rpc_server.hpp"
namespace ams::htc::server::rpc {
namespace {
constexpr inline size_t ReceiveThreadStackSize = os::MemoryPageSize;
alignas(os::ThreadStackAlignment) constinit u8 g_receive_thread_stack[ReceiveThreadStackSize];
}
HtcmiscRpcServer::HtcmiscRpcServer(driver::IDriver *driver, htclow::ChannelId channel)
: m_00(0),
m_driver(driver),
m_channel_id(channel),
m_receive_thread_stack(g_receive_thread_stack),
m_cancelled(false),
m_thread_running(false)
{
/* ... */
}
}

View file

@ -0,0 +1,52 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "htc_rpc_client.hpp"
namespace ams::htc::server::rpc {
namespace {
constexpr inline size_t ThreadStackSize = os::MemoryPageSize;
alignas(os::ThreadStackAlignment) constinit u8 g_receive_thread_stack[ThreadStackSize];
alignas(os::ThreadStackAlignment) constinit u8 g_send_thread_stack[ThreadStackSize];
constinit os::SdkMutex g_rpc_mutex;
}
RpcClient::RpcClient(driver::IDriver *driver, htclow::ChannelId channel)
: m_00(0),
m_driver(driver),
m_channel_id(channel),
m_receive_thread_stack(g_receive_thread_stack),
m_send_thread_stack(g_send_thread_stack),
m_mutex(g_rpc_mutex),
m_cancelled(false),
m_thread_running(false)
{
/* Initialize all events. */
/* TODO: MaxTaskCount? */
for (size_t i = 0; i < util::size(m_5F8_events); ++i) {
os::InitializeEvent(std::addressof(m_5F8_events[i]), false, os::EventClearMode_AutoClear);
os::InitializeEvent(std::addressof(m_1138_events[i]), false, os::EventClearMode_AutoClear);
}
/* TODO: Clear all of m_3C0 array to zero. */
}
}

View file

@ -28,7 +28,7 @@ namespace ams::htc::server::rpc {
void *m_send_thread_stack; void *m_send_thread_stack;
os::ThreadType m_receive_thread; os::ThreadType m_receive_thread;
os::ThreadType m_send_thread; os::ThreadType m_send_thread;
os::SdkMutex *m_p_mutex; os::SdkMutex &m_mutex;
/* TODO: m_task_id_free_list */ /* TODO: m_task_id_free_list */
/* TODO: m_task_table */ /* TODO: m_task_table */
/* TODO: m_3C0[0x48] */ /* TODO: m_3C0[0x48] */

View file

@ -351,6 +351,22 @@ namespace ams::htclow::ctrl {
this->DisconnectInternal(); this->DisconnectInternal();
} }
void HtcctrlService::DisconnectInternal() {
/* Disconnect, if we need to. */
if (m_state_machine->IsDisconnectionNeeded()) {
/* Send a disconnect packet. */
m_send_buffer.AddPacket(m_packet_factory->MakeDisconnectPacket());
/* Signal our event. */
m_event.Signal();
/* Wait for us to be disconnected. */
while (!m_state_machine->IsDisconnected()) {
m_condvar.Wait(m_mutex);
}
}
}
void HtcctrlService::Resume() { void HtcctrlService::Resume() {
/* Lock ourselves. */ /* Lock ourselves. */
std::scoped_lock lk(m_mutex); std::scoped_lock lk(m_mutex);

View file

@ -64,6 +64,13 @@ namespace ams::htclow::ctrl {
return !ctrl::IsDisconnected(m_state) && m_state != HtcctrlState_DriverConnected; return !ctrl::IsDisconnected(m_state) && m_state != HtcctrlState_DriverConnected;
} }
bool HtcctrlStateMachine::IsDisconnectionNeeded() {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);
return !ctrl::IsDisconnected(m_state) && m_state != HtcctrlState_Sleep && m_state != HtcctrlState_DriverConnected;
}
bool HtcctrlStateMachine::IsConnected() { bool HtcctrlStateMachine::IsConnected() {
/* Lock ourselves. */ /* Lock ourselves. */
std::scoped_lock lk(m_mutex); std::scoped_lock lk(m_mutex);

View file

@ -59,6 +59,7 @@ namespace ams::htclow::ctrl {
bool IsSleepingStatusChanged(); bool IsSleepingStatusChanged();
bool IsInformationNeeded(); bool IsInformationNeeded();
bool IsDisconnectionNeeded();
bool IsConnected(); bool IsConnected();
bool IsReadied(); bool IsReadied();

View file

@ -16,9 +16,17 @@
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "htclow_mux_channel_impl.hpp" #include "htclow_mux_channel_impl.hpp"
#include "../htclow_packet_factory.hpp" #include "../htclow_packet_factory.hpp"
#include "../htclow_default_channel_config.hpp"
namespace ams::htclow::mux { namespace ams::htclow::mux {
SendBuffer::SendBuffer(impl::ChannelInternalType channel, PacketFactory *pf)
: m_channel(channel), m_packet_factory(pf), m_ring_buffer(), m_packet_list(),
m_version(ProtocolVersion), m_flow_control_enabled(true), m_max_packet_size(DefaultChannelConfig.max_packet_size)
{
/* ... */
}
SendBuffer::~SendBuffer() { SendBuffer::~SendBuffer() {
m_ring_buffer.Clear(); m_ring_buffer.Clear();
this->Clear(); this->Clear();