htc: declare and begin impl of HtclowManagerImpl interface

This commit is contained in:
Michael Scire 2021-02-09 12:36:37 -08:00 committed by SciresM
parent 968ce12492
commit e20c2450ce
20 changed files with 405 additions and 9 deletions

View file

@ -36,6 +36,8 @@ namespace ams::htclow {
struct ChannelConfig {
bool flow_control_enabled;
bool handshake_enabled;
size_t max_packet_size;
};
constexpr bool IsStateTransitionAllowed(ChannelState from, ChannelState to) {

View file

@ -21,6 +21,7 @@ namespace ams::htclow {
enum class ModuleId : u8 {
Htcfs = 1,
Htcmisc = 3,
Htcs = 4,
};

View file

@ -57,8 +57,8 @@ namespace ams::htc::server::driver {
R_TRY(m_manager->Open(GetHtclowChannel(channel, m_module_id)));
/* Set the send/receive buffers. */
m_manager->SetReceiveBuffer(receive_buffer, receive_buffer_size);
m_manager->SetSendBuffer(send_buffer, send_buffer_size);
m_manager->SetReceiveBuffer(GetHtclowChannel(channel, m_module_id), receive_buffer, receive_buffer_size);
m_manager->SetSendBuffer(GetHtclowChannel(channel, m_module_id), send_buffer, send_buffer_size);
return ResultSuccess();
}
@ -151,7 +151,7 @@ namespace ams::htc::server::driver {
size_t received = 0;
do {
size_t cur_received;
const Result result = this->ReceiveInternal(std::addressof(cur_received), static_cast<u8 *>(dst) + received, static_cast<size_t>(src_size) - received, channel, option);
const Result result = this->ReceiveInternal(std::addressof(cur_received), static_cast<u8 *>(dst) + received, static_cast<size_t>(dst_size) - received, channel, option);
if (R_FAILED(result)) {
if (htclow::ResultChannelReceiveBufferEmpty::Includes(result)) {

View file

@ -59,4 +59,9 @@ namespace ams::htclow::driver {
return m_open_driver;
}
void DriverManager::SetDebugDriver(IDriver *driver) {
m_debug_driver = driver;
m_driver_type = impl::DriverType::Debug;
}
}

View file

@ -35,6 +35,8 @@ namespace ams::htclow::driver {
Result OpenDriver(impl::DriverType driver_type);
IDriver *GetCurrentDriver();
void SetDebugDriver(IDriver *driver);
};
}

View file

@ -0,0 +1,28 @@
/*
* 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/>.
*/
#pragma once
#include <stratosphere.hpp>
#include "htclow_packet.hpp"
namespace ams::htclow {
constexpr inline const ChannelConfig DefaultChannelConfig = {
.flow_control_enabled = true,
.handshake_enabled = true,
.max_packet_size = 0xE000 + sizeof(PacketHeader),
};
}

View file

@ -36,8 +36,104 @@ namespace ams::htclow {
return m_impl->CloseDriver();
}
Result HtclowManager::Open(impl::ChannelInternalType channel) {
return m_impl->Open(channel);
}
Result HtclowManager::Close(impl::ChannelInternalType channel) {
return m_impl->Close(channel);
}
void HtclowManager::Resume() {
return m_impl->Resume();
}
void HtclowManager::Suspend() {
return m_impl->Suspend();
}
Result HtclowManager::ConnectBegin(u32 *out_task_id, impl::ChannelInternalType channel) {
return m_impl->ConnectBegin(out_task_id, channel);
}
Result HtclowManager::ConnectEnd(impl::ChannelInternalType channel, u32 task_id) {
return m_impl->ConnectEnd(channel, task_id);
}
void HtclowManager::Disconnect() {
return m_impl->Disconnect();
}
Result HtclowManager::FlushBegin(u32 *out_task_id, impl::ChannelInternalType channel) {
return m_impl->FlushBegin(out_task_id, channel);
}
Result HtclowManager::FlushEnd(u32 task_id) {
return m_impl->FlushEnd(task_id);
}
ChannelState HtclowManager::GetChannelState(impl::ChannelInternalType channel) {
return m_impl->GetChannelState(channel);
}
os::EventType *HtclowManager::GetChannelStateEvent(impl::ChannelInternalType channel) {
return m_impl->GetChannelStateEvent(channel);
}
impl::DriverType HtclowManager::GetDriverType() {
return m_impl->GetDriverType();
}
os::EventType *HtclowManager::GetTaskEvent(u32 task_id) {
return m_impl->GetTaskEvent(task_id);
}
void HtclowManager::NotifyAsleep() {
return m_impl->NotifyAsleep();
}
void HtclowManager::NotifyAwake() {
return m_impl->NotifyAwake();
}
Result HtclowManager::ReceiveBegin(u32 *out_task_id, impl::ChannelInternalType channel, bool blocking) {
return m_impl->ReceiveBegin(out_task_id, channel, blocking);
}
Result HtclowManager::ReceiveEnd(size_t *out, void *dst, size_t dst_size, impl::ChannelInternalType channel, u32 task_id) {
return m_impl->ReceiveEnd(out, dst, dst_size, channel, task_id);
}
Result HtclowManager::SendBegin(u32 *out_task_id, size_t *out, const void *src, size_t src_size, impl::ChannelInternalType channel) {
return m_impl->SendBegin(out_task_id, out, src, src_size, channel);
}
Result HtclowManager::SendEnd(u32 task_id) {
return m_impl->SendEnd(task_id);
}
void HtclowManager::SetConfig(impl::ChannelInternalType channel, const ChannelConfig &config) {
return m_impl->SetConfig(channel, config);
}
void HtclowManager::SetDebugDriver(driver::IDriver *driver) {
return m_impl->SetDebugDriver(driver);
}
void HtclowManager::SetReceiveBuffer(impl::ChannelInternalType channel, void *buf, size_t buf_size) {
return m_impl->SetReceiveBuffer(channel, buf, buf_size);
}
void HtclowManager::SetSendBuffer(impl::ChannelInternalType channel, void *buf, size_t buf_size) {
return m_impl->SetSendBuffer(channel, buf, buf_size);
}
void HtclowManager::SetSendBufferWithData(impl::ChannelInternalType channel, const void *buf, size_t buf_size) {
return m_impl->SetSendBufferWithData(channel, buf, buf_size);
}
Result HtclowManager::Shutdown(impl::ChannelInternalType channel) {
return m_impl->Shutdown(channel);
}
}

View file

@ -15,6 +15,7 @@
*/
#pragma once
#include <stratosphere.hpp>
#include "driver/htclow_i_driver.hpp"
namespace ams::htclow {
@ -31,7 +32,45 @@ namespace ams::htclow {
Result OpenDriver(impl::DriverType driver_type);
void CloseDriver();
Result Open(impl::ChannelInternalType channel);
Result Close(impl::ChannelInternalType channel);
void Resume();
void Suspend();
Result ConnectBegin(u32 *out_task_id, impl::ChannelInternalType channel);
Result ConnectEnd(impl::ChannelInternalType channel, u32 task_id);
void Disconnect();
Result FlushBegin(u32 *out_task_id, impl::ChannelInternalType channel);
Result FlushEnd(u32 task_id);
ChannelState GetChannelState(impl::ChannelInternalType channel);
os::EventType *GetChannelStateEvent(impl::ChannelInternalType channel);
impl::DriverType GetDriverType();
os::EventType *GetTaskEvent(u32 task_id);
void NotifyAsleep();
void NotifyAwake();
Result ReceiveBegin(u32 *out_task_id, impl::ChannelInternalType channel, bool blocking);
Result ReceiveEnd(size_t *out, void *dst, size_t dst_size, impl::ChannelInternalType channel, u32 task_id);
Result SendBegin(u32 *out_task_id, size_t *out, const void *src, size_t src_size, impl::ChannelInternalType channel);
Result SendEnd(u32 task_id);
void SetConfig(impl::ChannelInternalType channel, const ChannelConfig &config);
void SetDebugDriver(driver::IDriver *driver);
void SetReceiveBuffer(impl::ChannelInternalType channel, void *buf, size_t buf_size);
void SetSendBuffer(impl::ChannelInternalType channel, void *buf, size_t buf_size);
void SetSendBufferWithData(impl::ChannelInternalType channel, const void *buf, size_t buf_size);
Result Shutdown(impl::ChannelInternalType channel);
};
}

View file

@ -56,8 +56,116 @@ namespace ams::htclow {
AMS_ABORT("HtclowManagerImpl::CloseDriver");
}
Result HtclowManagerImpl::Open(impl::ChannelInternalType channel) {
return m_mux.Open(channel);
}
Result HtclowManagerImpl::Close(impl::ChannelInternalType channel) {
/* TODO: Used by HtclowDriver */
AMS_ABORT("HtclowManagerImpl::Close");
}
void HtclowManagerImpl::Resume() {
AMS_ABORT("HtclowManagerImpl::Resume");
}
void HtclowManagerImpl::Suspend() {
AMS_ABORT("HtclowManagerImpl::Suspend");
}
Result HtclowManagerImpl::ConnectBegin(u32 *out_task_id, impl::ChannelInternalType channel) {
/* TODO: Used by HtclowDriver */
AMS_ABORT("HtclowManagerImpl::ConnectBegin");
}
Result HtclowManagerImpl::ConnectEnd(impl::ChannelInternalType channel, u32 task_id) {
/* TODO: Used by HtclowDriver */
AMS_ABORT("HtclowManagerImpl::ConnectEnd");
}
void HtclowManagerImpl::Disconnect() {
AMS_ABORT("HtclowManagerImpl::Disconnect");
}
Result HtclowManagerImpl::FlushBegin(u32 *out_task_id, impl::ChannelInternalType channel) {
AMS_ABORT("HtclowManagerImpl::FlushBegin");
}
Result HtclowManagerImpl::FlushEnd(u32 task_id) {
AMS_ABORT("HtclowManagerImpl::FlushEnd");
}
ChannelState HtclowManagerImpl::GetChannelState(impl::ChannelInternalType channel) {
/* TODO: Used by HtclowDriver */
AMS_ABORT("HtclowManagerImpl::GetChannelState");
}
os::EventType *HtclowManagerImpl::GetChannelStateEvent(impl::ChannelInternalType channel) {
/* TODO: Used by HtclowDriver */
AMS_ABORT("HtclowManagerImpl::GetChannelStateEvent");
}
impl::DriverType HtclowManagerImpl::GetDriverType() {
AMS_ABORT("HtclowManagerImpl::GetDriverType");
}
os::EventType *HtclowManagerImpl::GetTaskEvent(u32 task_id) {
return m_mux.GetTaskEvent(task_id);
}
void HtclowManagerImpl::NotifyAsleep() {
AMS_ABORT("HtclowManagerImpl::NotifyAsleep");
}
void HtclowManagerImpl::NotifyAwake() {
AMS_ABORT("HtclowManagerImpl::NotifyAwake");
}
Result HtclowManagerImpl::ReceiveBegin(u32 *out_task_id, impl::ChannelInternalType channel, bool blocking) {
/* TODO: Used by HtclowDriver */
AMS_ABORT("HtclowManagerImpl::ReceiveBegin");
}
Result HtclowManagerImpl::ReceiveEnd(size_t *out, void *dst, size_t dst_size, impl::ChannelInternalType channel, u32 task_id) {
/* TODO: Used by HtclowDriver */
AMS_ABORT("HtclowManagerImpl::ReceiveEnd");
}
Result HtclowManagerImpl::SendBegin(u32 *out_task_id, size_t *out, const void *src, size_t src_size, impl::ChannelInternalType channel) {
/* TODO: Used by HtclowDriver */
AMS_ABORT("HtclowManagerImpl::SendBegin");
}
Result HtclowManagerImpl::SendEnd(u32 task_id) {
/* TODO: Used by HtclowDriver */
AMS_ABORT("HtclowManagerImpl::SendEnd");
}
void HtclowManagerImpl::SetConfig(impl::ChannelInternalType channel, const ChannelConfig &config) {
AMS_ABORT("HtclowManagerImpl::SetConfig");
}
void HtclowManagerImpl::SetDebugDriver(driver::IDriver *driver) {
m_driver_manager.SetDebugDriver(driver);
}
void HtclowManagerImpl::SetReceiveBuffer(impl::ChannelInternalType channel, void *buf, size_t buf_size) {
/* TODO: Used by HtclowDriver */
AMS_ABORT("HtclowManagerImpl::SetReceiveBuffer");
}
void HtclowManagerImpl::SetSendBuffer(impl::ChannelInternalType channel, void *buf, size_t buf_size) {
/* TODO: Used by HtclowDriver */
AMS_ABORT("HtclowManagerImpl::SetSendBuffer");
}
void HtclowManagerImpl::SetSendBufferWithData(impl::ChannelInternalType channel, const void *buf, size_t buf_size) {
AMS_ABORT("HtclowManagerImpl::SetSendBufferWithData");
}
Result HtclowManagerImpl::Shutdown(impl::ChannelInternalType channel) {
/* TODO: Used by HtclowDriver */
AMS_ABORT("HtclowManagerImpl::Shutdown");
}
}

View file

@ -44,7 +44,45 @@ namespace ams::htclow {
Result OpenDriver(impl::DriverType driver_type);
void CloseDriver();
Result Open(impl::ChannelInternalType channel);
Result Close(impl::ChannelInternalType channel);
void Resume();
void Suspend();
Result ConnectBegin(u32 *out_task_id, impl::ChannelInternalType channel);
Result ConnectEnd(impl::ChannelInternalType channel, u32 task_id);
void Disconnect();
Result FlushBegin(u32 *out_task_id, impl::ChannelInternalType channel);
Result FlushEnd(u32 task_id);
ChannelState GetChannelState(impl::ChannelInternalType channel);
os::EventType *GetChannelStateEvent(impl::ChannelInternalType channel);
impl::DriverType GetDriverType();
os::EventType *GetTaskEvent(u32 task_id);
void NotifyAsleep();
void NotifyAwake();
Result ReceiveBegin(u32 *out_task_id, impl::ChannelInternalType channel, bool blocking);
Result ReceiveEnd(size_t *out, void *dst, size_t dst_size, impl::ChannelInternalType channel, u32 task_id);
Result SendBegin(u32 *out_task_id, size_t *out, const void *src, size_t src_size, impl::ChannelInternalType channel);
Result SendEnd(u32 task_id);
void SetConfig(impl::ChannelInternalType channel, const ChannelConfig &config);
void SetDebugDriver(driver::IDriver *driver);
void SetReceiveBuffer(impl::ChannelInternalType channel, void *buf, size_t buf_size);
void SetSendBuffer(impl::ChannelInternalType channel, void *buf, size_t buf_size);
void SetSendBufferWithData(impl::ChannelInternalType channel, const void *buf, size_t buf_size);
Result Shutdown(impl::ChannelInternalType channel);
};
}

View file

@ -166,4 +166,27 @@ namespace ams::htclow::mux {
}
}
Result Mux::Open(impl::ChannelInternalType channel) {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);
/* Check that the channel doesn't already exist. */
R_UNLESS(!m_channel_impl_map.Exists(channel), htclow::ResultChannelAlreadyExist());
/* Add the channel. */
R_TRY(m_channel_impl_map.AddChannel(channel));
/* Set the channel version. */
m_channel_impl_map.GetChannelImpl(channel).SetVersion(m_version);
return ResultSuccess();
}
os::EventType *Mux::GetTaskEvent(u32 task_id) {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);
return m_task_manager.GetTaskEvent(task_id);
}
}

