/* receiver.c: Fetches replies coming from Process9, writing them in the appropriate buffer. (c) TuxSH, 2016-2017 This is part of 3ds_pxi, which is licensed under the MIT license (see LICENSE for details). */ #include "receiver.h" #include "PXI.h" #include "memory.h" static inline void receiveFromArm9(void) { u32 serviceId = PXIReceiveWord(); //The offcical implementation can return 0xD90043FA if(((serviceId >= 10)) || (sessionManager.sessionData[serviceId].state != STATE_SENT_TO_ARM9)) svcBreak(USERBREAK_PANIC); sessionManager.receivedServiceId = serviceId; RecursiveLock_Lock(&sessionManager.sessionData[serviceId].lock); u32 replyHeader = PXIReceiveWord(); u32 replySizeWords = (replyHeader & 0x3F) + ((replyHeader & 0xFC0) >> 6) + 1; if(replySizeWords > 0x40) svcBreak(USERBREAK_PANIC); u32 *buf = sessionManager.sessionData[serviceId].buffer; buf[0] = replyHeader; PXIReceiveBuffer(buf + 1, replySizeWords - 1); sessionManager.sessionData[serviceId].state = STATE_RECEIVED_FROM_ARM9; RecursiveLock_Unlock(&sessionManager.sessionData[serviceId].lock); if(serviceId == 0 && shouldTerminate) { assertSuccess(svcSignalEvent(terminationRequestedEvent)); return; } if(serviceId != 9) { s32 count; assertSuccess(svcReleaseSemaphore(&count, sessionManager.replySemaphore, 1)); } else { assertSuccess(svcSignalEvent(sessionManager.PXISRV11CommandReceivedEvent)); assertSuccess(svcWaitSynchronization(sessionManager.PXISRV11ReplySentEvent, -1LL)); if( (sessionManager.sessionData[serviceId].state != STATE_SENT_TO_ARM9)) svcBreak(USERBREAK_PANIC); } } void receiver(void) { Handle handles[] = {PXISyncInterrupt, terminationRequestedEvent}; assertSuccess(svcWaitSynchronization(sessionManager.PXISRV11ReplySentEvent, -1LL)); while(true) { s32 index; assertSuccess(svcWaitSynchronizationN(&index, handles, 2, false, -1LL)); if(index == 1) return; while(!PXIIsReceiveFIFOEmpty()) receiveFromArm9(); } }