Revert "hoc-clk: add live vdd2, live boost clock and basic pwm dimming"

This reverts commit 15b7df8ef1.
This commit is contained in:
souldbminersmwc
2025-11-09 16:14:52 -05:00
parent 22ec140738
commit 21a3f953d7
3804 changed files with 435 additions and 570162 deletions

View File

@@ -1,45 +0,0 @@
/*
* Copyright (c) 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::usb::impl {
constexpr int GetEndpointIndex(u8 address) {
int idx = address & UsbEndpointAddressMask_EndpointNumber;
if ((address & UsbEndpointAddressMask_Dir) == UsbEndpointAddressMask_DirDevicetoHost) {
idx += 0x10;
}
return idx;
}
template<typename T>
class ScopedRefCount {
NON_COPYABLE(ScopedRefCount);
NON_MOVEABLE(ScopedRefCount);
private:
T &m_obj;
public:
ALWAYS_INLINE ScopedRefCount(T &o) : m_obj(o) {
++m_obj;
}
ALWAYS_INLINE ~ScopedRefCount() {
--m_obj;
}
};
}

View File

@@ -1,815 +0,0 @@
/*
* Copyright (c) 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 "usb_remote_ds_root_session.hpp"
#include "usb_remote_ds_service.hpp"
#include "impl/usb_util.hpp"
namespace ams::usb {
Result DsClient::Initialize(ComplexId complex_id) {
/* Clear interfaces. */
for (size_t i = 0; i < util::size(m_interfaces); ++i) {
m_interfaces[i] = nullptr;
}
/* Initialize heap. */
m_heap_handle = lmem::CreateExpHeap(m_heap_buffer, sizeof(m_heap_buffer), lmem::CreateOption_None);
R_UNLESS(m_heap_handle != nullptr, usb::ResultMemAllocFailure());
/* Attach our allocator. */
m_allocator.Attach(m_heap_handle);
/* Connect to usb:ds. */
/* NOTE: Here, Nintendo does m_domain.InitializeByDomain<...>(...); m_domain.SetSessionCount(1); */
{
#if defined(ATMOSPHERE_OS_HORIZON)
os::NativeHandle h;
R_TRY(sm::GetServiceHandle(std::addressof(h), sm::ServiceName::Encode("usb:ds")));
::Service srv;
::serviceCreate(&srv, h);
R_ABORT_UNLESS(serviceConvertToDomain(std::addressof(srv)));
using Allocator = decltype(m_allocator);
using ObjectFactory = sf::ObjectFactory<Allocator::Policy>;
if (hos::GetVersion() >= hos::Version_11_0_0) {
m_root_session = ObjectFactory::CreateSharedEmplaced<ds::IDsRootSession, RemoteDsRootSession>(std::addressof(m_allocator), srv, std::addressof(m_allocator));
R_TRY(m_root_session->GetService(std::addressof(m_ds_service)));
} else {
m_ds_service = ObjectFactory::CreateSharedEmplaced<ds::IDsService, RemoteDsService>(std::addressof(m_allocator), srv, std::addressof(m_allocator));
}
#else
AMS_ABORT("TODO");
#endif
}
/* Bind the client process. */
R_TRY(m_ds_service->Bind(complex_id, sf::CopyHandle(dd::GetCurrentProcessHandle(), false)));
/* Get the state change event. */
sf::NativeHandle event_handle;
R_TRY(m_ds_service->GetStateChangeEvent(std::addressof(event_handle)));
/* Attach the state change event handle to our event. */
os::AttachReadableHandleToSystemEvent(std::addressof(m_state_change_event), event_handle.GetOsHandle(), event_handle.IsManaged(), os::EventClearMode_ManualClear);
event_handle.Detach();
/* Mark ourselves as initialized. */
m_is_initialized = true;
R_SUCCEED();
}
Result DsClient::Finalize() {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Disable and finalize all interfaces. */
R_TRY(this->DisableDevice());
for (size_t i = 0; i < util::size(m_interfaces); ++i) {
if (m_interfaces[i] != nullptr) {
R_TRY(m_interfaces[i]->Finalize());
}
}
/* Check our reference count .*/
R_UNLESS(m_reference_count <= 1, usb::ResultResourceBusy());
/* Finalize members. */
m_is_initialized = false;
os::DestroySystemEvent(std::addressof(m_state_change_event));
lmem::DestroyExpHeap(m_heap_handle);
m_heap_handle = nullptr;
/* Destroy interface objects. */
m_ds_service = nullptr;
m_root_session = nullptr;
R_SUCCEED();
}
bool DsClient::IsInitialized() {
return m_is_initialized;
}
Result DsClient::EnableDevice() {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Enable all interfaces. */
if (hos::GetVersion() < hos::Version_11_0_0) {
for (size_t i = 0; i < util::size(m_interfaces); ++i) {
if (m_interfaces[i] != nullptr) {
R_TRY(m_interfaces[i]->Enable());
}
}
}
/* Enable the device. */
R_TRY(m_ds_service->Enable());
/* Mark disabled. */
m_is_enabled = true;
R_SUCCEED();
}
Result DsClient::DisableDevice() {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Disable the device. */
R_TRY(m_ds_service->Disable());
/* Disable all interfaces. */
if (hos::GetVersion() < hos::Version_11_0_0) {
for (size_t i = 0; i < util::size(m_interfaces); ++i) {
if (m_interfaces[i] != nullptr) {
R_TRY(m_interfaces[i]->Disable());
}
}
}
/* Mark disabled. */
m_is_enabled = false;
R_SUCCEED();
}
os::SystemEventType *DsClient::GetStateChangeEvent() {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
return m_is_initialized ? std::addressof(m_state_change_event) : nullptr;
}
Result DsClient::GetState(UsbState *out) {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Check that we have a service. */
AMS_ABORT_UNLESS(m_ds_service != nullptr);
R_RETURN(m_ds_service->GetState(out));
}
Result DsClient::ClearDeviceData() {
R_RETURN(m_ds_service->ClearDeviceData());
}
Result DsClient::AddUsbStringDescriptor(u8 *out_index, UsbStringDescriptor *desc) {
R_RETURN(m_ds_service->AddUsbStringDescriptor(out_index, sf::InBuffer(reinterpret_cast<const u8 *>(desc), sizeof(*desc))));
}
Result DsClient::DeleteUsbStringDescriptor(u8 index) {
R_RETURN(m_ds_service->DeleteUsbStringDescriptor(index));
}
Result DsClient::SetUsbDeviceDescriptor(UsbDeviceDescriptor *desc, UsbDeviceSpeed speed) {
R_RETURN(m_ds_service->SetUsbDeviceDescriptor(sf::InBuffer(reinterpret_cast<const u8 *>(desc), sizeof(*desc)), speed));
}
Result DsClient::SetBinaryObjectStore(u8 *data, int size) {
R_RETURN(m_ds_service->SetBinaryObjectStore(sf::InBuffer(reinterpret_cast<const u8 *>(data), size)));
}
Result DsClient::AddInterface(DsInterface *intf, sf::SharedPointer<ds::IDsInterface> *out_srv, uint8_t bInterfaceNumber) {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Check that we have a service. */
AMS_ABORT_UNLESS(m_ds_service != nullptr);
/* Register the interface. */
R_TRY(m_ds_service->RegisterInterface(out_srv, bInterfaceNumber));
/* Set interface. */
m_interfaces[bInterfaceNumber] = intf;
R_SUCCEED();
}
Result DsClient::DeleteInterface(uint8_t bInterfaceNumber) {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Check that we have the interface. */
R_UNLESS(m_interfaces[bInterfaceNumber] != nullptr, usb::ResultOperationDenied());
/* Clear the interface. */
m_interfaces[bInterfaceNumber] = nullptr;
R_SUCCEED();
}
Result DsInterface::Initialize(DsClient *client, u8 bInterfaceNumber) {
/* Check that we haven't already initialized. */
R_UNLESS(!m_is_initialized, usb::ResultAlreadyInitialized());
/* Set our client. */
m_client = client;
/* Clear all endpoints. */
for (size_t i = 0; i < util::size(m_endpoints); ++i) {
m_endpoints[i] = nullptr;
}
/* Set our interface number. */
R_UNLESS(bInterfaceNumber < util::size(m_client->m_interfaces), usb::ResultInvalidParameter());
m_interface_num = bInterfaceNumber;
/* Add the interface. */
R_TRY(m_client->AddInterface(this, std::addressof(m_interface), m_interface_num));
/* Ensure we cleanup if we fail after this. */
auto intf_guard = SCOPE_GUARD { m_client->DeleteInterface(m_interface_num); m_interface = nullptr; };
/* Get events. */
sf::NativeHandle setup_event_handle;
sf::NativeHandle ctrl_in_event_handle;
sf::NativeHandle ctrl_out_event_handle;
R_TRY(m_interface->GetSetupEvent(std::addressof(setup_event_handle)));
R_TRY(m_interface->GetCtrlInCompletionEvent(std::addressof(ctrl_in_event_handle)));
R_TRY(m_interface->GetCtrlOutCompletionEvent(std::addressof(ctrl_out_event_handle)));
/* Attach events. */
os::AttachReadableHandleToSystemEvent(std::addressof(m_setup_event), setup_event_handle.GetOsHandle(), setup_event_handle.IsManaged(), os::EventClearMode_ManualClear);
os::AttachReadableHandleToSystemEvent(std::addressof(m_ctrl_in_completion_event), ctrl_in_event_handle.GetOsHandle(), ctrl_in_event_handle.IsManaged(), os::EventClearMode_ManualClear);
os::AttachReadableHandleToSystemEvent(std::addressof(m_ctrl_out_completion_event), ctrl_out_event_handle.GetOsHandle(), ctrl_out_event_handle.IsManaged(), os::EventClearMode_ManualClear);
setup_event_handle.Detach();
ctrl_in_event_handle.Detach();
ctrl_out_event_handle.Detach();
/* Increment our client's reference count. */
++m_client->m_reference_count;
/* Set ourselves as initialized. */
m_is_initialized = true;
intf_guard.Cancel();
R_SUCCEED();
}
Result DsInterface::Finalize() {
/* Validate that we have a service. */
AMS_ABORT_UNLESS(m_interface != nullptr);
/* We must be disabled. */
R_UNLESS(!m_client->m_is_enabled, usb::ResultResourceBusy());
/* Finalize all endpoints. */
for (size_t i = 0; i < util::size(m_endpoints); ++i) {
if (m_endpoints[i] != nullptr) {
R_TRY(m_endpoints[i]->Finalize());
}
}
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Check our reference count .*/
R_UNLESS(m_reference_count <= 1, usb::ResultResourceBusy());
/* Finalize members. */
m_is_initialized = false;
os::DestroySystemEvent(std::addressof(m_setup_event));
os::DestroySystemEvent(std::addressof(m_ctrl_in_completion_event));
os::DestroySystemEvent(std::addressof(m_ctrl_out_completion_event));
/* Delete ourselves from our cleint. */
m_client->DeleteInterface(m_interface_num);
/* Destroy our service. */
m_interface = nullptr;
/* Close our reference to our client. */
--m_client->m_reference_count;
m_client = nullptr;
R_SUCCEED();
}
Result DsInterface::AppendConfigurationData(UsbDeviceSpeed speed, void *data, u32 size) {
R_RETURN(m_interface->AppendConfigurationData(m_interface_num, speed, sf::InBuffer(data, size)));
}
bool DsInterface::IsInitialized() {
return m_is_initialized;
}
os::SystemEventType *DsInterface::GetSetupEvent() {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
return m_is_initialized ? std::addressof(m_setup_event) : nullptr;
}
Result DsInterface::GetSetupPacket(UsbCtrlRequest *out) {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Check that we have a service. */
AMS_ABORT_UNLESS(m_interface != nullptr);
R_RETURN(m_interface->GetSetupPacket(sf::OutBuffer(out, sizeof(*out))));
}
Result DsInterface::Enable() {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* If we're already enabled, nothing to do. */
R_SUCCEED_IF(m_client->m_is_enabled);
/* Check that we have a service. */
AMS_ABORT_UNLESS(m_interface != nullptr);
/* Perform the enable. */
R_TRY(m_interface->Enable());
R_SUCCEED();
}
Result DsInterface::Disable() {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* If we're already disabled, nothing to do. */
R_SUCCEED_IF(!m_client->m_is_enabled);
/* Check that we have a service. */
AMS_ABORT_UNLESS(m_interface != nullptr);
/* Perform the disable. */
R_TRY(m_interface->Disable());
R_SUCCEED();
}
Result DsInterface::AddEndpoint(DsEndpoint *ep, u8 bEndpointAddress, sf::SharedPointer<ds::IDsEndpoint> *out) {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Check that we're not already enabled. */
R_UNLESS(!m_client->m_is_enabled, usb::ResultOperationDenied());
/* Check that we have a service. */
AMS_ABORT_UNLESS(m_interface != nullptr);
/* Register the endpoint. */
R_TRY(m_interface->RegisterEndpoint(bEndpointAddress, out));
/* Set the endpoint. */
m_endpoints[impl::GetEndpointIndex(bEndpointAddress)] = ep;
R_SUCCEED();
}
Result DsInterface::DeleteEndpoint(u8 bEndpointAddress) {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Check that we're disabled and have the endpoint. */
const auto index = impl::GetEndpointIndex(bEndpointAddress);
R_UNLESS(!m_client->m_is_enabled, usb::ResultOperationDenied());
R_UNLESS(m_endpoints[index] != nullptr, usb::ResultOperationDenied());
/* Clear the endpoint. */
m_endpoints[index] = nullptr;
R_SUCCEED();
}
Result DsInterface::CtrlIn(u32 *out_transferred, void *dst, u32 size) {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Check that we're enabled. */
R_UNLESS(m_client->m_is_enabled, usb::ResultOperationDenied());
/* Check that the data is aligned. */
R_UNLESS(usb::IsDmaAligned(reinterpret_cast<u64>(dst)), usb::ResultAlignmentError());
/* If we should, flush cache. */
if (size != 0) {
dd::FlushDataCache(dst, size);
}
/* Check that we have a service. */
AMS_ABORT_UNLESS(m_interface != nullptr);
/* Perform the transfer. */
u32 urb_id;
R_TRY(m_interface->CtrlInAsync(std::addressof(urb_id), reinterpret_cast<u64>(dst), size));
/* Wait for control to finish. */
os::WaitSystemEvent(std::addressof(m_ctrl_in_completion_event));
os::ClearSystemEvent(std::addressof(m_ctrl_in_completion_event));
/* Get the urb report. */
R_ABORT_UNLESS(m_interface->GetCtrlInUrbReport(std::addressof(m_report)));
/* Check the report is for our urb. */
R_UNLESS(m_report.count == 1, usb::ResultInternalStateError());
R_UNLESS(m_report.reports[0].id == urb_id, usb::ResultInternalStateError());
/* Set output bytes. */
if (out_transferred != nullptr) {
*out_transferred = m_report.reports[0].transferred_size;
}
/* Handle the report. */
switch (m_report.reports[0].status) {
case UrbStatus_Cancelled:
R_THROW(usb::ResultInterrupted());
case UrbStatus_Failed:
R_THROW(usb::ResultTransactionError());
case UrbStatus_Finished:
R_SUCCEED();
default:
R_THROW(usb::ResultInternalStateError());
}
}
Result DsInterface::CtrlOut(u32 *out_transferred, void *dst, u32 size) {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Check that we're enabled. */
R_UNLESS(m_client->m_is_enabled, usb::ResultOperationDenied());
/* Check that the data is aligned. */
R_UNLESS(usb::IsDmaAligned(reinterpret_cast<u64>(dst)), usb::ResultAlignmentError());
/* If we should, invalidate cache. */
if (size != 0) {
dd::InvalidateDataCache(dst, size);
}
/* Check that we have a service. */
AMS_ABORT_UNLESS(m_interface != nullptr);
/* Perform the transfer. */
u32 urb_id;
R_TRY(m_interface->CtrlOutAsync(std::addressof(urb_id), reinterpret_cast<u64>(dst), size));
/* Wait for control to finish. */
os::WaitSystemEvent(std::addressof(m_ctrl_out_completion_event));
os::ClearSystemEvent(std::addressof(m_ctrl_out_completion_event));
/* Ensure that cache remains consistent. */
ON_SCOPE_EXIT {
if (size != 0) {
dd::InvalidateDataCache(dst, size);
}
};
/* Get the urb report. */
R_ABORT_UNLESS(m_interface->GetCtrlOutUrbReport(std::addressof(m_report)));
/* Check the report is for our urb. */
R_UNLESS(m_report.count == 1, usb::ResultInternalStateError());
R_UNLESS(m_report.reports[0].id == urb_id, usb::ResultInternalStateError());
/* Set output bytes. */
if (out_transferred != nullptr) {
*out_transferred = m_report.reports[0].transferred_size;
}
/* Handle the report. */
switch (m_report.reports[0].status) {
case UrbStatus_Cancelled:
R_THROW(usb::ResultInterrupted());
case UrbStatus_Failed:
R_THROW(usb::ResultTransactionError());
case UrbStatus_Finished:
R_SUCCEED();
default:
R_THROW(usb::ResultInternalStateError());
}
}
Result DsInterface::CtrlRead(u32 *out_transferred, void *dst, u32 size) {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Do the data transfer. */
Result result = this->CtrlOut(out_transferred, dst, size);
/* Do the status transfer. */
if (R_SUCCEEDED(result)) {
result = this->CtrlIn(nullptr, nullptr, 0);
}
/* If we fail, stall. */
if (R_FAILED(result)) {
result = this->CtrlStall();
}
R_RETURN(result);
}
Result DsInterface::CtrlWrite(u32 *out_transferred, void *dst, u32 size) {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Do the data transfer. */
Result result = this->CtrlIn(out_transferred, dst, size);
/* Do the status transfer. */
if (R_SUCCEEDED(result)) {
result = this->CtrlOut(nullptr, nullptr, 0);
}
/* If we failed, stall. */
if (R_FAILED(result)) {
result = this->CtrlStall();
}
R_RETURN(result);
}
Result DsInterface::CtrlDone() {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Do the status transfer. */
Result result = this->CtrlIn(nullptr, nullptr, 0);
/* If we failed, stall. */
if (R_FAILED(result)) {
result = this->CtrlStall();
}
R_RETURN(result);
}
Result DsInterface::CtrlStall() {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Check that we're enabled. */
R_UNLESS(m_client->m_is_enabled, usb::ResultOperationDenied());
/* Check that we have a service. */
AMS_ABORT_UNLESS(m_interface != nullptr);
R_RETURN(m_interface->CtrlStall());
}
Result DsEndpoint::Initialize(DsInterface *interface, u8 bEndpointAddress) {
/* Check that the interface is valid. */
AMS_ABORT_UNLESS(interface != nullptr);
/* Check that we're not already initialized. */
R_UNLESS(!m_is_initialized, usb::ResultAlreadyInitialized());
/* Set our interface. */
m_interface = interface;
/* Add the endpoint. */
R_TRY(m_interface->AddEndpoint(this, bEndpointAddress, std::addressof(m_endpoint)));
/* Set our address. */
m_address = bEndpointAddress;
/* Ensure we clean up if we fail after this. */
auto ep_guard = SCOPE_GUARD { m_interface->DeleteEndpoint(m_address); m_endpoint = nullptr; };
/* Get completion event. */
sf::NativeHandle event_handle;
R_TRY(m_endpoint->GetCompletionEvent(std::addressof(event_handle)));
/* Increment our interface's reference count. */
++m_interface->m_reference_count;
++m_interface->m_client->m_reference_count;
/* Attach our event. */
os::AttachReadableHandleToSystemEvent(std::addressof(m_completion_event), event_handle.GetOsHandle(), event_handle.IsManaged(), os::EventClearMode_ManualClear);
event_handle.Detach();
/* Mark initialized. */
m_is_initialized = true;
ep_guard.Cancel();
R_SUCCEED();
}
Result DsEndpoint::Finalize() {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Cancel any pending transactions. */
m_endpoint->Cancel();
/* Wait for us to be at one reference count. */
while (m_reference_count > 1) {
os::SleepThread(TimeSpan::FromMilliSeconds(25));
}
/* Destroy our event. */
os::DestroySystemEvent(std::addressof(m_completion_event));
/* Decrement our interface's reference count. */
--m_interface->m_reference_count;
--m_interface->m_client->m_reference_count;
/* Delete ourselves. */
R_TRY(m_interface->DeleteEndpoint(m_address));
/* Clear ourselves. */
m_interface = nullptr;
m_endpoint = nullptr;
/* Mark uninitialized. */
m_is_initialized = false;
R_SUCCEED();
}
bool DsEndpoint::IsInitialized() {
return m_is_initialized;
}
Result DsEndpoint::PostBuffer(u32 *out_transferred, void *buf, u32 size) {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Post buffer. */
u32 urb_id;
R_TRY(this->PostBufferAsync(std::addressof(urb_id), buf, size));
/* Wait for completion. */
os::WaitSystemEvent(std::addressof(m_completion_event));
os::ClearSystemEvent(std::addressof(m_completion_event));
/* Get URB report. */
UrbReport report;
AMS_ABORT_UNLESS(m_endpoint != nullptr);
R_ABORT_UNLESS(m_endpoint->GetUrbReport(std::addressof(report)));
/* Check the report is for our urb. */
R_UNLESS(report.count == 1, usb::ResultInternalStateError());
R_UNLESS(report.reports[0].id == urb_id, usb::ResultInternalStateError());
/* Set output bytes. */
if (out_transferred != nullptr) {
*out_transferred = report.reports[0].transferred_size;
}
/* Handle the report. */
switch (report.reports[0].status) {
case UrbStatus_Cancelled:
R_THROW(usb::ResultInterrupted());
case UrbStatus_Failed:
R_THROW(usb::ResultTransactionError());
case UrbStatus_Finished:
R_SUCCEED();
default:
R_THROW(usb::ResultInternalStateError());
}
}
Result DsEndpoint::PostBufferAsync(u32 *out_urb_id, void *buf, u32 size) {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Check that the buffer is DMA aligned. */
R_UNLESS(usb::IsDmaAligned(reinterpret_cast<u64>(buf)), usb::ResultAlignmentError());
/* Check that we have a service. */
AMS_ABORT_UNLESS(m_endpoint != nullptr);
/* Post */
u32 urb_id = 0;
R_TRY(m_endpoint->PostBufferAsync(std::addressof(urb_id), reinterpret_cast<u64>(buf), size));
*out_urb_id = urb_id;
R_SUCCEED();
}
os::SystemEventType *DsEndpoint::GetCompletionEvent() {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
return m_is_initialized ? std::addressof(m_completion_event) : nullptr;
}
Result DsEndpoint::GetUrbReport(UrbReport *out) {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Check that we have a service. */
AMS_ABORT_UNLESS(m_endpoint != nullptr);
R_RETURN(m_endpoint->GetUrbReport(out));
}
Result DsEndpoint::Cancel() {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Check that we have a service. */
AMS_ABORT_UNLESS(m_endpoint != nullptr);
R_RETURN(m_endpoint->Cancel());
}
Result DsEndpoint::SetZeroLengthTransfer(bool zlt) {
/* Create a scoped reference. */
impl::ScopedRefCount scoped_ref(m_reference_count);
/* Check that we're initialized. */
R_UNLESS(m_is_initialized, usb::ResultNotInitialized());
/* Check that we have a service. */
AMS_ABORT_UNLESS(m_endpoint != nullptr);
R_RETURN(m_endpoint->SetZlt(zlt));
}
}

