htc: implement htcmisc service object commands

This commit is contained in:
Michael Scire
2021-02-23 15:47:28 -08:00
committed by SciresM
parent 8b32b9eadf
commit b5ab491603
13 changed files with 302 additions and 41 deletions

View File

@@ -15,6 +15,7 @@
*/
#include <stratosphere.hpp>
#include "htc_htc_service_object.hpp"
#include "../../htcfs/htcfs_working_directory.hpp"
namespace ams::htc::server {
@@ -29,75 +30,125 @@ namespace ams::htc::server {
}
Result HtcServiceObject::GetEnvironmentVariable(sf::Out<s32> out_size, const sf::OutBuffer &out, const sf::InBuffer &name) {
AMS_ABORT("HtcServiceObject::GetEnvironmentVariable");
/* Get the variable. */
size_t var_size;
R_TRY(m_misc_impl.GetEnvironmentVariable(std::addressof(var_size), reinterpret_cast<char *>(out.GetPointer()), out.GetSize(), reinterpret_cast<const char *>(name.GetPointer()), name.GetSize()));
/* Check the output size. */
R_UNLESS(util::IsIntValueRepresentable<s32>(var_size), htc::ResultUnknown());
/* Set the output size. */
*out_size = static_cast<s32>(var_size);
return ResultSuccess();
}
Result HtcServiceObject::GetEnvironmentVariableLength(sf::Out<s32> out_size, const sf::InBuffer &name) {
AMS_ABORT("HtcServiceObject::GetEnvironmentVariableLength");
/* Get the variable. */
size_t var_size;
R_TRY(m_misc_impl.GetEnvironmentVariableLength(std::addressof(var_size), reinterpret_cast<const char *>(name.GetPointer()), name.GetSize()));
/* Check the output size. */
R_UNLESS(util::IsIntValueRepresentable<s32>(var_size), htc::ResultUnknown());
/* Set the output size. */
*out_size = static_cast<s32>(var_size);
return ResultSuccess();
}
Result HtcServiceObject::GetHostConnectionEvent(sf::OutCopyHandle out) {
AMS_ABORT("HtcServiceObject::GetHostConnectionEvent");
/* Set the output handle. */
*out = m_observer.GetConnectEvent()->GetReadableHandle();
return ResultSuccess();
}
Result HtcServiceObject::GetHostDisconnectionEvent(sf::OutCopyHandle out) {
AMS_ABORT("HtcServiceObject::GetHostDisconnectionEvent");
/* Set the output handle. */
*out = m_observer.GetDisconnectEvent()->GetReadableHandle();
return ResultSuccess();
}
Result HtcServiceObject::GetHostConnectionEventForSystem(sf::OutCopyHandle out) {
AMS_ABORT("HtcServiceObject::GetHostConnectionEventForSystem");
/* NOTE: Nintendo presumably reserved this command in case they need it, but they haven't implemented it yet. */
AMS_ABORT("HostEventForSystem not implemented.");
}
Result HtcServiceObject::GetHostDisconnectionEventForSystem(sf::OutCopyHandle out) {
AMS_ABORT("HtcServiceObject::GetHostDisconnectionEventForSystem");
}
Result HtcServiceObject::GetBridgeIpAddress(const sf::OutBuffer &out) {
AMS_ABORT("HtcServiceObject::GetBridgeIpAddress");
}
Result HtcServiceObject::GetBridgePort(const sf::OutBuffer &out) {
AMS_ABORT("HtcServiceObject::GetBridgePort");
}
Result HtcServiceObject::SetCradleAttached(bool attached) {
AMS_ABORT("HtcServiceObject::SetCradleAttached");
}
Result HtcServiceObject::GetBridgeSubnetMask(const sf::OutBuffer &out) {
AMS_ABORT("HtcServiceObject::GetBridgeSubnetMask");
}
Result HtcServiceObject::GetBridgeMacAddress(const sf::OutBuffer &out) {
AMS_ABORT("HtcServiceObject::GetBridgeMacAddress");
/* NOTE: Nintendo presumably reserved this command in case they need it, but they haven't implemented it yet. */
AMS_ABORT("HostEventForSystem not implemented.");
}
Result HtcServiceObject::GetWorkingDirectoryPath(const sf::OutBuffer &out, s32 max_len) {
AMS_ABORT("HtcServiceObject::GetWorkingDirectoryPath");
return htcfs::GetWorkingDirectory(reinterpret_cast<char *>(out.GetPointer()), max_len);
}
Result HtcServiceObject::GetWorkingDirectoryPathSize(sf::Out<s32> out_size) {
AMS_ABORT("HtcServiceObject::GetWorkingDirectoryPathSize");
return htcfs::GetWorkingDirectorySize(out_size.GetPointer());
}
Result HtcServiceObject::RunOnHostStart(sf::Out<u32> out_id, sf::OutCopyHandle out, const sf::InBuffer &args) {
AMS_ABORT("HtcServiceObject::RunOnHostStart");
/* Begin the run on host task. */
R_TRY(m_misc_impl.RunOnHostBegin(out_id.GetPointer(), out.GetHandlePointer(), reinterpret_cast<const char *>(args.GetPointer()), args.GetSize()));
/* Add the task id to our set. */
{
std::scoped_lock lk(m_mutex);
m_set.insert(*out_id);
}
/* Mark the output event as managed. */
out.SetManaged(true);
return ResultSuccess();
}
Result HtcServiceObject::RunOnHostResults(sf::Out<s32> out_result, u32 id) {
AMS_ABORT("HtcServiceObject::RunOnHostResults");
/* Verify that we have the task. */
{
std::scoped_lock lk(m_mutex);
R_UNLESS(m_set.erase(id), htc::ResultInvalidTaskId());
}
/* Finish the run on host task. */
return m_misc_impl.RunOnHostEnd(out_result.GetPointer(), id);
}
Result HtcServiceObject::GetBridgeIpAddress(const sf::OutBuffer &out) {
/* NOTE: Atmosphere does not support HostBridge, and it's unclear if we ever will. */
AMS_ABORT("HostBridge currently not supported.");
}
Result HtcServiceObject::GetBridgePort(const sf::OutBuffer &out) {
/* NOTE: Atmosphere does not support HostBridge, and it's unclear if we ever will. */
AMS_ABORT("HostBridge currently not supported.");
}
Result HtcServiceObject::SetCradleAttached(bool attached) {
/* NOTE: Atmosphere does not support HostBridge, and it's unclear if we ever will. */
AMS_ABORT("HostBridge currently not supported.");
}
Result HtcServiceObject::GetBridgeSubnetMask(const sf::OutBuffer &out) {
/* NOTE: Atmosphere does not support HostBridge, and it's unclear if we ever will. */
AMS_ABORT("HostBridge currently not supported.");
}
Result HtcServiceObject::GetBridgeMacAddress(const sf::OutBuffer &out) {
/* NOTE: Atmosphere does not support HostBridge, and it's unclear if we ever will. */
AMS_ABORT("HostBridge currently not supported.");
}
Result HtcServiceObject::SetBridgeIpAddress(const sf::InBuffer &arg) {
AMS_ABORT("HtcServiceObject::SetBridgeIpAddress");
/* NOTE: Atmosphere does not support HostBridge, and it's unclear if we ever will. */
AMS_ABORT("HostBridge currently not supported.");
}
Result HtcServiceObject::SetBridgeSubnetMask(const sf::InBuffer &arg) {
AMS_ABORT("HtcServiceObject::SetBridgeSubnetMask");
/* NOTE: Atmosphere does not support HostBridge, and it's unclear if we ever will. */
AMS_ABORT("HostBridge currently not supported.");
}
Result HtcServiceObject::SetBridgePort(const sf::InBuffer &arg) {
AMS_ABORT("HtcServiceObject::SetBridgePort");
/* NOTE: Atmosphere does not support HostBridge, and it's unclear if we ever will. */
AMS_ABORT("HostBridge currently not supported.");
}
}

