From 42caa4ffd12db168b9a10469a4474b97adfcaf6f Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sat, 31 Oct 2020 21:50:21 -0700 Subject: [PATCH] i2c/gpio: hook up open session for sf interface --- .../gpio/driver/gpio_pad_accessor.hpp | 2 +- .../include/stratosphere/i2c.hpp | 3 + .../stratosphere/i2c/driver/i2c_bus_api.hpp | 45 +++++++++ .../i2c/driver/impl/i2c_i2c_session_impl.hpp | 93 +++++++++++++++++++ .../include/stratosphere/i2c/i2c_bus_api.hpp | 36 +++++++ .../i2c/i2c_device_name.board.nintendo_nx.hpp | 53 +++++++++++ .../stratosphere/sf/sf_service_object.hpp | 25 +++-- .../gpio/server/gpio_server_manager_impl.cpp | 15 ++- .../server/gpio_server_pad_session_impl.hpp | 4 +- .../source/i2c/i2c_client_api.cpp | 75 +++++++++++++++ .../source/i2c/server/i2c_server_api.cpp | 46 +++++++++ .../i2c/server/i2c_server_manager_impl.cpp | 61 ++++++++++++ .../i2c/server/i2c_server_manager_impl.hpp | 42 +++++++++ .../i2c/server/i2c_server_session_impl.hpp | 76 +++++++++++++++ .../boot/source/boot_driver_management.cpp | 11 ++- 15 files changed, 571 insertions(+), 16 deletions(-) create mode 100644 libraries/libstratosphere/include/stratosphere/i2c/driver/i2c_bus_api.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/i2c/driver/impl/i2c_i2c_session_impl.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/i2c/i2c_bus_api.hpp create mode 100644 libraries/libstratosphere/source/i2c/server/i2c_server_api.cpp create mode 100644 libraries/libstratosphere/source/i2c/server/i2c_server_manager_impl.cpp create mode 100644 libraries/libstratosphere/source/i2c/server/i2c_server_manager_impl.hpp create mode 100644 libraries/libstratosphere/source/i2c/server/i2c_server_session_impl.hpp diff --git a/libraries/libstratosphere/include/stratosphere/gpio/driver/gpio_pad_accessor.hpp b/libraries/libstratosphere/include/stratosphere/gpio/driver/gpio_pad_accessor.hpp index 5b84a26a7..e060f8a57 100644 --- a/libraries/libstratosphere/include/stratosphere/gpio/driver/gpio_pad_accessor.hpp +++ b/libraries/libstratosphere/include/stratosphere/gpio/driver/gpio_pad_accessor.hpp @@ -31,7 +31,7 @@ namespace ams::gpio::driver { util::TypedStorage _impl; }; - Result OpenSession(GpioPadSession *out, DeviceCode device_code); + Result OpenSession(GpioPadSession *out, DeviceCode device_code, ddsf::AccessMode access_mode); void CloseSession(GpioPadSession *session); Result SetDirection(GpioPadSession *session, gpio::Direction direction); diff --git a/libraries/libstratosphere/include/stratosphere/i2c.hpp b/libraries/libstratosphere/include/stratosphere/i2c.hpp index c87f96732..dad6bc5b1 100644 --- a/libraries/libstratosphere/include/stratosphere/i2c.hpp +++ b/libraries/libstratosphere/include/stratosphere/i2c.hpp @@ -23,4 +23,7 @@ #include #include #include +#include +#include #include +#include diff --git a/libraries/libstratosphere/include/stratosphere/i2c/driver/i2c_bus_api.hpp b/libraries/libstratosphere/include/stratosphere/i2c/driver/i2c_bus_api.hpp new file mode 100644 index 000000000..85968e765 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/i2c/driver/i2c_bus_api.hpp @@ -0,0 +1,45 @@ +/* + * 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 . + */ +#pragma once +#include +#include + +namespace ams::i2c::driver { + + namespace impl { + + constexpr inline size_t I2cSessionSize = 0x60; + constexpr inline size_t I2cSessionAlign = 8; + struct alignas(I2cSessionAlign) I2cSessionImplPadded; + + } + + struct I2cSession { + util::TypedStorage _impl; + }; + + Result OpenSession(I2cSession *out, DeviceCode device_code); + void CloseSession(I2cSession &session); + + Result Send(I2cSession &session, const void *src, size_t src_size, TransactionOption option); + Result Receive(void *dst, size_t dst_size, I2cSession &session, TransactionOption option); + + Result ExecuteCommandList(void *dst, size_t dst_size, I2cSession &session, const void *src, size_t src_size); + + Result SetRetryPolicy(I2cSession &session, int max_retry_count, int retry_interval_ms); + +} + diff --git a/libraries/libstratosphere/include/stratosphere/i2c/driver/impl/i2c_i2c_session_impl.hpp b/libraries/libstratosphere/include/stratosphere/i2c/driver/impl/i2c_i2c_session_impl.hpp new file mode 100644 index 000000000..23f561a5e --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/i2c/driver/impl/i2c_i2c_session_impl.hpp @@ -0,0 +1,93 @@ +/* + * 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 . + */ +#pragma once +#include +#include +#include + +namespace ams::i2c::driver { + + class I2cDeviceProperty; + +} + +namespace ams::i2c::driver::impl { + + class I2cSessionImpl : public ::ams::ddsf::ISession { + NON_COPYABLE(I2cSessionImpl); + NON_MOVEABLE(I2cSessionImpl); + AMS_DDSF_CASTABLE_TRAITS(ams::i2c::driver::impl::I2cSessionImpl, ::ams::ddsf::ISession); + private: + enum class Command { + Send = 0, + Receive = 1, + }; + private: + TimeSpan retry_interval; + int max_retry_count; + private: + Result SendHandler(const u8 **cur_cmd, u8 **cur_dst); + Result ReceiveHandler(const u8 **cur_cmd, u8 **cur_dst); + Result ExtensionHandler(const u8 **cur_cmd, u8 **cur_dst); + + Result ExecuteTransactionWithRetry(void *dst, Command command, const void *src, size_t size, TransactionOption option); + public: + I2cSessionImpl(int mr, TimeSpan rt) : retry_interval(rt), max_retry_count(mr) { /* ... */ } + + ~I2cSessionImpl() { + this->Close(); + } + + Result Open(I2cDeviceProperty *device, ddsf::AccessMode access_mode); + void Close(); + + Result Send(const void *src, size_t src_size, TransactionOption option); + Result Receive(void *dst, size_t dst_size, TransactionOption option); + Result ExecuteCommandList(void *dst, size_t dst_size, const void *src, size_t src_size); + Result SetRetryPolicy(int mr, int interval_ms); + }; + static_assert( sizeof(I2cSessionImpl) <= I2cSessionSize); + static_assert(alignof(I2cSessionImpl) <= I2cSessionAlign); + + struct alignas(I2cSessionAlign) I2cSessionImplPadded { + I2cSessionImpl _impl; + u8 _padding[I2cSessionSize - sizeof(I2cSessionImpl)]; + }; + static_assert( sizeof(I2cSessionImplPadded) == I2cSessionSize); + static_assert(alignof(I2cSessionImplPadded) == I2cSessionAlign); + + ALWAYS_INLINE I2cSessionImpl &GetI2cSessionImpl(I2cSession &session) { + return GetReference(session._impl)._impl; + } + + ALWAYS_INLINE const I2cSessionImpl &GetI2cSessionImpl(const I2cSession &session) { + return GetReference(session._impl)._impl; + } + + ALWAYS_INLINE I2cSessionImpl &GetOpenI2cSessionImpl(I2cSession &session) { + auto &ref = GetReference(session._impl)._impl; + AMS_ASSERT(ref.IsOpen()); + return ref; + } + + ALWAYS_INLINE const I2cSessionImpl &GetOpenI2cSessionImpl(const I2cSession &session) { + const auto &ref = GetReference(session._impl)._impl; + AMS_ASSERT(ref.IsOpen()); + return ref; + } + +} + diff --git a/libraries/libstratosphere/include/stratosphere/i2c/i2c_bus_api.hpp b/libraries/libstratosphere/include/stratosphere/i2c/i2c_bus_api.hpp new file mode 100644 index 000000000..699a18042 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/i2c/i2c_bus_api.hpp @@ -0,0 +1,36 @@ +/* + * 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 . + */ +#pragma once +#include +#include + +namespace ams::i2c { + + struct I2cSession { + void *_session; + }; + + Result OpenSession(I2cSession *out, DeviceCode device_code); + void CloseSession(I2cSession &session); + + Result Send(const I2cSession &session, const void *src, size_t src_size, TransactionOption option); + Result Receive(void *dst, size_t dst_size, const I2cSession &session, TransactionOption option); + + Result ExecuteCommandList(void *dst, size_t dst_size, const I2cSession &session, const void *src, size_t src_size); + + void SetRetryPolicy(const I2cSession &session, int max_retry_count, int retry_interval_ms); + +} diff --git a/libraries/libstratosphere/include/stratosphere/i2c/i2c_device_name.board.nintendo_nx.hpp b/libraries/libstratosphere/include/stratosphere/i2c/i2c_device_name.board.nintendo_nx.hpp index f9706f812..7039f3904 100644 --- a/libraries/libstratosphere/include/stratosphere/i2c/i2c_device_name.board.nintendo_nx.hpp +++ b/libraries/libstratosphere/include/stratosphere/i2c/i2c_device_name.board.nintendo_nx.hpp @@ -194,4 +194,57 @@ namespace ams::i2c { } } + constexpr inline I2cDevice ConvertToI2cDevice(DeviceCode dc) { + switch (dc.GetInternalValue()) { + case DeviceCode_ClassicController.GetInternalValue(): return I2cDevice_ClassicController; + case DeviceCode_Ftm3bd56 .GetInternalValue(): return I2cDevice_Ftm3bd56; + case DeviceCode_Tmp451 .GetInternalValue(): return I2cDevice_Tmp451; + /* case DeviceCode_Nct72 .GetInternalValue(): return I2cDevice_Nct72; */ + case DeviceCode_Alc5639 .GetInternalValue(): return I2cDevice_Alc5639; + case DeviceCode_Max77620Rtc .GetInternalValue(): return I2cDevice_Max77620Rtc; + case DeviceCode_Max77620Pmic .GetInternalValue(): return I2cDevice_Max77620Pmic; + case DeviceCode_Max77621Cpu .GetInternalValue(): return I2cDevice_Max77621Cpu; + case DeviceCode_Max77621Gpu .GetInternalValue(): return I2cDevice_Max77621Gpu; + case DeviceCode_Bq24193 .GetInternalValue(): return I2cDevice_Bq24193; + case DeviceCode_Max17050 .GetInternalValue(): return I2cDevice_Max17050; + case DeviceCode_Bm92t30mwv .GetInternalValue(): return I2cDevice_Bm92t30mwv; + case DeviceCode_Ina226Vdd15v0Hb .GetInternalValue(): return I2cDevice_Ina226Vdd15v0Hb; + case DeviceCode_Ina226VsysCpuDs .GetInternalValue(): return I2cDevice_Ina226VsysCpuDs; + case DeviceCode_Ina226VsysGpuDs .GetInternalValue(): return I2cDevice_Ina226VsysGpuDs; + case DeviceCode_Ina226VsysDdrDs .GetInternalValue(): return I2cDevice_Ina226VsysDdrDs; + case DeviceCode_Ina226VsysAp .GetInternalValue(): return I2cDevice_Ina226VsysAp; + case DeviceCode_Ina226VsysBlDs .GetInternalValue(): return I2cDevice_Ina226VsysBlDs; + case DeviceCode_Bh1730 .GetInternalValue(): return I2cDevice_Bh1730; + case DeviceCode_Ina226VsysCore .GetInternalValue(): return I2cDevice_Ina226VsysCore; + case DeviceCode_Ina226Soc1V8 .GetInternalValue(): return I2cDevice_Ina226Soc1V8; + case DeviceCode_Ina226Lpddr1V8 .GetInternalValue(): return I2cDevice_Ina226Lpddr1V8; + case DeviceCode_Ina226Reg1V32 .GetInternalValue(): return I2cDevice_Ina226Reg1V32; + case DeviceCode_Ina226Vdd3V3Sys .GetInternalValue(): return I2cDevice_Ina226Vdd3V3Sys; + case DeviceCode_HdmiDdc .GetInternalValue(): return I2cDevice_HdmiDdc; + case DeviceCode_HdmiScdc .GetInternalValue(): return I2cDevice_HdmiScdc; + case DeviceCode_HdmiHdcp .GetInternalValue(): return I2cDevice_HdmiHdcp; + case DeviceCode_Fan53528 .GetInternalValue(): return I2cDevice_Fan53528; + case DeviceCode_Max77812_3 .GetInternalValue(): return I2cDevice_Max77812_3; + case DeviceCode_Max77812_2 .GetInternalValue(): return I2cDevice_Max77812_2; + case DeviceCode_Ina226VddDdr0V6 .GetInternalValue(): return I2cDevice_Ina226VddDdr0V6; + case DeviceCode_HoagNfcIc .GetInternalValue(): return I2cDevice_HoagNfcIc; + AMS_UNREACHABLE_DEFAULT_CASE(); + } + } + + constexpr bool IsPowerBusDeviceCode(DeviceCode device_code) { + switch (device_code.GetInternalValue()) { + case DeviceCode_Max77620Pmic.GetInternalValue(): + case DeviceCode_Max77812_3 .GetInternalValue(): + case DeviceCode_Max77621Cpu .GetInternalValue(): + case DeviceCode_Max77621Gpu .GetInternalValue(): + case DeviceCode_Fan53528 .GetInternalValue(): + case DeviceCode_Max77812_2 .GetInternalValue(): + case DeviceCode_Max77620Rtc .GetInternalValue(): + return true; + default: + return false; + } + } + } diff --git a/libraries/libstratosphere/include/stratosphere/sf/sf_service_object.hpp b/libraries/libstratosphere/include/stratosphere/sf/sf_service_object.hpp index 4a587066b..6681861b2 100644 --- a/libraries/libstratosphere/include/stratosphere/sf/sf_service_object.hpp +++ b/libraries/libstratosphere/include/stratosphere/sf/sf_service_object.hpp @@ -62,34 +62,45 @@ namespace ams::sf { return std::make_shared>(std::make_shared(std::forward(args)...)); } - template - class ServiceObjectAllocator { + template + class ServiceObjectAllocatorImpl { + private: + template + friend class ServiceObjectAllocatorImpl; public: - using value_type = typename Interface::ImplHolder; + using value_type = T; private: MemoryResource * const memory_resource; public: - constexpr ServiceObjectAllocator(MemoryResource *mr) : memory_resource(mr) { /* ... */ } + constexpr ServiceObjectAllocatorImpl(MemoryResource *mr) : memory_resource(mr) { /* ... */ } + + template + constexpr ServiceObjectAllocatorImpl(const ServiceObjectAllocatorImpl &rhs) : memory_resource(rhs.memory_resource) { /* ... */ } value_type *allocate(size_t n) const { void *mem = this->memory_resource->Allocate(n * sizeof(value_type), alignof(value_type)); AMS_ABORT_UNLESS(mem != nullptr); - return mem; + return static_cast(mem); } void deallocate(void *p, size_t n) const { this->memory_resource->Deallocate(p, n * sizeof(value_type), alignof(value_type)); } - inline bool operator==(const ServiceObjectAllocator &rhs) const { + template + inline bool operator==(const ServiceObjectAllocatorImpl &rhs) const { return this->memory_resource->is_equal(*rhs->memory_resource); } - inline bool operator!=(const ServiceObjectAllocator &rhs) const { + template + inline bool operator!=(const ServiceObjectAllocatorImpl &rhs) const { return !(*this == rhs); } }; + template + using ServiceObjectAllocator = ServiceObjectAllocatorImpl>; + template requires std::constructible_from constexpr ALWAYS_INLINE std::shared_ptr> AllocateShared(const Allocator &allocator, Arguments &&... args) { diff --git a/libraries/libstratosphere/source/gpio/server/gpio_server_manager_impl.cpp b/libraries/libstratosphere/source/gpio/server/gpio_server_manager_impl.cpp index 4a7554ae6..0089ea77b 100644 --- a/libraries/libstratosphere/source/gpio/server/gpio_server_manager_impl.cpp +++ b/libraries/libstratosphere/source/gpio/server/gpio_server_manager_impl.cpp @@ -33,8 +33,7 @@ namespace ams::gpio::server { } Result ManagerImpl::OpenSession(ams::sf::Out> out, gpio::GpioPadName pad_name) { - /* TODO */ - AMS_ABORT(); + return this->OpenSession2(out, ConvertToDeviceCode(pad_name), ddsf::AccessMode_ReadWrite); } Result ManagerImpl::OpenSessionForTest(ams::sf::Out> out, gpio::GpioPadName pad_name) { @@ -63,8 +62,15 @@ namespace ams::gpio::server { } Result ManagerImpl::OpenSession2(ams::sf::Out> out, DeviceCode device_code, ddsf::AccessMode access_mode) { - /* TODO */ - AMS_ABORT(); + /* Allocate a session. */ + auto session = ams::sf::AllocateShared(this->pad_allocator, this); + + /* Open the session. */ + R_TRY(session->GetImpl().OpenSession(device_code, access_mode)); + + /* We succeeded. */ + out.SetValue(std::move(session)); + return ResultSuccess(); } Result ManagerImpl::IsWakeEventActive2(ams::sf::Out out, DeviceCode device_code) { @@ -82,5 +88,4 @@ namespace ams::gpio::server { AMS_ABORT(); } - } diff --git a/libraries/libstratosphere/source/gpio/server/gpio_server_pad_session_impl.hpp b/libraries/libstratosphere/source/gpio/server/gpio_server_pad_session_impl.hpp index 299a10962..afe6681bb 100644 --- a/libraries/libstratosphere/source/gpio/server/gpio_server_pad_session_impl.hpp +++ b/libraries/libstratosphere/source/gpio/server/gpio_server_pad_session_impl.hpp @@ -35,10 +35,10 @@ namespace ams::gpio::server { } } - Result OpenSession(DeviceCode device_code) { + Result OpenSession(DeviceCode device_code, ddsf::AccessMode access_mode) { AMS_ABORT_UNLESS(!this->has_session); - R_TRY(gpio::driver::OpenSession(std::addressof(this->internal_pad_session), device_code)); + R_TRY(gpio::driver::OpenSession(std::addressof(this->internal_pad_session), device_code, access_mode)); this->has_session = true; return ResultSuccess(); } diff --git a/libraries/libstratosphere/source/i2c/i2c_client_api.cpp b/libraries/libstratosphere/source/i2c/i2c_client_api.cpp index b155fe189..fdce3c579 100644 --- a/libraries/libstratosphere/source/i2c/i2c_client_api.cpp +++ b/libraries/libstratosphere/source/i2c/i2c_client_api.cpp @@ -30,6 +30,21 @@ namespace ams::i2c { std::shared_ptr g_i2c_pcv_manager; constinit int g_i2c_pcv_count = 0; + using InternalSession = std::shared_ptr; + + InternalSession &GetInterface(const I2cSession &session) { + AMS_ASSERT(session._session != nullptr); + return *static_cast(session._session); + } + + std::shared_ptr GetManager(DeviceCode device_code) { + if (IsPowerBusDeviceCode(device_code)) { + return g_i2c_pcv_manager; + } else { + return g_i2c_manager; + } + } + } void InitializeWith(std::shared_ptr &&sp, std::shared_ptr &&sp_pcv) { @@ -83,4 +98,64 @@ namespace ams::i2c { } } + Result OpenSession(I2cSession *out, DeviceCode device_code) { + /* Allocate the session. */ + InternalSession *internal_session = new (std::nothrow) InternalSession; + AMS_ABORT_UNLESS(internal_session != nullptr); + auto session_guard = SCOPE_GUARD { delete internal_session; }; + + /* Get manager for the device. */ + auto manager = GetManager(device_code); + + /* Get the session. */ + { + ams::sf::cmif::ServiceObjectHolder object_holder; + if (hos::GetVersion() >= hos::Version_6_0_0) { + R_TRY(manager->OpenSession2(std::addressof(object_holder), device_code)); + } else { + R_TRY(manager->OpenSession(std::addressof(object_holder), ConvertToI2cDevice(device_code))); + } + *internal_session = object_holder.GetServiceObject(); + } + + /* Set output. */ + out->_session = internal_session; + + /* We succeeded. */ + session_guard.Cancel(); + return ResultSuccess(); + } + + void CloseSession(I2cSession &session) { + /* Close the session. */ + delete std::addressof(GetInterface(session)); + session._session = nullptr; + } + + Result Send(const I2cSession &session, const void *src, size_t src_size, TransactionOption option) { + const ams::sf::InAutoSelectBuffer buf(src, src_size); + + return GetInterface(session)->Send(buf, option); + } + + Result Receive(void *dst, size_t dst_size, const I2cSession &session, TransactionOption option) { + const ams::sf::OutAutoSelectBuffer buf(dst, dst_size); + + return GetInterface(session)->Receive(buf, option); + } + + Result ExecuteCommandList(void *dst, size_t dst_size, const I2cSession &session, const void *src, size_t src_size) { + const ams::sf::OutAutoSelectBuffer buf(dst, dst_size); + const ams::sf::InPointerArray arr(static_cast(src), src_size); + + return GetInterface(session)->ExecuteCommandList(buf, arr); + } + + void SetRetryPolicy(const I2cSession &session, int max_retry_count, int retry_interval_ms) { + AMS_ASSERT(max_retry_count >= 0); + AMS_ASSERT(retry_interval_ms >= 0); + + R_ABORT_UNLESS(GetInterface(session)->SetRetryPolicy(max_retry_count, retry_interval_ms)); + } + } diff --git a/libraries/libstratosphere/source/i2c/server/i2c_server_api.cpp b/libraries/libstratosphere/source/i2c/server/i2c_server_api.cpp new file mode 100644 index 000000000..dcd6a987c --- /dev/null +++ b/libraries/libstratosphere/source/i2c/server/i2c_server_api.cpp @@ -0,0 +1,46 @@ +/* + * 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 . + */ +#include +#include "i2c_server_manager_impl.hpp" + +namespace ams::i2c::server { + + namespace { + + ManagerImpl g_manager_impl; + ManagerImpl g_pcv_manager_impl; + + std::shared_ptr GetManagerServiceObject() { + static std::shared_ptr s_sp = ams::sf::GetSharedPointerTo(g_manager_impl); + return s_sp; + } + + std::shared_ptr GetManagerServiceObjectPowerBus() { + static std::shared_ptr s_sp = ams::sf::GetSharedPointerTo(g_pcv_manager_impl); + return s_sp; + } + + } + + std::shared_ptr GetServiceObject() { + return GetManagerServiceObject(); + } + + std::shared_ptr GetServiceObjectPowerBus() { + return GetManagerServiceObjectPowerBus(); + } + +} diff --git a/libraries/libstratosphere/source/i2c/server/i2c_server_manager_impl.cpp b/libraries/libstratosphere/source/i2c/server/i2c_server_manager_impl.cpp new file mode 100644 index 000000000..579fccd24 --- /dev/null +++ b/libraries/libstratosphere/source/i2c/server/i2c_server_manager_impl.cpp @@ -0,0 +1,61 @@ +/* + * 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 . + */ +#include +#include "i2c_server_manager_impl.hpp" + +namespace ams::i2c::server { + + ManagerImpl::ManagerImpl() : session_memory_resource(), allocator(std::addressof(session_memory_resource)) { + this->heap_handle = lmem::CreateExpHeap(this->heap_buffer, sizeof(this->heap_buffer), lmem::CreateOption_None); + this->session_memory_resource.Attach(this->heap_handle); + } + + ManagerImpl::~ManagerImpl() { + lmem::DestroyExpHeap(this->heap_handle); + } + + Result ManagerImpl::OpenSessionForDev(ams::sf::Out> out, s32 bus_idx, u16 slave_address, i2c::AddressingMode addressing_mode, i2c::SpeedMode speed_mode) { + /* TODO */ + AMS_ABORT(); + } + + Result ManagerImpl::OpenSession(ams::sf::Out> out, i2c::I2cDevice device) { + return this->OpenSession2(out, ConvertToDeviceCode(device)); + } + + Result ManagerImpl::HasDevice(ams::sf::Out out, i2c::I2cDevice device) { + /* TODO */ + AMS_ABORT(); + } + + Result ManagerImpl::HasDeviceForDev(ams::sf::Out out, i2c::I2cDevice device) { + /* TODO */ + AMS_ABORT(); + } + + Result ManagerImpl::OpenSession2(ams::sf::Out> out, DeviceCode device_code) { + /* Allocate a session. */ + auto session = ams::sf::AllocateShared(this->allocator, this); + + /* Open the session. */ + R_TRY(session->GetImpl().OpenSession(device_code)); + + /* We succeeded. */ + out.SetValue(std::move(session)); + return ResultSuccess(); + } + +} diff --git a/libraries/libstratosphere/source/i2c/server/i2c_server_manager_impl.hpp b/libraries/libstratosphere/source/i2c/server/i2c_server_manager_impl.hpp new file mode 100644 index 000000000..821504648 --- /dev/null +++ b/libraries/libstratosphere/source/i2c/server/i2c_server_manager_impl.hpp @@ -0,0 +1,42 @@ +/* + * 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 . + */ +#pragma once +#include +#include "i2c_server_session_impl.hpp" + +namespace ams::i2c::server { + + class ManagerImpl { + private: + lmem::HeapHandle heap_handle; + ams::sf::ExpHeapMemoryResource session_memory_resource; + typename ams::sf::ServiceObjectAllocator allocator; + u8 heap_buffer[4_KB]; + public: + ManagerImpl(); + + ~ManagerImpl(); + public: + /* Actual commands. */ + Result OpenSessionForDev(ams::sf::Out> out, s32 bus_idx, u16 slave_address, i2c::AddressingMode addressing_mode, i2c::SpeedMode speed_mode); + Result OpenSession(ams::sf::Out> out, i2c::I2cDevice device); + Result HasDevice(ams::sf::Out out, i2c::I2cDevice device); + Result HasDeviceForDev(ams::sf::Out out, i2c::I2cDevice device); + Result OpenSession2(ams::sf::Out> out, DeviceCode device_code); + }; + static_assert(i2c::sf::IsIManager); + +} diff --git a/libraries/libstratosphere/source/i2c/server/i2c_server_session_impl.hpp b/libraries/libstratosphere/source/i2c/server/i2c_server_session_impl.hpp new file mode 100644 index 000000000..9fc87889f --- /dev/null +++ b/libraries/libstratosphere/source/i2c/server/i2c_server_session_impl.hpp @@ -0,0 +1,76 @@ +/* + * 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 . + */ +#pragma once +#include + +namespace ams::i2c::server { + + class ManagerImpl; + + class SessionImpl { + private: + ManagerImpl *parent; /* NOTE: this is an sf::SharedPointer<> in Nintendo's code. */ + i2c::driver::I2cSession internal_session; + bool has_session; + public: + explicit SessionImpl(ManagerImpl *p) : parent(p), has_session(false) { /* ... */ } + + ~SessionImpl() { + if (this->has_session) { + i2c::driver::CloseSession(this->internal_session); + } + } + + Result OpenSession(DeviceCode device_code) { + AMS_ABORT_UNLESS(!this->has_session); + + R_TRY(i2c::driver::OpenSession(std::addressof(this->internal_session), device_code)); + this->has_session = true; + return ResultSuccess(); + } + public: + /* Actual commands. */ + Result SendOld(const ams::sf::InBuffer &in_data, i2c::TransactionOption option) { + return i2c::driver::Send(this->internal_session, in_data.GetPointer(), in_data.GetSize(), option); + } + + Result ReceiveOld(const ams::sf::OutBuffer &out_data, i2c::TransactionOption option) { + return i2c::driver::Receive(out_data.GetPointer(), out_data.GetSize(), this->internal_session, option); + } + + Result ExecuteCommandListOld(const ams::sf::OutBuffer &rcv_buf, const ams::sf::InPointerArray &command_list){ + return i2c::driver::ExecuteCommandList(rcv_buf.GetPointer(), rcv_buf.GetSize(), this->internal_session, command_list.GetPointer(), command_list.GetSize() * sizeof(i2c::I2cCommand)); + } + + Result Send(const ams::sf::InAutoSelectBuffer &in_data, i2c::TransactionOption option) { + return i2c::driver::Send(this->internal_session, in_data.GetPointer(), in_data.GetSize(), option); + } + + Result Receive(const ams::sf::OutAutoSelectBuffer &out_data, i2c::TransactionOption option) { + return i2c::driver::Receive(out_data.GetPointer(), out_data.GetSize(), this->internal_session, option); + } + + Result ExecuteCommandList(const ams::sf::OutAutoSelectBuffer &rcv_buf, const ams::sf::InPointerArray &command_list) { + return i2c::driver::ExecuteCommandList(rcv_buf.GetPointer(), rcv_buf.GetSize(), this->internal_session, command_list.GetPointer(), command_list.GetSize() * sizeof(i2c::I2cCommand)); + } + + Result SetRetryPolicy(s32 max_retry_count, s32 retry_interval_ms) { + return i2c::driver::SetRetryPolicy(this->internal_session, max_retry_count, retry_interval_ms); + } + }; + static_assert(i2c::sf::IsISession); + +} diff --git a/stratosphere/boot/source/boot_driver_management.cpp b/stratosphere/boot/source/boot_driver_management.cpp index 3a730401e..77e0c907e 100644 --- a/stratosphere/boot/source/boot_driver_management.cpp +++ b/stratosphere/boot/source/boot_driver_management.cpp @@ -33,11 +33,20 @@ namespace ams::boot { /* Initialize the i2c client library with the server manager object. */ i2c::InitializeWith(i2c::server::GetServiceObject(), i2c::server::GetServiceObjectPowerBus()); - /* Initialize the board driver without enabling interrupt handlers. */ + /* Initialize the board driver. */ i2c::driver::board::Initialize(); /* Initialize the driver library. */ i2c::driver::Initialize(); + + /* Initialize the pwm client library with the server manager object. */ + /* TODO: pwm::InitializeWith(pwm::server::GetServiceObject()); */ + + /* Initialize the pwm board driver. */ + /* TODO: pwm::driver::board::Initialize(); */ + + /* Initialize the pwm driver library. */ + /* TODO: pwm::driver::Initialize(); } }