htc: implement remaining worker thread send logic (for channel mux)
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "htclow_mux.hpp"
|
||||
#include "../htclow_packet_factory.hpp"
|
||||
#include "../ctrl/htclow_ctrl_state_machine.hpp"
|
||||
|
||||
namespace ams::htclow::mux {
|
||||
@@ -22,7 +23,7 @@ namespace ams::htclow::mux {
|
||||
Mux::Mux(PacketFactory *pf, ctrl::HtcctrlStateMachine *sm)
|
||||
: m_packet_factory(pf), m_state_machine(sm), m_task_manager(), m_event(os::EventClearMode_ManualClear),
|
||||
m_channel_impl_map(pf, sm, std::addressof(m_task_manager), std::addressof(m_event)), m_global_send_buffer(pf),
|
||||
m_mutex(), m_is_sleeping(false), m_version(ProtocolVersion)
|
||||
m_mutex(), m_state(MuxState::Normal), m_version(ProtocolVersion)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@@ -78,6 +79,50 @@ namespace ams::htclow::mux {
|
||||
}
|
||||
}
|
||||
|
||||
bool Mux::QuerySendPacket(PacketHeader *header, PacketBody *body, int *out_body_size) {
|
||||
/* Lock ourselves. */
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
/* Get our map. */
|
||||
auto &map = m_channel_impl_map.GetMap();
|
||||
|
||||
/* Iterate the map, checking for valid packet each time. */
|
||||
for (auto &pair : map) {
|
||||
/* Get the current channel impl. */
|
||||
auto &channel_impl = m_channel_impl_map.GetChannelImpl(pair.second);
|
||||
|
||||
/* Check for an error packet. */
|
||||
/* NOTE: it's unclear why Nintendo does this every iteration of the loop... */
|
||||
if (auto *error_packet = m_global_send_buffer.GetNextPacket(); error_packet != nullptr) {
|
||||
std::memcpy(header, error_packet->GetHeader(), sizeof(*header));
|
||||
*out_body_size = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* See if the channel has something for us to send. */
|
||||
if (channel_impl.QuerySendPacket(header, body, out_body_size)) {
|
||||
return this->IsSendable(header->packet_type);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Mux::RemovePacket(const PacketHeader &header) {
|
||||
/* Lock ourselves. */
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
/* Remove the packet from the appropriate source. */
|
||||
if (header.packet_type == PacketType_Error) {
|
||||
m_global_send_buffer.RemovePacket();
|
||||
} else if (m_channel_impl_map.Exists(header.channel)) {
|
||||
m_channel_impl_map[header.channel].RemovePacket(header);
|
||||
}
|
||||
|
||||
/* Notify the task manager. */
|
||||
m_task_manager.NotifySendReady();
|
||||
}
|
||||
|
||||
void Mux::UpdateChannelState() {
|
||||
/* Lock ourselves. */
|
||||
std::scoped_lock lk(m_mutex);
|
||||
@@ -95,9 +140,9 @@ namespace ams::htclow::mux {
|
||||
|
||||
/* Update whether we're sleeping. */
|
||||
if (m_state_machine->IsSleeping()) {
|
||||
m_is_sleeping = true;
|
||||
m_state = MuxState::Sleep;
|
||||
} else {
|
||||
m_is_sleeping = false;
|
||||
m_state = MuxState::Normal;
|
||||
m_event.Signal();
|
||||
}
|
||||
}
|
||||
@@ -108,8 +153,23 @@ namespace ams::htclow::mux {
|
||||
}
|
||||
|
||||
Result Mux::SendErrorPacket(impl::ChannelInternalType channel) {
|
||||
/* TODO */
|
||||
AMS_ABORT("Mux::SendErrorPacket");
|
||||
/* Create and send the packet. */
|
||||
R_TRY(m_global_send_buffer.AddPacket(m_packet_factory->MakeErrorPacket(channel)));
|
||||
|
||||
/* Signal our event. */
|
||||
m_event.Signal();
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
bool Mux::IsSendable(PacketType packet_type) const {
|
||||
switch (m_state) {
|
||||
case MuxState::Normal:
|
||||
return true;
|
||||
case MuxState::Sleep:
|
||||
return false;
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user