Integrate 3ds_pxi and 3ds_sm
This commit is contained in:
211
sysmodules/pxi/source/main.c
Normal file
211
sysmodules/pxi/source/main.c
Normal file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
main.c
|
||||
(De)initialization stuff. It's also here where sessions are being accepted.
|
||||
|
||||
(c) TuxSH, 2016-2017
|
||||
This is part of 3ds_pxi, which is licensed under the MIT license (see LICENSE for details).
|
||||
*/
|
||||
|
||||
#include "PXI.h"
|
||||
#include "common.h"
|
||||
#include "MyThread.h"
|
||||
#include "receiver.h"
|
||||
#include "sender.h"
|
||||
#include "memory.h"
|
||||
|
||||
Handle PXISyncInterrupt = 0, PXITransferMutex = 0;
|
||||
Handle terminationRequestedEvent = 0;
|
||||
bool shouldTerminate = false;
|
||||
SessionManager sessionManager = {0};
|
||||
|
||||
const char *serviceNames[10] =
|
||||
{
|
||||
"pxi:mc",
|
||||
|
||||
"PxiFS0",
|
||||
"PxiFS1",
|
||||
"PxiFSB",
|
||||
"PxiFSR",
|
||||
|
||||
"PxiPM",
|
||||
|
||||
"pxi:dev", //in the official PXI module maxSessions(pxi:dev) == 2. It doesn't matter anyways, since srvSysRegisterService is always called with 1
|
||||
"pxi:am9",
|
||||
"pxi:ps9",
|
||||
|
||||
"pxi:srv11",
|
||||
};
|
||||
|
||||
const u32 nbStaticBuffersByService[10] = {0, 2, 2, 2, 2, 1, 4, 4, 4, 0};
|
||||
|
||||
u32 ALIGN(0x1000) staticBuffers[NB_STATIC_BUFFERS][0x400] = {{0}};
|
||||
|
||||
static inline void initPXI(void)
|
||||
{
|
||||
Result res;
|
||||
|
||||
Handle handles[2] = {0};
|
||||
|
||||
PXIReset();
|
||||
|
||||
if(PXISyncInterrupt != 0) svcBreak(USERBREAK_PANIC); //0xE0A0183B
|
||||
assertSuccess(svcCreateEvent(&PXISyncInterrupt, RESET_ONESHOT));
|
||||
|
||||
if(PXITransferMutex != 0) svcBreak(USERBREAK_PANIC); //0xE0A0183B
|
||||
assertSuccess(svcCreateMutex(&PXITransferMutex, false));
|
||||
|
||||
assertSuccess(svcCreateEvent(&handles[0], RESET_ONESHOT)); //receive FIFO not empty
|
||||
assertSuccess(svcCreateEvent(&handles[1], RESET_ONESHOT)); //send FIFO empty
|
||||
assertSuccess(bindPXIInterrupts(&PXISyncInterrupt, &handles[0], &handles[1]));
|
||||
|
||||
s32 handleIndex;
|
||||
do
|
||||
{
|
||||
while(!PXIIsSendFIFOFull()) PXISendWord(0);
|
||||
|
||||
res = assertSuccess(svcWaitSynchronization(handles[0], 0LL));
|
||||
if(R_DESCRIPTION(res) == RD_TIMEOUT)
|
||||
assertSuccess(svcWaitSynchronizationN(&handleIndex, handles, 2, false, -1LL));
|
||||
else
|
||||
handleIndex = 0;
|
||||
} while(handleIndex != 0);
|
||||
|
||||
|
||||
|
||||
unbindPXIInterrupts(NULL, &handles[0], &handles[1]);
|
||||
|
||||
PXISendByte(1);
|
||||
while(PXIReceiveByte() < 1);
|
||||
|
||||
while (!PXIIsReceiveFIFOEmpty())
|
||||
PXIReceiveWord();
|
||||
|
||||
PXISendByte(2);
|
||||
while(PXIReceiveByte() < 2);
|
||||
|
||||
svcCloseHandle(handles[0]);
|
||||
svcCloseHandle(handles[1]);
|
||||
}
|
||||
|
||||
static inline void exitPXI(void)
|
||||
{
|
||||
unbindPXIInterrupts(&PXISyncInterrupt, NULL, NULL);
|
||||
svcCloseHandle(PXITransferMutex);
|
||||
svcCloseHandle(PXISyncInterrupt);
|
||||
PXIReset();
|
||||
}
|
||||
|
||||
static u8 ALIGN(8) receiverStack[THREAD_STACK_SIZE];
|
||||
static u8 ALIGN(8) senderStack[THREAD_STACK_SIZE];
|
||||
static u8 ALIGN(8) PXISRV11HandlerStack[THREAD_STACK_SIZE];
|
||||
|
||||
// this is called before main
|
||||
void __appInit()
|
||||
{
|
||||
assertSuccess(svcCreateEvent(&terminationRequestedEvent, RESET_STICKY));
|
||||
|
||||
assertSuccess(svcCreateEvent(&sessionManager.sendAllBuffersToArm9Event, RESET_ONESHOT));
|
||||
assertSuccess(svcCreateSemaphore(&sessionManager.replySemaphore, 0, 9));
|
||||
assertSuccess(svcCreateEvent(&sessionManager.PXISRV11CommandReceivedEvent, RESET_ONESHOT));
|
||||
assertSuccess(svcCreateEvent(&sessionManager.PXISRV11ReplySentEvent, RESET_ONESHOT));
|
||||
initPXI();
|
||||
|
||||
for(Result res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL))
|
||||
{
|
||||
res = srvInit();
|
||||
if(R_FAILED(res) && res != (Result)0xD88007FA)
|
||||
svcBreak(USERBREAK_PANIC);
|
||||
}
|
||||
}
|
||||
|
||||
// this is called after main exits
|
||||
void __appExit()
|
||||
{
|
||||
srvExit();
|
||||
exitPXI();
|
||||
|
||||
svcCloseHandle(terminationRequestedEvent);
|
||||
svcCloseHandle(sessionManager.sendAllBuffersToArm9Event);
|
||||
svcCloseHandle(sessionManager.replySemaphore);
|
||||
svcCloseHandle(sessionManager.PXISRV11CommandReceivedEvent);
|
||||
svcCloseHandle(sessionManager.PXISRV11ReplySentEvent);
|
||||
}
|
||||
|
||||
// stubs for non-needed pre-main functions
|
||||
void __system_initSyscalls(){}
|
||||
|
||||
|
||||
Result __sync_init(void);
|
||||
Result __sync_fini(void);
|
||||
|
||||
void __ctru_exit()
|
||||
{
|
||||
__appExit();
|
||||
__sync_fini();
|
||||
svcExitProcess();
|
||||
}
|
||||
|
||||
void initSystem()
|
||||
{
|
||||
__sync_init();
|
||||
__system_initSyscalls();
|
||||
__appInit();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Handle handles[10] = {0}; //notification handle + service handles
|
||||
MyThread receiverThread = {0}, senderThread = {0}, PXISRV11HandlerThread = {0};
|
||||
|
||||
for(u32 i = 0; i < 9; i++)
|
||||
assertSuccess(srvRegisterService(handles + 1 + i, serviceNames[i], 1));
|
||||
|
||||
assertSuccess(MyThread_Create(&receiverThread, receiver, receiverStack, THREAD_STACK_SIZE, 0x2D, -2));
|
||||
assertSuccess(MyThread_Create(&senderThread, sender, senderStack, THREAD_STACK_SIZE, 0x2D, -2));
|
||||
assertSuccess(MyThread_Create(&PXISRV11HandlerThread, PXISRV11Handler, PXISRV11HandlerStack, THREAD_STACK_SIZE, 0x2D, -2));
|
||||
|
||||
assertSuccess(srvEnableNotification(&handles[0]));
|
||||
|
||||
while(!shouldTerminate)
|
||||
{
|
||||
s32 index = 0;
|
||||
assertSuccess(svcWaitSynchronizationN(&index, handles, 10, false, -1LL));
|
||||
|
||||
if(index == 0)
|
||||
{
|
||||
u32 notificationId;
|
||||
assertSuccess(srvReceiveNotification(¬ificationId));
|
||||
if(notificationId == 0x100) shouldTerminate = true;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Handle session = 0;
|
||||
SessionData *data = &sessionManager.sessionData[index - 1];
|
||||
assertSuccess(svcAcceptSession(&session, handles[index]));
|
||||
|
||||
RecursiveLock_Lock(&sessionManager.senderLock);
|
||||
if(data->handle != 0)
|
||||
svcBreak(USERBREAK_PANIC);
|
||||
|
||||
data->handle = session;
|
||||
assertSuccess(svcSignalEvent(sessionManager.sendAllBuffersToArm9Event));
|
||||
|
||||
RecursiveLock_Unlock(&sessionManager.senderLock);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
u32 PXIMC_OnPXITerminate = 0x10000; //TODO: see if this is correct
|
||||
sessionManager.sessionData[0].state = STATE_SENT_TO_ARM9;
|
||||
sendPXICmdbuf(NULL, 0, &PXIMC_OnPXITerminate);
|
||||
|
||||
assertSuccess(MyThread_Join(&receiverThread, -1LL));
|
||||
assertSuccess(MyThread_Join(&senderThread, -1LL));
|
||||
assertSuccess(MyThread_Join(&PXISRV11HandlerThread, -1LL));
|
||||
|
||||
for(u32 i = 0; i < 10; i++)
|
||||
svcCloseHandle(handles[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user