View File

@@ -76,6 +76,61 @@ namespace ams::htc::server {
m_cancel_event.Signal();
}
void HtcmiscImpl::WaitTask(u32 task_id) {
return m_rpc_client.Wait(task_id);
}
Result HtcmiscImpl::GetEnvironmentVariable(size_t *out_size, char *dst, size_t dst_size, const char *name, size_t name_size) {
/* Begin the task. */
u32 task_id;
R_TRY(m_rpc_client.Begin<rpc::GetEnvironmentVariableTask>(std::addressof(task_id), name, name_size));
/* Wait for the task to complete. */
this->WaitTask(task_id);
/* Finish the task. */
R_TRY(m_rpc_client.End<rpc::GetEnvironmentVariableTask>(task_id, out_size, dst, dst_size));
return ResultSuccess();
}
Result HtcmiscImpl::GetEnvironmentVariableLength(size_t *out_size, const char *name, size_t name_size) {
/* Begin the task. */
u32 task_id;
R_TRY(m_rpc_client.Begin<rpc::GetEnvironmentVariableLengthTask>(std::addressof(task_id), name, name_size));
/* Wait for the task to complete. */
this->WaitTask(task_id);
/* Finish the task. */
R_TRY(m_rpc_client.End<rpc::GetEnvironmentVariableLengthTask>(task_id, out_size));
return ResultSuccess();
}
Result HtcmiscImpl::RunOnHostBegin(u32 *out_task_id, Handle *out_event, const char *args, size_t args_size) {
/* Begin the task. */
u32 task_id;
R_TRY(m_rpc_client.Begin<rpc::RunOnHostTask>(std::addressof(task_id), args, args_size));
/* Detach the task. */
*out_task_id = task_id;
*out_event = m_rpc_client.DetachReadableHandle(task_id);
return ResultSuccess();
}
Result HtcmiscImpl::RunOnHostEnd(s32 *out_result, u32 task_id) {
/* Finish the task. */
s32 res;
R_TRY(m_rpc_client.End<rpc::RunOnHostTask>(task_id, std::addressof(res)));
/* Set output. */
*out_result = res;
return ResultSuccess();
}
void HtcmiscImpl::ClientThread() {
/* Loop so long as we're not cancelled. */
while (!m_cancelled) {

View File

@@ -55,9 +55,16 @@ namespace ams::htc::server {
void SetServerConnectionEvent(bool en);
void UpdateConnectionEvent();
void WaitTask(u32 task_id);
public:
void Cancel();
/* TODO */
Result GetEnvironmentVariable(size_t *out_size, char *dst, size_t dst_size, const char *name, size_t name_size);
Result GetEnvironmentVariableLength(size_t *out_size, const char *name, size_t name_size);
Result RunOnHostBegin(u32 *out_task_id, Handle *out_event, const char *args, size_t args_size);
Result RunOnHostEnd(s32 *out_result, u32 task_id);
};
}

View File

@@ -41,6 +41,9 @@ namespace ams::htc::server {
Result Start();
void UpdateEvent();
public:
os::SystemEvent *GetConnectEvent() { return std::addressof(m_connect_event); }
os::SystemEvent *GetDisconnectEvent() { return std::addressof(m_disconnect_event); }
};
}

