mirror of
				https://github.com/Atmosphere-NX/Atmosphere-libs.git
				synced 2025-10-31 03:25:47 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			151 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * 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>
 | |
| 
 | |
| namespace ams::ddsf {
 | |
| 
 | |
|     Result DeviceCodeEntryManager::Add(DeviceCode device_code, IDevice *device) {
 | |
|         /* Check pre-conditions. */
 | |
|         AMS_ASSERT(device != nullptr);
 | |
|         AMS_ASSERT(device->IsDriverAttached());
 | |
| 
 | |
|         /* Acquire exclusive access to the manager. */
 | |
|         std::scoped_lock lk(m_entry_list_lock);
 | |
| 
 | |
|         /* Check that we don't already have an entry with the code. */
 | |
|         for (const auto &holder : m_entry_list) {
 | |
|             AMS_ASSERT(holder.IsConstructed());
 | |
|             AMS_ASSERT(holder.Get().GetDeviceCode() != device_code);
 | |
|             AMS_UNUSED(holder);
 | |
|         }
 | |
| 
 | |
|         /* Allocate memory for a new device code entry holder. */
 | |
|         void *holder_storage = m_memory_resource->Allocate(sizeof(DeviceCodeEntryHolder));
 | |
|         R_UNLESS(holder_storage != nullptr, ddsf::ResultOutOfResource());
 | |
| 
 | |
|         /* Initialize the new holder. */
 | |
|         auto *holder = std::construct_at(static_cast<DeviceCodeEntryHolder *>(holder_storage));
 | |
|         holder->Construct(device_code, device);
 | |
| 
 | |
|         /* Link the new holder. */
 | |
|         holder->AddTo(m_entry_list);
 | |
| 
 | |
|         R_SUCCEED();
 | |
|     }
 | |
| 
 | |
|     bool DeviceCodeEntryManager::Remove(DeviceCode device_code) {
 | |
|         /* Acquire exclusive access to the manager. */
 | |
|         std::scoped_lock lk(m_entry_list_lock);
 | |
| 
 | |
|         /* Find and erase the entry. */
 | |
|         bool erased = false;
 | |
|         for (auto it = m_entry_list.begin(); it != m_entry_list.end(); /* ... */) {
 | |
|             /* Get the current entry, and advance the iterator. */
 | |
|             DeviceCodeEntryHolder *cur = std::addressof(*(it++));
 | |
| 
 | |
|             /* If the entry matches the device code, remove it. */
 | |
|             AMS_ASSERT(cur->IsConstructed());
 | |
|             if (cur->Get().GetDeviceCode() == device_code) {
 | |
|                 /* Destroy and deallocate the holder. */
 | |
|                 cur->Destroy();
 | |
|                 std::destroy_at(cur);
 | |
|                 m_memory_resource->Deallocate(cur, sizeof(*cur));
 | |
| 
 | |
|                 erased = true;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return erased;
 | |
|     }
 | |
| 
 | |
|     Result DeviceCodeEntryManager::FindDeviceCodeEntry(DeviceCodeEntry **out, DeviceCode device_code) {
 | |
|         /* Check arguments. */
 | |
|         AMS_ASSERT(out != nullptr);
 | |
|         R_UNLESS(out != nullptr, ddsf::ResultInvalidArgument());
 | |
| 
 | |
|         /* Find the device. */
 | |
|         bool found = false;
 | |
|         this->ForEachEntry([&](DeviceCodeEntry &entry) -> bool {
 | |
|             if (entry.GetDeviceCode() == device_code) {
 | |
|                 found = true;
 | |
|                 *out = std::addressof(entry);
 | |
|                 return false;
 | |
|             }
 | |
|             return true;
 | |
|         });
 | |
| 
 | |
|         /* Check that we found the device. */
 | |
|         R_UNLESS(found, ddsf::ResultDeviceCodeNotFound());
 | |
| 
 | |
|         R_SUCCEED();
 | |
|     }
 | |
| 
 | |
|     Result DeviceCodeEntryManager::FindDeviceCodeEntry(const DeviceCodeEntry **out, DeviceCode device_code) const {
 | |
|         /* Check arguments. */
 | |
|         AMS_ASSERT(out != nullptr);
 | |
|         R_UNLESS(out != nullptr, ddsf::ResultInvalidArgument());
 | |
| 
 | |
|         /* Find the device. */
 | |
|         bool found = false;
 | |
|         this->ForEachEntry([&](const DeviceCodeEntry &entry) -> bool {
 | |
|             if (entry.GetDeviceCode() == device_code) {
 | |
|                 found = true;
 | |
|                 *out = std::addressof(entry);
 | |
|                 return false;
 | |
|             }
 | |
|             return true;
 | |
|         });
 | |
| 
 | |
|         /* Check that we found the device. */
 | |
|         R_UNLESS(found, ddsf::ResultDeviceCodeNotFound());
 | |
| 
 | |
|         R_SUCCEED();
 | |
|     }
 | |
| 
 | |
|     Result DeviceCodeEntryManager::FindDevice(IDevice **out, DeviceCode device_code) {
 | |
|         /* Check pre-conditions. */
 | |
|         AMS_ASSERT(out != nullptr);
 | |
| 
 | |
|         /* Find the entry. */
 | |
|         DeviceCodeEntry *entry;
 | |
|         R_TRY(this->FindDeviceCodeEntry(std::addressof(entry), device_code));
 | |
| 
 | |
|         /* Set the output. */
 | |
|         if (out != nullptr) {
 | |
|             *out = std::addressof(entry->GetDevice());
 | |
|         }
 | |
| 
 | |
|         R_SUCCEED();
 | |
|     }
 | |
| 
 | |
|     Result DeviceCodeEntryManager::FindDevice(const IDevice **out, DeviceCode device_code) const {
 | |
|         /* Check pre-conditions. */
 | |
|         AMS_ASSERT(out != nullptr);
 | |
| 
 | |
|         /* Find the entry. */
 | |
|         const DeviceCodeEntry *entry;
 | |
|         R_TRY(this->FindDeviceCodeEntry(std::addressof(entry), device_code));
 | |
| 
 | |
|         /* Set the output. */
 | |
|         if (out != nullptr) {
 | |
|             *out = std::addressof(entry->GetDevice());
 | |
|         }
 | |
| 
 | |
|         R_SUCCEED();
 | |
|     }
 | |
| 
 | |
| }
 |