diff options
| -rw-r--r-- | src/common/logging/backend.cpp | 1 | ||||
| -rw-r--r-- | src/common/logging/log.h | 1 | ||||
| -rw-r--r-- | src/core/hle/service/mic_u.cpp | 322 | ||||
| -rw-r--r-- | src/core/hle/service/mic_u.h | 1 |
4 files changed, 309 insertions, 16 deletions
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 88209081d..7fd397fe5 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp | |||
| @@ -43,6 +43,7 @@ namespace Log { | |||
| 43 | SUB(Service, AM) \ | 43 | SUB(Service, AM) \ |
| 44 | SUB(Service, PTM) \ | 44 | SUB(Service, PTM) \ |
| 45 | SUB(Service, LDR) \ | 45 | SUB(Service, LDR) \ |
| 46 | SUB(Service, MIC) \ | ||
| 46 | SUB(Service, NDM) \ | 47 | SUB(Service, NDM) \ |
| 47 | SUB(Service, NIM) \ | 48 | SUB(Service, NIM) \ |
| 48 | SUB(Service, NWM) \ | 49 | SUB(Service, NWM) \ |
diff --git a/src/common/logging/log.h b/src/common/logging/log.h index 8d3a2d03e..8011534b8 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h | |||
| @@ -60,6 +60,7 @@ enum class Class : ClassType { | |||
| 60 | Service_AM, ///< The AM (Application manager) service | 60 | Service_AM, ///< The AM (Application manager) service |
| 61 | Service_PTM, ///< The PTM (Power status & misc.) service | 61 | Service_PTM, ///< The PTM (Power status & misc.) service |
| 62 | Service_LDR, ///< The LDR (3ds dll loader) service | 62 | Service_LDR, ///< The LDR (3ds dll loader) service |
| 63 | Service_MIC, ///< The MIC (microphone) service | ||
| 63 | Service_NDM, ///< The NDM (Network daemon manager) service | 64 | Service_NDM, ///< The NDM (Network daemon manager) service |
| 64 | Service_NIM, ///< The NIM (Network interface manager) service | 65 | Service_NIM, ///< The NIM (Network interface manager) service |
| 65 | Service_NWM, ///< The NWM (Network wlan manager) service | 66 | Service_NWM, ///< The NWM (Network wlan manager) service |
diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp index edd1ea97b..563341504 100644 --- a/src/core/hle/service/mic_u.cpp +++ b/src/core/hle/service/mic_u.cpp | |||
| @@ -2,6 +2,9 @@ | |||
| 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 "common/logging/log.h" | ||
| 6 | #include "core/hle/kernel/event.h" | ||
| 7 | #include "core/hle/kernel/shared_memory.h" | ||
| 5 | #include "core/hle/service/mic_u.h" | 8 | #include "core/hle/service/mic_u.h" |
| 6 | 9 | ||
| 7 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 10 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -9,23 +12,298 @@ | |||
| 9 | 12 | ||
| 10 | namespace MIC_U { | 13 | namespace MIC_U { |
| 11 | 14 | ||
| 15 | enum class Encoding : u8 { | ||
| 16 | PCM8 = 0, | ||
| 17 | PCM16 = 1, | ||
| 18 | PCM8Signed = 2, | ||
| 19 | PCM16Signed = 3, | ||
| 20 | }; | ||
| 21 | |||
| 22 | enum class SampleRate : u8 { | ||
| 23 | SampleRate32730 = 0, | ||
| 24 | SampleRate16360 = 1, | ||
| 25 | SampleRate10910 = 2, | ||
| 26 | SampleRate8180 = 3 | ||
| 27 | }; | ||
| 28 | |||
| 29 | static Kernel::SharedPtr<Kernel::Event> buffer_full_event; | ||
| 30 | static Kernel::SharedPtr<Kernel::SharedMemory> shared_memory; | ||
| 31 | static u8 mic_gain = 0; | ||
| 32 | static bool mic_power = false; | ||
| 33 | static bool is_sampling = false; | ||
| 34 | static bool allow_shell_closed; | ||
| 35 | static bool clamp = false; | ||
| 36 | static Encoding encoding; | ||
| 37 | static SampleRate sample_rate; | ||
| 38 | static s32 audio_buffer_offset; | ||
| 39 | static u32 audio_buffer_size; | ||
| 40 | static bool audio_buffer_loop; | ||
| 41 | |||
| 42 | /** | ||
| 43 | * MIC::MapSharedMem service function | ||
| 44 | * Inputs: | ||
| 45 | * 0 : Header Code[0x00010042] | ||
| 46 | * 1 : Shared-mem size | ||
| 47 | * 2 : CopyHandleDesc | ||
| 48 | * 3 : Shared-mem handle | ||
| 49 | * Outputs: | ||
| 50 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 51 | */ | ||
| 52 | static void MapSharedMem(Service::Interface* self) { | ||
| 53 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 54 | u32 size = cmd_buff[1]; | ||
| 55 | Handle mem_handle = cmd_buff[3]; | ||
| 56 | shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(mem_handle); | ||
| 57 | if (shared_memory) { | ||
| 58 | shared_memory->name = "MIC_U:shared_memory"; | ||
| 59 | } | ||
| 60 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | ||
| 61 | LOG_WARNING(Service_MIC, "called, size=0x%X, mem_handle=0x%08X", size, mem_handle); | ||
| 62 | } | ||
| 63 | |||
| 64 | /** | ||
| 65 | * MIC::UnmapSharedMem service function | ||
| 66 | * Inputs: | ||
| 67 | * 0 : Header Code[0x00020000] | ||
| 68 | * Outputs: | ||
| 69 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 70 | */ | ||
| 71 | static void UnmapSharedMem(Service::Interface* self) { | ||
| 72 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 73 | |||
| 74 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | ||
| 75 | LOG_WARNING(Service_MIC, "called"); | ||
| 76 | } | ||
| 77 | |||
| 78 | /** | ||
| 79 | * MIC::StartSampling service function | ||
| 80 | * Inputs: | ||
| 81 | * 0 : Header Code[0x00030140] | ||
| 82 | * 1 : Encoding | ||
| 83 | * 2 : SampleRate | ||
| 84 | * 3 : Base offset for audio data in sharedmem | ||
| 85 | * 4 : Size of the audio data in sharedmem | ||
| 86 | * 5 : Loop at end of buffer | ||
| 87 | * Outputs: | ||
| 88 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 89 | */ | ||
| 90 | static void StartSampling(Service::Interface* self) { | ||
| 91 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 92 | |||
| 93 | encoding = static_cast<Encoding>(cmd_buff[1] & 0xFF); | ||
| 94 | sample_rate = static_cast<SampleRate>(cmd_buff[2] & 0xFF); | ||
| 95 | audio_buffer_offset = cmd_buff[3]; | ||
| 96 | audio_buffer_size = cmd_buff[4]; | ||
| 97 | audio_buffer_loop = static_cast<bool>(cmd_buff[5] & 0xFF); | ||
| 98 | |||
| 99 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | ||
| 100 | is_sampling = true; | ||
| 101 | LOG_WARNING(Service_MIC, "(STUBBED) called, encoding=%u, sample_rate=%u, " | ||
| 102 | "audio_buffer_offset=%d, audio_buffer_size=%u, audio_buffer_loop=%u", | ||
| 103 | encoding, sample_rate, audio_buffer_offset, audio_buffer_size, audio_buffer_loop); | ||
| 104 | } | ||
| 105 | |||
| 106 | /** | ||
| 107 | * MIC::AdjustSampling service function | ||
| 108 | * Inputs: | ||
| 109 | * 0 : Header Code[0x00040040] | ||
| 110 | * 1 : SampleRate | ||
| 111 | * Outputs: | ||
| 112 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 113 | */ | ||
| 114 | static void AdjustSampling(Service::Interface* self) { | ||
| 115 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 116 | sample_rate = static_cast<SampleRate>(cmd_buff[1] & 0xFF); | ||
| 117 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | ||
| 118 | LOG_WARNING(Service_MIC, "(STUBBED) called, sample_rate=%u", sample_rate); | ||
| 119 | } | ||
| 120 | |||
| 121 | /** | ||
| 122 | * MIC::StopSampling service function | ||
| 123 | * Inputs: | ||
| 124 | * 0 : Header Code[0x00050000] | ||
| 125 | * Outputs: | ||
| 126 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 127 | */ | ||
| 128 | static void StopSampling(Service::Interface* self) { | ||
| 129 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 130 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | ||
| 131 | is_sampling = false; | ||
| 132 | LOG_WARNING(Service_MIC, "(STUBBED) called"); | ||
| 133 | } | ||
| 134 | |||
| 135 | /** | ||
| 136 | * MIC::IsSampling service function | ||
| 137 | * Inputs: | ||
| 138 | * 0 : Header Code[0x00060000] | ||
| 139 | * Outputs: | ||
| 140 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 141 | * 2 : 0 = sampling, non-zero = sampling | ||
| 142 | */ | ||
| 143 | static void IsSampling(Service::Interface* self) { | ||
| 144 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 145 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | ||
| 146 | cmd_buff[2] = is_sampling; | ||
| 147 | LOG_WARNING(Service_MIC, "(STUBBED) called"); | ||
| 148 | } | ||
| 149 | |||
| 150 | /** | ||
| 151 | * MIC::GetBufferFullEvent service function | ||
| 152 | * Inputs: | ||
| 153 | * 0 : Header Code[0x00070000] | ||
| 154 | * Outputs: | ||
| 155 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 156 | * 3 : Event handle | ||
| 157 | */ | ||
| 158 | static void GetBufferFullEvent(Service::Interface* self) { | ||
| 159 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 160 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | ||
| 161 | cmd_buff[3] = Kernel::g_handle_table.Create(buffer_full_event).MoveFrom(); | ||
| 162 | LOG_WARNING(Service_MIC, "(STUBBED) called"); | ||
| 163 | } | ||
| 164 | |||
| 165 | /** | ||
| 166 | * MIC::SetGain service function | ||
| 167 | * Inputs: | ||
| 168 | * 0 : Header Code[0x00080040] | ||
| 169 | * 1 : Gain | ||
| 170 | * Outputs: | ||
| 171 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 172 | */ | ||
| 173 | static void SetGain(Service::Interface* self) { | ||
| 174 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 175 | mic_gain = cmd_buff[1] & 0xFF; | ||
| 176 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | ||
| 177 | LOG_WARNING(Service_MIC, "(STUBBED) called, mic_gain=%u", mic_gain); | ||
| 178 | } | ||
| 179 | |||
| 180 | /** | ||
| 181 | * MIC::GetGain service function | ||
| 182 | * Inputs: | ||
| 183 | * 0 : Header Code[0x00090000] | ||
| 184 | * Outputs: | ||
| 185 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 186 | * 2 : Gain | ||
| 187 | */ | ||
| 188 | static void GetGain(Service::Interface* self) { | ||
| 189 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 190 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | ||
| 191 | cmd_buff[2] = mic_gain; | ||
| 192 | LOG_WARNING(Service_MIC, "(STUBBED) called"); | ||
| 193 | } | ||
| 194 | |||
| 195 | /** | ||
| 196 | * MIC::SetPower service function | ||
| 197 | * Inputs: | ||
| 198 | * 0 : Header Code[0x000A0040] | ||
| 199 | * 1 : Power (0 = off, 1 = on) | ||
| 200 | * Outputs: | ||
| 201 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 202 | */ | ||
| 203 | static void SetPower(Service::Interface* self) { | ||
| 204 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 205 | mic_power = static_cast<bool>(cmd_buff[1] & 0xFF); | ||
| 206 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | ||
| 207 | LOG_WARNING(Service_MIC, "(STUBBED) called, mic_power=%u", mic_power); | ||
| 208 | } | ||
| 209 | |||
| 210 | /** | ||
| 211 | * MIC::GetPower service function | ||
| 212 | * Inputs: | ||
| 213 | * 0 : Header Code[0x000B0000] | ||
| 214 | * Outputs: | ||
| 215 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 216 | * 2 : Power | ||
| 217 | */ | ||
| 218 | static void GetPower(Service::Interface* self) { | ||
| 219 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 220 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | ||
| 221 | cmd_buff[2] = mic_power; | ||
| 222 | LOG_WARNING(Service_MIC, "(STUBBED) called"); | ||
| 223 | } | ||
| 224 | |||
| 225 | /** | ||
| 226 | * MIC::SetIirFilterMic service function | ||
| 227 | * Inputs: | ||
| 228 | * 0 : Header Code[0x000C0042] | ||
| 229 | * 1 : Size | ||
| 230 | * 2 : (Size << 4) | 0xA | ||
| 231 | * 3 : Pointer to IIR Filter Data | ||
| 232 | * Outputs: | ||
| 233 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 234 | */ | ||
| 235 | static void SetIirFilterMic(Service::Interface* self) { | ||
| 236 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 237 | |||
| 238 | u32 size = cmd_buff[1]; | ||
| 239 | VAddr buffer = cmd_buff[3]; | ||
| 240 | |||
| 241 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | ||
| 242 | LOG_WARNING(Service_MIC, "(STUBBED) called, size=0x%X, buffer=0x%08X", size, buffer); | ||
| 243 | } | ||
| 244 | |||
| 245 | /** | ||
| 246 | * MIC::SetClamp service function | ||
| 247 | * Inputs: | ||
| 248 | * 0 : Header Code[0x000D0040] | ||
| 249 | * 1 : Clamp (0 = don't clamp, non-zero = clamp) | ||
| 250 | * Outputs: | ||
| 251 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 252 | */ | ||
| 253 | static void SetClamp(Service::Interface* self) { | ||
| 254 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 255 | clamp = static_cast<bool>(cmd_buff[1] & 0xFF); | ||
| 256 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | ||
| 257 | LOG_WARNING(Service_MIC, "(STUBBED) called, clamp=%u", clamp); | ||
| 258 | } | ||
| 259 | |||
| 260 | /** | ||
| 261 | * MIC::GetClamp service function | ||
| 262 | * Inputs: | ||
| 263 | * 0 : Header Code[0x000E0000] | ||
| 264 | * Outputs: | ||
| 265 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 266 | * 2 : Clamp (0 = don't clamp, non-zero = clamp) | ||
| 267 | */ | ||
| 268 | static void GetClamp(Service::Interface* self) { | ||
| 269 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 270 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | ||
| 271 | cmd_buff[2] = clamp; | ||
| 272 | LOG_WARNING(Service_MIC, "(STUBBED) called"); | ||
| 273 | } | ||
| 274 | |||
| 275 | /** | ||
| 276 | * MIC::SetAllowShellClosed service function | ||
| 277 | * Inputs: | ||
| 278 | * 0 : Header Code[0x000D0040] | ||
| 279 | * 1 : Sampling allowed while shell closed (0 = disallow, non-zero = allow) | ||
| 280 | * Outputs: | ||
| 281 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 282 | */ | ||
| 283 | static void SetAllowShellClosed(Service::Interface* self) { | ||
| 284 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 285 | allow_shell_closed = static_cast<bool>(cmd_buff[1] & 0xFF); | ||
| 286 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | ||
| 287 | LOG_WARNING(Service_MIC, "(STUBBED) called, allow_shell_closed=%u", allow_shell_closed); | ||
| 288 | } | ||
| 289 | |||
| 12 | const Interface::FunctionInfo FunctionTable[] = { | 290 | const Interface::FunctionInfo FunctionTable[] = { |
| 13 | {0x00010042, nullptr, "MapSharedMem"}, | 291 | {0x00010042, MapSharedMem, "MapSharedMem"}, |
| 14 | {0x00020000, nullptr, "UnmapSharedMem"}, | 292 | {0x00020000, UnmapSharedMem, "UnmapSharedMem"}, |
| 15 | {0x00030140, nullptr, "Initialize"}, | 293 | {0x00030140, StartSampling, "StartSampling"}, |
| 16 | {0x00040040, nullptr, "AdjustSampling"}, | 294 | {0x00040040, AdjustSampling, "AdjustSampling"}, |
| 17 | {0x00050000, nullptr, "StopSampling"}, | 295 | {0x00050000, StopSampling, "StopSampling"}, |
| 18 | {0x00060000, nullptr, "IsSampling"}, | 296 | {0x00060000, IsSampling, "IsSampling"}, |
| 19 | {0x00070000, nullptr, "GetEventHandle"}, | 297 | {0x00070000, GetBufferFullEvent, "GetBufferFullEvent"}, |
| 20 | {0x00080040, nullptr, "SetGain"}, | 298 | {0x00080040, SetGain, "SetGain"}, |
| 21 | {0x00090000, nullptr, "GetGain"}, | 299 | {0x00090000, GetGain, "GetGain"}, |
| 22 | {0x000A0040, nullptr, "SetPower"}, | 300 | {0x000A0040, SetPower, "SetPower"}, |
| 23 | {0x000B0000, nullptr, "GetPower"}, | 301 | {0x000B0000, GetPower, "GetPower"}, |
| 24 | {0x000C0042, nullptr, "size"}, | 302 | {0x000C0042, SetIirFilterMic, "SetIirFilterMic"}, |
| 25 | {0x000D0040, nullptr, "SetClamp"}, | 303 | {0x000D0040, SetClamp, "SetClamp"}, |
| 26 | {0x000E0000, nullptr, "GetClamp"}, | 304 | {0x000E0000, GetClamp, "GetClamp"}, |
| 27 | {0x000F0040, nullptr, "SetAllowShellClosed"}, | 305 | {0x000F0040, SetAllowShellClosed, "SetAllowShellClosed"}, |
| 28 | {0x00100040, nullptr, "unknown_input2"}, | 306 | {0x00100040, nullptr, "SetClientSDKVersion"}, |
| 29 | }; | 307 | }; |
| 30 | 308 | ||
| 31 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 309 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -33,6 +311,18 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 33 | 311 | ||
| 34 | Interface::Interface() { | 312 | Interface::Interface() { |
| 35 | Register(FunctionTable); | 313 | Register(FunctionTable); |
| 314 | shared_memory = nullptr; | ||
| 315 | buffer_full_event = | ||
| 316 | Kernel::Event::Create(Kernel::ResetType::OneShot, "MIC_U::buffer_full_event"); | ||
| 317 | mic_gain = 0; | ||
| 318 | mic_power = false; | ||
| 319 | is_sampling = false; | ||
| 320 | clamp = false; | ||
| 321 | } | ||
| 322 | |||
| 323 | Interface::~Interface() { | ||
| 324 | shared_memory = nullptr; | ||
| 325 | buffer_full_event = nullptr; | ||
| 36 | } | 326 | } |
| 37 | 327 | ||
| 38 | } // namespace | 328 | } // namespace |
diff --git a/src/core/hle/service/mic_u.h b/src/core/hle/service/mic_u.h index dc795d14c..1cff7390e 100644 --- a/src/core/hle/service/mic_u.h +++ b/src/core/hle/service/mic_u.h | |||
| @@ -16,6 +16,7 @@ namespace MIC_U { | |||
| 16 | class Interface : public Service::Interface { | 16 | class Interface : public Service::Interface { |
| 17 | public: | 17 | public: |
| 18 | Interface(); | 18 | Interface(); |
| 19 | ~Interface(); | ||
| 19 | 20 | ||
| 20 | std::string GetPortName() const override { | 21 | std::string GetPortName() const override { |
| 21 | return "mic:u"; | 22 | return "mic:u"; |