View file

@ -53,6 +53,10 @@ namespace ams::htclow::mux {
void UpdateChannelState();
void UpdateMuxState();
public:
Result Open(impl::ChannelInternalType channel);
os::EventType *GetTaskEvent(u32 task_id);
private:
Result CheckChannelExist(impl::ChannelInternalType channel);

View file

@ -16,9 +16,20 @@
#include <stratosphere.hpp>
#include "htclow_mux_channel_impl.hpp"
#include "../ctrl/htclow_ctrl_state_machine.hpp"
#include "../htclow_default_channel_config.hpp"
namespace ams::htclow::mux {
ChannelImpl::ChannelImpl(impl::ChannelInternalType channel, PacketFactory *pf, ctrl::HtcctrlStateMachine *sm, TaskManager *tm, os::Event *ev)
: m_channel(channel), m_packet_factory(pf), m_state_machine(sm), m_task_manager(tm), m_event(ev),
m_send_buffer(m_channel, pf), m_receive_buffer(), m_version(ProtocolVersion), m_config(DefaultChannelConfig),
m_offset(0), m_total_send_size(0), m_next_max_data(0), m_cur_max_data(0), m_share(),
m_state_change_event(os::EventClearMode_ManualClear), m_state(ChannelState_Unconnectable)
{
this->UpdateState();
}
void ChannelImpl::SetVersion(s16 version) {
/* Sanity check the version. */
AMS_ASSERT(version <= ProtocolVersion);

View file

@ -43,10 +43,10 @@ namespace ams::htclow::mux {
RingBuffer m_receive_buffer;
s16 m_version;
ChannelConfig m_config;
u64 m_offset;
u64 m_total_send_size;
u64 m_next_max_data;
u64 m_cur_max_data;
u64 m_offset;
std::optional<u64> m_share;
os::Event m_state_change_event;
ChannelState m_state;

View file

@ -43,4 +43,28 @@ namespace ams::htclow::mux {
return this->GetChannelImpl(it->second);
}
Result ChannelImplMap::AddChannel(impl::ChannelInternalType channel) {
/* Find a free storage. */
int idx;
for (idx = 0; idx < MaxChannelCount; ++idx) {
if (!m_storage_valid[idx]) {
break;
}
}
/* Validate that the storage is free. */
R_UNLESS(idx < MaxChannelCount, htclow::ResultOutOfResource());
/* Create the channel impl. */
std::construct_at(GetPointer(m_channel_storage[idx]), channel, m_packet_factory, m_state_machine, m_task_manager, m_event);
/* Mark the storage valid. */
m_storage_valid[idx] = true;
/* Insert into our map. */
m_map.insert(std::pair<const impl::ChannelInternalType, int>{channel, idx});
return ResultSuccess();
}
}

View file

@ -46,6 +46,8 @@ namespace ams::htclow::mux {
bool Exists(impl::ChannelInternalType channel) const {
return m_map.find(channel) != m_map.end();
}
Result AddChannel(impl::ChannelInternalType channel);
private:
public:
MapType &GetMap() {

View file

@ -18,6 +18,14 @@
namespace ams::htclow::mux {
os::EventType *TaskManager::GetTaskEvent(u32 task_id) {
/* Check pre-conditions. */
AMS_ASSERT(0 <= task_id && task_id < MaxTaskCount);
AMS_ASSERT(m_valid[task_id]);
return std::addressof(m_tasks[task_id].event);
}
void TaskManager::NotifyDisconnect(impl::ChannelInternalType channel) {
for (auto i = 0; i < MaxTaskCount; ++i) {
if (m_valid[i] && m_tasks[i].channel == channel) {

View file

@ -51,6 +51,8 @@ namespace ams::htclow::mux {
public:
TaskManager() : m_valid() { /* ... */ }
os::EventType *GetTaskEvent(u32 task_id);
void NotifyDisconnect(impl::ChannelInternalType channel);
void NotifyReceiveData(impl::ChannelInternalType channel, size_t size);
void NotifySendReady();

View file

@ -23,8 +23,11 @@ namespace ams::htclow {
R_DEFINE_ERROR_RESULT(ConnectionFailure, 1);
R_DEFINE_ERROR_RESULT(UnknownDriverType, 3);
R_DEFINE_ERROR_RESULT(NonBlockingReceiveFailed, 5);
R_DEFINE_ERROR_RESULT(ChannelAlreadyExist, 9);
R_DEFINE_ERROR_RESULT(ChannelNotExist, 10);
R_DEFINE_ERROR_RESULT(OutOfResource, 151);
R_DEFINE_ERROR_RESULT(InvalidChannelState, 200);
R_DEFINE_ERROR_RESULT(InvalidChannelStateDisconnected, 201);

View file

@ -21,6 +21,7 @@
#include <vapours/util/util_type_traits.hpp>
#include <vapours/util/util_alignment.hpp>
#include <vapours/util/util_size.hpp>
#include <vapours/util/util_int_util.hpp>
#include <vapours/util/util_aligned_buffer.hpp>
#include <vapours/util/util_endian.hpp>
#include <vapours/util/util_exchange.hpp>
@ -39,7 +40,6 @@
#include <vapours/util/util_uuid.hpp>
#include <vapours/util/util_bounded_map.hpp>
#include <vapours/util/util_overlap.hpp>
#include <vapours/util/util_int_util.hpp>
#include <vapours/util/util_string_util.hpp>
#include <vapours/util/util_string_view.hpp>
#include <vapours/util/util_variadic.hpp>