View File

@@ -61,7 +61,7 @@ namespace ams::htc::server::rpc {
Task::Complete();
}
Result GetEnvironmentVariableTask::GetResult(size_t *out, char *dst, size_t size) {
Result GetEnvironmentVariableTask::GetResult(size_t *out, char *dst, size_t size) const {
/* Check our task state. */
AMS_ASSERT(this->GetTaskState() == RpcTaskState::Completed);
@@ -166,7 +166,7 @@ namespace ams::htc::server::rpc {
Task::Complete();
}
Result GetEnvironmentVariableLengthTask::GetResult(size_t *out) {
Result GetEnvironmentVariableLengthTask::GetResult(size_t *out) const {
/* Check our task state. */
AMS_ASSERT(this->GetTaskState() == RpcTaskState::Completed);
@@ -241,7 +241,7 @@ namespace ams::htc::server::rpc {
Task::Complete();
}
Result RunOnHostTask::GetResult(int *out) {
Result RunOnHostTask::GetResult(int *out) const {
*out = m_host_result;
return ResultSuccess();
}
@@ -290,5 +290,4 @@ namespace ams::htc::server::rpc {
return m_system_event.GetBase();
}
}

View File

@@ -88,7 +88,7 @@ namespace ams::htc::server::rpc {
Result SetArguments(const char *args, size_t size);
void Complete(HtcmiscResult result, const char *data, size_t size);
Result GetResult(size_t *out, char *dst, size_t size);
Result GetResult(size_t *out, char *dst, size_t size) const;
const char *GetName() const { return m_name; }
int GetNameSize() const { return m_name_size; }
@@ -110,7 +110,7 @@ namespace ams::htc::server::rpc {
Result SetArguments(const char *args, size_t size);
void Complete(HtcmiscResult result, const char *data, size_t size);
Result GetResult(size_t *out);
Result GetResult(size_t *out) const;
const char *GetName() const { return m_name; }
int GetNameSize() const { return m_name_size; }
@@ -133,7 +133,7 @@ namespace ams::htc::server::rpc {
Result SetArguments(const char *args, size_t size);
void Complete(int host_result);
Result GetResult(int *out);
Result GetResult(int *out) const;
const char *GetCommand() const { return m_command; }
int GetCommandSize() const { return m_command_size; }