diff --git a/.gitmodules b/.gitmodules
index d07594aa..d2de66eb 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -14,3 +14,6 @@
[submodule "app/libraries/lz4"]
path = app/libraries/lz4
url = https://github.com/lz4/lz4.git
+[submodule "app/libraries/frozen"]
+ path = app/libraries/frozen
+ url = https://github.com/serge-sans-paille/frozen
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 1f272f82..410dc16c 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -7,6 +7,22 @@
+
+
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 8bfaf805..323530b1 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -3,9 +3,10 @@
+
-
+
\ No newline at end of file
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index c7473c2c..8827e54c 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -22,6 +22,7 @@ add_subdirectory("libraries/lz4/contrib/cmake_unofficial")
include_directories("libraries/lz4/lib")
include_directories("libraries/oboe/include")
include_directories("libraries/vkhpp/include")
+include_directories("libraries/frozen/include")
set(CMAKE_POLICY_DEFAULT_CMP0048 NEW)
find_package(mbedtls REQUIRED CONFIG)
@@ -114,6 +115,7 @@ add_library(skyline SHARED
${source_DIR}/skyline/services/fssrv/IStorage.cpp
${source_DIR}/skyline/services/nvdrv/INvDrvServices.cpp
${source_DIR}/skyline/services/nvdrv/driver.cpp
+ ${source_DIR}/skyline/services/nvdrv/devices/nvdevice.cpp
${source_DIR}/skyline/services/nvdrv/devices/nvmap.cpp
${source_DIR}/skyline/services/nvdrv/devices/nvhost_ctrl_gpu.cpp
${source_DIR}/skyline/services/nvdrv/devices/nvhost_ctrl.cpp
diff --git a/app/build.gradle b/app/build.gradle
index 2d8d9904..fb82c1be 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -4,11 +4,11 @@ apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 30
- buildToolsVersion '30.0.0'
+ buildToolsVersion '30.0.2'
defaultConfig {
applicationId "skyline.emu"
minSdkVersion 26
- targetSdkVersion 29
+ targetSdkVersion 30
versionCode 3
versionName "0.3"
ndk {
@@ -59,7 +59,7 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.2.0'
- implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+ implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
implementation 'androidx.preference:preference:1.1.1'
implementation 'com.google.android.material:material:1.3.0-alpha02'
implementation "androidx.core:core-ktx:1.3.1"
diff --git a/app/libraries/frozen b/app/libraries/frozen
new file mode 160000
index 00000000..30b47527
--- /dev/null
+++ b/app/libraries/frozen
@@ -0,0 +1 @@
+Subproject commit 30b475274c044f456c37b6d15de3d04c85112698
diff --git a/app/src/main/cpp/skyline/common.h b/app/src/main/cpp/skyline/common.h
index c692d3cf..e313a8a8 100644
--- a/app/src/main/cpp/skyline/common.h
+++ b/app/src/main/cpp/skyline/common.h
@@ -8,21 +8,24 @@
#include
#include
#include
-#include
#include
#include
#include
-#include
-#include
-#include
-#include
#include
#include
#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
#include
#include "nce/guest_common.h"
namespace skyline {
+ namespace frz = frozen;
using KHandle = u32; //!< The type of a kernel handle
/**
@@ -194,6 +197,10 @@ namespace skyline {
}
return result;
}
+
+ constexpr std::size_t Hash(const std::string_view& view) {
+ return frz::elsa{}(frz::string(view.data(), view.size()), 0);
+ }
}
/**
diff --git a/app/src/main/cpp/skyline/services/hosbinder/GraphicBufferProducer.cpp b/app/src/main/cpp/skyline/services/hosbinder/GraphicBufferProducer.cpp
index 0d7de4ca..3c579ba7 100644
--- a/app/src/main/cpp/skyline/services/hosbinder/GraphicBufferProducer.cpp
+++ b/app/src/main/cpp/skyline/services/hosbinder/GraphicBufferProducer.cpp
@@ -124,7 +124,7 @@ namespace skyline::service::hosbinder {
std::shared_ptr nvBuffer{};
auto driver = nvdrv::driver.lock();
- auto nvmap = driver->GetDevice(nvdrv::device::NvDeviceType::nvmap);
+ auto nvmap = driver->nvMap.lock();
if (gbpBuffer.nvmapHandle) {
nvBuffer = nvmap->handleTable.at(gbpBuffer.nvmapHandle);
diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.cpp
new file mode 100644
index 00000000..745f5a8a
--- /dev/null
+++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.cpp
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: MPL-2.0
+// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
+
+#include "nvdevice.h"
+
+namespace skyline::service::nvdrv::device {
+ NvDevice::NvDevice(const DeviceState &state, std::unordered_map > vTable) : state(state), vTable(vTable) {}
+
+ std::string NvDevice::GetName() {
+ int status{};
+ size_t length{};
+ auto mangledName{typeid(*this).name()};
+
+ std::unique_ptr demangled{ abi::__cxa_demangle(mangledName, nullptr, &length, &status), std::free};
+
+ return (status == 0) ? std::string(demangled.get() + std::char_traits::length("skyline::service::nvdrv::device")) : mangledName;
+ }
+
+ void NvDevice::HandleIoctl(u32 cmd, IoctlData &input) {
+ std::function function;
+ try {
+ function = vTable.at(cmd);
+ } catch (std::out_of_range &) {
+ state.logger->Warn("Cannot find IOCTL for device '{}': 0x{:X}", GetName(), cmd);
+ input.status = NvStatus::NotImplemented;
+ return;
+ }
+ try {
+ function(input);
+ } catch (std::exception &e) {
+ throw exception("{} (Device: {})", e.what(), GetName());
+ }
+ }
+}
diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.h b/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.h
index 3f3f5f4e..1a9bb7d0 100644
--- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.h
+++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.h
@@ -3,6 +3,7 @@
#pragma once
+#include
#include
#include
#include
@@ -12,54 +13,6 @@
namespace skyline::service::nvdrv::device {
using namespace kernel;
- /**
- * @brief An enumeration of all the devices that can be opened by nvdrv
- */
- enum class NvDeviceType {
- nvhost_ctrl, //!< https://switchbrew.org/wiki/NV_services#.2Fdev.2Fnvhost-ctrl
- nvhost_gpu, //!< https://switchbrew.org/wiki/NV_services#Channels
- nvhost_nvdec, //!< https://switchbrew.org/wiki/NV_services#Channels
- nvhost_vic, //!< https://switchbrew.org/wiki/NV_services#Channels
- nvmap, //!< https://switchbrew.org/wiki/NV_services#.2Fdev.2Fnvmap
- nvdisp_ctrl, //!< https://switchbrew.org/wiki/NV_services#.2Fdev.2Fnvdisp-ctrl
- nvdisp_disp0, //!< https://switchbrew.org/wiki/NV_services#.2Fdev.2Fnvdisp-disp0.2C_.2Fdev.2Fnvdisp-disp1
- nvdisp_disp1, //!< https://switchbrew.org/wiki/NV_services#.2Fdev.2Fnvdisp-disp0.2C_.2Fdev.2Fnvdisp-disp1
- nvcec_ctrl, //!< https://switchbrew.org/wiki/NV_services#.2Fdev.2Fnvcec-ctrl
- nvhdcp_up_ctrl, //!< https://switchbrew.org/wiki/NV_services#.2Fdev.2Fnvhdcp_up-ctrl
- nvdcutil_disp0, //!< https://switchbrew.org/wiki/NV_services#.2Fdev.2Fnvdcutil-disp0.2C_.2Fdev.2Fnvdcutil-disp1
- nvdcutil_disp1, //!< https://switchbrew.org/wiki/NV_services#.2Fdev.2Fnvdcutil-disp0.2C_.2Fdev.2Fnvdcutil-disp1
- nvsched_ctrl, //!< https://switchbrew.org/wiki/NV_services#.2Fdev.2Fnvsched-ctrl
- nverpt_ctrl, //!< https://switchbrew.org/wiki/NV_services#.2Fdev.2Fnverpt-ctrl
- nvhost_as_gpu, //!< https://switchbrew.org/wiki/NV_services#.2Fdev.2Fnvhost-as-gpu
- nvhost_dbg_gpu, //!< https://switchbrew.org/wiki/NV_services#.2Fdev.2Fnvhost-dbg-gpu
- nvhost_prof_gpu, //!< https://switchbrew.org/wiki/NV_services#.2Fdev.2Fnvhost-prof-gpu
- nvhost_ctrl_gpu //!< https://switchbrew.org/wiki/NV_services#.2Fdev.2Fnvhost-ctrl-gpu
- };
-
- /**
- * @brief A mapping from a device's path to it's nvDevice entry
- */
- const static std::unordered_map nvDeviceMap{
- {"/dev/nvhost-ctrl", NvDeviceType::nvhost_ctrl},
- {"/dev/nvhost-gpu", NvDeviceType::nvhost_gpu},
- {"/dev/nvhost-nvdec", NvDeviceType::nvhost_nvdec},
- {"/dev/nvhost-vic", NvDeviceType::nvhost_vic},
- {"/dev/nvmap", NvDeviceType::nvmap},
- {"/dev/nvdisp-ctrl", NvDeviceType::nvdisp_ctrl},
- {"/dev/nvdisp-disp0", NvDeviceType::nvdisp_disp0},
- {"/dev/nvdisp-disp1", NvDeviceType::nvdisp_disp1},
- {"/dev/nvcec-ctrl", NvDeviceType::nvcec_ctrl},
- {"/dev/nvhdcp_up-ctrl", NvDeviceType::nvhdcp_up_ctrl},
- {"/dev/nvdcutil-disp0", NvDeviceType::nvdcutil_disp0},
- {"/dev/nvdcutil-disp1", NvDeviceType::nvdcutil_disp1},
- {"/dev/nvsched-ctrl", NvDeviceType::nvsched_ctrl},
- {"/dev/nverpt-ctrl", NvDeviceType::nverpt_ctrl},
- {"/dev/nvhost-as-gpu", NvDeviceType::nvhost_as_gpu},
- {"/dev/nvhost-dbg-gpu", NvDeviceType::nvhost_dbg_gpu},
- {"/dev/nvhost-prof-gpu", NvDeviceType::nvhost_prof_gpu},
- {"/dev/nvhost-ctrl-gpu", NvDeviceType::nvhost_ctrl_gpu},
- };
-
/**
* @brief This enumerates all the possible error codes returned by the Nvidia driver (https://switchbrew.org/wiki/NV_services#Errors)
*/
@@ -134,7 +87,7 @@ namespace skyline::service::nvdrv::device {
};
/**
- * @brief NvDevice is the base class all /dev/nv* devices inherit from
+ * @brief NvDevice is the base class that all /dev/nv* devices inherit from
*/
class NvDevice {
protected:
@@ -142,53 +95,27 @@ namespace skyline::service::nvdrv::device {
std::unordered_map> vTable; //!< This holds the mapping from an Ioctl to the actual function
public:
- u16 refCount{1}; //!< The amount of handles to the device
- NvDeviceType deviceType; //!< The type of the device
-
/**
* @param state The state of the device
- * @param deviceType The type of the device
* @param vTable The functions in this device
*/
- NvDevice(const DeviceState &state, NvDeviceType deviceType, std::unordered_map> vTable) : state(state), deviceType(deviceType), vTable(vTable) {}
+ NvDevice(const DeviceState &state, std::unordered_map> vTable);
virtual ~NvDevice() = default;
/**
- * @brief This returns the name of the current service
- * @note It may not return the exact name the service was initialized with if there are multiple entries in ServiceString
- * @return The name of the service
+ * @return The name of the class
*/
- std::string getName() {
- std::string serviceName;
- for (const auto&[name, type] : nvDeviceMap)
- if (type == deviceType)
- serviceName = name;
- return serviceName;
- }
+ std::string GetName();
/**
* @brief This handles IOCTL calls for devices
* @param cmd The IOCTL command that was called
* @param input The input to the IOCTL call
*/
- void HandleIoctl(u32 cmd, IoctlData &input) {
- std::function function;
- try {
- function = vTable.at(cmd);
- } catch (std::out_of_range &) {
- state.logger->Warn("Cannot find IOCTL for device '{}': 0x{:X}", getName(), cmd);
- input.status = NvStatus::NotImplemented;
- return;
- }
- try {
- function(input);
- } catch (std::exception &e) {
- throw exception("{} (Device: {})", e.what(), getName());
- }
- }
+ void HandleIoctl(u32 cmd, IoctlData &input);
- virtual std::shared_ptr QueryEvent(u32 eventId) {
+ inline virtual std::shared_ptr QueryEvent(u32 eventId) {
return nullptr;
}
};
diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_as_gpu.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_as_gpu.cpp
index 48ba5853..c0aba4f9 100644
--- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_as_gpu.cpp
@@ -9,7 +9,7 @@
#include "nvhost_as_gpu.h"
namespace skyline::service::nvdrv::device {
- NvHostAsGpu::NvHostAsGpu(const DeviceState &state) : NvDevice(state, NvDeviceType::nvhost_as_gpu, {
+ NvHostAsGpu::NvHostAsGpu(const DeviceState &state) : NvDevice(state, {
{0x4101, NFUNC(NvHostAsGpu::BindChannel)},
{0x4102, NFUNC(NvHostAsGpu::AllocSpace)},
{0x4105, NFUNC(NvHostAsGpu::UnmapBuffer)},
@@ -71,10 +71,11 @@ namespace skyline::service::nvdrv::device {
return;
auto driver = nvdrv::driver.lock();
- auto nvmap = driver->GetDevice(nvdrv::device::NvDeviceType::nvmap)->handleTable.at(region.nvmapHandle);
+ auto nvmap = driver->nvMap.lock();
+ auto mapping = nvmap->handleTable.at(region.nvmapHandle);
- u64 mapPhysicalAddress = region.bufferOffset + nvmap->address;
- u64 mapSize = region.mappingSize ? region.mappingSize : nvmap->size;
+ u64 mapPhysicalAddress = region.bufferOffset + mapping->address;
+ u64 mapSize = region.mappingSize ? region.mappingSize : mapping->size;
if (region.flags & 1)
region.offset = state.gpu->memoryManager.MapFixed(region.offset, mapPhysicalAddress, mapSize);
@@ -135,10 +136,11 @@ namespace skyline::service::nvdrv::device {
for (auto entry : entries) {
try {
auto driver = nvdrv::driver.lock();
- auto nvmap = driver->GetDevice(nvdrv::device::NvDeviceType::nvmap)->handleTable.at(entry.nvmapHandle);
+ auto nvmap = driver->nvMap.lock();
+ auto mapping = nvmap->handleTable.at(entry.nvmapHandle);
u64 mapAddress = static_cast(entry.gpuOffset) << MinAlignmentShift;
- u64 mapPhysicalAddress = nvmap->address + (static_cast(entry.mapOffset) << MinAlignmentShift);
+ u64 mapPhysicalAddress = mapping->address + (static_cast(entry.mapOffset) << MinAlignmentShift);
u64 mapSize = static_cast(entry.pages) << MinAlignmentShift;
state.gpu->memoryManager.MapFixed(mapAddress, mapPhysicalAddress, mapSize);
diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_channel.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_channel.cpp
index 73be2424..a73285ff 100644
--- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_channel.cpp
+++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_channel.cpp
@@ -8,7 +8,7 @@
#include "nvhost_channel.h"
namespace skyline::service::nvdrv::device {
- NvHostChannel::NvHostChannel(const DeviceState &state, NvDeviceType type) : smExceptionBreakpointIntReportEvent(std::make_shared(state)), smExceptionBreakpointPauseReportEvent(std::make_shared(state)), errorNotifierEvent(std::make_shared(state)), NvDevice(state, type, {
+ NvHostChannel::NvHostChannel(const DeviceState &state) : smExceptionBreakpointIntReportEvent(std::make_shared(state)), smExceptionBreakpointPauseReportEvent(std::make_shared(state)), errorNotifierEvent(std::make_shared(state)), NvDevice(state, {
{0x4801, NFUNC(NvHostChannel::SetNvmapFd)},
{0x4803, NFUNC(NvHostChannel::SetSubmitTimeout)},
{0x4808, NFUNC(NvHostChannel::SubmitGpfifo)},
diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_channel.h b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_channel.h
index dcee6de3..2c959fcb 100644
--- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_channel.h
+++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_channel.h
@@ -25,7 +25,7 @@ namespace skyline::service::nvdrv::device {
std::shared_ptr errorNotifierEvent;
public:
- NvHostChannel(const DeviceState &state, NvDeviceType type);
+ NvHostChannel(const DeviceState &state);
/**
* @brief This sets the nvmap file descriptor (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_NVMAP_FD)
diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_ctrl.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_ctrl.cpp
index 9d155205..908b7ac5 100644
--- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_ctrl.cpp
+++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_ctrl.cpp
@@ -37,7 +37,7 @@ namespace skyline::service::nvdrv::device {
}
}
- NvHostCtrl::NvHostCtrl(const DeviceState &state) : NvDevice(state, NvDeviceType::nvhost_ctrl, {
+ NvHostCtrl::NvHostCtrl(const DeviceState &state) : NvDevice(state, {
{0x001B, NFUNC(NvHostCtrl::GetConfig)},
{0x001C, NFUNC(NvHostCtrl::EventSignal)},
{0x001D, NFUNC(NvHostCtrl::EventWait)},
diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_ctrl_gpu.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_ctrl_gpu.cpp
index d658b569..43700840 100644
--- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_ctrl_gpu.cpp
+++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_ctrl_gpu.cpp
@@ -5,7 +5,7 @@
#include "nvhost_ctrl_gpu.h"
namespace skyline::service::nvdrv::device {
- NvHostCtrlGpu::NvHostCtrlGpu(const DeviceState &state) : errorNotifierEvent(std::make_shared(state)), unknownEvent(std::make_shared(state)), NvDevice(state, NvDeviceType::nvhost_ctrl_gpu, {
+ NvHostCtrlGpu::NvHostCtrlGpu(const DeviceState &state) : errorNotifierEvent(std::make_shared(state)), unknownEvent(std::make_shared(state)), NvDevice(state, {
{0x4701, NFUNC(NvHostCtrlGpu::ZCullGetCtxSize)},
{0x4702, NFUNC(NvHostCtrlGpu::ZCullGetInfo)},
{0x4706, NFUNC(NvHostCtrlGpu::GetTpcMasks)},
diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.cpp
index 74c5400c..aec8e350 100644
--- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.cpp
+++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.cpp
@@ -7,7 +7,7 @@
namespace skyline::service::nvdrv::device {
NvMap::NvMapObject::NvMapObject(u32 id, u32 size) : id(id), size(size) {}
- NvMap::NvMap(const DeviceState &state) : NvDevice(state, NvDeviceType::nvmap, {
+ NvMap::NvMap(const DeviceState &state) : NvDevice(state, {
{0x0101, NFUNC(NvMap::Create)},
{0x0103, NFUNC(NvMap::FromId)},
{0x0104, NFUNC(NvMap::Alloc)},
diff --git a/app/src/main/cpp/skyline/services/nvdrv/driver.cpp b/app/src/main/cpp/skyline/services/nvdrv/driver.cpp
index 35861dc2..505d4516 100644
--- a/app/src/main/cpp/skyline/services/nvdrv/driver.cpp
+++ b/app/src/main/cpp/skyline/services/nvdrv/driver.cpp
@@ -13,56 +13,45 @@ namespace skyline::service::nvdrv {
u32 Driver::OpenDevice(const std::string &path) {
state.logger->Debug("Opening NVDRV device ({}): {}", fdIndex, path);
- auto type = device::nvDeviceMap.at(path);
- for (const auto &device : fdMap) {
- if (device.second->deviceType == type) {
- device.second->refCount++;
- fdMap[fdIndex] = device.second;
- return fdIndex++;
- }
- }
- std::shared_ptr object;
- switch (type) {
- case device::NvDeviceType::nvhost_ctrl:
- object = std::make_shared(state);
- break;
-
- case device::NvDeviceType::nvhost_gpu:
- case device::NvDeviceType::nvhost_vic:
- case device::NvDeviceType::nvhost_nvdec:
- object = std::make_shared(state, type);
- break;
-
- case device::NvDeviceType::nvhost_ctrl_gpu:
- object = std::make_shared(state);
- break;
-
- case device::NvDeviceType::nvmap:
- object = std::make_shared(state);
- break;
-
- case device::NvDeviceType::nvhost_as_gpu:
- object = std::make_shared(state);
- break;
+ switch (util::Hash(path)) {
+ #define NVDEVICE(type, name, devicePath) \
+ case util::Hash(devicePath): { \
+ std::shared_ptr device{}; \
+ if (name.expired()) { \
+ device = device.make_shared(state); \
+ name = device; \
+ } else { \
+ device = name.lock(); \
+ } \
+ devices.push_back(device); \
+ break; \
+ }
+ NVDEVICE_LIST
+ #undef NVDEVICE
default:
throw exception("Cannot find NVDRV device");
}
- deviceMap[type] = object;
- fdMap[fdIndex] = object;
-
return fdIndex++;
}
- void Driver::CloseDevice(skyline::u32 fd) {
+ std::shared_ptr Driver::GetDevice(u32 fd) {
try {
- auto& device = fdMap.at(fd);
- if (!--device->refCount)
- deviceMap.erase(device->deviceType);
+ auto item = devices.at(fd);
+ if (!item)
+ throw exception("GetDevice was called with a closed file descriptor: 0x{:X}", fd);
+ return item;
+ } catch (std::out_of_range) {
+ throw exception("GetDevice was called with invalid file descriptor: 0x{:X}", fd);
+ }
+ }
- fdMap.erase(fd);
+ void Driver::CloseDevice(u32 fd) {
+ try {
+ auto &device = devices.at(fd);
+ device.reset();
} catch (const std::out_of_range &) {
state.logger->Warn("Trying to close non-existent FD");
}
diff --git a/app/src/main/cpp/skyline/services/nvdrv/driver.h b/app/src/main/cpp/skyline/services/nvdrv/driver.h
index bd669161..850b0ae8 100644
--- a/app/src/main/cpp/skyline/services/nvdrv/driver.h
+++ b/app/src/main/cpp/skyline/services/nvdrv/driver.h
@@ -5,10 +5,22 @@
#include "devices/nvhost_syncpoint.h"
+#define NVDEVICE_LIST \
+ NVDEVICE(NvHostCtrl, nvHostCtrl, "/dev/nvhost-ctrl") \
+ NVDEVICE(NvHostChannel, nvHostGpu, "/dev/nvhost-gpu") \
+ NVDEVICE(NvHostChannel, nvHostNvdec, "/dev/nvhost-nvdec") \
+ NVDEVICE(NvHostChannel, nvHostVic, "/dev/nvhost-vic") \
+ NVDEVICE(NvMap, nvMap, "/dev/nvmap") \
+ NVDEVICE(NvHostAsGpu, nvHostAsGpu, "/dev/nvhost-as-gpu") \
+ NVDEVICE(NvHostCtrlGpu, nvHostCtrlGpu, "/dev/nvhost-ctrl-gpu")
+
namespace skyline::service::nvdrv {
namespace device {
class NvDevice;
- enum class NvDeviceType;
+
+ #define NVDEVICE(type, name, path) class type;
+ NVDEVICE_LIST
+ #undef NVDEVICE
}
/**
@@ -17,13 +29,16 @@ namespace skyline::service::nvdrv {
class Driver {
private:
const DeviceState &state;
- std::unordered_map> deviceMap; //!< A map from a NvDeviceType to the NvDevice object
- std::unordered_map> fdMap; //!< A map from an FD to a shared pointer to it's NvDevice object
+ std::vector> devices; //!< A map from an FD to a shared pointer to it's NvDevice object
u32 fdIndex{}; //!< The index of a file descriptor
public:
NvHostSyncpoint hostSyncpoint;
+ #define NVDEVICE(type, name, path) std::weak_ptr name;
+ NVDEVICE_LIST
+ #undef NVDEVICE
+
Driver(const DeviceState &state);
/**
@@ -34,9 +49,11 @@ namespace skyline::service::nvdrv {
u32 OpenDevice(const std::string &path);
/**
- * @brief Closes the specified device with it's file descriptor
+ * @brief Returns a particular device with a specific FD
+ * @param fd The file descriptor to retrieve
+ * @return A shared pointer to the device
*/
- void CloseDevice(u32 fd);
+ std::shared_ptr GetDevice(u32 fd);
/**
* @brief Returns a particular device with a specific FD
@@ -44,31 +61,15 @@ namespace skyline::service::nvdrv {
* @param fd The file descriptor to retrieve
* @return A shared pointer to the device
*/
- template
- std::shared_ptr GetDevice(u32 fd) {
- try {
- auto item = fdMap.at(fd);
- return std::static_pointer_cast(item);
- } catch (std::out_of_range) {
- throw exception("GetDevice was called with invalid file descriptor: 0x{:X}", fd);
- }
+ template
+ inline std::shared_ptr GetDevice(u32 fd) {
+ return std::static_pointer_cast(GetDevice(fd));
}
/**
- * @brief Returns a particular device with a specific type
- * @tparam objectClass The class of the device to return
- * @param type The type of the device to return
- * @return A shared pointer to the device
+ * @brief Closes the specified device with it's file descriptor
*/
- template
- std::shared_ptr GetDevice(device::NvDeviceType type) {
- try {
- auto item = deviceMap.at(type);
- return std::static_pointer_cast(item);
- } catch (std::out_of_range) {
- throw exception("GetDevice was called with invalid type: 0x{:X}", type);
- }
- }
+ void CloseDevice(u32 fd);
};
extern std::weak_ptr driver; //!< A globally shared instance of the Driver