mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
htc: Implement (almost) all host-directory commands
This commit is contained in:
parent
e79417c37c
commit
9daec3a66a
7 changed files with 235 additions and 13 deletions
|
@ -16,6 +16,7 @@
|
|||
#pragma once
|
||||
#include <stratosphere.hpp>
|
||||
#include "htcfs_client_impl.hpp"
|
||||
#include "htcfs_result_utils.hpp"
|
||||
|
||||
namespace ams::htcfs {
|
||||
|
||||
|
@ -25,8 +26,14 @@ namespace ams::htcfs {
|
|||
public:
|
||||
Client(htclow::HtclowManager *manager) : m_impl(manager) { /* ... */ }
|
||||
public:
|
||||
Result OpenDirectory(s32 *out_handle, const char *path, fs::OpenDirectoryMode mode, bool case_sensitive) { return m_impl.OpenDirectory(out_handle, path, mode, case_sensitive); }
|
||||
Result CloseDirectory(s32 handle) { return m_impl.CloseDirectory(handle); }
|
||||
Result OpenDirectory(s32 *out_handle, const char *path, fs::OpenDirectoryMode mode, bool case_sensitive) { return ConvertToFsResult(m_impl.OpenDirectory(out_handle, path, mode, case_sensitive)); }
|
||||
Result CloseDirectory(s32 handle) { return ConvertToFsResult(m_impl.CloseDirectory(handle)); }
|
||||
|
||||
Result GetEntryCount(s64 *out, s32 handle) { return ConvertToFsResult(m_impl.GetEntryCount(out, handle)); }
|
||||
Result ReadDirectory(s64 *out, fs::DirectoryEntry *out_entries, size_t max_out_entries, s32 handle) { return ConvertToFsResult(m_impl.ReadDirectory(out, out_entries, max_out_entries, handle)); }
|
||||
Result ReadDirectoryLarge(s64 *out, fs::DirectoryEntry *out_entries, size_t max_out_entries, s32 handle) { return ConvertToFsResult( m_impl.ReadDirectoryLarge(out, out_entries, max_out_entries, handle)); }
|
||||
Result GetPriorityForDirectory(s32 *out, s32 handle) { return ConvertToFsResult(m_impl.GetPriorityForDirectory(out, handle)); }
|
||||
Result SetPriorityForDirectory(s32 priority, s32 handle) { return ConvertToFsResult(m_impl.SetPriorityForDirectory(priority, handle)); }
|
||||
};
|
||||
|
||||
void InitializeClient(htclow::HtclowManager *manager);
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include <stratosphere.hpp>
|
||||
#include "htcfs_client_impl.hpp"
|
||||
#include "htcfs_result.hpp"
|
||||
#include "../htclow/htclow_default_channel_config.hpp"
|
||||
|
||||
namespace ams::htcfs {
|
||||
|
||||
|
@ -413,4 +412,152 @@ namespace ams::htcfs {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ClientImpl::GetEntryCount(s64 *out, s32 handle) {
|
||||
/* 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.MakeGetEntryCountHeader(std::addressof(request), handle);
|
||||
|
||||
/* 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, 0));
|
||||
|
||||
/* Check that we succeeded. */
|
||||
R_TRY(ConvertHtcfsResult(response.params[0]));
|
||||
|
||||
/* Check our operation's result. */
|
||||
R_TRY(ConvertNativeResult(response.params[1]));
|
||||
|
||||
/* Set the output count. */
|
||||
*out = response.params[2];
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ClientImpl::ReadDirectory(s64 *out, fs::DirectoryEntry *out_entries, size_t max_out_entries, s32 handle) {
|
||||
/* 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.MakeReadDirectoryHeader(std::addressof(request), handle, max_out_entries);
|
||||
|
||||
/* 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. */
|
||||
R_TRY(ConvertHtcfsResult(response.params[0]));
|
||||
|
||||
/* Check our operation's result. */
|
||||
R_TRY(ConvertNativeResult(response.params[1]));
|
||||
|
||||
/* Check that the response body size is expected. */
|
||||
R_UNLESS(static_cast<size_t>(response.body_size) == max_out_entries * sizeof(*out_entries), htcfs::ResultUnexpectedResponseBody());
|
||||
|
||||
/* Check that the number of entries read is allowable. */
|
||||
R_UNLESS(static_cast<size_t>(response.params[2]) <= max_out_entries, htcfs::ResultUnexpectedResponseBody());
|
||||
|
||||
/* Receive the entries. */
|
||||
*out = response.params[2];
|
||||
return this->ReceiveFromRpcChannel(out_entries, response.body_size);
|
||||
}
|
||||
|
||||
Result ClientImpl::ReadDirectoryLarge(s64 *out, fs::DirectoryEntry *out_entries, size_t max_out_entries, s32 handle) {
|
||||
/* 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.MakeReadDirectoryLargeHeader(std::addressof(request), handle, max_out_entries);
|
||||
|
||||
AMS_ABORT("TODO: Data channel setup/teardown");
|
||||
}
|
||||
|
||||
Result ClientImpl::GetPriorityForDirectory(s32 *out, s32 handle) {
|
||||
/* 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.MakeGetPriorityForDirectoryHeader(std::addressof(request), handle);
|
||||
|
||||
/* 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, 0));
|
||||
|
||||
/* Check that we succeeded. */
|
||||
R_TRY(ConvertHtcfsResult(response.params[0]));
|
||||
|
||||
/* Set the output. */
|
||||
*out = static_cast<s32>(response.params[1]);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ClientImpl::SetPriorityForDirectory(s32 priority, s32 handle) {
|
||||
/* 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.MakeSetPriorityForDirectoryHeader(std::addressof(request), handle, priority);
|
||||
|
||||
/* 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, 0));
|
||||
|
||||
/* Check that we succeeded. */
|
||||
R_TRY(ConvertHtcfsResult(response.params[0]));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,14 +19,17 @@
|
|||
#include "../htclow/htclow_channel.hpp"
|
||||
#include "htcfs_cache_manager.hpp"
|
||||
#include "htcfs_header_factory.hpp"
|
||||
#include "../htclow/htclow_default_channel_config.hpp"
|
||||
|
||||
namespace ams::htcfs {
|
||||
|
||||
class ClientImpl {
|
||||
public:
|
||||
static constexpr size_t MaxPacketBodySize = htclow::DefaultChannelConfig.max_packet_size - sizeof(htclow::PacketHeader);
|
||||
private:
|
||||
u8 m_receive_buffer[0x1C040];
|
||||
u8 m_send_buffer[0x1C040];
|
||||
u8 m_packet_buffer[0xE020];
|
||||
u8 m_packet_buffer[MaxPacketBodySize + sizeof(htclow::PacketHeader)];
|
||||
htclow::HtclowManager *m_htclow_manager;
|
||||
CacheManager m_cache_manager;
|
||||
HeaderFactory m_header_factory;
|
||||
|
@ -55,6 +58,12 @@ namespace ams::htcfs {
|
|||
public:
|
||||
Result OpenDirectory(s32 *out_handle, const char *path, fs::OpenDirectoryMode mode, bool case_sensitive);
|
||||
Result CloseDirectory(s32 handle);
|
||||
|
||||
Result GetEntryCount(s64 *out, s32 handle);
|
||||
Result ReadDirectory(s64 *out, fs::DirectoryEntry *out_entries, size_t max_out_entries, s32 handle);
|
||||
Result ReadDirectoryLarge(s64 *out, fs::DirectoryEntry *out_entries, size_t max_out_entries, s32 handle);
|
||||
Result GetPriorityForDirectory(s32 *out, s32 handle);
|
||||
Result SetPriorityForDirectory(s32 priority, s32 handle);
|
||||
private:
|
||||
int WaitAny(htclow::ChannelState state, os::EventType *event);
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <stratosphere.hpp>
|
||||
#include "htcfs_directory_service_object.hpp"
|
||||
#include "htcfs_client.hpp"
|
||||
#include "../htclow/htclow_default_channel_config.hpp"
|
||||
|
||||
namespace ams::htcfs {
|
||||
|
||||
|
@ -26,19 +27,23 @@ namespace ams::htcfs {
|
|||
}
|
||||
|
||||
Result DirectoryServiceObject::GetEntryCount(ams::sf::Out<s64> out) {
|
||||
AMS_ABORT("DirectoryServiceObject::GetEntryCount");
|
||||
return htcfs::GetClient().GetEntryCount(out.GetPointer(), m_handle);
|
||||
}
|
||||
|
||||
Result DirectoryServiceObject::Read(ams::sf::Out<s64> out, const ams::sf::OutMapAliasArray<fs::DirectoryEntry> &out_entries) {
|
||||
AMS_ABORT("DirectoryServiceObject::Read");
|
||||
if (out_entries.GetSize() * sizeof(fs::DirectoryEntry) >= ClientImpl::MaxPacketBodySize) {
|
||||
return htcfs::GetClient().ReadDirectoryLarge(out.GetPointer(), out_entries.GetPointer(), out_entries.GetSize(), m_handle);
|
||||
} else {
|
||||
return htcfs::GetClient().ReadDirectory(out.GetPointer(), out_entries.GetPointer(), out_entries.GetSize(), m_handle);
|
||||
}
|
||||
}
|
||||
|
||||
Result DirectoryServiceObject::SetPriorityForDirectory(s32 priority) {
|
||||
AMS_ABORT("DirectoryServiceObject::SetPriorityForDirectory");
|
||||
return htcfs::GetClient().SetPriorityForDirectory(priority, m_handle);
|
||||
}
|
||||
|
||||
Result DirectoryServiceObject::GetPriorityForDirectory(ams::sf::Out<s32> out) {
|
||||
AMS_ABORT("DirectoryServiceObject::GetPriorityForDirectory");
|
||||
return htcfs::GetClient().GetPriorityForDirectory(out.GetPointer(), m_handle);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -122,6 +122,26 @@ namespace ams::htcfs {
|
|||
void MakeCloseDirectoryHeader(Header *out, s32 handle) {
|
||||
return this->MakeRequestHeader(out, PacketType::CloseDirectory, 0, handle);
|
||||
}
|
||||
|
||||
void MakeGetEntryCountHeader(Header *out, s32 handle) {
|
||||
return this->MakeRequestHeader(out, PacketType::GetEntryCount, 0, handle);
|
||||
}
|
||||
|
||||
void MakeReadDirectoryHeader(Header *out, s32 handle, size_t max_out_entries) {
|
||||
return this->MakeRequestHeader(out, PacketType::ReadDirectory, 0, handle, max_out_entries);
|
||||
}
|
||||
|
||||
void MakeReadDirectoryLargeHeader(Header *out, s32 handle, size_t max_out_entries) {
|
||||
return this->MakeRequestHeader(out, PacketType::ReadDirectoryLarge, 0, handle, max_out_entries);
|
||||
}
|
||||
|
||||
void MakeGetPriorityForDirectoryHeader(Header *out, s32 handle) {
|
||||
return this->MakeRequestHeader(out, PacketType::GetPriorityForDirectory, 0, handle);
|
||||
}
|
||||
|
||||
void MakeSetPriorityForDirectoryHeader(Header *out, s32 handle, s32 priority) {
|
||||
return this->MakeRequestHeader(out, PacketType::SetPriorityForDirectory, 0, handle, priority);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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 {
|
||||
|
||||
inline Result ConvertToFsResult(Result result) {
|
||||
R_TRY_CATCH(result) {
|
||||
R_CONVERT(htcfs::ResultInvalidArgument, fs::ResultInvalidArgument())
|
||||
R_CONVERT(htcfs::ResultConnectionFailure, fs::ResultTargetNotFound())
|
||||
R_CONVERT(htcfs::ResultOutOfHandle, fs::ResultOpenCountLimit())
|
||||
R_CONVERT(htcfs::ResultInternalError, fs::ResultInternal())
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -32,11 +32,13 @@ namespace ams::htcfs {
|
|||
R_DEFINE_ERROR_RESULT(UnexpectedResponsePacketCategory, 113);
|
||||
R_DEFINE_ERROR_RESULT(UnexpectedResponsePacketType, 114);
|
||||
R_DEFINE_ERROR_RESULT(UnexpectedResponseBodySize, 115);
|
||||
R_DEFINE_ERROR_RESULT(UnexpectedResponseBody, 116);
|
||||
|
||||
R_DEFINE_ERROR_RESULT(UnknownError, 211);
|
||||
R_DEFINE_ERROR_RESULT(UnsupportedProtocolVersion, 212);
|
||||
R_DEFINE_ERROR_RESULT(InvalidRequest, 213);
|
||||
R_DEFINE_ERROR_RESULT(InvalidHandle, 214);
|
||||
R_DEFINE_ERROR_RESULT(OutOfHandle, 215);
|
||||
R_DEFINE_ERROR_RANGE(InternalError, 200, 299);
|
||||
R_DEFINE_ERROR_RESULT(UnknownError, 211);
|
||||
R_DEFINE_ERROR_RESULT(UnsupportedProtocolVersion, 212);
|
||||
R_DEFINE_ERROR_RESULT(InvalidRequest, 213);
|
||||
R_DEFINE_ERROR_RESULT(InvalidHandle, 214);
|
||||
R_DEFINE_ERROR_RESULT(OutOfHandle, 215);
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue