From d2f772c960c65a632dea836abc4023f932aaf5a0 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Fri, 6 Nov 2015 22:02:37 -0800 Subject: [PATCH] Rewrite MIC service code, clean up microphone example. --- examples/audio/mic/source/main.c | 93 ++++---- libctru/include/3ds/services/mic.h | 136 +++++++----- libctru/source/services/mic.c | 345 +++++++++++++---------------- 3 files changed, 283 insertions(+), 291 deletions(-) diff --git a/examples/audio/mic/source/main.c b/examples/audio/mic/source/main.c index ca3ac65..95cb1af 100644 --- a/examples/audio/mic/source/main.c +++ b/examples/audio/mic/source/main.c @@ -6,26 +6,37 @@ int main() { - u8 *framebuf; - u32 *sharedmem = NULL, sharedmem_size = 0x30000; - u8 *audiobuf; - u32 audiobuf_size = 0x100000, audiobuf_pos = 0; - u8 control=0x40; - u32 audio_initialized = 0; - gfxInitDefault(); consoleInit(GFX_BOTTOM, NULL); - if(csndInit()==0) + bool initialized = true; + + u32 micbuf_size = 0x30000; + u32 micbuf_pos = 0; + u8* micbuf = memalign(micbuf_size, 0x1000); + + printf("Initializing CSND...\n"); + if(R_FAILED(csndInit())) { - printf("Init success\n"); - audio_initialized = 1; - } + initialized = false; + printf("Could not initialize CSND.\n"); + } else printf("CSND initialized.\n"); - sharedmem = (u32*)memalign(0x1000, sharedmem_size); - audiobuf = linearAlloc(audiobuf_size); + printf("Initializing MIC...\n"); + if(R_FAILED(micInit(micbuf, micbuf_size))) + { + initialized = false; + printf("Could not initialize MIC.\n"); + } else printf("MIC initialized.\n"); - MIC_Initialize(sharedmem, sharedmem_size, control, 0, 3, 1, 1);//See mic.h. + u32 micbuf_datasize = micGetSampleDataSize(); + + u32 audiobuf_size = 0x100000; + u32 audiobuf_pos = 0; + u8* audiobuf = linearAlloc(audiobuf_size); + + if(initialized) printf("Hold A to record, release to play.\n"); + printf("Press START to exit.\n"); while(aptMainLoop()) { @@ -36,45 +47,42 @@ int main() if (kDown & KEY_START) break; // break in order to return to hbmenu - if(audio_initialized) + if(initialized) { - framebuf = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL); - if(kDown & KEY_A) { audiobuf_pos = 0; - printf("Stopping audio playback\n"); - CSND_SetPlayState(0x8, 0);//Stop audio playback. - CSND_UpdateInfo(0); + micbuf_pos = 0; - MIC_SetRecording(1); + printf("Stopping audio playback...\n"); + CSND_SetPlayState(0x8, 0); + if(R_FAILED(CSND_UpdateInfo(0))) printf("Failed to stop audio playback.\n"); - memset(framebuf, 0x20, 0x46500); - printf("Now recording\n"); + printf("Starting sampling...\n"); + if(R_SUCCEEDED(MICU_SetPower(true)) && R_SUCCEEDED(MICU_StartSampling(MICU_ENCODING_PCM16_SIGNED, MICU_SAMPLE_RATE_16360, 0, micbuf_datasize, true))) printf("Now recording.\n"); + else printf("Failed to start sampling.\n"); } if((hidKeysHeld() & KEY_A) && audiobuf_pos < audiobuf_size) { - audiobuf_pos+= MIC_ReadAudioData(&audiobuf[audiobuf_pos], audiobuf_size-audiobuf_pos, 1); - if(audiobuf_pos > audiobuf_size)audiobuf_pos = audiobuf_size; - - memset(framebuf, 0x60, 0x46500); + u32 micbuf_readpos = micbuf_pos; + micbuf_pos = micGetLastSampleOffset(); + while(audiobuf_pos < audiobuf_size && micbuf_readpos != micbuf_pos) + { + audiobuf[audiobuf_pos] = micbuf[micbuf_readpos]; + audiobuf_pos++; + micbuf_readpos = (micbuf_readpos + 1) % micbuf_datasize; + } } if(hidKeysUp() & KEY_A) { - printf("Playing the recorded sample\n"); - MIC_SetRecording(0); - GSPGPU_FlushDataCache(NULL, audiobuf, audiobuf_pos); - csndPlaySound(0x8, SOUND_ONE_SHOT | SOUND_FORMAT_16BIT, 16000, 1.0, 0.0, (u32*)audiobuf, NULL, audiobuf_pos); + printf("Stoping sampling...\n"); + if(R_FAILED(MICU_StopSampling()) || R_FAILED(MICU_SetPower(false))) printf("Failed to stop sampling.\n"); - memset(framebuf, 0xe0, 0x46500); - - gfxFlushBuffers(); - gfxSwapBuffers(); - - framebuf = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL); - memset(framebuf, 0xe0, 0x46500); + printf("Starting audio playback...\n"); + if(R_SUCCEEDED(GSPGPU_FlushDataCache(audiobuf, audiobuf_pos)) && R_SUCCEEDED(csndPlaySound(0x8, SOUND_ONE_SHOT | SOUND_FORMAT_16BIT, 16360, 1.0, 0.0, (u32*)audiobuf, NULL, audiobuf_pos))) printf("Now playing.\n"); + else printf("Failed to start playback.\n"); } } @@ -82,13 +90,12 @@ int main() gfxSwapBuffers(); } - MIC_Shutdown(); - - if(audio_initialized)csndExit(); - - free(sharedmem); linearFree(audiobuf); + micExit(); + free(micbuf); + + csndExit(); gfxExit(); return 0; } diff --git a/libctru/include/3ds/services/mic.h b/libctru/include/3ds/services/mic.h index 8efd032..609f759 100644 --- a/libctru/include/3ds/services/mic.h +++ b/libctru/include/3ds/services/mic.h @@ -4,95 +4,125 @@ */ #pragma once -//See also: http://3dbrew.org/wiki/MIC_Services +/// Microphone audio encodings. +typedef enum +{ + MICU_ENCODING_PCM8 = 0, ///< Unsigned 8-bit PCM. + MICU_ENCODING_PCM16 = 1, ///< Unsigned 16-bit PCM. + MICU_ENCODING_PCM8_SIGNED = 2, ///< Signed 8-bit PCM. + MICU_ENCODING_PCM16_SIGNED = 3, ///< Signed 16-bit PCM. +} MICU_Encoding; + +/// Microphone audio sampling rates. +typedef enum +{ + MICU_SAMPLE_RATE_32730 = 0, ///< 32730 Hz + MICU_SAMPLE_RATE_16360 = 1, ///< 16360 Hz + MICU_SAMPLE_RATE_10910 = 2, ///< 10910 Hz + MICU_SAMPLE_RATE_8180 = 3, ///< 8180 Hz +} MICU_SampleRate; /** * @brief Initializes MIC. - * @param sharedmem Shared memory block to use. Must be 0x1000-bytes aligned. - * @param sharedmem_size Size of the shared memory block to use. (audiodata size + 4, aligned to 0x1000-bytes) - * @param control Control value. Bits 0-6 = Amplification. - * @param unk0 Unknown. Typically 3. - * @param unk1 Unknown. Typically 1. - * @param unk2 Unknown. Typically 1. + * @param size Shared memory buffer to write audio data to. Must be aligned to 0x1000 bytes. + * @param handle Size of the shared memory buffer. */ -Result MIC_Initialize(u32 *sharedmem, u32 sharedmem_size, u8 control, u8 recording, u8 unk0, u8 unk1, u8 unk2); +Result micInit(u8* buffer, u32 bufferSize); -/// Shuts down MIC. -Result MIC_Shutdown(void); +/// Exits MIC. +void micExit(void); /** - * @brief Gets the current shared memory offset. - * @return The current shared memory offset. + * @brief Gets the size of the sample data area within the shared memory buffer. + * @return The sample data's size. */ -u32 MIC_GetSharedMemOffsetValue(void); +u32 micGetSampleDataSize(void); /** - * @brief Reads MIC audio data. - * @param outbuf Buffer to write audio data to. - * @param readsize Size of the buffer to write to. - * @param waitforevent Whether to wait for the MIC service to signal that audio data is ready. (non-zero = wait) - * @return Actual number of bytes read. + * @brief Gets the offset within the shared memory buffer of the last sample written. + * @return The last sample's offset. */ -u32 MIC_ReadAudioData(u8 *outbuf, u32 readsize, u32 waitforevent); +u32 micGetLastSampleOffset(void); /** - * @brief Maps MIC's shared memory. - * @param handle Handle of the shared memory. + * @brief Maps MIC shared memory. * @param size Size of the shared memory. + * @param handle Handle of the shared memory. */ -Result MIC_MapSharedMem(Handle handle, u32 size); +Result MICU_MapSharedMem(u32 size, Handle handle); -/// Unmaps MIC's shardd memory. -Result MIC_UnmapSharedMem(void); +/// Unmaps MIC shared memory. +Result MICU_UnmapSharedMem(void); /** - * @brief Initializes MIC. - * @param unk0 Unknown. - * @param unk1 Unknown. - * @param sharedmem_baseoffset Base offset of shared memory. - * @param sharedmem_endoffset End offset of shared memory. - * @param unk2 Unknown. + * @brief Begins sampling microphone input. + * @param encoding Encoding of outputted audio. + * @param sampleRate Sample rate of outputted audio. + * @param sharedMemAudioOffset Offset to write audio data to in the shared memory buffer. + * @param sharedMemAudioSize Size of audio data to write to the shared memory buffer. This should be at most "bufferSize - 4". + * @param loop Whether to loop back to the beginning of the buffer when the end is reached. */ -Result MIC_cmd3_Initialize(u8 unk0, u8 unk1, u32 sharedmem_baseoffset, u32 sharedmem_endoffset, u8 unk2); - -/// Unknown MIC command. -Result MIC_cmd5(void); +Result MICU_StartSampling(MICU_Encoding encoding, MICU_SampleRate sampleRate, u32 offset, u32 size, bool loop); /** - * @brief Gets CNT bit 15 from MIC. - * @param out Pointer to output the bit to. + * @brief Adjusts the configuration of the current sampling session. + * @param sampleRate Sample rate of outputted audio. */ -Result MIC_GetCNTBit15(u8 *out); +Result MICU_AdjustSampling(MICU_SampleRate sampleRate); + +/// Stops sampling microphone input. +Result MICU_StopSampling(void); /** - * @brief Gets the event handle signaled by MIC when data is ready. + * @brief Gets whether microphone input is currently being sampled. + * @param sampling Pointer to output the sampling state to. + */ +Result MICU_IsSampling(bool* sampling); + +/** + * @brief Gets an event handle triggered when the shared memory buffer is full. * @param handle Pointer to output the event handle to. */ -Result MIC_GetEventHandle(Handle *handle); +Result MICU_GetEventHandle(Handle* handle); /** - * Sets the control value. - * @note Bits 0-6 = Amplification. - * @param value Control value to set. + * @brief Sets the microphone's gain. + * @param gain Gain to set. */ -Result MIC_SetControl(u8 value); +Result MICU_SetGain(u8 gain); /** - * Gets the control value. - * @note Bits 0-6 = Amplification. - * @param value Pointer to output the control value to. + * @brief Gets the microphone's gain. + * @param gain Pointer to output the current gain to. */ -Result MIC_GetControl(u8 *value); +Result MICU_GetGain(u8* gain); /** - * Sets whether the microphone is recording. - * @param value Whether the microphone is recording. + * @brief Sets whether the microphone is powered on. + * @param power Whether the microphone is powered on. */ -Result MIC_SetRecording(u8 value); +Result MICU_SetPower(bool power); /** - * Gets whether the microphone is recording. - * @param value Pointer to output whether the microphone is recording to. + * @brief Gets whether the microphone is powered on. + * @param power Pointer to output the power state to. */ -Result MIC_IsRecoding(u8 *value); +Result MICU_GetPower(bool* power); +/** + * @brief Sets whether to clamp microphone input. + * @param clamp Whether to clamp microphone input. + */ +Result MICU_SetClamp(bool clamp); + +/** + * @brief Gets whether to clamp microphone input. + * @param clamp Pointer to output the clamp state to. + */ +Result MICU_GetClamp(bool* clamp); + +/** + * @brief Sets whether to allow sampling when the shell is closed. + * @param allowShellClosed Whether to allow sampling when the shell is closed. + */ +Result MICU_SetAllowShellClosed(bool allowShellClosed); diff --git a/libctru/source/services/mic.c b/libctru/source/services/mic.c index 1743280..9458a6b 100644 --- a/libctru/source/services/mic.c +++ b/libctru/source/services/mic.c @@ -1,271 +1,226 @@ #include -#include #include <3ds/types.h> #include <3ds/svc.h> #include <3ds/srv.h> #include <3ds/services/mic.h> #include <3ds/ipc.h> +#include <3ds/synchronization.h> +#include <3ds/result.h> -//See also: http://3dbrew.org/wiki/MIC_Services +static Handle micHandle; +static int micRefCount; -Handle MIC_handle; +static u8* micSharedMem; +static u32 micSharedMemSize; +static Handle micSharedMemHandle; -static u8 *MIC_sharedmem; -static u32 MIC_sharedmem_size; -static u32 *MIC_sharedmem_offsetfield, MIC_sharedmem_offsetfield_location; -static Handle MIC_sharedmem_handle; -static Handle MIC_event; - -static u32 MIC_prev_endpos, MIC_cur_endpos; - -Result MIC_Initialize(u32 *sharedmem, u32 sharedmem_size, u8 control, u8 recording, u8 unk0, u8 unk1, u8 unk2) +Result micInit(u8* buffer, u32 bufferSize) { - Result ret=0; + Result ret = 0; - MIC_sharedmem = (u8*)sharedmem; - MIC_sharedmem_size = sharedmem_size; - MIC_sharedmem_offsetfield_location = MIC_sharedmem_size - 4; - MIC_sharedmem_offsetfield = (u32*)&MIC_sharedmem[MIC_sharedmem_offsetfield_location]; - MIC_event = 0; - MIC_prev_endpos = 0; - MIC_cur_endpos = 0; + if (AtomicPostIncrement(&micRefCount)) return 0; - ret = srvGetServiceHandle(&MIC_handle, "mic:u"); - if(ret!=0)return ret; + ret = srvGetServiceHandle(&micHandle, "mic:u"); + if (R_FAILED(ret)) goto end; - ret = svcCreateMemoryBlock(&MIC_sharedmem_handle, (u32)MIC_sharedmem, MIC_sharedmem_size, 3, 3); - if(ret!=0)return ret; + micSharedMem = buffer; + micSharedMemSize = bufferSize; - ret = MIC_SetControl(control); - if(ret!=0)return ret; + ret = svcCreateMemoryBlock(&micSharedMemHandle, (u32) micSharedMem, micSharedMemSize, MEMPERM_READ | MEMPERM_WRITE, MEMPERM_READ | MEMPERM_WRITE); + if (R_FAILED(ret)) goto end; - ret = MIC_MapSharedMem(MIC_sharedmem_handle, sharedmem_size); - if(ret!=0)return ret; + ret = MICU_MapSharedMem(micSharedMemSize, micSharedMemHandle); +end: + if (R_FAILED(ret)) micExit(); + return ret; +} - ret = MIC_SetRecording(recording); - if(ret!=0)return ret; +void micExit(void) +{ + if (AtomicDecrement(&micRefCount)) return; - ret = MIC_cmd3_Initialize(unk0, unk1, 0, MIC_sharedmem_size-4, unk2); - if(ret!=0)return ret; + if (micSharedMemHandle) + { + MICU_UnmapSharedMem(); + svcCloseHandle(micSharedMemHandle); + micSharedMemHandle = 0; + } - ret = MIC_GetEventHandle(&MIC_event); - if(ret!=0)return ret; - svcClearEvent(MIC_event); + if(micHandle) + { + svcCloseHandle(micHandle); + micHandle = 0; + } + micSharedMem = NULL; + micSharedMemSize = 0; +} + +u32 micGetSampleDataSize(void) +{ + return micSharedMemSize - 4; +} + +u32 micGetLastSampleOffset(void) +{ + if(micSharedMem) return *(u32*) &micSharedMem[micGetSampleDataSize()]; return 0; } -Result MIC_Shutdown(void) +Result MICU_MapSharedMem(u32 size, Handle handle) { - Result ret=0; - - MIC_cmd5(); - MIC_SetRecording(0); - - ret = MIC_UnmapSharedMem(); - if(ret!=0)return ret; - - MIC_cmd5(); - - ret = svcCloseHandle(MIC_sharedmem_handle); - if(ret!=0)return ret; - - ret = svcCloseHandle(MIC_event); - if(ret!=0)return ret; - - ret = svcCloseHandle(MIC_handle); - if(ret!=0)return ret; - - MIC_sharedmem_offsetfield = NULL; - MIC_sharedmem = NULL; - MIC_sharedmem_size = 0; - MIC_handle = 0; - MIC_event = 0; - - return 0; -} - -u32 MIC_GetSharedMemOffsetValue(void) -{ - u32 pos = 0; - - if(MIC_sharedmem_offsetfield==NULL)return pos; - pos = *MIC_sharedmem_offsetfield; - if(pos > MIC_sharedmem_offsetfield_location)pos = MIC_sharedmem_offsetfield_location; - - return pos; -} - -u32 MIC_ReadAudioData(u8 *outbuf, u32 readsize, u32 waitforevent) -{ - u32 pos = 0, bufpos = 0; - - if(waitforevent) - { - svcClearEvent(MIC_event); - svcWaitSynchronization(MIC_event, U64_MAX); - } - - MIC_prev_endpos = MIC_cur_endpos; - MIC_cur_endpos = MIC_GetSharedMemOffsetValue(); - pos = MIC_prev_endpos; - - while(pos != MIC_cur_endpos) - { - if(pos >= MIC_sharedmem_offsetfield_location)pos = 0; - if(bufpos>=readsize)break; - - outbuf[bufpos] = MIC_sharedmem[pos]; - bufpos++; - pos++; - } - - return bufpos; -} - -Result MIC_MapSharedMem(Handle handle, u32 size) -{ - Result ret=0; - u32 *cmdbuf = getThreadCommandBuffer(); - + Result ret = 0; + u32* cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x1,1,2); // 0x10042 cmdbuf[1] = size; cmdbuf[2] = IPC_Desc_SharedHandles(1); cmdbuf[3] = handle; - if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret; - - return (Result)cmdbuf[1]; + if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret; + return cmdbuf[1]; } -Result MIC_UnmapSharedMem(void) +Result MICU_UnmapSharedMem(void) { - Result ret=0; - u32 *cmdbuf = getThreadCommandBuffer(); - + Result ret = 0; + u32* cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x2,0,0); // 0x20000 - if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret; - - return (Result)cmdbuf[1]; + if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret; + return cmdbuf[1]; } -Result MIC_cmd3_Initialize(u8 unk0, u8 unk1, u32 sharedmem_baseoffset, u32 sharedmem_endoffset, u8 unk2) +Result MICU_StartSampling(MICU_Encoding encoding, MICU_SampleRate sampleRate, u32 offset, u32 size, bool loop) { - Result ret=0; - u32 *cmdbuf = getThreadCommandBuffer(); - + Result ret = 0; + u32* cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x3,5,0); // 0x30140 - cmdbuf[1] = unk0; - cmdbuf[2] = unk1; - cmdbuf[3] = sharedmem_baseoffset; - cmdbuf[4] = sharedmem_endoffset; - cmdbuf[5] = unk2; + cmdbuf[1] = encoding; + cmdbuf[2] = sampleRate; + cmdbuf[3] = offset; + cmdbuf[4] = size; + cmdbuf[5] = loop; - if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret; - - return (Result)cmdbuf[1]; + if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret; + return cmdbuf[1]; } -Result MIC_cmd5(void) +Result MICU_AdjustSampling(MICU_SampleRate sampleRate) { - Result ret=0; - u32 *cmdbuf = getThreadCommandBuffer(); + Result ret = 0; + u32* cmdbuf = getThreadCommandBuffer(); + cmdbuf[0] = IPC_MakeHeader(0x4,1,0); // 0x40040 + cmdbuf[1] = sampleRate; + if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret; + return cmdbuf[1]; +} + +Result MICU_StopSampling(void) +{ + Result ret = 0; + u32* cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x5,0,0); // 0x50000 - if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret; - - return (Result)cmdbuf[1]; + if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret; + return cmdbuf[1]; } -Result MIC_GetCNTBit15(u8 *out) +Result MICU_IsSampling(bool* sampling) { - Result ret=0; - u32 *cmdbuf = getThreadCommandBuffer(); - + Result ret = 0; + u32* cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x6,0,0); // 0x60000 - if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret; - - if(out)*out = cmdbuf[2]; - - return (Result)cmdbuf[1]; + if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret; + if (sampling) *sampling = cmdbuf[2] & 0xFF; + return cmdbuf[1]; } -Result MIC_GetEventHandle(Handle *handle) +Result MICU_GetEventHandle(Handle* handle) { - Result ret=0; - u32 *cmdbuf = getThreadCommandBuffer(); - - if(MIC_event) - { - *handle = MIC_event; - return 0; - } - + Result ret = 0; + u32* cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x7,0,0); // 0x70000 - if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret; - - if(handle)*handle = cmdbuf[3]; - - return (Result)cmdbuf[1]; + if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret; + if (handle) *handle = cmdbuf[3]; + return cmdbuf[1]; } -Result MIC_SetControl(u8 value) +Result MICU_SetGain(u8 gain) { - Result ret=0; - u32 *cmdbuf = getThreadCommandBuffer(); - + Result ret = 0; + u32* cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x8,1,0); // 0x80040 - cmdbuf[1] = value; + cmdbuf[1] = gain; - if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret; - - return (Result)cmdbuf[1]; + if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret; + return cmdbuf[1]; } -Result MIC_GetControl(u8 *value) +Result MICU_GetGain(u8* gain) { - Result ret=0; - u32 *cmdbuf = getThreadCommandBuffer(); - + Result ret = 0; + u32* cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x9,0,0); // 0x90000 - if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret; - - if(value)*value = cmdbuf[2]; - - return (Result)cmdbuf[1]; + if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret; + if (gain) *gain = cmdbuf[2] & 0xFF; + return cmdbuf[1]; } -Result MIC_SetRecording(u8 value) +Result MICU_SetPower(bool power) { - Result ret=0; - u32 *cmdbuf = getThreadCommandBuffer(); - + Result ret = 0; + u32* cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0xA,1,0); // 0xA0040 - cmdbuf[1] = value; + cmdbuf[1] = power; - if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret; - - if(value==1)MIC_cur_endpos = MIC_GetSharedMemOffsetValue(); - - return (Result)cmdbuf[1]; + if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret; + return cmdbuf[1]; } -Result MIC_IsRecoding(u8 *value) +Result MICU_GetPower(bool* power) { - Result ret=0; - u32 *cmdbuf = getThreadCommandBuffer(); - + Result ret = 0; + u32* cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0xB,0,0); // 0xB0000 - if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret; - - if(value)*value = cmdbuf[2]; - - return (Result)cmdbuf[1]; + if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret; + if (power) *power = cmdbuf[2] & 0xFF; + return cmdbuf[1]; } +Result MICU_SetClamp(bool clamp) +{ + Result ret = 0; + u32* cmdbuf = getThreadCommandBuffer(); + cmdbuf[0] = IPC_MakeHeader(0xD,1,0); // 0xD0040 + cmdbuf[1] = clamp; + + if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret; + return cmdbuf[1]; +} + +Result MICU_GetClamp(bool* clamp) +{ + Result ret = 0; + u32* cmdbuf = getThreadCommandBuffer(); + cmdbuf[0] = IPC_MakeHeader(0xE,0,0); // 0xE0000 + + if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret; + if (clamp) *clamp = cmdbuf[2] & 0xFF; + return cmdbuf[1]; +} + +Result MICU_SetAllowShellClosed(bool allowShellClosed) +{ + Result ret = 0; + u32* cmdbuf = getThreadCommandBuffer(); + cmdbuf[0] = IPC_MakeHeader(0xF,1,0); // 0xF0040 + cmdbuf[1] = allowShellClosed; + + if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret; + return cmdbuf[1]; +}