libctru/libctru/source/services/mic.c
2015-11-08 11:24:04 -08:00

231 lines
5.2 KiB
C

#include <stdlib.h>
#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>
static Handle micHandle;
static int micRefCount;
static u8* micSharedMem;
static u32 micSharedMemSize;
static Handle micSharedMemHandle;
Result micInit(u8* buffer, u32 bufferSize)
{
Result ret = 0;
if (AtomicPostIncrement(&micRefCount)) return 0;
ret = srvGetServiceHandle(&micHandle, "mic:u");
if (R_FAILED(ret)) goto end;
micSharedMem = buffer;
micSharedMemSize = bufferSize;
ret = svcCreateMemoryBlock(&micSharedMemHandle, (u32) micSharedMem, micSharedMemSize, MEMPERM_READ | MEMPERM_WRITE, MEMPERM_READ | MEMPERM_WRITE);
if (R_FAILED(ret)) goto end;
ret = MICU_MapSharedMem(micSharedMemSize, micSharedMemHandle);
if (R_FAILED(ret)) goto end;
ret = MICU_SetPower(true);
end:
if (R_FAILED(ret)) micExit();
return ret;
}
void micExit(void)
{
if (AtomicDecrement(&micRefCount)) return;
if (micSharedMemHandle)
{
MICU_UnmapSharedMem();
svcCloseHandle(micSharedMemHandle);
micSharedMemHandle = 0;
}
if (micHandle)
{
MICU_SetPower(false);
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 MICU_MapSharedMem(u32 size, Handle handle)
{
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 (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
return cmdbuf[1];
}
Result MICU_UnmapSharedMem(void)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x2,0,0); // 0x20000
if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
return cmdbuf[1];
}
Result MICU_StartSampling(MICU_Encoding encoding, MICU_SampleRate sampleRate, u32 offset, u32 size, bool loop)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x3,5,0); // 0x30140
cmdbuf[1] = encoding;
cmdbuf[2] = sampleRate;
cmdbuf[3] = offset;
cmdbuf[4] = size;
cmdbuf[5] = loop;
if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
return cmdbuf[1];
}
Result MICU_AdjustSampling(MICU_SampleRate sampleRate)
{
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 (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
return cmdbuf[1];
}
Result MICU_IsSampling(bool* sampling)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x6,0,0); // 0x60000
if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
if (sampling) *sampling = cmdbuf[2] & 0xFF;
return cmdbuf[1];
}
Result MICU_GetEventHandle(Handle* handle)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x7,0,0); // 0x70000
if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
if (handle) *handle = cmdbuf[3];
return cmdbuf[1];
}
Result MICU_SetGain(u8 gain)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x8,1,0); // 0x80040
cmdbuf[1] = gain;
if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
return cmdbuf[1];
}
Result MICU_GetGain(u8* gain)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x9,0,0); // 0x90000
if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
if (gain) *gain = cmdbuf[2] & 0xFF;
return cmdbuf[1];
}
Result MICU_SetPower(bool power)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0xA,1,0); // 0xA0040
cmdbuf[1] = power;
if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
return cmdbuf[1];
}
Result MICU_GetPower(bool* power)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0xB,0,0); // 0xB0000
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];
}