summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/hle/service/friend/errors.h12
-rw-r--r--src/core/hle/service/friend/friend.cpp115
-rw-r--r--src/core/hle/service/friend/friend.h1
-rw-r--r--src/core/hle/service/friend/interface.cpp2
5 files changed, 130 insertions, 1 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index cb77b99ee..a35e6066a 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -270,6 +270,7 @@ add_library(core STATIC
270 hle/service/filesystem/fsp_srv.h 270 hle/service/filesystem/fsp_srv.h
271 hle/service/fgm/fgm.cpp 271 hle/service/fgm/fgm.cpp
272 hle/service/fgm/fgm.h 272 hle/service/fgm/fgm.h
273 hle/service/friend/errors.h
273 hle/service/friend/friend.cpp 274 hle/service/friend/friend.cpp
274 hle/service/friend/friend.h 275 hle/service/friend/friend.h
275 hle/service/friend/interface.cpp 276 hle/service/friend/interface.cpp
diff --git a/src/core/hle/service/friend/errors.h b/src/core/hle/service/friend/errors.h
new file mode 100644
index 000000000..b3996e275
--- /dev/null
+++ b/src/core/hle/service/friend/errors.h
@@ -0,0 +1,12 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/result.h"
8
9namespace Service::Friend {
10
11constexpr ResultCode ERR_NO_NOTIFICATIONS{ErrorModule::Account, 15};
12}
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp
index 5100e376c..dec541f2e 100644
--- a/src/core/hle/service/friend/friend.cpp
+++ b/src/core/hle/service/friend/friend.cpp
@@ -2,8 +2,13 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <queue>
5#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "common/uuid.h"
6#include "core/hle/ipc_helpers.h" 8#include "core/hle/ipc_helpers.h"
9#include "core/hle/kernel/readable_event.h"
10#include "core/hle/kernel/writable_event.h"
11#include "core/hle/service/friend/errors.h"
7#include "core/hle/service/friend/friend.h" 12#include "core/hle/service/friend/friend.h"
8#include "core/hle/service/friend/interface.h" 13#include "core/hle/service/friend/interface.h"
9 14
@@ -109,6 +114,105 @@ private:
109 } 114 }
110}; 115};
111 116
117class INotificationService final : public ServiceFramework<INotificationService> {
118public:
119 INotificationService(Common::UUID uuid) : ServiceFramework("INotificationService"), uuid(uuid) {
120 // clang-format off
121 static const FunctionInfo functions[] = {
122 {0, &INotificationService::GetEvent, "GetEvent"},
123 {1, &INotificationService::Clear, "Clear"},
124 {2, &INotificationService::Pop, "Pop"}
125 };
126 // clang-format on
127
128 RegisterHandlers(functions);
129 }
130
131private:
132 void GetEvent(Kernel::HLERequestContext& ctx) {
133 LOG_DEBUG(Service_ACC, "called");
134
135 IPC::ResponseBuilder rb{ctx, 2, 1};
136 rb.Push(RESULT_SUCCESS);
137
138 if (!is_event_created) {
139 auto& kernel = Core::System::GetInstance().Kernel();
140 notification_event = Kernel::WritableEvent::CreateEventPair(
141 kernel, Kernel::ResetType::Manual, "INotificationService:NotifyEvent");
142 is_event_created = true;
143 }
144 rb.PushCopyObjects(notification_event.readable);
145 }
146
147 void Clear(Kernel::HLERequestContext& ctx) {
148 LOG_DEBUG(Service_ACC, "called");
149 while (!notifications.empty()) {
150 notifications.pop();
151 }
152 std::memset(&states, 0, sizeof(States));
153
154 IPC::ResponseBuilder rb{ctx, 2};
155 rb.Push(RESULT_SUCCESS);
156 }
157
158 void Pop(Kernel::HLERequestContext& ctx) {
159 LOG_DEBUG(Service_ACC, "called");
160
161 if (notifications.empty()) {
162 LOG_ERROR(Service_ACC, "No notifications in queue!");
163 IPC::ResponseBuilder rb{ctx, 2};
164 rb.Push(ERR_NO_NOTIFICATIONS);
165 return;
166 }
167
168 const auto notification = notifications.front();
169 notifications.pop();
170
171 switch (notification.notification_type) {
172 case NotificationTypes::HasUpdatedFriendsList:
173 states.has_updated_friends = false;
174 break;
175 case NotificationTypes::HasReceivedFriendRequest:
176 states.has_received_friend_request = false;
177 break;
178 default:
179 // HOS seems not have an error case for an unknown notification
180 LOG_WARNING(Service_ACC, "Unknown notification {:08X}",
181 static_cast<u32>(notification.notification_type));
182 break;
183 }
184
185 IPC::ResponseBuilder rb{ctx, 6};
186 rb.Push(RESULT_SUCCESS);
187 rb.PushRaw<SizedNotificationInfo>(notification);
188 }
189
190 enum class NotificationTypes : u32 {
191 HasUpdatedFriendsList = 0x65,
192 HasReceivedFriendRequest = 0x1
193 };
194
195 struct SizedNotificationInfo {
196 NotificationTypes notification_type;
197 INSERT_PADDING_WORDS(
198 1); // TODO(ogniK): This doesn't seem to be used within any IPC returns as of now
199 u64_le account_id;
200 };
201 static_assert(sizeof(SizedNotificationInfo) == 0x10,
202 "SizedNotificationInfo is an incorrect size");
203
204 struct States {
205 bool has_updated_friends;
206 bool has_received_friend_request;
207 };
208
209 Common::UUID uuid;
210 bool is_event_created = false;
211 Kernel::EventPair notification_event;
212 std::queue<SizedNotificationInfo> notifications;
213 States states{};
214};
215
112void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) { 216void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) {
113 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 217 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
114 rb.Push(RESULT_SUCCESS); 218 rb.Push(RESULT_SUCCESS);
@@ -116,6 +220,17 @@ void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) {
116 LOG_DEBUG(Service_ACC, "called"); 220 LOG_DEBUG(Service_ACC, "called");
117} 221}
118 222
223void Module::Interface::CreateNotificationService(Kernel::HLERequestContext& ctx) {
224 IPC::RequestParser rp{ctx};
225 auto uuid = rp.PopRaw<Common::UUID>();
226
227 LOG_DEBUG(Service_ACC, "called, uuid={}", uuid.Format());
228
229 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
230 rb.Push(RESULT_SUCCESS);
231 rb.PushIpcInterface<INotificationService>(uuid);
232}
233
119Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) 234Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
120 : ServiceFramework(name), module(std::move(module)) {} 235 : ServiceFramework(name), module(std::move(module)) {}
121 236
diff --git a/src/core/hle/service/friend/friend.h b/src/core/hle/service/friend/friend.h
index e762840cb..38d05fa8e 100644
--- a/src/core/hle/service/friend/friend.h
+++ b/src/core/hle/service/friend/friend.h
@@ -16,6 +16,7 @@ public:
16 ~Interface() override; 16 ~Interface() override;
17 17
18 void CreateFriendService(Kernel::HLERequestContext& ctx); 18 void CreateFriendService(Kernel::HLERequestContext& ctx);
19 void CreateNotificationService(Kernel::HLERequestContext& ctx);
19 20
20 protected: 21 protected:
21 std::shared_ptr<Module> module; 22 std::shared_ptr<Module> module;
diff --git a/src/core/hle/service/friend/interface.cpp b/src/core/hle/service/friend/interface.cpp
index 5a6840af5..5b384f733 100644
--- a/src/core/hle/service/friend/interface.cpp
+++ b/src/core/hle/service/friend/interface.cpp
@@ -10,7 +10,7 @@ Friend::Friend(std::shared_ptr<Module> module, const char* name)
10 : Interface(std::move(module), name) { 10 : Interface(std::move(module), name) {
11 static const FunctionInfo functions[] = { 11 static const FunctionInfo functions[] = {
12 {0, &Friend::CreateFriendService, "CreateFriendService"}, 12 {0, &Friend::CreateFriendService, "CreateFriendService"},
13 {1, nullptr, "CreateNotificationService"}, 13 {1, &Friend::CreateNotificationService, "CreateNotificationService"},
14 {2, nullptr, "CreateDaemonSuspendSessionService"}, 14 {2, nullptr, "CreateDaemonSuspendSessionService"},
15 }; 15 };
16 RegisterHandlers(functions); 16 RegisterHandlers(functions);