libctru/libctru/source/services/irrst.c
2014-12-13 16:36:54 +00:00

149 lines
2.9 KiB
C

/*
_irrst.c - C-stick, ZL/ZR
*/
#include <stdlib.h>
#include <string.h>
#include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/irrst.h>
Handle irrstHandle;
Handle irrstMemHandle;
Handle irrstEvent;
vu32* irrstSharedMem;
static u32 kHeld;
static circlePosition csPos;
static bool irrstUsed = false;
Result irrstInit(u32* sharedMem)
{
if(irrstUsed)return 0;
if(!sharedMem)sharedMem=(u32*)IRRST_SHAREDMEM_DEFAULT;
Result ret=0;
// Request service.
if((ret=srvGetServiceHandle(&irrstHandle, "ir:rst")))return ret;
// Get sharedmem handle.
if((ret=IRRST_GetHandles(&irrstMemHandle, &irrstEvent))) goto cleanup1;
// Map ir:rst shared memory at addr "sharedMem".
irrstSharedMem=sharedMem;
if((ret=svcMapMemoryBlock(irrstMemHandle, (u32)irrstSharedMem, MEMPERM_READ, 0x10000000)))goto cleanup2;
// Reset internal state.
irrstUsed = true;
kHeld = 0;
return 0;
cleanup2:
svcCloseHandle(irrstMemHandle);
cleanup1:
svcCloseHandle(irrstHandle);
return ret;
}
void irrstExit()
{
if(!irrstUsed)return;
irrstUsed = false;
svcCloseHandle(irrstEvent);
// Unmap ir:rst sharedmem and close handles.
svcUnmapMemoryBlock(irrstMemHandle, (u32)irrstSharedMem);
svcCloseHandle(irrstMemHandle);
svcCloseHandle(irrstHandle);
}
void irrstWaitForEvent(bool nextEvent)
{
if(nextEvent)svcClearEvent(irrstEvent);
svcWaitSynchronization(irrstEvent, U64_MAX);
if(!nextEvent)svcClearEvent(irrstEvent);
}
u32 irrstCheckSectionUpdateTime(vu32 *sharedmem_section, u32 id)
{
s64 tick0=0, tick1=0;
if(id==0)
{
tick0 = *((u64*)&sharedmem_section[0]);
tick1 = *((u64*)&sharedmem_section[2]);
if(tick0==tick1 || tick0<0 || tick1<0)return 1;
}
return 0;
}
void irrstScanInput()
{
if(!irrstUsed)return;
u32 Id=0;
kHeld = 0;
memset(&csPos, 0, sizeof(circlePosition));
Id = irrstSharedMem[4]; //PAD / circle-pad
if(Id>7)Id=7;
if(irrstCheckSectionUpdateTime(irrstSharedMem, Id)==0)
{
kHeld = irrstSharedMem[6 + Id*4];
csPos = *(circlePosition*)&irrstSharedMem[6 + Id*4 + 3];
}
}
u32 irrstKeysHeld()
{
if(irrstUsed)return kHeld;
return 0;
}
void irrstCstickRead(circlePosition* pos)
{
if (pos) *pos = csPos;
}
Result IRRST_GetHandles(Handle* outMemHandle, Handle* outEventHandle)
{
u32* cmdbuf=getThreadCommandBuffer();
cmdbuf[0]=0x00010000; //request header code
Result ret=0;
if((ret=svcSendSyncRequest(irrstHandle)))return ret;
if(outMemHandle)*outMemHandle=cmdbuf[3];
if(outEventHandle)*outEventHandle=cmdbuf[4];
return cmdbuf[1];
}
Result IRRST_Initialize(u32 unk1, u8 unk2)
{
u32* cmdbuf=getThreadCommandBuffer();
cmdbuf[0]=0x00020080; //request header code
cmdbuf[1]=unk1;
cmdbuf[2]=unk2;
Result ret=0;
if((ret=svcSendSyncRequest(irrstHandle)))return ret;
return cmdbuf[1];
}
Result IRRST_Shutdown(void)
{
u32* cmdbuf=getThreadCommandBuffer();
cmdbuf[0]=0x00030000; //request header code
Result ret=0;
if((ret=svcSendSyncRequest(irrstHandle)))return ret;
return cmdbuf[1];
}