Lorenzo DellacĂ
a39053c3c3
* origin/master: (98 commits) rosalina: fix for latest libctru changes pm: fix critical bugs where 1.0(?) titles not in the list have scheduling mode misconfigured loader: revert to use the NS patch due to a Nintendo bug: https://www.3dbrew.org/wiki/NCCH/Extended_Header#Flag1 loader: replace NS N3DS CPU patch with exheader override, fix overriding exheader with homebrew rosalina: ntp: use PTMSYSM_SetRtcTime revert the memory map to the old one (mostly) fix module loading kext: fix outer memory cacheability on newer versions so bascially rosalina's image... rosalina: add hidden debug info menu rosalina: refactor menu handling rosalina: rephrase brightness warning rosalina: add brightness control menu rosalina/pm: remove fs patch, use pm instead rosalina: cleanup variable names rosalina: reorder menus Fix latest commit rosalina menu: add scrolling, cpad and inputredir support (note: no ZL/ZR due to technical reasons) stuff newlib... ... # Conflicts: # k11_extension/source/main.c # k11_extension/source/svc/UnmapProcessMemoryEx.c # sysmodules/rosalina/Makefile # sysmodules/rosalina/include/menu.h # sysmodules/rosalina/include/utils.h # sysmodules/rosalina/source/errdisp.c # sysmodules/rosalina/source/main.c # sysmodules/rosalina/source/menu.c # sysmodules/rosalina/source/menus.c
200 lines
5.7 KiB
C
200 lines
5.7 KiB
C
/*
|
|
notifications.c
|
|
|
|
(c) TuxSH, 2017-2020
|
|
This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for details).
|
|
*/
|
|
|
|
#include "notifications.h"
|
|
#include "processes.h"
|
|
|
|
static bool doPublishNotification(ProcessData *processData, u32 notificationId, u32 flags)
|
|
{
|
|
if((flags & 1) && processData->nbPendingNotifications != 0) // only send if not already pending
|
|
{
|
|
for(u16 i = 0; i < processData->nbPendingNotifications; i++)
|
|
{
|
|
if(processData->pendingNotifications[(processData->receivedNotificationIndex + i) % 16] == notificationId)
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Handle special case for home button notifications on Mode3 O3DS with plugin loaded
|
|
if ((notificationId == 0x204 || notificationId == 0x205)
|
|
&& *(u32 *)0x1FF80030 == 3 && *(u32 *)0x1FF800F0)
|
|
{
|
|
svcKernelSetState(0x10007, 1);
|
|
return true;
|
|
}
|
|
|
|
if(processData->nbPendingNotifications < 0x10)
|
|
{
|
|
s32 count;
|
|
|
|
processData->pendingNotifications[processData->pendingNotificationIndex] = notificationId;
|
|
processData->pendingNotificationIndex = (processData->pendingNotificationIndex + 1) % 16;
|
|
++processData->nbPendingNotifications;
|
|
assertSuccess(svcReleaseSemaphore(&count, processData->notificationSemaphore, 1));
|
|
|
|
return true;
|
|
}
|
|
else
|
|
return (flags & 2) != 0;
|
|
}
|
|
|
|
Result EnableNotification(SessionData *sessionData, Handle *notificationSemaphore)
|
|
{
|
|
ProcessData *processData = findProcessData(sessionData->pid);
|
|
|
|
if(processData == NULL)
|
|
{
|
|
// Section 0 modules have access to all services, so we need to register them here for notifications
|
|
if(sessionData->pid < nbSection0Modules)
|
|
processData = doRegisterProcess(sessionData->pid, NULL, 0);
|
|
else
|
|
return 0xD8806404;
|
|
}
|
|
|
|
processData->notificationEnabled = true;
|
|
*notificationSemaphore = processData->notificationSemaphore;
|
|
|
|
return 0;
|
|
}
|
|
|
|
Result Subscribe(SessionData *sessionData, u32 notificationId)
|
|
{
|
|
ProcessData *processData = findProcessData(sessionData->pid);
|
|
|
|
|
|
if(processData == NULL || !processData->notificationEnabled)
|
|
return 0xD8806404;
|
|
|
|
for(u16 i = 0; i < processData->nbSubscribed; i++)
|
|
{
|
|
if(processData->subscribedNotifications[i] == notificationId)
|
|
return 0xD9006403;
|
|
}
|
|
|
|
if(processData->nbSubscribed < 0x11)
|
|
{
|
|
processData->subscribedNotifications[processData->nbSubscribed++] = notificationId;
|
|
return 0;
|
|
}
|
|
else
|
|
return 0xD9006405;
|
|
}
|
|
|
|
Result Unsubscribe(SessionData *sessionData, u32 notificationId)
|
|
{
|
|
ProcessData *processData = findProcessData(sessionData->pid);
|
|
|
|
if(processData == NULL || !processData->notificationEnabled)
|
|
return 0xD8806404;
|
|
|
|
u16 i;
|
|
for(i = 0; i < processData->nbSubscribed && processData->subscribedNotifications[i] != notificationId; i++);
|
|
|
|
if(i == processData->nbSubscribed)
|
|
return 0xD8806404;
|
|
else
|
|
{
|
|
processData->subscribedNotifications[i] = processData->subscribedNotifications[--processData->nbSubscribed];
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
Result ReceiveNotification(SessionData *sessionData, u32 *notificationId)
|
|
{
|
|
ProcessData *processData = findProcessData(sessionData->pid);
|
|
|
|
if(processData == NULL || !processData->notificationEnabled || processData->nbPendingNotifications == 0)
|
|
{
|
|
if(processData != NULL && processData->nbPendingNotifications)
|
|
*notificationId = 0;
|
|
return 0xD8806404;
|
|
}
|
|
else
|
|
{
|
|
--processData->nbPendingNotifications;
|
|
*notificationId = processData->pendingNotifications[processData->receivedNotificationIndex];
|
|
processData->receivedNotificationIndex = (processData->receivedNotificationIndex + 1) % 16;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
Result PublishToSubscriber(u32 notificationId, u32 flags)
|
|
{
|
|
for(ProcessData *node = processDataInUseList.first; node != NULL; node = node->next)
|
|
{
|
|
if(!node->notificationEnabled)
|
|
continue;
|
|
|
|
u16 i;
|
|
for(i = 0; i < node->nbSubscribed && node->subscribedNotifications[i] != notificationId; i++);
|
|
if(i >= node->nbSubscribed)
|
|
continue;
|
|
|
|
if(!doPublishNotification(node, notificationId, flags))
|
|
return 0xD8606408;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
Result PublishAndGetSubscriber(u32 *pidCount, u32 *pidList, u32 notificationId, u32 flags)
|
|
{
|
|
u32 nb = 0;
|
|
for(ProcessData *node = processDataInUseList.first; node != NULL; node = node->next)
|
|
{
|
|
if(!node->notificationEnabled)
|
|
continue;
|
|
|
|
u16 i;
|
|
for(i = 0; i < node->nbSubscribed && node->subscribedNotifications[i] != notificationId; i++);
|
|
if(i >= node->nbSubscribed)
|
|
continue;
|
|
|
|
if(!doPublishNotification(node, notificationId, flags))
|
|
return 0xD8606408;
|
|
else if(pidList != NULL && nb < 60)
|
|
pidList[nb++] = node->pid;
|
|
}
|
|
|
|
if(pidCount != NULL)
|
|
*pidCount = nb;
|
|
|
|
return 0;
|
|
}
|
|
|
|
Result PublishToProcess(Handle process, u32 notificationId)
|
|
{
|
|
u32 pid;
|
|
Result res = svcGetProcessId(&pid, process);
|
|
if(R_FAILED(res))
|
|
return res;
|
|
|
|
ProcessData *processData = findProcessData(pid);
|
|
if(processData == NULL || !processData->notificationEnabled)
|
|
res = 0xD8806404;
|
|
else if(!doPublishNotification(processData, notificationId, 0))
|
|
res = 0xD8606408;
|
|
else
|
|
res = 0;
|
|
|
|
svcCloseHandle(process);
|
|
return res;
|
|
}
|
|
|
|
Result PublishToAll(u32 notificationId)
|
|
{
|
|
for(ProcessData *node = processDataInUseList.first; node != NULL; node = node->next)
|
|
{
|
|
if(!node->notificationEnabled)
|
|
continue;
|
|
else if(!doPublishNotification(node, notificationId, 0))
|
|
return 0xD8606408;
|
|
}
|
|
|
|
return 0;
|
|
}
|