Implemented INotificationService
This commit is contained in:
parent
221996a194
commit
e49ae3bf92
|
@ -272,6 +272,7 @@ add_library(core STATIC
|
||||||
hle/service/filesystem/fsp_srv.h
|
hle/service/filesystem/fsp_srv.h
|
||||||
hle/service/fgm/fgm.cpp
|
hle/service/fgm/fgm.cpp
|
||||||
hle/service/fgm/fgm.h
|
hle/service/fgm/fgm.h
|
||||||
|
hle/service/friend/errors.h
|
||||||
hle/service/friend/friend.cpp
|
hle/service/friend/friend.cpp
|
||||||
hle/service/friend/friend.h
|
hle/service/friend/friend.h
|
||||||
hle/service/friend/interface.cpp
|
hle/service/friend/interface.cpp
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright 2018 yuzu emulator team
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/result.h"
|
||||||
|
|
||||||
|
namespace Service::Friend {
|
||||||
|
|
||||||
|
constexpr ResultCode ERR_NO_NOTIFICATIONS{ErrorModule::Account, 15};
|
||||||
|
}
|
|
@ -2,8 +2,13 @@
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
#include "common/uuid.h"
|
||||||
#include "core/hle/ipc_helpers.h"
|
#include "core/hle/ipc_helpers.h"
|
||||||
|
#include "core/hle/kernel/readable_event.h"
|
||||||
|
#include "core/hle/kernel/writable_event.h"
|
||||||
|
#include "core/hle/service/friend/errors.h"
|
||||||
#include "core/hle/service/friend/friend.h"
|
#include "core/hle/service/friend/friend.h"
|
||||||
#include "core/hle/service/friend/interface.h"
|
#include "core/hle/service/friend/interface.h"
|
||||||
|
|
||||||
|
@ -109,6 +114,103 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class INotificationService final : public ServiceFramework<INotificationService> {
|
||||||
|
public:
|
||||||
|
INotificationService(Common::UUID uuid) : ServiceFramework("INotificationService"), uuid(uuid) {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &INotificationService::GetEvent, "GetEvent"},
|
||||||
|
{1, &INotificationService::Clear, "Clear"},
|
||||||
|
{2, &INotificationService::Pop, "Pop"}
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void GetEvent(Kernel::HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_ACC, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
|
||||||
|
if (is_event_created) {
|
||||||
|
rb.PushCopyObjects(notification_event.readable);
|
||||||
|
} else {
|
||||||
|
auto& kernel = Core::System::GetInstance().Kernel();
|
||||||
|
notification_event = Kernel::WritableEvent::CreateEventPair(
|
||||||
|
kernel, Kernel::ResetType::Manual, "INotificationService:NotifyEvent");
|
||||||
|
is_event_created = true;
|
||||||
|
rb.PushCopyObjects(notification_event.readable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear(Kernel::HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_ACC, "called");
|
||||||
|
while (!notifications.empty()) {
|
||||||
|
notifications.pop();
|
||||||
|
}
|
||||||
|
states.has_recieved_friend_request = false;
|
||||||
|
states.has_updated_friends = false;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pop(Kernel::HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_ACC, "called");
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
|
||||||
|
if (notifications.empty()) {
|
||||||
|
LOG_ERROR(Service_ACC, "No notifications in queue!");
|
||||||
|
rb.Push(ERR_NO_NOTIFICATIONS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto notification = notifications.front();
|
||||||
|
notifications.pop();
|
||||||
|
|
||||||
|
switch (notification.notification_type) {
|
||||||
|
case NotificationTypes::HasUpdatedFriendsList:
|
||||||
|
states.has_updated_friends = false;
|
||||||
|
break;
|
||||||
|
case NotificationTypes::HasRecievedFriendRequest:
|
||||||
|
states.has_recieved_friend_request = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// HOS seems not have an error case for an unknown notification
|
||||||
|
LOG_WARNING(Service_ACC, "Unknown notification {:08X}",
|
||||||
|
static_cast<u32>(notification.notification_type));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class NotificationTypes : u32_le {
|
||||||
|
HasUpdatedFriendsList = 0x65,
|
||||||
|
HasRecievedFriendRequest = 0x1
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SizedNotificationInfo {
|
||||||
|
NotificationTypes notification_type;
|
||||||
|
INSERT_PADDING_WORDS(
|
||||||
|
1); // TODO(ogniK): This doesn't seem to be used within any IPC returns as of now
|
||||||
|
Common::UUID user_uuid;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct States {
|
||||||
|
bool has_updated_friends;
|
||||||
|
bool has_recieved_friend_request;
|
||||||
|
};
|
||||||
|
|
||||||
|
Common::UUID uuid{};
|
||||||
|
bool is_event_created = false;
|
||||||
|
Kernel::EventPair notification_event;
|
||||||
|
std::queue<SizedNotificationInfo> notifications{};
|
||||||
|
States states{};
|
||||||
|
};
|
||||||
|
|
||||||
void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
@ -116,6 +218,16 @@ void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_ACC, "called");
|
LOG_DEBUG(Service_ACC, "called");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Module::Interface::CreateNotificationService(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
auto uuid = rp.PopRaw<Common::UUID>();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.PushIpcInterface<INotificationService>(uuid);
|
||||||
|
LOG_DEBUG(Service_ACC, "called");
|
||||||
|
}
|
||||||
|
|
||||||
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
|
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
|
||||||
: ServiceFramework(name), module(std::move(module)) {}
|
: ServiceFramework(name), module(std::move(module)) {}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ public:
|
||||||
~Interface() override;
|
~Interface() override;
|
||||||
|
|
||||||
void CreateFriendService(Kernel::HLERequestContext& ctx);
|
void CreateFriendService(Kernel::HLERequestContext& ctx);
|
||||||
|
void CreateNotificationService(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<Module> module;
|
std::shared_ptr<Module> module;
|
||||||
|
|
|
@ -10,7 +10,7 @@ Friend::Friend(std::shared_ptr<Module> module, const char* name)
|
||||||
: Interface(std::move(module), name) {
|
: Interface(std::move(module), name) {
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &Friend::CreateFriendService, "CreateFriendService"},
|
{0, &Friend::CreateFriendService, "CreateFriendService"},
|
||||||
{1, nullptr, "CreateNotificationService"},
|
{1, &Friend::CreateNotificationService, "CreateNotificationService"},
|
||||||
{2, nullptr, "CreateDaemonSuspendSessionService"},
|
{2, nullptr, "CreateDaemonSuspendSessionService"},
|
||||||
};
|
};
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
|
|
Reference in New Issue