-
Notifications
You must be signed in to change notification settings - Fork 2.6k
/
STM.cpp
119 lines (98 loc) · 3.09 KB
/
STM.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Copyright 2016 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "Core/IOS/STM/STM.h"
#include <functional>
#include <memory>
#include "Common/ChunkFile.h"
#include "Common/Logging/Log.h"
#include "Core/Core.h"
#include "Core/HW/Memmap.h"
namespace IOS::HLE
{
static std::unique_ptr<IOCtlRequest> s_event_hook_request;
std::optional<IPCReply> STMImmediateDevice::IOCtl(const IOCtlRequest& request)
{
s32 return_value = IPC_SUCCESS;
switch (request.request)
{
case IOCTL_STM_IDLE:
case IOCTL_STM_SHUTDOWN:
NOTICE_LOG_FMT(IOS_STM, "IOCTL_STM_IDLE or IOCTL_STM_SHUTDOWN received, shutting down");
Core::QueueHostJob(&Core::Stop, false);
break;
case IOCTL_STM_RELEASE_EH:
if (!s_event_hook_request)
{
return_value = IPC_ENOENT;
break;
}
Memory::Write_U32(0, s_event_hook_request->buffer_out);
m_ios.EnqueueIPCReply(*s_event_hook_request, IPC_SUCCESS);
s_event_hook_request.reset();
break;
case IOCTL_STM_HOTRESET:
INFO_LOG_FMT(IOS_STM, "{} - IOCtl:", GetDeviceName());
INFO_LOG_FMT(IOS_STM, " IOCTL_STM_HOTRESET");
break;
case IOCTL_STM_VIDIMMING: // (Input: 20 bytes, Output: 20 bytes)
INFO_LOG_FMT(IOS_STM, "{} - IOCtl:", GetDeviceName());
INFO_LOG_FMT(IOS_STM, " IOCTL_STM_VIDIMMING");
// Memory::Write_U32(1, buffer_out);
// return_value = 1;
break;
case IOCTL_STM_LEDMODE: // (Input: 20 bytes, Output: 20 bytes)
INFO_LOG_FMT(IOS_STM, "{} - IOCtl:", GetDeviceName());
INFO_LOG_FMT(IOS_STM, " IOCTL_STM_LEDMODE");
break;
default:
request.DumpUnknown(GetDeviceName(), Common::Log::LogType::IOS_STM);
}
return IPCReply(return_value);
}
STMEventHookDevice::~STMEventHookDevice()
{
s_event_hook_request.reset();
}
std::optional<IPCReply> STMEventHookDevice::IOCtl(const IOCtlRequest& request)
{
if (request.request != IOCTL_STM_EVENTHOOK)
return IPCReply(IPC_EINVAL);
if (s_event_hook_request)
return IPCReply(IPC_EEXIST);
// IOCTL_STM_EVENTHOOK waits until the reset button or power button is pressed.
s_event_hook_request = std::make_unique<IOCtlRequest>(request.address);
return std::nullopt;
}
void STMEventHookDevice::DoState(PointerWrap& p)
{
u32 address = s_event_hook_request ? s_event_hook_request->address : 0;
p.Do(address);
if (address != 0)
s_event_hook_request = std::make_unique<IOCtlRequest>(address);
else
s_event_hook_request.reset();
Device::DoState(p);
}
bool STMEventHookDevice::HasHookInstalled() const
{
return s_event_hook_request != nullptr;
}
void STMEventHookDevice::TriggerEvent(const u32 event) const
{
// If the device isn't open, ignore the button press.
if (!m_is_active || !s_event_hook_request)
return;
Memory::Write_U32(event, s_event_hook_request->buffer_out);
m_ios.EnqueueIPCReply(*s_event_hook_request, IPC_SUCCESS);
s_event_hook_request.reset();
}
void STMEventHookDevice::ResetButton() const
{
// The reset button triggers STM_EVENT_RESET.
TriggerEvent(STM_EVENT_RESET);
}
void STMEventHookDevice::PowerButton() const
{
TriggerEvent(STM_EVENT_POWER);
}
} // namespace IOS::HLE