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/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 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
 | 
			
		||||
// 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,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) {
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
@ -116,6 +218,16 @@ 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>();
 | 
			
		||||
 | 
			
		||||
    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)
 | 
			
		||||
    : 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