Merge pull request #2604 from ogniK5377/INotificationService
Implemented INotificationService
This commit is contained in:
		
						commit
						58032e0085
					
				| @ -270,6 +270,7 @@ add_library(core STATIC | ||||
|     hle/service/filesystem/fsp_srv.h | ||||
|     hle/service/fgm/fgm.cpp | ||||
|     hle/service/fgm/fgm.h | ||||
|     hle/service/friend/errors.h | ||||
|     hle/service/friend/friend.cpp | ||||
|     hle/service/friend/friend.h | ||||
|     hle/service/friend/interface.cpp | ||||
|  | ||||
							
								
								
									
										12
									
								
								src/core/hle/service/friend/errors.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/core/hle/service/friend/errors.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| // Copyright 2019 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
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <queue> | ||||
| #include "common/logging/log.h" | ||||
| #include "common/uuid.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/interface.h" | ||||
| 
 | ||||
| @ -109,6 +114,105 @@ 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) { | ||||
|             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(); | ||||
|         } | ||||
|         std::memset(&states, 0, sizeof(States)); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|     } | ||||
| 
 | ||||
|     void Pop(Kernel::HLERequestContext& ctx) { | ||||
|         LOG_DEBUG(Service_ACC, "called"); | ||||
| 
 | ||||
|         if (notifications.empty()) { | ||||
|             LOG_ERROR(Service_ACC, "No notifications in queue!"); | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(ERR_NO_NOTIFICATIONS); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const auto notification = notifications.front(); | ||||
|         notifications.pop(); | ||||
| 
 | ||||
|         switch (notification.notification_type) { | ||||
|         case NotificationTypes::HasUpdatedFriendsList: | ||||
|             states.has_updated_friends = false; | ||||
|             break; | ||||
|         case NotificationTypes::HasReceivedFriendRequest: | ||||
|             states.has_received_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; | ||||
|         } | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 6}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|         rb.PushRaw<SizedNotificationInfo>(notification); | ||||
|     } | ||||
| 
 | ||||
|     enum class NotificationTypes : u32 { | ||||
|         HasUpdatedFriendsList = 0x65, | ||||
|         HasReceivedFriendRequest = 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
 | ||||
|         u64_le account_id; | ||||
|     }; | ||||
|     static_assert(sizeof(SizedNotificationInfo) == 0x10, | ||||
|                   "SizedNotificationInfo is an incorrect size"); | ||||
| 
 | ||||
|     struct States { | ||||
|         bool has_updated_friends; | ||||
|         bool has_received_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) { | ||||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
| @ -116,6 +220,17 @@ void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_ACC, "called"); | ||||
| } | ||||
| 
 | ||||
| void Module::Interface::CreateNotificationService(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     auto uuid = rp.PopRaw<Common::UUID>(); | ||||
| 
 | ||||
|     LOG_DEBUG(Service_ACC, "called, uuid={}", uuid.Format()); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.PushIpcInterface<INotificationService>(uuid); | ||||
| } | ||||
| 
 | ||||
| Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) | ||||
|     : ServiceFramework(name), module(std::move(module)) {} | ||||
| 
 | ||||
|  | ||||
| @ -16,6 +16,7 @@ public: | ||||
|         ~Interface() override; | ||||
| 
 | ||||
|         void CreateFriendService(Kernel::HLERequestContext& ctx); | ||||
|         void CreateNotificationService(Kernel::HLERequestContext& ctx); | ||||
| 
 | ||||
|     protected: | ||||
|         std::shared_ptr<Module> module; | ||||
|  | ||||
| @ -10,7 +10,7 @@ Friend::Friend(std::shared_ptr<Module> module, const char* name) | ||||
|     : Interface(std::move(module), name) { | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {0, &Friend::CreateFriendService, "CreateFriendService"}, | ||||
|         {1, nullptr, "CreateNotificationService"}, | ||||
|         {1, &Friend::CreateNotificationService, "CreateNotificationService"}, | ||||
|         {2, nullptr, "CreateDaemonSuspendSessionService"}, | ||||
|     }; | ||||
|     RegisterHandlers(functions); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 bunnei
						bunnei