1
0
Fork 0

Merge pull request #279 from yuriks/session

Remove SyncRequest from K::Object and create a new K::Session type
This commit is contained in:
bunnei 2014-12-15 18:45:53 -05:00
commit d0ce9d58f6
15 changed files with 129 additions and 104 deletions

View File

@ -108,6 +108,7 @@ set(HEADERS
hle/kernel/kernel.h hle/kernel/kernel.h
hle/kernel/mutex.h hle/kernel/mutex.h
hle/kernel/semaphore.h hle/kernel/semaphore.h
hle/kernel/session.h
hle/kernel/shared_memory.h hle/kernel/shared_memory.h
hle/kernel/thread.h hle/kernel/thread.h
hle/service/ac_u.h hle/service/ac_u.h

View File

@ -2,6 +2,8 @@
// Licensed under GPLv2 // Licensed under GPLv2
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <map>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/file_util.h" #include "common/file_util.h"
#include "common/math_util.h" #include "common/math_util.h"
@ -10,8 +12,8 @@
#include "core/file_sys/archive_sdmc.h" #include "core/file_sys/archive_sdmc.h"
#include "core/file_sys/directory.h" #include "core/file_sys/directory.h"
#include "core/hle/kernel/archive.h" #include "core/hle/kernel/archive.h"
#include "core/hle/kernel/session.h"
#include "core/hle/result.h" #include "core/hle/result.h"
#include "core/hle/service/service.h"
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Kernel namespace // Kernel namespace
@ -41,19 +43,15 @@ enum class DirectoryCommand : u32 {
Close = 0x08020000, Close = 0x08020000,
}; };
class Archive : public Object { class Archive : public Kernel::Session {
public: public:
std::string GetTypeName() const override { return "Archive"; } std::string GetName() const override { return "Archive: " + name; }
std::string GetName() const override { return name; }
static Kernel::HandleType GetStaticHandleType() { return HandleType::Archive; }
Kernel::HandleType GetHandleType() const override { return HandleType::Archive; }
std::string name; ///< Name of archive (optional) std::string name; ///< Name of archive (optional)
FileSys::Archive* backend; ///< Archive backend interface FileSys::Archive* backend; ///< Archive backend interface
ResultVal<bool> SyncRequest() override { ResultVal<bool> SyncRequest() override {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
switch (cmd) { switch (cmd) {
@ -102,7 +100,8 @@ public:
default: default:
{ {
LOG_ERROR(Service_FS, "Unknown command=0x%08X", cmd); 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 cmd_buff[1] = 0; // No error
@ -110,19 +109,15 @@ public:
} }
}; };
class File : public Object { class File : public Kernel::Session {
public: public:
std::string GetTypeName() const override { return "File"; } std::string GetName() const override { return "Path: " + path.DebugStr(); }
std::string GetName() const override { return path.DebugStr(); }
static Kernel::HandleType GetStaticHandleType() { return HandleType::File; }
Kernel::HandleType GetHandleType() const override { return HandleType::File; }
FileSys::Path path; ///< Path of the file FileSys::Path path; ///< Path of the file
std::unique_ptr<FileSys::File> backend; ///< File backend interface std::unique_ptr<FileSys::File> backend; ///< File backend interface
ResultVal<bool> SyncRequest() override { ResultVal<bool> SyncRequest() override {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
switch (cmd) { switch (cmd) {
@ -188,19 +183,15 @@ public:
} }
}; };
class Directory : public Object { class Directory : public Kernel::Session {
public: public:
std::string GetTypeName() const override { return "Directory"; } std::string GetName() const override { return "Directory: " + path.DebugStr(); }
std::string GetName() const override { return path.DebugStr(); }
static Kernel::HandleType GetStaticHandleType() { return HandleType::Directory; }
Kernel::HandleType GetHandleType() const override { return HandleType::Directory; }
FileSys::Path path; ///< Path of the directory FileSys::Path path; ///< Path of the directory
std::unique_ptr<FileSys::Directory> backend; ///< File backend interface std::unique_ptr<FileSys::Directory> backend; ///< File backend interface
ResultVal<bool> SyncRequest() override { ResultVal<bool> SyncRequest() override {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]);
switch (cmd) { switch (cmd) {
@ -230,7 +221,7 @@ public:
LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd);
ResultCode error = UnimplementedFunction(ErrorModule::FS); ResultCode error = UnimplementedFunction(ErrorModule::FS);
cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. 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 cmd_buff[1] = 0; // No error
return MakeResult<bool>(false); return MakeResult<bool>(false);

View File

@ -22,7 +22,7 @@ enum KernelHandle {
enum class HandleType : u32 { enum class HandleType : u32 {
Unknown = 0, Unknown = 0,
Port = 1, Port = 1,
Service = 2, Session = 2,
Event = 3, Event = 3,
Mutex = 4, Mutex = 4,
SharedMemory = 5, SharedMemory = 5,
@ -30,10 +30,7 @@ enum class HandleType : u32 {
Thread = 7, Thread = 7,
Process = 8, Process = 8,
AddressArbiter = 9, AddressArbiter = 9,
File = 10, Semaphore = 10,
Semaphore = 11,
Archive = 12,
Directory = 13,
}; };
enum { enum {
@ -52,15 +49,6 @@ public:
virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; } virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; }
virtual Kernel::HandleType GetHandleType() const = 0; 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. * Wait for kernel object to synchronize.
* @return True if the current thread should wait as a result of the wait * @return True if the current thread should wait as a result of the wait

View 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;
};
}

View File

@ -18,7 +18,7 @@ namespace AC_U {
* 2 : Output connection type, 0 = none, 1 = Old3DS Internet, 2 = New3DS Internet. * 2 : Output connection type, 0 = none, 1 = Old3DS Internet, 2 = New3DS Internet.
*/ */
void GetWifiStatus(Service::Interface* self) { void GetWifiStatus(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
// TODO(purpasmart96): This function is only a stub, // TODO(purpasmart96): This function is only a stub,
// it returns a valid result without implementing full functionality. // it returns a valid result without implementing full functionality.

View File

@ -40,7 +40,7 @@ enum class SignalType : u32 {
}; };
void Initialize(Service::Interface* self) { 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[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 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) { 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 u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field
if (0 == lock_handle) { if (0 == lock_handle) {
@ -78,14 +78,14 @@ void GetLockHandle(Service::Interface* self) {
} }
void Enable(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? u32 unk = cmd_buff[1]; // TODO(bunnei): What is this field used for?
cmd_buff[1] = 0; // No error cmd_buff[1] = 0; // No error
LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk); LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk);
} }
void InquireNotification(Service::Interface* self) { void InquireNotification(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
u32 app_id = cmd_buff[2]; u32 app_id = cmd_buff[2];
cmd_buff[1] = 0; // No error cmd_buff[1] = 0; // No error
cmd_buff[2] = static_cast<u32>(SignalType::None); // Signal type cmd_buff[2] = static_cast<u32>(SignalType::None); // Signal type
@ -112,7 +112,7 @@ void InquireNotification(Service::Interface* self) {
* 8 : Output parameter buffer ptr * 8 : Output parameter buffer ptr
*/ */
void ReceiveParameter(Service::Interface* self) { void ReceiveParameter(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
u32 app_id = cmd_buff[1]; u32 app_id = cmd_buff[1];
u32 buffer_size = cmd_buff[2]; u32 buffer_size = cmd_buff[2];
cmd_buff[1] = 0; // No error cmd_buff[1] = 0; // No error
@ -143,7 +143,7 @@ void ReceiveParameter(Service::Interface* self) {
* 8 : Output parameter buffer ptr * 8 : Output parameter buffer ptr
*/ */
void GlanceParameter(Service::Interface* self) { void GlanceParameter(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
u32 app_id = cmd_buff[1]; u32 app_id = cmd_buff[1];
u32 buffer_size = cmd_buff[2]; 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 * 1 : Result of function, 0 on success, otherwise error code
*/ */
void AppletUtility(Service::Interface* self) { 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. // These are from 3dbrew - I'm not really sure what they're used for.
u32 unk = cmd_buff[1]; u32 unk = cmd_buff[1];
@ -196,7 +196,7 @@ void AppletUtility(Service::Interface* self) {
void GetSharedFont(Service::Interface* self) { void GetSharedFont(Service::Interface* self) {
LOG_TRACE(Kernel_SVC, "called"); LOG_TRACE(Kernel_SVC, "called");
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
if (!shared_font.empty()) { if (!shared_font.empty()) {
// TODO(bunnei): This function shouldn't copy the shared font every time it's called. // TODO(bunnei): This function shouldn't copy the shared font every time it's called.

View File

@ -52,7 +52,7 @@ static const std::array<u16, 187> country_codes = {
* 2 : Country's 2-char string * 2 : Country's 2-char string
*/ */
static void GetCountryCodeString(Service::Interface* self) { static void GetCountryCodeString(Service::Interface* self) {
u32* cmd_buffer = Service::GetCommandBuffer(); u32* cmd_buffer = Kernel::GetCommandBuffer();
u32 country_code_id = cmd_buffer[1]; u32 country_code_id = cmd_buffer[1];
if (country_code_id >= country_codes.size() || 0 == country_codes[country_code_id]) { 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 * 2 : Country Code ID
*/ */
static void GetCountryCodeID(Service::Interface* self) { 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 = cmd_buffer[1];
u16 country_code_id = 0; u16 country_code_id = 0;

View File

@ -25,7 +25,7 @@ static Handle interrupt_event;
* 2 : (inaddr << 1) + 0x1FF40000 (where 0x1FF00000 is the DSP RAM address) * 2 : (inaddr << 1) + 0x1FF40000 (where 0x1FF00000 is the DSP RAM address)
*/ */
void ConvertProcessAddressFromDspDram(Service::Interface* self) { void ConvertProcessAddressFromDspDram(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
u32 addr = cmd_buff[1]; u32 addr = cmd_buff[1];
@ -48,7 +48,7 @@ void ConvertProcessAddressFromDspDram(Service::Interface* self) {
* 2 : Component loaded, 0 on not loaded, 1 on loaded * 2 : Component loaded, 0 on not loaded, 1 on loaded
*/ */
void LoadComponent(Service::Interface* self) { void LoadComponent(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
cmd_buff[1] = 0; // No error cmd_buff[1] = 0; // No error
cmd_buff[2] = 1; // Pretend that we actually loaded the DSP firmware 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 * 3 : Semaphore event handle
*/ */
void GetSemaphoreEventHandle(Service::Interface* self) { void GetSemaphoreEventHandle(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
cmd_buff[1] = 0; // No error cmd_buff[1] = 0; // No error
cmd_buff[3] = semaphore_event; // Event handle 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 * 1 : Result of function, 0 on success, otherwise error code
*/ */
void RegisterInterruptEvents(Service::Interface* self) { void RegisterInterruptEvents(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
interrupt_event = static_cast<Handle>(cmd_buff[4]); 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 * 1 : Result of function, 0 on success, otherwise error code
*/ */
void WriteReg0x10(Service::Interface* self) { void WriteReg0x10(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
Kernel::SignalEvent(interrupt_event); Kernel::SignalEvent(interrupt_event);
@ -121,7 +121,7 @@ void WriteReg0x10(Service::Interface* self) {
* 2 : Number of bytes read from pipe * 2 : Number of bytes read from pipe
*/ */
void ReadPipeIfPossible(Service::Interface* self) { 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 u32 size = cmd_buff[3] & 0xFFFF;// Lower 16 bits are size
VAddr addr = cmd_buff[0x41]; VAddr addr = cmd_buff[0x41];

View File

@ -17,7 +17,7 @@
namespace FS_User { namespace FS_User {
static void Initialize(Service::Interface* self) { 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 // TODO(Link Mauve): check the behavior when cmd_buff[1] isn't 32, as per
// http://3dbrew.org/wiki/FS:Initialize#Request // http://3dbrew.org/wiki/FS:Initialize#Request
@ -43,7 +43,7 @@ static void Initialize(Service::Interface* self) {
* 3 : File handle * 3 : File handle
*/ */
static void OpenFile(Service::Interface* self) { 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 // 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. // 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 * 3 : File handle
*/ */
static void OpenFileDirectly(Service::Interface* self) { 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 archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[2]);
auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]); 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 * 1 : Result of function, 0 on success, otherwise error code
*/ */
void DeleteFile(Service::Interface* self) { 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 // 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. // 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 * 1 : Result of function, 0 on success, otherwise error code
*/ */
void RenameFile(Service::Interface* self) { 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 // 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. // 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 * 1 : Result of function, 0 on success, otherwise error code
*/ */
void DeleteDirectory(Service::Interface* self) { 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 // 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. // 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 * 1 : Result of function, 0 on success, otherwise error code
*/ */
static void CreateDirectory(Service::Interface* self) { 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 // 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. // 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 * 1 : Result of function, 0 on success, otherwise error code
*/ */
void RenameDirectory(Service::Interface* self) { 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 // 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. // 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) { 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 // 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. // 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) * 3 : Archive handle upper word (same as file handle)
*/ */
static void OpenArchive(Service::Interface* self) { 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 archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[1]);
auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]); 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 * 2 : Whether the Sdmc could be detected
*/ */
static void IsSdmcDetected(Service::Interface* self) { static void IsSdmcDetected(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
cmd_buff[1] = 0; cmd_buff[1] = 0;
cmd_buff[2] = Settings::values.use_virtual_sd ? 1 : 0; cmd_buff[2] = Settings::values.use_virtual_sd ? 1 : 0;

View File

@ -72,7 +72,7 @@ static void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) {
/// Write a GSP GPU hardware register /// Write a GSP GPU hardware register
static void WriteHWRegs(Service::Interface* self) { static void WriteHWRegs(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
u32 reg_addr = cmd_buff[1]; u32 reg_addr = cmd_buff[1];
u32 size = cmd_buff[2]; u32 size = cmd_buff[2];
@ -83,7 +83,7 @@ static void WriteHWRegs(Service::Interface* self) {
/// Read a GSP GPU hardware register /// Read a GSP GPU hardware register
static void ReadHWRegs(Service::Interface* self) { static void ReadHWRegs(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
u32 reg_addr = cmd_buff[1]; u32 reg_addr = cmd_buff[1];
u32 size = cmd_buff[2]; u32 size = cmd_buff[2];
@ -136,7 +136,7 @@ static void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) {
* 1: Result code * 1: Result code
*/ */
static void SetBufferSwap(Service::Interface* self) { static void SetBufferSwap(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
u32 screen_id = cmd_buff[1]; u32 screen_id = cmd_buff[1];
FrameBufferInfo* fb_info = (FrameBufferInfo*)&cmd_buff[2]; FrameBufferInfo* fb_info = (FrameBufferInfo*)&cmd_buff[2];
SetBufferSwap(screen_id, *fb_info); SetBufferSwap(screen_id, *fb_info);
@ -155,7 +155,7 @@ static void SetBufferSwap(Service::Interface* self) {
* 4 : Handle to GSP shared memory * 4 : Handle to GSP shared memory
*/ */
static void RegisterInterruptRelayQueue(Service::Interface* self) { static void RegisterInterruptRelayQueue(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
u32 flags = cmd_buff[1]; u32 flags = cmd_buff[1];
g_interrupt_event = cmd_buff[3]; g_interrupt_event = cmd_buff[3];
g_shared_memory = Kernel::CreateSharedMemory("GSPSharedMem"); 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 cmd_buff[1] = 0; // No error
} }

View File

@ -153,7 +153,7 @@ void PadUpdateComplete() {
* 8 : Event signaled by HID_User * 8 : Event signaled by HID_User
*/ */
static void GetIPCHandles(Service::Interface* self) { static void GetIPCHandles(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
cmd_buff[1] = 0; // No error cmd_buff[1] = 0; // No error
cmd_buff[3] = shared_mem; cmd_buff[3] = shared_mem;

View File

@ -34,7 +34,7 @@ static bool battery_is_charging = true;
* 2 : Output of function, 0 = not charging, 1 = charging. * 2 : Output of function, 0 = not charging, 1 = charging.
*/ */
static void GetAdapterState(Service::Interface* self) { static void GetAdapterState(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
// TODO(purpasmart96): This function is only a stub, // TODO(purpasmart96): This function is only a stub,
// it returns a valid result without implementing full functionality. // 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) * 2 : Whether the 3DS's physical shell casing is open (1) or closed (0)
*/ */
static void GetShellState(Service::Interface* self) { static void GetShellState(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
cmd_buff[1] = 0; cmd_buff[1] = 0;
cmd_buff[2] = shell_open ? 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. * 3 = half full battery, 2 = low battery, 1 = critical battery.
*/ */
static void GetBatteryLevel(Service::Interface* self) { static void GetBatteryLevel(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
// TODO(purpasmart96): This function is only a stub, // TODO(purpasmart96): This function is only a stub,
// it returns a valid result without implementing full functionality. // 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. * 2 : Output of function, 0 = not charging, 1 = charging.
*/ */
static void GetBatteryChargeState(Service::Interface* self) { static void GetBatteryChargeState(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
// TODO(purpasmart96): This function is only a stub, // TODO(purpasmart96): This function is only a stub,
// it returns a valid result without implementing full functionality. // it returns a valid result without implementing full functionality.

View File

@ -14,6 +14,7 @@
#include "core/mem_map.h" #include "core/mem_map.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/session.h"
#include "core/hle/svc.h" #include "core/hle/svc.h"
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
@ -21,30 +22,19 @@
namespace Service { namespace Service {
static const int kMaxPortSize = 0x08; ///< Maximum size of a port name (8 characters) static const int kMaxPortSize = 8; ///< 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);
}
class Manager; class Manager;
/// Interface to a CTROS service /// 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; friend class Manager;
public: public:
std::string GetName() const override { return GetPortName(); } 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*); typedef void (*Function)(Interface*);
@ -77,7 +67,7 @@ public:
} }
ResultVal<bool> SyncRequest() override { ResultVal<bool> SyncRequest() override {
u32* cmd_buff = GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
auto itr = m_functions.find(cmd_buff[0]); auto itr = m_functions.find(cmd_buff[0]);
if (itr == m_functions.end() || itr->second.func == nullptr) { if (itr == m_functions.end() || itr->second.func == nullptr) {

View File

@ -16,7 +16,7 @@ static Handle g_event_handle = 0;
static void Initialize(Service::Interface* self) { static void Initialize(Service::Interface* self) {
LOG_DEBUG(Service_SRV, "called"); LOG_DEBUG(Service_SRV, "called");
u32* cmd_buff = Service::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
cmd_buff[1] = 0; // No error cmd_buff[1] = 0; // No error
} }
@ -24,7 +24,7 @@ static void Initialize(Service::Interface* self) {
static void GetProcSemaphore(Service::Interface* self) { static void GetProcSemaphore(Service::Interface* self) {
LOG_TRACE(Service_SRV, "called"); 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 // TODO(bunnei): Change to a semaphore once these have been implemented
g_event_handle = Kernel::CreateEvent(RESETTYPE_ONESHOT, "SRV:Event"); 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) { static void GetServiceHandle(Service::Interface* self) {
ResultCode res = RESULT_SUCCESS; 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); std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize);
Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); Service::Interface* service = Service::g_manager->FetchFromPortName(port_name);

View File

@ -88,17 +88,14 @@ static Result ConnectToPort(Handle* out, const char* port_name) {
/// Synchronize to an OS service /// Synchronize to an OS service
static Result SendSyncRequest(Handle handle) { static Result SendSyncRequest(Handle handle) {
// TODO(yuriks): ObjectPool::Get tries to check the Object type, which fails since this is a generic base Object, Kernel::Session* session = Kernel::g_object_pool.Get<Kernel::Session>(handle);
// so we are forced to use GetFast and manually verify the handle. if (session == nullptr) {
if (!Kernel::g_object_pool.IsValid(handle)) {
return InvalidHandle(ErrorModule::Kernel).raw; 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, session->GetName().c_str());
LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, object->GetTypeName().c_str());
ResultVal<bool> wait = object->SyncRequest(); ResultVal<bool> wait = session->SyncRequest();
if (wait.Succeeded() && *wait) { if (wait.Succeeded() && *wait) {
Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct?
} }