From 87165e0f08afe0579be7b0fdf61baaa17d3dcedb Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Tue, 9 Feb 2021 17:42:39 -0800 Subject: [PATCH] htc: implement remaining htclow::HtclowManagerImpl funcs (mux impls pending) --- .../htclow/driver/htclow_driver_manager.cpp | 8 ++ .../htclow/driver/htclow_driver_manager.hpp | 2 + .../source/htclow/htclow_manager_impl.cpp | 97 ++++++++++++------- .../source/htclow/mux/htclow_mux.cpp | 36 +++++++ .../source/htclow/mux/htclow_mux.hpp | 4 + .../htclow/mux/htclow_mux_channel_impl.cpp | 31 ++++++ .../htclow/mux/htclow_mux_channel_impl.hpp | 4 + .../htclow/mux/htclow_mux_ring_buffer.cpp | 23 +++++ .../htclow/mux/htclow_mux_ring_buffer.hpp | 3 + .../htclow/mux/htclow_mux_send_buffer.cpp | 12 +++ .../htclow/mux/htclow_mux_send_buffer.hpp | 4 + 11 files changed, 190 insertions(+), 34 deletions(-) diff --git a/libraries/libstratosphere/source/htclow/driver/htclow_driver_manager.cpp b/libraries/libstratosphere/source/htclow/driver/htclow_driver_manager.cpp index 1b79aeb93..e08f2529d 100644 --- a/libraries/libstratosphere/source/htclow/driver/htclow_driver_manager.cpp +++ b/libraries/libstratosphere/source/htclow/driver/htclow_driver_manager.cpp @@ -49,9 +49,17 @@ namespace ams::htclow::driver { return htclow::ResultUnknownDriverType(); } + /* Set the driver type. */ + m_driver_type = driver_type; + return ResultSuccess(); } + impl::DriverType DriverManager::GetDriverType() { + /* Lock ourselves. */ + return m_driver_type.value_or(impl::DriverType::Unknown); + } + IDriver *DriverManager::GetCurrentDriver() { /* Lock ourselves. */ std::scoped_lock lk(m_mutex); diff --git a/libraries/libstratosphere/source/htclow/driver/htclow_driver_manager.hpp b/libraries/libstratosphere/source/htclow/driver/htclow_driver_manager.hpp index c1ae457fb..1b0d3d967 100644 --- a/libraries/libstratosphere/source/htclow/driver/htclow_driver_manager.hpp +++ b/libraries/libstratosphere/source/htclow/driver/htclow_driver_manager.hpp @@ -34,6 +34,8 @@ namespace ams::htclow::driver { Result OpenDriver(impl::DriverType driver_type); + impl::DriverType GetDriverType(); + IDriver *GetCurrentDriver(); void SetDebugDriver(IDriver *driver); diff --git a/libraries/libstratosphere/source/htclow/htclow_manager_impl.cpp b/libraries/libstratosphere/source/htclow/htclow_manager_impl.cpp index 97c5b51fa..7ff313ac5 100644 --- a/libraries/libstratosphere/source/htclow/htclow_manager_impl.cpp +++ b/libraries/libstratosphere/source/htclow/htclow_manager_impl.cpp @@ -15,6 +15,7 @@ */ #include #include "htclow_manager_impl.hpp" +#include "htclow_default_channel_config.hpp" namespace ams::htclow { @@ -53,7 +54,24 @@ namespace ams::htclow { } void HtclowManagerImpl::CloseDriver() { - AMS_ABORT("HtclowManagerImpl::CloseDriver"); + /* Close the driver, if we're open. */ + if (m_is_driver_open) { + /* Cancel the driver. */ + m_driver_manager.Cancel(); + + /* Stop our listener. */ + m_listener.Cancel(); + m_listener.Wait(); + + /* Close the driver. */ + m_driver_manager.CloseDriver(); + + /* Set the driver type to unknown. */ + m_ctrl_service.SetDriverType(impl::DriverType::Unknown); + + /* Note the driver as closed. */ + m_is_driver_open = false; + } } Result HtclowManagerImpl::Open(impl::ChannelInternalType channel) { @@ -61,52 +79,70 @@ namespace ams::htclow { } Result HtclowManagerImpl::Close(impl::ChannelInternalType channel) { - /* TODO: Used by HtclowDriver */ - AMS_ABORT("HtclowManagerImpl::Close"); + return m_mux.Close(channel); } void HtclowManagerImpl::Resume() { - AMS_ABORT("HtclowManagerImpl::Resume"); + /* Get our driver. */ + auto *driver = m_driver_manager.GetCurrentDriver(); + + /* Resume our driver. */ + driver->Resume(); + + /* Start the listener. */ + m_listener.Start(driver); + + /* Resume our control service. */ + m_ctrl_service.Resume(); } void HtclowManagerImpl::Suspend() { - AMS_ABORT("HtclowManagerImpl::Suspend"); + /* Suspend our control service. */ + m_ctrl_service.Suspend(); + + /* Stop our listener. */ + m_listener.Cancel(); + m_listener.Wait(); + + /* Suspend our driver. */ + m_driver_manager.GetCurrentDriver()->Suspend(); } Result HtclowManagerImpl::ConnectBegin(u32 *out_task_id, impl::ChannelInternalType channel) { - /* TODO: Used by HtclowDriver */ - AMS_ABORT("HtclowManagerImpl::ConnectBegin"); + /* Begin connecting. */ + R_TRY(m_mux.ConnectBegin(out_task_id, channel)); + + /* Try to ready ourselves. */ + m_ctrl_service.TryReady(); + return ResultSuccess(); } Result HtclowManagerImpl::ConnectEnd(impl::ChannelInternalType channel, u32 task_id) { - /* TODO: Used by HtclowDriver */ - AMS_ABORT("HtclowManagerImpl::ConnectEnd"); + return m_mux.ConnectEnd(channel, task_id); } void HtclowManagerImpl::Disconnect() { - AMS_ABORT("HtclowManagerImpl::Disconnect"); + return m_ctrl_service.Disconnect(); } Result HtclowManagerImpl::FlushBegin(u32 *out_task_id, impl::ChannelInternalType channel) { - AMS_ABORT("HtclowManagerImpl::FlushBegin"); + return m_mux.FlushBegin(out_task_id, channel); } Result HtclowManagerImpl::FlushEnd(u32 task_id) { - AMS_ABORT("HtclowManagerImpl::FlushEnd"); + return m_mux.FlushEnd(task_id); } ChannelState HtclowManagerImpl::GetChannelState(impl::ChannelInternalType channel) { - /* TODO: Used by HtclowDriver */ - AMS_ABORT("HtclowManagerImpl::GetChannelState"); + return m_mux.GetChannelState(channel); } os::EventType *HtclowManagerImpl::GetChannelStateEvent(impl::ChannelInternalType channel) { - /* TODO: Used by HtclowDriver */ - AMS_ABORT("HtclowManagerImpl::GetChannelStateEvent"); + return m_mux.GetChannelStateEvent(channel); } impl::DriverType HtclowManagerImpl::GetDriverType() { - AMS_ABORT("HtclowManagerImpl::GetDriverType"); + return m_driver_manager.GetDriverType(); } os::EventType *HtclowManagerImpl::GetTaskEvent(u32 task_id) { @@ -114,31 +150,27 @@ namespace ams::htclow { } void HtclowManagerImpl::NotifyAsleep() { - AMS_ABORT("HtclowManagerImpl::NotifyAsleep"); + return m_ctrl_service.NotifyAsleep(); } void HtclowManagerImpl::NotifyAwake() { - AMS_ABORT("HtclowManagerImpl::NotifyAwake"); + return m_ctrl_service.NotifyAwake(); } Result HtclowManagerImpl::ReceiveBegin(u32 *out_task_id, impl::ChannelInternalType channel, bool blocking) { - /* TODO: Used by HtclowDriver */ - AMS_ABORT("HtclowManagerImpl::ReceiveBegin"); + return m_mux.ReceiveBegin(out_task_id, channel, blocking); } 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"); + return m_mux.ReceiveEnd(out, dst, dst_size, channel, task_id); } 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"); + return m_mux.SendBegin(out_task_id, out, src, src_size, channel); } Result HtclowManagerImpl::SendEnd(u32 task_id) { - /* TODO: Used by HtclowDriver */ - AMS_ABORT("HtclowManagerImpl::SendEnd"); + return m_mux.SendEnd(task_id); } void HtclowManagerImpl::SetConfig(impl::ChannelInternalType channel, const ChannelConfig &config) { @@ -150,22 +182,19 @@ namespace ams::htclow { } void HtclowManagerImpl::SetReceiveBuffer(impl::ChannelInternalType channel, void *buf, size_t buf_size) { - /* TODO: Used by HtclowDriver */ - AMS_ABORT("HtclowManagerImpl::SetReceiveBuffer"); + return m_mux.SetReceiveBuffer(channel, buf, buf_size); } void HtclowManagerImpl::SetSendBuffer(impl::ChannelInternalType channel, void *buf, size_t buf_size) { - /* TODO: Used by HtclowDriver */ - AMS_ABORT("HtclowManagerImpl::SetSendBuffer"); + return m_mux.SetSendBuffer(channel, buf, buf_size, m_driver_manager.GetDriverType() == impl::DriverType::Usb ? sizeof(PacketBody) : DefaultChannelConfig.max_packet_size); } void HtclowManagerImpl::SetSendBufferWithData(impl::ChannelInternalType channel, const void *buf, size_t buf_size) { - AMS_ABORT("HtclowManagerImpl::SetSendBufferWithData"); + return m_mux.SetSendBufferWithData(channel, buf, buf_size, m_driver_manager.GetDriverType() == impl::DriverType::Usb ? sizeof(PacketBody) : DefaultChannelConfig.max_packet_size); } Result HtclowManagerImpl::Shutdown(impl::ChannelInternalType channel) { - /* TODO: Used by HtclowDriver */ - AMS_ABORT("HtclowManagerImpl::Shutdown"); + return m_mux.Shutdown(channel); } } diff --git a/libraries/libstratosphere/source/htclow/mux/htclow_mux.cpp b/libraries/libstratosphere/source/htclow/mux/htclow_mux.cpp index a9e907511..656ce104f 100644 --- a/libraries/libstratosphere/source/htclow/mux/htclow_mux.cpp +++ b/libraries/libstratosphere/source/htclow/mux/htclow_mux.cpp @@ -189,4 +189,40 @@ namespace ams::htclow::mux { return m_task_manager.GetTaskEvent(task_id); } + void Mux::SetSendBuffer(impl::ChannelInternalType channel, void *buf, size_t buf_size, size_t max_packet_size) { + /* Lock ourselves. */ + std::scoped_lock lk(m_mutex); + + /* Find the channel. */ + auto it = m_channel_impl_map.GetMap().find(channel); + AMS_ABORT_UNLESS(it != m_channel_impl_map.GetMap().end()); + + /* Set the send buffer. */ + m_channel_impl_map[it->second].SetSendBuffer(buf, buf_size, max_packet_size); + } + + void Mux::SetSendBufferWithData(impl::ChannelInternalType channel, const void *buf, size_t buf_size, size_t max_packet_size) { + /* Lock ourselves. */ + std::scoped_lock lk(m_mutex); + + /* Find the channel. */ + auto it = m_channel_impl_map.GetMap().find(channel); + AMS_ABORT_UNLESS(it != m_channel_impl_map.GetMap().end()); + + /* Set the send buffer. */ + m_channel_impl_map[it->second].SetSendBufferWithData(buf, buf_size, max_packet_size); + } + + void Mux::SetReceiveBuffer(impl::ChannelInternalType channel, void *buf, size_t buf_size) { + /* Lock ourselves. */ + std::scoped_lock lk(m_mutex); + + /* Find the channel. */ + auto it = m_channel_impl_map.GetMap().find(channel); + AMS_ABORT_UNLESS(it != m_channel_impl_map.GetMap().end()); + + /* Set the send buffer. */ + m_channel_impl_map[it->second].SetReceiveBuffer(buf, buf_size); + } + } diff --git a/libraries/libstratosphere/source/htclow/mux/htclow_mux.hpp b/libraries/libstratosphere/source/htclow/mux/htclow_mux.hpp index 9829310bb..39d900aad 100644 --- a/libraries/libstratosphere/source/htclow/mux/htclow_mux.hpp +++ b/libraries/libstratosphere/source/htclow/mux/htclow_mux.hpp @@ -57,6 +57,10 @@ namespace ams::htclow::mux { Result Open(impl::ChannelInternalType channel); os::EventType *GetTaskEvent(u32 task_id); + + void SetSendBuffer(impl::ChannelInternalType channel, void *buf, size_t buf_size, size_t max_packet_size); + void SetReceiveBuffer(impl::ChannelInternalType channel, void *buf, size_t buf_size); + void SetSendBufferWithData(impl::ChannelInternalType channel, const void *buf, size_t buf_size, size_t max_packet_size); private: Result CheckChannelExist(impl::ChannelInternalType channel); diff --git a/libraries/libstratosphere/source/htclow/mux/htclow_mux_channel_impl.cpp b/libraries/libstratosphere/source/htclow/mux/htclow_mux_channel_impl.cpp index 0c7c7390c..c683aaa76 100644 --- a/libraries/libstratosphere/source/htclow/mux/htclow_mux_channel_impl.cpp +++ b/libraries/libstratosphere/source/htclow/mux/htclow_mux_channel_impl.cpp @@ -228,4 +228,35 @@ namespace ams::htclow::mux { } } + void ChannelImpl::SetSendBuffer(void *buf, size_t buf_size, size_t max_packet_size) { + /* Set buffer. */ + m_send_buffer.SetBuffer(buf, buf_size); + + /* Determine true max packet size. */ + if (m_config.flow_control_enabled) { + max_packet_size = std::min(max_packet_size, m_config.max_packet_size); + } + + /* Set max packet size. */ + m_send_buffer.SetMaxPacketSize(max_packet_size); + } + + void ChannelImpl::SetReceiveBuffer(void *buf, size_t buf_size) { + /* Set the buffer. */ + m_receive_buffer.Initialize(buf, buf_size); + } + + void ChannelImpl::SetSendBufferWithData(const void *buf, size_t buf_size, size_t max_packet_size) { + /* Set buffer. */ + m_send_buffer.SetReadOnlyBuffer(buf, buf_size); + + /* Determine true max packet size. */ + if (m_config.flow_control_enabled) { + max_packet_size = std::min(max_packet_size, m_config.max_packet_size); + } + + /* Set max packet size. */ + m_send_buffer.SetMaxPacketSize(max_packet_size); + } + } diff --git a/libraries/libstratosphere/source/htclow/mux/htclow_mux_channel_impl.hpp b/libraries/libstratosphere/source/htclow/mux/htclow_mux_channel_impl.hpp index c167343ea..27191d2e1 100644 --- a/libraries/libstratosphere/source/htclow/mux/htclow_mux_channel_impl.hpp +++ b/libraries/libstratosphere/source/htclow/mux/htclow_mux_channel_impl.hpp @@ -62,6 +62,10 @@ namespace ams::htclow::mux { void RemovePacket(const PacketHeader &header); void UpdateState(); + public: + void SetSendBuffer(void *buf, size_t buf_size, size_t max_packet_size); + void SetReceiveBuffer(void *buf, size_t buf_size); + void SetSendBufferWithData(const void *buf, size_t buf_size, size_t max_packet_size); private: void ShutdownForce(); void SetState(ChannelState state); diff --git a/libraries/libstratosphere/source/htclow/mux/htclow_mux_ring_buffer.cpp b/libraries/libstratosphere/source/htclow/mux/htclow_mux_ring_buffer.cpp index 0e8903dcc..e27f36b60 100644 --- a/libraries/libstratosphere/source/htclow/mux/htclow_mux_ring_buffer.cpp +++ b/libraries/libstratosphere/source/htclow/mux/htclow_mux_ring_buffer.cpp @@ -18,6 +18,29 @@ namespace ams::htclow::mux { + void RingBuffer::Initialize(void *buffer, size_t buffer_size) { + /* Validate pre-conditions. */ + AMS_ASSERT(m_buffer == nullptr); + AMS_ASSERT(m_read_only_buffer == nullptr); + + /* Set our fields. */ + m_buffer = buffer; + m_buffer_size = buffer_size; + m_is_read_only = false; + } + + void RingBuffer::InitializeForReadOnly(const void *buffer, size_t buffer_size) { + /* Validate pre-conditions. */ + AMS_ASSERT(m_buffer == nullptr); + AMS_ASSERT(m_read_only_buffer == nullptr); + + /* Set our fields. */ + m_read_only_buffer = const_cast(buffer); + m_buffer_size = buffer_size; + m_data_size = buffer_size; + m_is_read_only = true; + } + Result RingBuffer::Write(const void *data, size_t size) { /* Validate pre-conditions. */ AMS_ASSERT(!m_is_read_only); diff --git a/libraries/libstratosphere/source/htclow/mux/htclow_mux_ring_buffer.hpp b/libraries/libstratosphere/source/htclow/mux/htclow_mux_ring_buffer.hpp index 2cae14183..1ed9c8d38 100644 --- a/libraries/libstratosphere/source/htclow/mux/htclow_mux_ring_buffer.hpp +++ b/libraries/libstratosphere/source/htclow/mux/htclow_mux_ring_buffer.hpp @@ -30,6 +30,9 @@ namespace ams::htclow::mux { public: RingBuffer() : m_buffer(), m_read_only_buffer(), m_is_read_only(true), m_buffer_size(), m_data_size(), m_offset(), m_can_discard(false) { /* ... */ } + void Initialize(void *buffer, size_t buffer_size); + void InitializeForReadOnly(const void *buffer, size_t buffer_size); + size_t GetDataSize() { return m_data_size; } Result Write(const void *data, size_t size); diff --git a/libraries/libstratosphere/source/htclow/mux/htclow_mux_send_buffer.cpp b/libraries/libstratosphere/source/htclow/mux/htclow_mux_send_buffer.cpp index 8e5c510ce..b7961a8ba 100644 --- a/libraries/libstratosphere/source/htclow/mux/htclow_mux_send_buffer.cpp +++ b/libraries/libstratosphere/source/htclow/mux/htclow_mux_send_buffer.cpp @@ -115,6 +115,18 @@ namespace ams::htclow::mux { } } + void SendBuffer::SetBuffer(void *buffer, size_t buffer_size) { + m_ring_buffer.Initialize(buffer, buffer_size); + } + + void SendBuffer::SetReadOnlyBuffer(const void *buffer, size_t buffer_size) { + m_ring_buffer.InitializeForReadOnly(buffer, buffer_size); + } + + void SendBuffer::SetMaxPacketSize(size_t max_packet_size) { + m_max_packet_size = max_packet_size; + } + bool SendBuffer::Empty() { return m_packet_list.empty() && m_ring_buffer.GetDataSize() == 0; } diff --git a/libraries/libstratosphere/source/htclow/mux/htclow_mux_send_buffer.hpp b/libraries/libstratosphere/source/htclow/mux/htclow_mux_send_buffer.hpp index 2c7ee6b5d..65aa19fe5 100644 --- a/libraries/libstratosphere/source/htclow/mux/htclow_mux_send_buffer.hpp +++ b/libraries/libstratosphere/source/htclow/mux/htclow_mux_send_buffer.hpp @@ -52,6 +52,10 @@ namespace ams::htclow::mux { void RemovePacket(const PacketHeader &header); + void SetBuffer(void *buffer, size_t buffer_size); + void SetReadOnlyBuffer(const void *buffer, size_t buffer_size); + void SetMaxPacketSize(size_t max_packet_size); + bool Empty(); void Clear();