mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
htc: ReadDirectoryLarge/data channel support
This commit is contained in:
parent
9daec3a66a
commit
1961cb1034
4 changed files with 100 additions and 5 deletions
|
@ -23,6 +23,7 @@ namespace ams::htcfs {
|
|||
|
||||
/* TODO: Move to a header? */
|
||||
constexpr u16 RpcChannelId = 0;
|
||||
constexpr u16 DataChannelId = 1;
|
||||
|
||||
alignas(os::ThreadStackAlignment) constinit u8 g_monitor_thread_stack[os::MemoryPageSize];
|
||||
|
||||
|
@ -266,6 +267,14 @@ namespace ams::htcfs {
|
|||
return this->ReceiveFromHtclow(dst, size, std::addressof(m_rpc_channel));
|
||||
}
|
||||
|
||||
Result ClientImpl::ReceiveFromDataChannel(s64 size) {
|
||||
return m_data_channel.WaitReceive(size);
|
||||
}
|
||||
|
||||
Result ClientImpl::SendToDataChannel() {
|
||||
return m_data_channel.Flush();
|
||||
}
|
||||
|
||||
Result ClientImpl::SendToHtclow(const void *src, s64 size, htclow::Channel *channel) {
|
||||
/* Check size. */
|
||||
R_UNLESS(size >= 0, htcfs::ResultInvalidArgument());
|
||||
|
@ -316,6 +325,52 @@ namespace ams::htcfs {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void ClientImpl::InitializeDataChannelForReceive(void *dst, size_t size) {
|
||||
/* Open the data channel. */
|
||||
R_ABORT_UNLESS(m_data_channel.Open(std::addressof(m_module), DataChannelId));
|
||||
|
||||
/* Set our config. */
|
||||
constexpr htclow::ChannelConfig BulkReceiveConfig = {
|
||||
.flow_control_enabled = false,
|
||||
.handshake_enabled = false,
|
||||
.max_packet_size = 0x3E000,
|
||||
};
|
||||
m_data_channel.SetConfig(BulkReceiveConfig);
|
||||
|
||||
/* Set receive buffer. */
|
||||
m_data_channel.SetReceiveBuffer(dst, size);
|
||||
|
||||
/* Connect. */
|
||||
R_ABORT_UNLESS(m_data_channel.Connect());
|
||||
}
|
||||
|
||||
void ClientImpl::InitializeDataChannelForSend(const void *src, size_t size) {
|
||||
/* Open the data channel. */
|
||||
R_ABORT_UNLESS(m_data_channel.Open(std::addressof(m_module), DataChannelId));
|
||||
|
||||
/* Check that the size is valid. */
|
||||
AMS_ASSERT(util::IsIntValueRepresentable<s64>(size));
|
||||
|
||||
/* Set our config. */
|
||||
constexpr htclow::ChannelConfig BulkSendConfig = {
|
||||
.flow_control_enabled = false,
|
||||
.handshake_enabled = false,
|
||||
.max_packet_size = 0xE020,
|
||||
};
|
||||
m_data_channel.SetConfig(BulkSendConfig);
|
||||
|
||||
/* Set our send buffer. */
|
||||
m_data_channel.SetSendBufferWithData(src, size);
|
||||
|
||||
/* Connect. */
|
||||
R_ABORT_UNLESS(m_data_channel.Connect());
|
||||
}
|
||||
|
||||
void ClientImpl::FinalizeDataChannel() {
|
||||
/* Close our data channel. */
|
||||
m_data_channel.Close();
|
||||
}
|
||||
|
||||
Result ClientImpl::SendRequest(const Header &request, const void *arg1, size_t arg1_size, const void *arg2, size_t arg2_size) {
|
||||
/* Try to perform an optimized send. */
|
||||
if (sizeof(request) + arg1_size + arg2_size < sizeof(m_packet_buffer)) {
|
||||
|
@ -492,13 +547,46 @@ namespace ams::htcfs {
|
|||
/* Initialize our rpc channel. */
|
||||
R_TRY(this->InitializeRpcChannel());
|
||||
|
||||
/* Setup data channel. */
|
||||
const bool use_data_channel = max_out_entries > 0;
|
||||
if (use_data_channel) {
|
||||
this->InitializeDataChannelForReceive(out_entries, max_out_entries * sizeof(*out_entries));
|
||||
}
|
||||
ON_SCOPE_EXIT { if (use_data_channel) { this->FinalizeDataChannel(); } };
|
||||
|
||||
/* 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);
|
||||
m_header_factory.MakeReadDirectoryLargeHeader(std::addressof(request), handle, max_out_entries, DataChannelId);
|
||||
|
||||
AMS_ABORT("TODO: Data channel setup/teardown");
|
||||
/* 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]));
|
||||
|
||||
/* Check that the number of entries read is allowable. */
|
||||
R_UNLESS(static_cast<size_t>(response.params[2]) <= max_out_entries, htcfs::ResultUnexpectedResponseBody());
|
||||
|
||||
/* Read the entries, if there are any. */
|
||||
if (response.params[2] > 0) {
|
||||
R_TRY(this->ReceiveFromDataChannel(response.params[2] * sizeof(*out_entries)));
|
||||
}
|
||||
|
||||
/* Set the number of output entries. */
|
||||
*out = response.params[2];
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ClientImpl::GetPriorityForDirectory(s32 *out, s32 handle) {
|
||||
|
|
|
@ -82,12 +82,19 @@ namespace ams::htcfs {
|
|||
Result SendToRpcChannel(const void *src, s64 size);
|
||||
Result ReceiveFromRpcChannel(void *dst, s64 size);
|
||||
|
||||
Result ReceiveFromDataChannel(s64 size);
|
||||
Result SendToDataChannel();
|
||||
|
||||
Result SendToHtclow(const void *src, s64 size, htclow::Channel *channel);
|
||||
Result ReceiveFromHtclow(void *dst, s64 size, htclow::Channel *channel);
|
||||
|
||||
Result SendRequest(const Header &request) { return this->SendRequest(request, nullptr, 0, nullptr, 0); }
|
||||
Result SendRequest(const Header &request, const void *arg1, size_t arg1_size) { return this->SendRequest(request, arg1, arg1_size, nullptr, 0); }
|
||||
Result SendRequest(const Header &request, const void *arg1, size_t arg1_size, const void *arg2, size_t arg2_size);
|
||||
|
||||
void InitializeDataChannelForReceive(void *dst, size_t size);
|
||||
void InitializeDataChannelForSend(const void *src, size_t size);
|
||||
void FinalizeDataChannel();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -131,8 +131,8 @@ namespace ams::htcfs {
|
|||
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 MakeReadDirectoryLargeHeader(Header *out, s32 handle, size_t max_out_entries, u16 data_channel_id) {
|
||||
return this->MakeRequestHeader(out, PacketType::ReadDirectoryLarge, 0, handle, max_out_entries, data_channel_id);
|
||||
}
|
||||
|
||||
void MakeGetPriorityForDirectoryHeader(Header *out, s32 handle) {
|
||||
|
|
|
@ -305,7 +305,7 @@ namespace ams::htclow::mux {
|
|||
auto it = m_channel_impl_map.GetMap().find(channel);
|
||||
R_UNLESS(it != m_channel_impl_map.GetMap().end(), htclow::ResultChannelNotExist());
|
||||
|
||||
/* Perform the RECEIVE. */
|
||||
/* Perform the receive. */
|
||||
return m_channel_impl_map[it->second].DoReceiveEnd(out, dst, dst_size);
|
||||
} else {
|
||||
*out = 0;
|
||||
|
|
Loading…
Reference in a new issue