View File

@@ -1,68 +0,0 @@
/*
* Copyright (c) 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 "usb_remote_ds_endpoint.hpp"
namespace ams::usb {
#if defined(ATMOSPHERE_OS_HORIZON)
Result RemoteDsEndpoint::PostBufferAsync(sf::Out<u32> out_urb_id, u64 address, u32 size) {
const struct {
u32 size;
u64 address;
} in = { size, address };
serviceAssumeDomain(std::addressof(m_srv));
R_RETURN(serviceDispatchInOut(std::addressof(m_srv), 0, in, *out_urb_id));
}
Result RemoteDsEndpoint::Cancel() {
serviceAssumeDomain(std::addressof(m_srv));
R_RETURN(serviceDispatch(std::addressof(m_srv), 1));
}
Result RemoteDsEndpoint::GetCompletionEvent(sf::OutCopyHandle out) {
serviceAssumeDomain(std::addressof(m_srv));
os::NativeHandle event_handle;
R_TRY((serviceDispatch(std::addressof(m_srv), 2,
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
.out_handles = std::addressof(event_handle),
)));
out.SetValue(event_handle, true);
R_SUCCEED();
}
Result RemoteDsEndpoint::GetUrbReport(sf::Out<usb::UrbReport> out) {
serviceAssumeDomain(std::addressof(m_srv));
R_RETURN(serviceDispatchOut(std::addressof(m_srv), 3, *out));
}
Result RemoteDsEndpoint::Stall() {
serviceAssumeDomain(std::addressof(m_srv));
R_RETURN(serviceDispatch(std::addressof(m_srv), 4));
}
Result RemoteDsEndpoint::SetZlt(bool zlt) {
const u8 in = zlt ? 1 : 0;
serviceAssumeDomain(std::addressof(m_srv));
R_RETURN(serviceDispatchIn(std::addressof(m_srv), 5, in));
}
#endif
}

View File

@@ -1,39 +0,0 @@
/*
* Copyright (c) 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::usb {
#if defined(ATMOSPHERE_OS_HORIZON)
class RemoteDsEndpoint {
private:
Service m_srv;
public:
RemoteDsEndpoint(Service &srv) : m_srv(srv) { /* ... */ }
virtual ~RemoteDsEndpoint() { serviceClose(std::addressof(m_srv)); }
public:
Result PostBufferAsync(sf::Out<u32> out_urb_id, u64 address, u32 size);
Result Cancel();
Result GetCompletionEvent(sf::OutCopyHandle out);
Result GetUrbReport(sf::Out<usb::UrbReport> out);
Result Stall();
Result SetZlt(bool zlt);
};
static_assert(ds::IsIDsEndpoint<RemoteDsEndpoint>);
#endif
}

