htc: implement mux side of connecting (and more)

This commit is contained in:
Michael Scire 2021-02-09 19:07:51 -08:00 committed by SciresM
parent 70aae4e27a
commit 42cf3f50d7
24 changed files with 474 additions and 12 deletions

View file

@ -40,7 +40,7 @@ namespace ams::htclow::ctrl {
}
HtcctrlService::HtcctrlService(HtcctrlPacketFactory *pf, HtcctrlStateMachine *sm, mux::Mux *mux)
: m_settings_holder(), m_beacon_response(), m_1100(), m_packet_factory(pf), m_state_machine(sm), m_mux(mux), m_event(os::EventClearMode_ManualClear),
: m_settings_holder(), m_beacon_response(), m_information_body(), m_packet_factory(pf), m_state_machine(sm), m_mux(mux), m_event(os::EventClearMode_ManualClear),
m_send_buffer(pf), m_mutex(), m_condvar(), m_service_channels_packet(), m_version(ProtocolVersion)
{
/* Lock ourselves. */
@ -78,6 +78,10 @@ namespace ams::htclow::ctrl {
);
}
void HtcctrlService::UpdateInformationBody(const char *status) {
util::SNPrintf(m_information_body, sizeof(m_information_body), "{\r\n \"Status\" : \"%s\"\r\n}\r\n", status);
}
void HtcctrlService::SetDriverType(impl::DriverType driver_type) {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);
@ -333,6 +337,89 @@ namespace ams::htclow::ctrl {
}
}
void HtcctrlService::TryReady() {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);
this->TryReadyInternal();
}
void HtcctrlService::Disconnect() {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);
this->DisconnectInternal();
}
void HtcctrlService::Resume() {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);
/* Send resume packet, if we can. */
if (const auto state = m_state_machine->GetHtcctrlState(); state == HtcctrlState_Sleep || state == HtcctrlState_ExitSleep) {
/* Send a resume packet. */
m_send_buffer.AddPacket(m_packet_factory->MakeResumePacket());
/* Signal our event. */
m_event.Signal();
}
}
void HtcctrlService::Suspend() {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);
/* If we can, perform a suspend. */
if (m_state_machine->GetHtcctrlState() == HtcctrlState_Ready) {
/* Send a suspend packet. */
m_send_buffer.AddPacket(m_packet_factory->MakeSuspendPacket());
/* Signal our event. */
m_event.Signal();
/* Wait for our state to transition. */
for (auto state = m_state_machine->GetHtcctrlState(); state == HtcctrlState_Ready || state == HtcctrlState_SentSuspendFromTarget; state = m_state_machine->GetHtcctrlState()) {
m_condvar.Wait(m_mutex);
}
} else {
/* Otherwise, just disconnect. */
this->DisconnectInternal();
}
}
void HtcctrlService::NotifyAwake() {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);
/* Update our information. */
this->UpdateInformationBody("Awake");
/* Send information to host. */
this->SendInformation();
}
void HtcctrlService::NotifyAsleep() {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);
/* Update our information. */
this->UpdateInformationBody("Asleep");
/* Send information to host. */
this->SendInformation();
}
void HtcctrlService::SendInformation() {
/* If we need information, send information. */
if (m_state_machine->IsInformationNeeded()) {
/* Send an information packet. */
m_send_buffer.AddPacket(m_packet_factory->MakeInformationPacket(m_information_body, util::Strnlen(m_information_body, sizeof(m_information_body)) + 1));
/* Signal our event. */
m_event.Signal();
}
}
Result HtcctrlService::NotifyDriverConnected() {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);

View file

@ -42,7 +42,7 @@ namespace ams::htclow::ctrl {
private:
SettingsHolder m_settings_holder;
char m_beacon_response[0x1000];
u8 m_1100[0x1000];
char m_information_body[0x1000];
HtcctrlPacketFactory *m_packet_factory;
HtcctrlStateMachine *m_state_machine;
mux::Mux *m_mux;
@ -56,6 +56,9 @@ namespace ams::htclow::ctrl {
const char *GetConnectionType(impl::DriverType driver_type) const;
void UpdateBeaconResponse(const char *connection);
void UpdateInformationBody(const char *status);
void SendInformation();
Result ProcessReceiveConnectPacket();
Result ProcessReceiveReadyPacket(const void *body, size_t body_size);
@ -72,10 +75,12 @@ namespace ams::htclow::ctrl {
void ProcessSendDisconnectPacket();
void UpdateServiceChannels(const void *body, size_t body_size);
void TryReadyInternal();
void PrintServiceChannels(char *dst, size_t dst_size);
void TryReadyInternal();
void DisconnectInternal();
Result SetState(HtcctrlState state);
void ReflectState();
public:
@ -91,6 +96,15 @@ namespace ams::htclow::ctrl {
bool QuerySendPacket(HtcctrlPacketHeader *header, HtcctrlPacketBody *body, int *out_body_size);
void RemovePacket(const HtcctrlPacketHeader &header);
void TryReady();
void Disconnect();
void Resume();
void Suspend();
void NotifyAwake();
void NotifyAsleep();
Result NotifyDriverConnected();
Result NotifyDriverDisconnected();
};

View file

@ -57,6 +57,13 @@ namespace ams::htclow::ctrl {
return ResultSuccess();
}
bool HtcctrlStateMachine::IsInformationNeeded() {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);
return !ctrl::IsDisconnected(m_state) && m_state != HtcctrlState_DriverConnected;
}
bool HtcctrlStateMachine::IsConnected() {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);
@ -149,6 +156,16 @@ namespace ams::htclow::ctrl {
return ctrl::IsConnected(m_state) && (it == m_map.end() || it->second.connect != ServiceChannelConnect_ConnectingChecked);
}
void HtcctrlStateMachine::SetConnecting(const impl::ChannelInternalType &channel) {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);
auto it = m_map.find(channel);
if (it != m_map.end() && it->second.connect != ServiceChannelConnect_ConnectingChecked) {
it->second.connect = ServiceChannelConnect_Connecting;
}
}
void HtcctrlStateMachine::SetNotConnecting(const impl::ChannelInternalType &channel) {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);

View file

@ -58,6 +58,8 @@ namespace ams::htclow::ctrl {
bool IsConnectedStatusChanged();
bool IsSleepingStatusChanged();
bool IsInformationNeeded();
bool IsConnected();
bool IsReadied();
bool IsUnconnectable();
@ -68,6 +70,7 @@ namespace ams::htclow::ctrl {
bool IsUnsupportedServiceChannelToShutdown(const impl::ChannelInternalType &channel);
bool IsConnectable(const impl::ChannelInternalType &channel);
void SetConnecting(const impl::ChannelInternalType &channel);
void SetNotConnecting(const impl::ChannelInternalType &channel);
void SetConnectingChecked();