mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-10 07:06:34 +00:00
htc: implement htcmisc service object commands
This commit is contained in:
parent
8b32b9eadf
commit
b5ab491603
13 changed files with 302 additions and 41 deletions
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
#include <stratosphere.hpp>
|
#include <stratosphere.hpp>
|
||||||
#include "htc_htc_service_object.hpp"
|
#include "htc_htc_service_object.hpp"
|
||||||
|
#include "../../htcfs/htcfs_working_directory.hpp"
|
||||||
|
|
||||||
namespace ams::htc::server {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
Result HtcServiceObject::GetHostDisconnectionEventForSystem(sf::OutCopyHandle out) {
|
||||||
AMS_ABORT("HtcServiceObject::GetHostDisconnectionEventForSystem");
|
/* 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::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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result HtcServiceObject::GetWorkingDirectoryPath(const sf::OutBuffer &out, s32 max_len) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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.");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,61 @@ namespace ams::htc::server {
|
||||||
m_cancel_event.Signal();
|
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() {
|
void HtcmiscImpl::ClientThread() {
|
||||||
/* Loop so long as we're not cancelled. */
|
/* Loop so long as we're not cancelled. */
|
||||||
while (!m_cancelled) {
|
while (!m_cancelled) {
|
||||||
|
|
|
@ -55,9 +55,16 @@ namespace ams::htc::server {
|
||||||
void SetServerConnectionEvent(bool en);
|
void SetServerConnectionEvent(bool en);
|
||||||
|
|
||||||
void UpdateConnectionEvent();
|
void UpdateConnectionEvent();
|
||||||
|
|
||||||
|
void WaitTask(u32 task_id);
|
||||||
public:
|
public:
|
||||||
void Cancel();
|
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);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,9 @@ namespace ams::htc::server {
|
||||||
Result Start();
|
Result Start();
|
||||||
|
|
||||||
void UpdateEvent();
|
void UpdateEvent();
|
||||||
|
public:
|
||||||
|
os::SystemEvent *GetConnectEvent() { return std::addressof(m_connect_event); }
|
||||||
|
os::SystemEvent *GetDisconnectEvent() { return std::addressof(m_disconnect_event); }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ namespace ams::htc::server::rpc {
|
||||||
Task::Complete();
|
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. */
|
/* Check our task state. */
|
||||||
AMS_ASSERT(this->GetTaskState() == RpcTaskState::Completed);
|
AMS_ASSERT(this->GetTaskState() == RpcTaskState::Completed);
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ namespace ams::htc::server::rpc {
|
||||||
Task::Complete();
|
Task::Complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetEnvironmentVariableLengthTask::GetResult(size_t *out) {
|
Result GetEnvironmentVariableLengthTask::GetResult(size_t *out) const {
|
||||||
/* Check our task state. */
|
/* Check our task state. */
|
||||||
AMS_ASSERT(this->GetTaskState() == RpcTaskState::Completed);
|
AMS_ASSERT(this->GetTaskState() == RpcTaskState::Completed);
|
||||||
|
|
||||||
|
@ -241,7 +241,7 @@ namespace ams::htc::server::rpc {
|
||||||
Task::Complete();
|
Task::Complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result RunOnHostTask::GetResult(int *out) {
|
Result RunOnHostTask::GetResult(int *out) const {
|
||||||
*out = m_host_result;
|
*out = m_host_result;
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -290,5 +290,4 @@ namespace ams::htc::server::rpc {
|
||||||
return m_system_event.GetBase();
|
return m_system_event.GetBase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ namespace ams::htc::server::rpc {
|
||||||
|
|
||||||
Result SetArguments(const char *args, size_t size);
|
Result SetArguments(const char *args, size_t size);
|
||||||
void Complete(HtcmiscResult result, const char *data, 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; }
|
const char *GetName() const { return m_name; }
|
||||||
int GetNameSize() const { return m_name_size; }
|
int GetNameSize() const { return m_name_size; }
|
||||||
|
@ -110,7 +110,7 @@ namespace ams::htc::server::rpc {
|
||||||
|
|
||||||
Result SetArguments(const char *args, size_t size);
|
Result SetArguments(const char *args, size_t size);
|
||||||
void Complete(HtcmiscResult result, const char *data, 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; }
|
const char *GetName() const { return m_name; }
|
||||||
int GetNameSize() const { return m_name_size; }
|
int GetNameSize() const { return m_name_size; }
|
||||||
|
@ -133,7 +133,7 @@ namespace ams::htc::server::rpc {
|
||||||
|
|
||||||
Result SetArguments(const char *args, size_t size);
|
Result SetArguments(const char *args, size_t size);
|
||||||
void Complete(int host_result);
|
void Complete(int host_result);
|
||||||
Result GetResult(int *out);
|
Result GetResult(int *out) const;
|
||||||
|
|
||||||
const char *GetCommand() const { return m_command; }
|
const char *GetCommand() const { return m_command; }
|
||||||
int GetCommandSize() const { return m_command_size; }
|
int GetCommandSize() const { return m_command_size; }
|
||||||
|
|
|
@ -60,6 +60,9 @@ namespace ams::htcfs {
|
||||||
Result FlushFile(s32 handle) { return ConvertToFsResult(m_impl.FlushFile(handle)); }
|
Result FlushFile(s32 handle) { return ConvertToFsResult(m_impl.FlushFile(handle)); }
|
||||||
Result GetPriorityForFile(s32 *out, s32 handle) { return ConvertToFsResult(m_impl.GetPriorityForFile(out, handle)); }
|
Result GetPriorityForFile(s32 *out, s32 handle) { return ConvertToFsResult(m_impl.GetPriorityForFile(out, handle)); }
|
||||||
Result SetPriorityForFile(s32 priority, s32 handle) { return ConvertToFsResult(m_impl.SetPriorityForFile(priority, handle)); }
|
Result SetPriorityForFile(s32 priority, s32 handle) { return ConvertToFsResult(m_impl.SetPriorityForFile(priority, handle)); }
|
||||||
|
|
||||||
|
Result GetWorkingDirectory(char *dst, size_t dst_size) { return ConvertToFsResult(m_impl.GetWorkingDirectory(dst, dst_size)); }
|
||||||
|
Result GetWorkingDirectorySize(s32 *out) { return ConvertToFsResult(m_impl.GetWorkingDirectorySize(out)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
void InitializeClient(htclow::HtclowManager *manager);
|
void InitializeClient(htclow::HtclowManager *manager);
|
||||||
|
|
|
@ -1539,5 +1539,83 @@ namespace ams::htcfs {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result ClientImpl::GetWorkingDirectory(char *dst, size_t dst_size) {
|
||||||
|
/* Lock ourselves. */
|
||||||
|
std::scoped_lock lk(m_mutex);
|
||||||
|
|
||||||
|
/* Initialize our rpc channel. */
|
||||||
|
R_TRY(this->InitializeRpcChannel());
|
||||||
|
|
||||||
|
/* Create space for request and response. */
|
||||||
|
Header request, response;
|
||||||
|
|
||||||
|
/* Create header for the request. */
|
||||||
|
m_header_factory.MakeGetWorkingDirectoryHeader(std::addressof(request));
|
||||||
|
|
||||||
|
/* Send the request to the host. */
|
||||||
|
R_TRY(this->SendRequest(request));
|
||||||
|
|
||||||
|
/* Receive response from the host. */
|
||||||
|
R_TRY(this->ReceiveFromRpcChannel(std::addressof(response), sizeof(response)));
|
||||||
|
|
||||||
|
/* Check the response header. */
|
||||||
|
R_TRY(this->CheckResponseHeader(response, request.packet_type));
|
||||||
|
|
||||||
|
/* Check that we succeeded. */
|
||||||
|
const auto htcfs_result = ConvertHtcfsResult(response.params[0]);
|
||||||
|
if (R_FAILED(htcfs_result)) {
|
||||||
|
R_UNLESS(response.body_size == 0, htcfs::ResultUnexpectedResponseBodySize());
|
||||||
|
return htcfs_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the body size is valid. */
|
||||||
|
R_UNLESS(response.body_size < static_cast<s64>(dst_size), htcfs::ResultUnexpectedResponseBodySize());
|
||||||
|
|
||||||
|
/* Receive the response body. */
|
||||||
|
R_TRY(this->ReceiveFromRpcChannel(dst, response.body_size));
|
||||||
|
|
||||||
|
/* Null-terminate the response body. */
|
||||||
|
dst[response.body_size] = '\x00';
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ClientImpl::GetWorkingDirectorySize(s32 *out) {
|
||||||
|
/* Lock ourselves. */
|
||||||
|
std::scoped_lock lk(m_mutex);
|
||||||
|
|
||||||
|
/* Initialize our rpc channel. */
|
||||||
|
R_TRY(this->InitializeRpcChannel());
|
||||||
|
|
||||||
|
/* Create space for request and response. */
|
||||||
|
Header request, response;
|
||||||
|
|
||||||
|
/* Create header for the request. */
|
||||||
|
m_header_factory.MakeGetWorkingDirectorySizeHeader(std::addressof(request));
|
||||||
|
|
||||||
|
/* Send the request to the host. */
|
||||||
|
R_TRY(this->SendRequest(request));
|
||||||
|
|
||||||
|
/* Receive response from the host. */
|
||||||
|
R_TRY(this->ReceiveFromRpcChannel(std::addressof(response), sizeof(response)));
|
||||||
|
|
||||||
|
/* Check the response header. */
|
||||||
|
R_TRY(this->CheckResponseHeader(response, request.packet_type));
|
||||||
|
|
||||||
|
/* Check that we succeeded. */
|
||||||
|
const auto htcfs_result = ConvertHtcfsResult(response.params[0]);
|
||||||
|
if (R_FAILED(htcfs_result)) {
|
||||||
|
R_UNLESS(response.body_size == 0, htcfs::ResultUnexpectedResponseBodySize());
|
||||||
|
return htcfs_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the size is representable. */
|
||||||
|
R_UNLESS(util::IsIntValueRepresentable<s32>(response.params[1]), htcfs::ResultInvalidSize());
|
||||||
|
|
||||||
|
/* Set the output size. */
|
||||||
|
*out = static_cast<s32>(response.params[1]);
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,9 @@ namespace ams::htcfs {
|
||||||
Result FlushFile(s32 handle);
|
Result FlushFile(s32 handle);
|
||||||
Result GetPriorityForFile(s32 *out, s32 handle);
|
Result GetPriorityForFile(s32 *out, s32 handle);
|
||||||
Result SetPriorityForFile(s32 priority, s32 handle);
|
Result SetPriorityForFile(s32 priority, s32 handle);
|
||||||
|
|
||||||
|
Result GetWorkingDirectory(char *dst, size_t dst_size);
|
||||||
|
Result GetWorkingDirectorySize(s32 *out);
|
||||||
private:
|
private:
|
||||||
int WaitAny(htclow::ChannelState state, os::EventType *event);
|
int WaitAny(htclow::ChannelState state, os::EventType *event);
|
||||||
|
|
||||||
|
|
|
@ -179,6 +179,14 @@ namespace ams::htcfs {
|
||||||
return this->MakeRequestHeader(out, PacketType::GetEntryCount, 0, handle);
|
return this->MakeRequestHeader(out, PacketType::GetEntryCount, 0, handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MakeGetWorkingDirectoryHeader(Header *out) {
|
||||||
|
return this->MakeRequestHeader(out, PacketType::GetWorkingDirectory, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MakeGetWorkingDirectorySizeHeader(Header *out) {
|
||||||
|
return this->MakeRequestHeader(out, PacketType::GetWorkingDirectorySize, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void MakeReadDirectoryHeader(Header *out, s32 handle, size_t max_out_entries) {
|
void MakeReadDirectoryHeader(Header *out, s32 handle, size_t max_out_entries) {
|
||||||
return this->MakeRequestHeader(out, PacketType::ReadDirectory, 0, handle, max_out_entries);
|
return this->MakeRequestHeader(out, PacketType::ReadDirectory, 0, handle, max_out_entries);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
#include "htcfs_client.hpp"
|
||||||
|
|
||||||
|
namespace ams::htcfs {
|
||||||
|
|
||||||
|
Result GetWorkingDirectory(char *dst, size_t dst_size) {
|
||||||
|
return htcfs::GetClient().GetWorkingDirectory(dst, dst_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetWorkingDirectorySize(s32 *out) {
|
||||||
|
return htcfs::GetClient().GetWorkingDirectorySize(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* 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>
|
||||||
|
|
||||||
|
namespace ams::htcfs {
|
||||||
|
|
||||||
|
Result GetWorkingDirectory(char *dst, size_t dst_size);
|
||||||
|
Result GetWorkingDirectorySize(s32 *out);
|
||||||
|
|
||||||
|
}
|
|
@ -35,6 +35,7 @@ namespace ams::htcfs {
|
||||||
R_DEFINE_ERROR_RESULT(UnexpectedResponseBody, 116);
|
R_DEFINE_ERROR_RESULT(UnexpectedResponseBody, 116);
|
||||||
|
|
||||||
R_DEFINE_ERROR_RANGE(InternalError, 200, 299);
|
R_DEFINE_ERROR_RANGE(InternalError, 200, 299);
|
||||||
|
R_DEFINE_ERROR_RESULT(InvalidSize, 201);
|
||||||
R_DEFINE_ERROR_RESULT(UnknownError, 211);
|
R_DEFINE_ERROR_RESULT(UnknownError, 211);
|
||||||
R_DEFINE_ERROR_RESULT(UnsupportedProtocolVersion, 212);
|
R_DEFINE_ERROR_RESULT(UnsupportedProtocolVersion, 212);
|
||||||
R_DEFINE_ERROR_RESULT(InvalidRequest, 213);
|
R_DEFINE_ERROR_RESULT(InvalidRequest, 213);
|
||||||
|
|
Loading…
Reference in a new issue