View File

@@ -1,156 +0,0 @@
/*
* Copyright (c) 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 "usb_remote_ds_interface.hpp"
#include "usb_remote_ds_endpoint.hpp"
namespace ams::usb {
#if defined(ATMOSPHERE_OS_HORIZON)
Result RemoteDsInterface::RegisterEndpoint(u8 endpoint_address, sf::Out<sf::SharedPointer<usb::ds::IDsEndpoint>> out) {
Service srv;
serviceAssumeDomain(std::addressof(m_srv));
R_TRY(serviceDispatchIn(std::addressof(m_srv), 0, endpoint_address,
.out_num_objects = 1,
.out_objects = std::addressof(srv),
));
*out = ObjectFactory::CreateSharedEmplaced<ds::IDsEndpoint, RemoteDsEndpoint>(m_allocator, srv);
R_SUCCEED();
}
Result RemoteDsInterface::GetSetupEvent(sf::OutCopyHandle out) {
serviceAssumeDomain(std::addressof(m_srv));
os::NativeHandle event_handle;
R_TRY((serviceDispatch(std::addressof(m_srv), 1,
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
.out_handles = std::addressof(event_handle),
)));
out.SetValue(event_handle, true);
R_SUCCEED();
}
Result RemoteDsInterface::GetSetupPacket(const sf::OutBuffer &out) {
serviceAssumeDomain(std::addressof(m_srv));
return serviceDispatch(std::addressof(m_srv), 2,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { out.GetPointer(), out.GetSize() } },
);
}
Result RemoteDsInterface::CtrlInAsync(sf::Out<u32> out_urb_id, u64 address, u32 size) {
const struct {
u32 size;
u64 address;
} in = { size, address };
serviceAssumeDomain(std::addressof(m_srv));
R_RETURN(serviceDispatchInOut(std::addressof(m_srv), hos::GetVersion() >= hos::Version_11_0_0 ? 3 : 5, in, *out_urb_id));
}
Result RemoteDsInterface::CtrlOutAsync(sf::Out<u32> out_urb_id, u64 address, u32 size) {
const struct {
u32 size;
u64 address;
} in = { size, address };
serviceAssumeDomain(std::addressof(m_srv));
R_RETURN(serviceDispatchInOut(std::addressof(m_srv), hos::GetVersion() >= hos::Version_11_0_0 ? 4 : 6, in, *out_urb_id));
}
Result RemoteDsInterface::GetCtrlInCompletionEvent(sf::OutCopyHandle out) {
serviceAssumeDomain(std::addressof(m_srv));
os::NativeHandle event_handle;
R_TRY((serviceDispatch(std::addressof(m_srv), hos::GetVersion() >= hos::Version_11_0_0 ? 5 : 7,
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
.out_handles = std::addressof(event_handle),
)));
out.SetValue(event_handle, true);
R_SUCCEED();
}
Result RemoteDsInterface::GetCtrlInUrbReport(sf::Out<usb::UrbReport> out) {
serviceAssumeDomain(std::addressof(m_srv));
R_RETURN(serviceDispatchOut(std::addressof(m_srv), hos::GetVersion() >= hos::Version_11_0_0 ? 6 : 8, *out));
}
Result RemoteDsInterface::GetCtrlOutCompletionEvent(sf::OutCopyHandle out) {
serviceAssumeDomain(std::addressof(m_srv));
os::NativeHandle event_handle;
R_TRY((serviceDispatch(std::addressof(m_srv), hos::GetVersion() >= hos::Version_11_0_0 ? 7 : 9,
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
.out_handles = std::addressof(event_handle),
)));
out.SetValue(event_handle, true);
R_SUCCEED();
}
Result RemoteDsInterface::GetCtrlOutUrbReport(sf::Out<usb::UrbReport> out) {
serviceAssumeDomain(std::addressof(m_srv));
R_RETURN(serviceDispatchOut(std::addressof(m_srv), hos::GetVersion() >= hos::Version_11_0_0 ? 8 : 10, *out));
}
Result RemoteDsInterface::CtrlStall() {
serviceAssumeDomain(std::addressof(m_srv));
R_RETURN(serviceDispatch(std::addressof(m_srv), hos::GetVersion() >= hos::Version_11_0_0 ? 9 : 11));
}
Result RemoteDsInterface::AppendConfigurationData(u8 bInterfaceNumber, usb::UsbDeviceSpeed device_speed, const sf::InBuffer &data) {
if (hos::GetVersion() >= hos::Version_11_0_0) {
serviceAssumeDomain(std::addressof(m_srv));
return serviceDispatchIn(std::addressof(m_srv), 10, device_speed,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { data.GetPointer(), data.GetSize() } },
);
} else {
const struct {
u8 bInterfaceNumber;
usb::UsbDeviceSpeed device_speed;
} in = { bInterfaceNumber, device_speed };
serviceAssumeDomain(std::addressof(m_srv));
return serviceDispatchIn(std::addressof(m_srv), 12, in,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { data.GetPointer(), data.GetSize() } },
);
}
}
Result RemoteDsInterface::Enable() {
R_SUCCEED_IF(hos::GetVersion() >= hos::Version_11_0_0);
serviceAssumeDomain(std::addressof(m_srv));
R_RETURN(serviceDispatch(std::addressof(m_srv), 3));
}
Result RemoteDsInterface::Disable() {
R_SUCCEED_IF(hos::GetVersion() >= hos::Version_11_0_0);
serviceAssumeDomain(std::addressof(m_srv));
R_RETURN(serviceDispatch(std::addressof(m_srv), 3));
}
#endif
}

View File

@@ -1,50 +0,0 @@
/*
* Copyright (c) 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::usb {
#if defined(ATMOSPHERE_OS_HORIZON)
class RemoteDsInterface {
private:
using Allocator = sf::ExpHeapAllocator;
using ObjectFactory = sf::ObjectFactory<Allocator::Policy>;
private:
Service m_srv;
Allocator *m_allocator;
public:
RemoteDsInterface(Service &srv, sf::ExpHeapAllocator *allocator) : m_srv(srv), m_allocator(allocator) { /* ... */ }
virtual ~RemoteDsInterface() { serviceClose(std::addressof(m_srv)); }
public:
Result RegisterEndpoint(u8 endpoint_address, sf::Out<sf::SharedPointer<usb::ds::IDsEndpoint>> out);
Result GetSetupEvent(sf::OutCopyHandle out);
Result GetSetupPacket(const sf::OutBuffer & out);
Result CtrlInAsync(sf::Out<u32> out_urb_id, u64 address, u32 size);
Result CtrlOutAsync(sf::Out<u32> out_urb_id, u64 address, u32 size);
Result GetCtrlInCompletionEvent(sf::OutCopyHandle out);
Result GetCtrlInUrbReport(sf::Out<usb::UrbReport> out);
Result GetCtrlOutCompletionEvent(sf::OutCopyHandle out);
Result GetCtrlOutUrbReport(sf::Out<usb::UrbReport> out);
Result CtrlStall();
Result AppendConfigurationData(u8 bInterfaceNumber, usb::UsbDeviceSpeed device_speed, const sf::InBuffer &data);
Result Enable();
Result Disable();
};
static_assert(ds::IsIDsInterface<RemoteDsInterface>);
#endif
}

