mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-18 01:46:47 +00:00
htc: fixes, can now enter ReadyState with wip starlink code
This commit is contained in:
parent
5fc1981061
commit
f28a410ba0
7 changed files with 182 additions and 7 deletions
|
@ -111,7 +111,6 @@ namespace ams::htc::server {
|
||||||
if (m_rpc_client.WaitAny(htclow::ChannelState_Disconnected, m_cancel_event.GetBase()) != 0) {
|
if (m_rpc_client.WaitAny(htclow::ChannelState_Disconnected, m_cancel_event.GetBase()) != 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +149,6 @@ namespace ams::htc::server {
|
||||||
if (m_rpc_server.WaitAny(htclow::ChannelState_Disconnected, m_cancel_event.GetBase()) != 0) {
|
if (m_rpc_server.WaitAny(htclow::ChannelState_Disconnected, m_cancel_event.GetBase()) != 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
166
libraries/libstratosphere/source/htcfs/htcfs_client_impl.cpp
Normal file
166
libraries/libstratosphere/source/htcfs/htcfs_client_impl.cpp
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
* 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 "htcfs_client_impl.hpp"
|
||||||
|
#include "../htclow/htclow_default_channel_config.hpp"
|
||||||
|
|
||||||
|
namespace ams::htcfs {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/* TODO: Move to a header? */
|
||||||
|
constexpr u16 RpcChannelId = 0;
|
||||||
|
|
||||||
|
alignas(os::ThreadStackAlignment) constinit u8 g_monitor_thread_stack[os::MemoryPageSize];
|
||||||
|
|
||||||
|
constinit u8 g_cache[32_KB];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientImpl::ClientImpl(htclow::HtclowManager *manager)
|
||||||
|
: m_htclow_manager(manager),
|
||||||
|
m_cache_manager(g_cache, sizeof(g_cache)),
|
||||||
|
m_header_factory(),
|
||||||
|
m_mutex(),
|
||||||
|
m_module(htclow::ModuleId::Htcfs),
|
||||||
|
m_rpc_channel(manager),
|
||||||
|
m_data_channel(manager),
|
||||||
|
m_connected(false),
|
||||||
|
m_event(os::EventClearMode_ManualClear)
|
||||||
|
{
|
||||||
|
/* Start our thread. */
|
||||||
|
this->Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientImpl::Start() {
|
||||||
|
/* Create our thread. */
|
||||||
|
os::CreateThread(std::addressof(m_monitor_thread), ThreadEntry, this, g_monitor_thread_stack, sizeof(g_monitor_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(htc, HtcfsMonitor));
|
||||||
|
|
||||||
|
/* Set thread name pointer. */
|
||||||
|
os::SetThreadNamePointer(std::addressof(m_monitor_thread), AMS_GET_SYSTEM_THREAD_NAME(htc, HtcfsMonitor));
|
||||||
|
|
||||||
|
/* Start our thread. */
|
||||||
|
os::StartThread(std::addressof(m_monitor_thread));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientImpl::Cancel() {
|
||||||
|
/* Signal our event. */
|
||||||
|
m_event.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientImpl::Wait() {
|
||||||
|
/* Wait for and destroy our thread. */
|
||||||
|
os::WaitThread(std::addressof(m_monitor_thread));
|
||||||
|
os::DestroyThread(std::addressof(m_monitor_thread));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientImpl::ThreadBody() {
|
||||||
|
/* Loop forever, until we're cancelled. */
|
||||||
|
while (!m_event.TryWait()) {
|
||||||
|
/* Lock ourselves. */
|
||||||
|
std::scoped_lock lk(m_mutex);
|
||||||
|
|
||||||
|
/* Open our channel. */
|
||||||
|
R_ABORT_UNLESS(m_rpc_channel.Open(std::addressof(m_module), RpcChannelId));
|
||||||
|
|
||||||
|
/* Ensure that we clean up our channel when we're done. */
|
||||||
|
ON_SCOPE_EXIT {
|
||||||
|
m_rpc_channel.Close();
|
||||||
|
m_cache_manager.Invalidate();
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Set our channel config and buffers. */
|
||||||
|
m_rpc_channel.SetConfig(htclow::DefaultChannelConfig);
|
||||||
|
m_rpc_channel.SetReceiveBuffer(m_receive_buffer, sizeof(m_receive_buffer));
|
||||||
|
m_rpc_channel.SetSendBuffer(m_send_buffer, sizeof(m_send_buffer));
|
||||||
|
|
||||||
|
/* Wait for our channel state to be connectable. */
|
||||||
|
if (this->WaitAny(htclow::ChannelState_Connectable, m_event.GetBase()) != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure that when we're done, we reset our connected status. */
|
||||||
|
ON_SCOPE_EXIT { m_connected = false; };
|
||||||
|
|
||||||
|
/* Try to connect. */
|
||||||
|
const Result conn_result = m_rpc_channel.Connect();
|
||||||
|
if (R_FAILED(conn_result)) {
|
||||||
|
/* DEBUG */
|
||||||
|
R_ABORT_UNLESS(conn_result);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure that we manage our connection correctly. */
|
||||||
|
auto conn_guard = SCOPE_GUARD { m_rpc_channel.Shutdown(); };
|
||||||
|
|
||||||
|
/* Try to set up the protocol. */
|
||||||
|
const Result setup_result = this->SetUpProtocol();
|
||||||
|
if (R_FAILED(setup_result)) {
|
||||||
|
R_ABORT_UNLESS(setup_result);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We're properly connected now. */
|
||||||
|
m_connected = true;
|
||||||
|
conn_guard.Cancel();
|
||||||
|
|
||||||
|
/* Tear down the protocol when we're done processing. */
|
||||||
|
ON_SCOPE_EXIT { this->TearDownProtocol(); };
|
||||||
|
|
||||||
|
/* Wait to become disconnected. */
|
||||||
|
if (this->WaitAny(htclow::ChannelState_Disconnected, m_event.GetBase()) != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ClientImpl::WaitAny(htclow::ChannelState state, os::EventType *event) {
|
||||||
|
/* Wait. */
|
||||||
|
int idx = 0;
|
||||||
|
while (m_rpc_channel.GetChannelState() != state) {
|
||||||
|
/* Get the channel state event. */
|
||||||
|
os::EventType *channel_state_event = m_rpc_channel.GetChannelStateEvent();
|
||||||
|
|
||||||
|
/* Perform wait with lock temporarily not held. */
|
||||||
|
{
|
||||||
|
m_mutex.Unlock();
|
||||||
|
idx = os::WaitAny(channel_state_event, event);
|
||||||
|
m_mutex.Lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we're cancel-signalled, we're done. */
|
||||||
|
if (idx != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the channel state event. */
|
||||||
|
os::ClearEvent(channel_state_event);;
|
||||||
|
}
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ClientImpl::SetUpProtocol() {
|
||||||
|
/* TODO: Actual client <-> host RPC here. */
|
||||||
|
m_header_factory.SetVersion(1);
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientImpl::TearDownProtocol() {
|
||||||
|
/* Set the header factory version to zero. */
|
||||||
|
m_header_factory.SetVersion(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -32,11 +32,15 @@ namespace ams::htcfs {
|
||||||
HeaderFactory m_header_factory;
|
HeaderFactory m_header_factory;
|
||||||
os::SdkMutex m_mutex;
|
os::SdkMutex m_mutex;
|
||||||
htclow::Module m_module;
|
htclow::Module m_module;
|
||||||
htclow::Channel m_channel;
|
htclow::Channel m_rpc_channel;
|
||||||
htclow::Channel m_data_channel;
|
htclow::Channel m_data_channel;
|
||||||
bool m_connected;
|
bool m_connected;
|
||||||
os::ThreadType m_monitor_thread;
|
os::ThreadType m_monitor_thread;
|
||||||
os::Event m_event;
|
os::Event m_event;
|
||||||
|
private:
|
||||||
|
static void ThreadEntry(void *arg) { static_cast<ClientImpl *>(arg)->ThreadBody(); }
|
||||||
|
|
||||||
|
void ThreadBody();
|
||||||
public:
|
public:
|
||||||
ClientImpl(htclow::HtclowManager *manager);
|
ClientImpl(htclow::HtclowManager *manager);
|
||||||
|
|
||||||
|
@ -48,6 +52,11 @@ namespace ams::htcfs {
|
||||||
void Start();
|
void Start();
|
||||||
void Cancel();
|
void Cancel();
|
||||||
void Wait();
|
void Wait();
|
||||||
|
private:
|
||||||
|
int WaitAny(htclow::ChannelState state, os::EventType *event);
|
||||||
|
|
||||||
|
Result SetUpProtocol();
|
||||||
|
void TearDownProtocol();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,8 @@ namespace ams::htcfs {
|
||||||
public:
|
public:
|
||||||
HeaderFactory() : m_version() { /* ... */ }
|
HeaderFactory() : m_version() { /* ... */ }
|
||||||
public:
|
public:
|
||||||
/* ... */
|
s16 GetVersion() const { return m_version; }
|
||||||
|
void SetVersion(s16 version) { m_version = version; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace ams::htcfs {
|
||||||
|
|
||||||
static constexpr inline size_t NumServers = 1;
|
static constexpr inline size_t NumServers = 1;
|
||||||
static constexpr inline size_t MaxSessions = 30;
|
static constexpr inline size_t MaxSessions = 30;
|
||||||
static constexpr inline sm::ServiceName ServiceName = sm::ServiceName::Encode("htcfs");
|
static constexpr inline sm::ServiceName ServiceName = sm::ServiceName::Encode("file_io");
|
||||||
|
|
||||||
struct ServerOptions {
|
struct ServerOptions {
|
||||||
static constexpr size_t PointerBufferSize = 0x1000;
|
static constexpr size_t PointerBufferSize = 0x1000;
|
||||||
|
|
|
@ -21,6 +21,8 @@ namespace ams::htclow::ctrl {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
constexpr auto JsonParseFlags = rapidjson::kParseTrailingCommasFlag | rapidjson::kParseInsituFlag;
|
||||||
|
|
||||||
void ParseBody(s16 *out_version, const char **out_channels, int *out_num_channels, int max_channels, void *str, size_t str_size) {
|
void ParseBody(s16 *out_version, const char **out_channels, int *out_num_channels, int max_channels, void *str, size_t str_size) {
|
||||||
/* Create JSON handler. */
|
/* Create JSON handler. */
|
||||||
JsonHandler json_handler(out_version, out_channels, out_num_channels, max_channels);
|
JsonHandler json_handler(out_version, out_channels, out_num_channels, max_channels);
|
||||||
|
@ -32,7 +34,7 @@ namespace ams::htclow::ctrl {
|
||||||
rapidjson::InsituStringStream json_stream(static_cast<char *>(str));
|
rapidjson::InsituStringStream json_stream(static_cast<char *>(str));
|
||||||
|
|
||||||
/* Parse the json. */
|
/* Parse the json. */
|
||||||
json_reader.Parse(json_stream, json_handler);
|
json_reader.Parse<JsonParseFlags>(json_stream, json_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool IsNumericCharacter(char c) {
|
constexpr bool IsNumericCharacter(char c) {
|
||||||
|
|
|
@ -303,4 +303,3 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue