mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Merge pull request #279 from yuriks/session
Remove SyncRequest from K::Object and create a new K::Session type
This commit is contained in:
		
						commit
						d0ce9d58f6
					
				
					 15 changed files with 129 additions and 104 deletions
				
			
		|  | @ -108,6 +108,7 @@ set(HEADERS | |||
|             hle/kernel/kernel.h | ||||
|             hle/kernel/mutex.h | ||||
|             hle/kernel/semaphore.h | ||||
|             hle/kernel/session.h | ||||
|             hle/kernel/shared_memory.h | ||||
|             hle/kernel/thread.h | ||||
|             hle/service/ac_u.h | ||||
|  |  | |||
|  | @ -2,6 +2,8 @@ | |||
| // Licensed under GPLv2
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <map> | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| #include "common/file_util.h" | ||||
| #include "common/math_util.h" | ||||
|  | @ -10,8 +12,8 @@ | |||
| #include "core/file_sys/archive_sdmc.h" | ||||
| #include "core/file_sys/directory.h" | ||||
| #include "core/hle/kernel/archive.h" | ||||
| #include "core/hle/kernel/session.h" | ||||
| #include "core/hle/result.h" | ||||
| #include "core/hle/service/service.h" | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Kernel namespace
 | ||||
|  | @ -41,19 +43,15 @@ enum class DirectoryCommand : u32 { | |||
|     Close           = 0x08020000, | ||||
| }; | ||||
| 
 | ||||
| class Archive : public Object { | ||||
| class Archive : public Kernel::Session { | ||||
| public: | ||||
|     std::string GetTypeName() const override { return "Archive"; } | ||||
|     std::string GetName() const override { return name; } | ||||
| 
 | ||||
|     static Kernel::HandleType GetStaticHandleType() { return HandleType::Archive; } | ||||
|     Kernel::HandleType GetHandleType() const override { return HandleType::Archive; } | ||||
|     std::string GetName() const override { return "Archive: " + name; } | ||||
| 
 | ||||
|     std::string name;           ///< Name of archive (optional)
 | ||||
|     FileSys::Archive* backend;  ///< Archive backend interface
 | ||||
| 
 | ||||
|     ResultVal<bool> SyncRequest() override { | ||||
|         u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|         u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|         FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); | ||||
| 
 | ||||
|         switch (cmd) { | ||||
|  | @ -102,7 +100,8 @@ public: | |||
|         default: | ||||
|         { | ||||
|             LOG_ERROR(Service_FS, "Unknown command=0x%08X", cmd); | ||||
|             return UnimplementedFunction(ErrorModule::FS); | ||||
|             cmd_buff[0] = UnimplementedFunction(ErrorModule::FS).raw; | ||||
|             return MakeResult<bool>(false); | ||||
|         } | ||||
|         } | ||||
|         cmd_buff[1] = 0; // No error
 | ||||
|  | @ -110,19 +109,15 @@ public: | |||
|     } | ||||
| }; | ||||
| 
 | ||||
| class File : public Object { | ||||
| class File : public Kernel::Session { | ||||
| public: | ||||
|     std::string GetTypeName() const override { return "File"; } | ||||
|     std::string GetName() const override { return path.DebugStr(); } | ||||
| 
 | ||||
|     static Kernel::HandleType GetStaticHandleType() { return HandleType::File; } | ||||
|     Kernel::HandleType GetHandleType() const override { return HandleType::File; } | ||||
|     std::string GetName() const override { return "Path: " + path.DebugStr(); } | ||||
| 
 | ||||
|     FileSys::Path path; ///< Path of the file
 | ||||
|     std::unique_ptr<FileSys::File> backend; ///< File backend interface
 | ||||
| 
 | ||||
|     ResultVal<bool> SyncRequest() override { | ||||
|         u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|         u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|         FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); | ||||
|         switch (cmd) { | ||||
| 
 | ||||
|  | @ -188,19 +183,15 @@ public: | |||
|     } | ||||
| }; | ||||
| 
 | ||||
| class Directory : public Object { | ||||
| class Directory : public Kernel::Session { | ||||
| public: | ||||
|     std::string GetTypeName() const override { return "Directory"; } | ||||
|     std::string GetName() const override { return path.DebugStr(); } | ||||
| 
 | ||||
|     static Kernel::HandleType GetStaticHandleType() { return HandleType::Directory; } | ||||
|     Kernel::HandleType GetHandleType() const override { return HandleType::Directory; } | ||||
|     std::string GetName() const override { return "Directory: " + path.DebugStr(); } | ||||
| 
 | ||||
|     FileSys::Path path; ///< Path of the directory
 | ||||
|     std::unique_ptr<FileSys::Directory> backend; ///< File backend interface
 | ||||
| 
 | ||||
|     ResultVal<bool> SyncRequest() override { | ||||
|         u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|         u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|         DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); | ||||
|         switch (cmd) { | ||||
| 
 | ||||
|  | @ -230,7 +221,7 @@ public: | |||
|             LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); | ||||
|             ResultCode error = UnimplementedFunction(ErrorModule::FS); | ||||
|             cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
 | ||||
|             return error; | ||||
|             return MakeResult<bool>(false); | ||||
|         } | ||||
|         cmd_buff[1] = 0; // No error
 | ||||
|         return MakeResult<bool>(false); | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ enum KernelHandle { | |||
| enum class HandleType : u32 { | ||||
|     Unknown         = 0, | ||||
|     Port            = 1, | ||||
|     Service         = 2, | ||||
|     Session         = 2, | ||||
|     Event           = 3, | ||||
|     Mutex           = 4, | ||||
|     SharedMemory    = 5, | ||||
|  | @ -30,10 +30,7 @@ enum class HandleType : u32 { | |||
|     Thread          = 7, | ||||
|     Process         = 8, | ||||
|     AddressArbiter  = 9, | ||||
|     File            = 10, | ||||
|     Semaphore       = 11, | ||||
|     Archive         = 12, | ||||
|     Directory       = 13, | ||||
|     Semaphore       = 10, | ||||
| }; | ||||
| 
 | ||||
| enum { | ||||
|  | @ -52,15 +49,6 @@ public: | |||
|     virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; } | ||||
|     virtual Kernel::HandleType GetHandleType() const = 0; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Synchronize kernel object. | ||||
|      * @return True if the current thread should wait as a result of the sync | ||||
|      */ | ||||
|     virtual ResultVal<bool> SyncRequest() { | ||||
|         LOG_ERROR(Kernel, "(UNIMPLEMENTED)"); | ||||
|         return UnimplementedFunction(ErrorModule::Kernel); | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Wait for kernel object to synchronize. | ||||
|      * @return True if the current thread should wait as a result of the wait | ||||
|  |  | |||
							
								
								
									
										58
									
								
								src/core/hle/kernel/session.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/core/hle/kernel/session.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | |||
| // Copyright 2014 Citra Emulator Project
 | ||||
| // Licensed under GPLv2+
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "core/hle/kernel/kernel.h" | ||||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of header
 | ||||
| 
 | ||||
| /**
 | ||||
|  * Returns a pointer to the command buffer in kernel memory | ||||
|  * @param offset Optional offset into command buffer | ||||
|  * @return Pointer to command buffer | ||||
|  */ | ||||
| inline static u32* GetCommandBuffer(const int offset=0) { | ||||
|     return (u32*)Memory::GetPointer(Memory::KERNEL_MEMORY_VADDR + kCommandHeaderOffset + offset); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Kernel object representing the client endpoint of an IPC session. Sessions are the basic CTR-OS | ||||
|  * primitive for communication between different processes, and are used to implement service calls | ||||
|  * to the various system services. | ||||
|  * | ||||
|  * To make a service call, the client must write the command header and parameters to the buffer | ||||
|  * located at offset 0x80 of the TLS (Thread-Local Storage) area, then execute a SendSyncRequest | ||||
|  * SVC call with its Session handle. The kernel will read the command header, using it to marshall | ||||
|  * the parameters to the process at the server endpoint of the session. After the server replies to | ||||
|  * the request, the response is marshalled back to the caller's TLS buffer and control is | ||||
|  * transferred back to it. | ||||
|  * | ||||
|  * In Citra, only the client endpoint is currently implemented and only HLE calls, where the IPC | ||||
|  * request is answered by C++ code in the emulator, are supported. When SendSyncRequest is called | ||||
|  * with the session handle, this class's SyncRequest method is called, which should read the TLS | ||||
|  * buffer and emulate the call accordingly. Since the code can directly read the emulated memory, | ||||
|  * no parameter marshalling is done. | ||||
|  * | ||||
|  * In the long term, this should be turned into the full-fledged IPC mechanism implemented by | ||||
|  * CTR-OS so that IPC calls can be optionally handled by the real implementations of processes, as | ||||
|  * opposed to HLE simulations. | ||||
|  */ | ||||
| class Session : public Object { | ||||
| public: | ||||
|     std::string GetTypeName() const override { return "Session"; } | ||||
| 
 | ||||
|     static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Session; } | ||||
|     Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Session; } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls | ||||
|      * aren't supported yet. | ||||
|      */ | ||||
|     virtual ResultVal<bool> SyncRequest() = 0; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  | @ -18,7 +18,7 @@ namespace AC_U { | |||
|  *      2 : Output connection type, 0 = none, 1 = Old3DS Internet, 2 = New3DS Internet. | ||||
|  */ | ||||
| void GetWifiStatus(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     // TODO(purpasmart96): This function is only a stub,
 | ||||
|     // it returns a valid result without implementing full functionality.
 | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ enum class SignalType : u32 { | |||
| }; | ||||
| 
 | ||||
| void Initialize(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     cmd_buff[3] = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Menu");  // APT menu event handle
 | ||||
|     cmd_buff[4] = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Pause"); // APT pause event handle
 | ||||
|  | @ -57,7 +57,7 @@ void Initialize(Service::Interface* self) { | |||
| } | ||||
| 
 | ||||
| void GetLockHandle(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|     u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field
 | ||||
| 
 | ||||
|     if (0 == lock_handle) { | ||||
|  | @ -78,14 +78,14 @@ void GetLockHandle(Service::Interface* self) { | |||
| } | ||||
| 
 | ||||
| void Enable(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|     u32 unk = cmd_buff[1]; // TODO(bunnei): What is this field used for?
 | ||||
|     cmd_buff[1] = 0; // No error
 | ||||
|     LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk); | ||||
| } | ||||
| 
 | ||||
| void InquireNotification(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|     u32 app_id = cmd_buff[2]; | ||||
|     cmd_buff[1] = 0; // No error
 | ||||
|     cmd_buff[2] = static_cast<u32>(SignalType::None); // Signal type
 | ||||
|  | @ -112,7 +112,7 @@ void InquireNotification(Service::Interface* self) { | |||
|  *      8 : Output parameter buffer ptr | ||||
|  */ | ||||
| void ReceiveParameter(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|     u32 app_id = cmd_buff[1]; | ||||
|     u32 buffer_size = cmd_buff[2]; | ||||
|     cmd_buff[1] = 0; // No error
 | ||||
|  | @ -143,7 +143,7 @@ void ReceiveParameter(Service::Interface* self) { | |||
|  *      8 : Output parameter buffer ptr | ||||
|  */ | ||||
| void GlanceParameter(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|     u32 app_id = cmd_buff[1]; | ||||
|     u32 buffer_size = cmd_buff[2]; | ||||
| 
 | ||||
|  | @ -170,7 +170,7 @@ void GlanceParameter(Service::Interface* self) { | |||
|  *      1 : Result of function, 0 on success, otherwise error code | ||||
|  */ | ||||
| void AppletUtility(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     // These are from 3dbrew - I'm not really sure what they're used for.
 | ||||
|     u32 unk = cmd_buff[1]; | ||||
|  | @ -196,7 +196,7 @@ void AppletUtility(Service::Interface* self) { | |||
| void GetSharedFont(Service::Interface* self) { | ||||
|     LOG_TRACE(Kernel_SVC, "called"); | ||||
| 
 | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     if (!shared_font.empty()) { | ||||
|         // TODO(bunnei): This function shouldn't copy the shared font every time it's called.
 | ||||
|  |  | |||
|  | @ -52,7 +52,7 @@ static const std::array<u16, 187> country_codes = { | |||
|  *      2 : Country's 2-char string | ||||
|  */ | ||||
| static void GetCountryCodeString(Service::Interface* self) { | ||||
|     u32* cmd_buffer = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buffer = Kernel::GetCommandBuffer(); | ||||
|     u32 country_code_id = cmd_buffer[1]; | ||||
| 
 | ||||
|     if (country_code_id >= country_codes.size() || 0 == country_codes[country_code_id]) { | ||||
|  | @ -74,7 +74,7 @@ static void GetCountryCodeString(Service::Interface* self) { | |||
|  *      2 : Country Code ID | ||||
|  */ | ||||
| static void GetCountryCodeID(Service::Interface* self) { | ||||
|     u32* cmd_buffer = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buffer = Kernel::GetCommandBuffer(); | ||||
|     u16 country_code = cmd_buffer[1]; | ||||
|     u16 country_code_id = 0; | ||||
| 
 | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ static Handle interrupt_event; | |||
|  *      2 : (inaddr << 1) + 0x1FF40000 (where 0x1FF00000 is the DSP RAM address) | ||||
|  */ | ||||
| void ConvertProcessAddressFromDspDram(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     u32 addr = cmd_buff[1]; | ||||
| 
 | ||||
|  | @ -48,7 +48,7 @@ void ConvertProcessAddressFromDspDram(Service::Interface* self) { | |||
|  *      2 : Component loaded, 0 on not loaded, 1 on loaded | ||||
|  */ | ||||
| void LoadComponent(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     cmd_buff[1] = 0; // No error
 | ||||
|     cmd_buff[2] = 1; // Pretend that we actually loaded the DSP firmware
 | ||||
|  | @ -65,7 +65,7 @@ void LoadComponent(Service::Interface* self) { | |||
|  *      3 : Semaphore event handle | ||||
|  */ | ||||
| void GetSemaphoreEventHandle(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     cmd_buff[1] = 0; // No error
 | ||||
|     cmd_buff[3] = semaphore_event; // Event handle
 | ||||
|  | @ -83,7 +83,7 @@ void GetSemaphoreEventHandle(Service::Interface* self) { | |||
|  *      1 : Result of function, 0 on success, otherwise error code | ||||
|  */ | ||||
| void RegisterInterruptEvents(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     interrupt_event = static_cast<Handle>(cmd_buff[4]); | ||||
| 
 | ||||
|  | @ -100,7 +100,7 @@ void RegisterInterruptEvents(Service::Interface* self) { | |||
|  *      1 : Result of function, 0 on success, otherwise error code | ||||
|  */ | ||||
| void WriteReg0x10(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     Kernel::SignalEvent(interrupt_event); | ||||
| 
 | ||||
|  | @ -121,7 +121,7 @@ void WriteReg0x10(Service::Interface* self) { | |||
|  *      2 : Number of bytes read from pipe | ||||
|  */ | ||||
| void ReadPipeIfPossible(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     u32 size = cmd_buff[3] & 0xFFFF;// Lower 16 bits are size
 | ||||
|     VAddr addr = cmd_buff[0x41]; | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ | |||
| namespace FS_User { | ||||
| 
 | ||||
| static void Initialize(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     // TODO(Link Mauve): check the behavior when cmd_buff[1] isn't 32, as per
 | ||||
|     // http://3dbrew.org/wiki/FS:Initialize#Request
 | ||||
|  | @ -43,7 +43,7 @@ static void Initialize(Service::Interface* self) { | |||
|  *      3 : File handle | ||||
|  */ | ||||
| static void OpenFile(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to
 | ||||
|     // 3dmoo's or ctrulib's implementations.  Triple check if it's really the case.
 | ||||
|  | @ -86,7 +86,7 @@ static void OpenFile(Service::Interface* self) { | |||
|  *      3 : File handle | ||||
|  */ | ||||
| static void OpenFileDirectly(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     auto archive_id       = static_cast<FileSys::Archive::IdCode>(cmd_buff[2]); | ||||
|     auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]); | ||||
|  | @ -141,7 +141,7 @@ static void OpenFileDirectly(Service::Interface* self) { | |||
|  *      1 : Result of function, 0 on success, otherwise error code | ||||
|  */ | ||||
| void DeleteFile(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to
 | ||||
|     // 3dmoo's or ctrulib's implementations.  Triple check if it's really the case.
 | ||||
|  | @ -175,7 +175,7 @@ void DeleteFile(Service::Interface* self) { | |||
|  *      1 : Result of function, 0 on success, otherwise error code | ||||
|  */ | ||||
| void RenameFile(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     // TODO(Link Mauve): cmd_buff[2] and cmd_buff[6], aka archive handle lower word, aren't used according to
 | ||||
|     // 3dmoo's or ctrulib's implementations.  Triple check if it's really the case.
 | ||||
|  | @ -210,7 +210,7 @@ void RenameFile(Service::Interface* self) { | |||
|  *      1 : Result of function, 0 on success, otherwise error code | ||||
|  */ | ||||
| void DeleteDirectory(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to
 | ||||
|     // 3dmoo's or ctrulib's implementations.  Triple check if it's really the case.
 | ||||
|  | @ -239,7 +239,7 @@ void DeleteDirectory(Service::Interface* self) { | |||
|  *      1 : Result of function, 0 on success, otherwise error code | ||||
|  */ | ||||
| static void CreateDirectory(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     // TODO: cmd_buff[2], aka archive handle lower word, isn't used according to
 | ||||
|     // 3dmoo's or ctrulib's implementations.  Triple check if it's really the case.
 | ||||
|  | @ -272,7 +272,7 @@ static void CreateDirectory(Service::Interface* self) { | |||
|  *      1 : Result of function, 0 on success, otherwise error code | ||||
|  */ | ||||
| void RenameDirectory(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     // TODO(Link Mauve): cmd_buff[2] and cmd_buff[6], aka archive handle lower word, aren't used according to
 | ||||
|     // 3dmoo's or ctrulib's implementations.  Triple check if it's really the case.
 | ||||
|  | @ -296,7 +296,7 @@ void RenameDirectory(Service::Interface* self) { | |||
| } | ||||
| 
 | ||||
| static void OpenDirectory(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to
 | ||||
|     // 3dmoo's or ctrulib's implementations.  Triple check if it's really the case.
 | ||||
|  | @ -332,7 +332,7 @@ static void OpenDirectory(Service::Interface* self) { | |||
|  *      3 : Archive handle upper word (same as file handle) | ||||
|  */ | ||||
| static void OpenArchive(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     auto archive_id       = static_cast<FileSys::Archive::IdCode>(cmd_buff[1]); | ||||
|     auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]); | ||||
|  | @ -365,7 +365,7 @@ static void OpenArchive(Service::Interface* self) { | |||
| *      2 : Whether the Sdmc could be detected | ||||
| */ | ||||
| static void IsSdmcDetected(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     cmd_buff[1] = 0; | ||||
|     cmd_buff[2] = Settings::values.use_virtual_sd ? 1 : 0; | ||||
|  |  | |||
|  | @ -72,7 +72,7 @@ static void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) { | |||
| 
 | ||||
| /// Write a GSP GPU hardware register
 | ||||
| static void WriteHWRegs(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|     u32 reg_addr = cmd_buff[1]; | ||||
|     u32 size = cmd_buff[2]; | ||||
| 
 | ||||
|  | @ -83,7 +83,7 @@ static void WriteHWRegs(Service::Interface* self) { | |||
| 
 | ||||
| /// Read a GSP GPU hardware register
 | ||||
| static void ReadHWRegs(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|     u32 reg_addr = cmd_buff[1]; | ||||
|     u32 size = cmd_buff[2]; | ||||
| 
 | ||||
|  | @ -136,7 +136,7 @@ static void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) { | |||
|  *      1: Result code | ||||
|  */ | ||||
| static void SetBufferSwap(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|     u32 screen_id = cmd_buff[1]; | ||||
|     FrameBufferInfo* fb_info = (FrameBufferInfo*)&cmd_buff[2]; | ||||
|     SetBufferSwap(screen_id, *fb_info); | ||||
|  | @ -155,7 +155,7 @@ static void SetBufferSwap(Service::Interface* self) { | |||
|  *      4 : Handle to GSP shared memory | ||||
|  */ | ||||
| static void RegisterInterruptRelayQueue(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|     u32 flags = cmd_buff[1]; | ||||
|     g_interrupt_event = cmd_buff[3]; | ||||
|     g_shared_memory = Kernel::CreateSharedMemory("GSPSharedMem"); | ||||
|  | @ -323,7 +323,7 @@ static void TriggerCmdReqQueue(Service::Interface* self) { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|     cmd_buff[1] = 0; // No error
 | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -153,7 +153,7 @@ void PadUpdateComplete() { | |||
|  *      8 : Event signaled by HID_User | ||||
|  */ | ||||
| static void GetIPCHandles(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     cmd_buff[1] = 0; // No error
 | ||||
|     cmd_buff[3] = shared_mem; | ||||
|  |  | |||
|  | @ -34,7 +34,7 @@ static bool battery_is_charging = true; | |||
|  *      2 : Output of function, 0 = not charging, 1 = charging. | ||||
|  */ | ||||
| static void GetAdapterState(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     // TODO(purpasmart96): This function is only a stub,
 | ||||
|     // it returns a valid result without implementing full functionality.
 | ||||
|  | @ -52,7 +52,7 @@ static void GetAdapterState(Service::Interface* self) { | |||
|  *      2 : Whether the 3DS's physical shell casing is open (1) or closed (0) | ||||
|  */ | ||||
| static void GetShellState(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     cmd_buff[1] = 0; | ||||
|     cmd_buff[2] = shell_open ? 1 : 0; | ||||
|  | @ -68,7 +68,7 @@ static void GetShellState(Service::Interface* self) { | |||
|  *          3 = half full battery, 2 =  low battery, 1 = critical battery. | ||||
|  */ | ||||
| static void GetBatteryLevel(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     // TODO(purpasmart96): This function is only a stub,
 | ||||
|     // it returns a valid result without implementing full functionality.
 | ||||
|  | @ -86,7 +86,7 @@ static void GetBatteryLevel(Service::Interface* self) { | |||
|  *      2 : Output of function, 0 = not charging, 1 = charging. | ||||
|  */ | ||||
| static void GetBatteryChargeState(Service::Interface* self) { | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     // TODO(purpasmart96): This function is only a stub,
 | ||||
|     // it returns a valid result without implementing full functionality.
 | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ | |||
| #include "core/mem_map.h" | ||||
| 
 | ||||
| #include "core/hle/kernel/kernel.h" | ||||
| #include "core/hle/kernel/session.h" | ||||
| #include "core/hle/svc.h" | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -21,30 +22,19 @@ | |||
| 
 | ||||
| namespace Service { | ||||
| 
 | ||||
| static const int kMaxPortSize           = 0x08; ///< Maximum size of a port name (8 characters)
 | ||||
| static const int kCommandHeaderOffset   = 0x80; ///< Offset into command buffer of header
 | ||||
| 
 | ||||
| /**
 | ||||
|  * Returns a pointer to the command buffer in kernel memory | ||||
|  * @param offset Optional offset into command buffer | ||||
|  * @return Pointer to command buffer | ||||
|  */ | ||||
| inline static u32* GetCommandBuffer(const int offset=0) { | ||||
|     return (u32*)Memory::GetPointer(Memory::KERNEL_MEMORY_VADDR + kCommandHeaderOffset + offset); | ||||
| } | ||||
| static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters)
 | ||||
| 
 | ||||
| class Manager; | ||||
| 
 | ||||
| /// Interface to a CTROS service
 | ||||
| class Interface  : public Kernel::Object { | ||||
| class Interface  : public Kernel::Session { | ||||
|     // TODO(yuriks): An "Interface" being a Kernel::Object is mostly non-sense. Interface should be
 | ||||
|     // just something that encapsulates a session and acts as a helper to implement service
 | ||||
|     // processes.
 | ||||
| 
 | ||||
|     friend class Manager; | ||||
| public: | ||||
| 
 | ||||
|     std::string GetName() const override { return GetPortName(); } | ||||
|     std::string GetTypeName() const override { return GetPortName(); } | ||||
| 
 | ||||
|     static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Service; } | ||||
|     Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Service; } | ||||
| 
 | ||||
|     typedef void (*Function)(Interface*); | ||||
| 
 | ||||
|  | @ -77,7 +67,7 @@ public: | |||
|     } | ||||
| 
 | ||||
|     ResultVal<bool> SyncRequest() override { | ||||
|         u32* cmd_buff = GetCommandBuffer(); | ||||
|         u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|         auto itr = m_functions.find(cmd_buff[0]); | ||||
| 
 | ||||
|         if (itr == m_functions.end() || itr->second.func == nullptr) { | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ static Handle g_event_handle = 0; | |||
| static void Initialize(Service::Interface* self) { | ||||
|     LOG_DEBUG(Service_SRV, "called"); | ||||
| 
 | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     cmd_buff[1] = 0; // No error
 | ||||
| } | ||||
|  | @ -24,7 +24,7 @@ static void Initialize(Service::Interface* self) { | |||
| static void GetProcSemaphore(Service::Interface* self) { | ||||
|     LOG_TRACE(Service_SRV, "called"); | ||||
| 
 | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     // TODO(bunnei): Change to a semaphore once these have been implemented
 | ||||
|     g_event_handle = Kernel::CreateEvent(RESETTYPE_ONESHOT, "SRV:Event"); | ||||
|  | @ -36,7 +36,7 @@ static void GetProcSemaphore(Service::Interface* self) { | |||
| 
 | ||||
| static void GetServiceHandle(Service::Interface* self) { | ||||
|     ResultCode res = RESULT_SUCCESS; | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize); | ||||
|     Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); | ||||
|  |  | |||
|  | @ -88,17 +88,14 @@ static Result ConnectToPort(Handle* out, const char* port_name) { | |||
| 
 | ||||
| /// Synchronize to an OS service
 | ||||
| static Result SendSyncRequest(Handle handle) { | ||||
|     // TODO(yuriks): ObjectPool::Get tries to check the Object type, which fails since this is a generic base Object,
 | ||||
|     // so we are forced to use GetFast and manually verify the handle.
 | ||||
|     if (!Kernel::g_object_pool.IsValid(handle)) { | ||||
|     Kernel::Session* session = Kernel::g_object_pool.Get<Kernel::Session>(handle); | ||||
|     if (session == nullptr) { | ||||
|         return InvalidHandle(ErrorModule::Kernel).raw; | ||||
|     } | ||||
|     Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle); | ||||
| 
 | ||||
|     _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!"); | ||||
|     LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, object->GetTypeName().c_str()); | ||||
|     LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str()); | ||||
| 
 | ||||
|     ResultVal<bool> wait = object->SyncRequest(); | ||||
|     ResultVal<bool> wait = session->SyncRequest(); | ||||
|     if (wait.Succeeded() && *wait) { | ||||
|         Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct?
 | ||||
|     } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue