mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-14 22:50:06 +00:00
Remove SyncRequest from K::Object and create a new K::Session type
This is a first step at fixing the conceptual insanity that is our handling of service and IPC calls. For now, interfaces still directly derived from Session because we don't have the infrastructure to do it properly. (That is, Processes and scheduling them.)
This commit is contained in:
parent
1ee740898a
commit
e321decf98
@ -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…
Reference in New Issue
Block a user