View File

@@ -1,35 +0,0 @@
/*
* Copyright (c) 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 "usb_remote_ds_root_session.hpp"
#include "usb_remote_ds_service.hpp"
namespace ams::usb {
#if defined(ATMOSPHERE_OS_HORIZON)
Result RemoteDsRootSession::GetService(sf::Out<sf::SharedPointer<usb::ds::IDsService>> out) {
Service srv;
serviceAssumeDomain(std::addressof(m_srv));
R_TRY(serviceDispatch(std::addressof(m_srv), 0, .out_num_objects = 1, .out_objects = std::addressof(srv)));
*out = ObjectFactory::CreateSharedEmplaced<ds::IDsService, RemoteDsService>(m_allocator, srv, m_allocator);
R_SUCCEED();
}
#endif
}

View File

@@ -1,38 +0,0 @@
/*
* Copyright (c) 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::usb {
#if defined(ATMOSPHERE_OS_HORIZON)
class RemoteDsRootSession {
private:
using Allocator = sf::ExpHeapAllocator;
using ObjectFactory = sf::ObjectFactory<Allocator::Policy>;
private:
Service m_srv;
Allocator *m_allocator;
public:
RemoteDsRootSession(Service &srv, sf::ExpHeapAllocator *allocator) : m_srv(srv), m_allocator(allocator) { /* ... */ }
virtual ~RemoteDsRootSession() { serviceClose(std::addressof(m_srv)); }
public:
Result GetService(sf::Out<sf::SharedPointer<usb::ds::IDsService>> out);
};
static_assert(ds::IsIDsRootSession<RemoteDsRootSession>);
#endif
}

View File

@@ -1,121 +0,0 @@
/*
* Copyright (c) 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 "usb_remote_ds_service.hpp"
#include "usb_remote_ds_interface.hpp"
namespace ams::usb {
#if defined(ATMOSPHERE_OS_HORIZON)
Result RemoteDsService::Bind(usb::ComplexId complex_id, sf::CopyHandle &&process_h) {
if (hos::GetVersion() >= hos::Version_11_0_0) {
serviceAssumeDomain(std::addressof(m_srv));
R_TRY(serviceDispatchIn(std::addressof(m_srv), 0, complex_id,
.in_num_handles = 1,
.in_handles = { process_h.GetOsHandle() }
));
} else {
serviceAssumeDomain(std::addressof(m_srv));
R_TRY(serviceDispatchIn(std::addressof(m_srv), 0, complex_id));
serviceAssumeDomain(std::addressof(m_srv));
R_TRY(serviceDispatch(std::addressof(m_srv), 1,
.in_num_handles = 1,
.in_handles = { process_h.GetOsHandle() })
);
}
R_SUCCEED();
}
Result RemoteDsService::RegisterInterface(sf::Out<sf::SharedPointer<usb::ds::IDsInterface>> out, u8 bInterfaceNumber) {
Service srv;
serviceAssumeDomain(std::addressof(m_srv));
R_TRY(serviceDispatchIn(std::addressof(m_srv), (hos::GetVersion() >= hos::Version_11_0_0 ? 1 : 2), bInterfaceNumber,
.out_num_objects = 1,
.out_objects = std::addressof(srv),
));
*out = ObjectFactory::CreateSharedEmplaced<ds::IDsInterface, RemoteDsInterface>(m_allocator, srv, m_allocator);
R_SUCCEED();
}
Result RemoteDsService::GetStateChangeEvent(sf::OutCopyHandle out) {
serviceAssumeDomain(std::addressof(m_srv));
os::NativeHandle event_handle;
R_TRY((serviceDispatch(std::addressof(m_srv), hos::GetVersion() >= hos::Version_11_0_0 ? 2 : 3,
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
.out_handles = std::addressof(event_handle),
)));
out.SetValue(event_handle, true);
R_SUCCEED();
}
Result RemoteDsService::GetState(sf::Out<usb::UsbState> out) {
serviceAssumeDomain(std::addressof(m_srv));
R_RETURN(serviceDispatchOut(std::addressof(m_srv), hos::GetVersion() >= hos::Version_11_0_0 ? 3 : 4, *out));
}
Result RemoteDsService::ClearDeviceData() {
serviceAssumeDomain(std::addressof(m_srv));
R_RETURN(serviceDispatch(std::addressof(m_srv), hos::GetVersion() >= hos::Version_11_0_0 ? 4 : 5));
}
Result RemoteDsService::AddUsbStringDescriptor(sf::Out<u8> out, const sf::InBuffer &desc) {
serviceAssumeDomain(std::addressof(m_srv));
return serviceDispatchOut(std::addressof(m_srv), hos::GetVersion() >= hos::Version_11_0_0 ? 5 : 6, *out,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { desc.GetPointer(), desc.GetSize() } },
);
}
Result RemoteDsService::DeleteUsbStringDescriptor(u8 index) {
serviceAssumeDomain(std::addressof(m_srv));
R_RETURN(serviceDispatchIn(std::addressof(m_srv), hos::GetVersion() >= hos::Version_11_0_0 ? 6 : 7, index));
}
Result RemoteDsService::SetUsbDeviceDescriptor(const sf::InBuffer &desc, usb::UsbDeviceSpeed speed) {
serviceAssumeDomain(std::addressof(m_srv));
return serviceDispatchIn(std::addressof(m_srv), hos::GetVersion() >= hos::Version_11_0_0 ? 7 : 8, speed,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { desc.GetPointer(), desc.GetSize() } },
);
}
Result RemoteDsService::SetBinaryObjectStore(const sf::InBuffer &bos) {
serviceAssumeDomain(std::addressof(m_srv));
return serviceDispatch(std::addressof(m_srv), hos::GetVersion() >= hos::Version_11_0_0 ? 8 : 9,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { bos.GetPointer(), bos.GetSize() } },
);
}
Result RemoteDsService::Enable() {
serviceAssumeDomain(std::addressof(m_srv));
R_RETURN(serviceDispatch(std::addressof(m_srv), hos::GetVersion() >= hos::Version_11_0_0 ? 9 : 10));
}
Result RemoteDsService::Disable() {
serviceAssumeDomain(std::addressof(m_srv));
R_RETURN(serviceDispatch(std::addressof(m_srv), hos::GetVersion() >= hos::Version_11_0_0 ? 10 : 11));
}
#endif
}

View File

@@ -1,48 +0,0 @@
/*
* Copyright (c) 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::usb {
#if defined(ATMOSPHERE_OS_HORIZON)
class RemoteDsService {
private:
using Allocator = sf::ExpHeapAllocator;
using ObjectFactory = sf::ObjectFactory<Allocator::Policy>;
private:
Service m_srv;
Allocator *m_allocator;
public:
RemoteDsService(Service &srv, sf::ExpHeapAllocator *allocator) : m_srv(srv), m_allocator(allocator) { /* ... */ }
virtual ~RemoteDsService() { serviceClose(std::addressof(m_srv)); }
public:
Result Bind(usb::ComplexId complex_id, sf::CopyHandle &&process_h);
Result RegisterInterface(sf::Out<sf::SharedPointer<usb::ds::IDsInterface>> out, u8 bInterfaceNumber);
Result GetStateChangeEvent(sf::OutCopyHandle out);
Result GetState(sf::Out<usb::UsbState> out);
Result ClearDeviceData();
Result AddUsbStringDescriptor(sf::Out<u8> out, const sf::InBuffer &desc);
Result DeleteUsbStringDescriptor(u8 index);
Result SetUsbDeviceDescriptor(const sf::InBuffer &desc, usb::UsbDeviceSpeed speed);
Result SetBinaryObjectStore(const sf::InBuffer &bos);
Result Enable();
Result Disable();
};
static_assert(ds::IsIDsService<RemoteDsService>);
#endif
}