Skip to content

Commit

Permalink
Async LED handler
Browse files Browse the repository at this point in the history
  • Loading branch information
GaryOderNichts committed Sep 1, 2023
1 parent 6f0a876 commit 2203a92
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 9 deletions.
6 changes: 6 additions & 0 deletions ios_mcp/imports.ld
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,14 @@ PROVIDE(IOS_GetThreadPriority = 0x0505683c);

PROVIDE(IOS_CreateMessageQueue = 0x0505684c);
PROVIDE(IOS_DestroyMessageQueue = 0x05056854);
PROVIDE(IOS_SendMessage = 0x0505685c);
PROVIDE(IOS_ReceiveMessage = 0x0505686c);

PROVIDE(IOS_CreateTimer = 0x05056884);
PROVIDE(IOS_RestartTimer = 0x0505688c);
PROVIDE(IOS_StopTimer = 0x05056894);
PROVIDE(IOS_DestroyTimer = 0x0505689c);

PROVIDE(IOS_CheckDebugMode = 0x050568ec);
PROVIDE(IOS_ReadOTP = 0x050568fc);

Expand Down
21 changes: 19 additions & 2 deletions ios_mcp/source/imports.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,32 @@ int UCReadSysConfig(int handle, uint32_t num, UCSysConfig_t* configs);
int UCClose(int handle);
int UCOpen(void);

int IOS_CreateThread(int (*fun)(void* arg), void* arg, void* stack_top, uint32_t stacksize, int priority, uint32_t flags);
typedef enum {
IOS_THREAD_FLAGS_NONE = 0,
IOS_THREAD_FLAGS_DETACHED = 1 << 0,
IOS_THREAD_FLAGS_TLS = 1 << 1,
} IOS_ThreadFlags;

int IOS_CreateThread(int (*fun)(void* arg), void* arg, void* stack_top, uint32_t stacksize, int priority, IOS_ThreadFlags flags);
int IOS_JoinThread(int threadid, int* retval);
int IOS_CancelThread(int threadid, int return_value);
int IOS_StartThread(int threadid);
int IOS_GetThreadPriority(int threadid);

typedef enum {
IOS_MESSAGE_FLAGS_NONE = 0,
IOS_MESSAGE_FLAGS_NON_BLOCKING = 1 << 0,
} IOS_MessageFlags;

int IOS_CreateMessageQueue(uint32_t* ptr, uint32_t n_msgs);
int IOS_DestroyMessageQueue(int queueid);
int IOS_ReceiveMessage(int queueid, uint32_t* message, uint32_t flags);
int IOS_SendMessage(int queueid, uint32_t message, IOS_MessageFlags flags);
int IOS_ReceiveMessage(int queueid, uint32_t* message, IOS_MessageFlags flags);

int IOS_CreateTimer(uint32_t delay, uint32_t period, int queueid, uint32_t message);
int IOS_RestartTimer(int timerid, uint32_t delay, uint32_t period);
int IOS_StopTimer(int timerid);
int IOS_DestroyTimer(int timerid);

int IOS_CheckDebugMode(void);
int IOS_ReadOTP(int index, void* buffer, uint32_t size);
Expand Down
2 changes: 1 addition & 1 deletion ios_mcp/source/mcp_ioctl100.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ int MCP_ioctl100_patch(void* msg)

// start the menu thread
if (!threadStarted) {
int tid = IOS_CreateThread(menuThread, NULL, threadStack + sizeof(threadStack), sizeof(threadStack), IOS_GetThreadPriority(0), 1);
int tid = IOS_CreateThread(menuThread, NULL, threadStack + sizeof(threadStack), sizeof(threadStack), IOS_GetThreadPriority(0), IOS_THREAD_FLAGS_DETACHED);
if (tid > 0) {
IOS_StartThread(tid);
}
Expand Down
10 changes: 8 additions & 2 deletions ios_mcp/source/menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,9 @@ static void option_Shutdown(void)
IOS_Close(fsaHandle);
}

// Finalize utils (doesn't really matter at this point since we don't have a clean shutdown anyways)
//finalizeUtils();

IOS_Shutdown(0);
}

Expand All @@ -334,7 +337,7 @@ int menuThread(void* arg)
printf("menuThread running\n");

// set LED to purple-orange blinking
SMC_SetNotificationLED(NOTIF_LED_RED | NOTIF_LED_RED_BLINKING | NOTIF_LED_BLUE | NOTIF_LED_BLUE_BLINKING | NOTIF_LED_ORANGE);
setNotificationLED(NOTIF_LED_RED | NOTIF_LED_RED_BLINKING | NOTIF_LED_BLUE | NOTIF_LED_BLUE_BLINKING | NOTIF_LED_ORANGE, 0);

// stop ppcHeartbeatThread and reset PPC
IOS_CancelThread(ppcHeartBeatThreadId, 0);
Expand All @@ -343,6 +346,9 @@ int menuThread(void* arg)
// cut power to the disc drive to not eject a disc every eject press
SMC_SetODDPower(0);

// Initialize utils
initializeUtils();

#ifdef DC_INIT
// (re-)init the graphics subsystem
GFX_SubsystemInit(0);
Expand Down Expand Up @@ -380,7 +386,7 @@ int menuThread(void* arg)
}

// set LED to purple
SMC_SetNotificationLED(NOTIF_LED_RED | NOTIF_LED_BLUE);
setNotificationLED(NOTIF_LED_RED | NOTIF_LED_BLUE, 0);

int selected = 0;
while (1) {
Expand Down
93 changes: 92 additions & 1 deletion ios_mcp/source/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,77 @@

#define HW_RSTB 0x0d800194

enum {
ASYNC_MESSAGE_STOP_THREAD,
ASYNC_MESSAGE_SET_LED,
};

static int asyncThreadHandle = -1;
static uint8_t asyncThreadStack[0x400] __attribute__((aligned(0x20)));
static uint32_t asyncMessageQueueBuf[0x20];
static int asyncMessageQueue = -1;
static int ledTimer = -1;
static uint8_t currentLedMask = NOTIF_LED_RED | NOTIF_LED_BLUE;

static int SMC_SetNotificationLED(uint8_t mask);

static int asyncThread(void* arg)
{
while (1) {
// Blocking wait for messages
uint32_t message;
if (IOS_ReceiveMessage(asyncMessageQueue, &message, IOS_MESSAGE_FLAGS_NONE) < 0) {
return 0;
}

switch (message) {
case ASYNC_MESSAGE_STOP_THREAD:
return 0;
case ASYNC_MESSAGE_SET_LED:
SMC_SetNotificationLED(currentLedMask);
break;
default:
break;
}
}
}

int initializeUtils(void)
{
asyncMessageQueue = IOS_CreateMessageQueue(asyncMessageQueueBuf, sizeof(asyncMessageQueueBuf) / 4);
if (asyncMessageQueue < 0) {
return -1;
}

asyncThreadHandle = IOS_CreateThread(asyncThread, NULL, asyncThreadStack + sizeof(asyncThreadStack), sizeof(asyncThreadStack), IOS_GetThreadPriority(0) - 0x20, IOS_THREAD_FLAGS_NONE);
if (asyncThreadHandle < 0) {
return -1;
}

if (IOS_StartThread(asyncThreadHandle) < 0) {
return -1;
}

ledTimer = IOS_CreateTimer(0, 0, asyncMessageQueue, ASYNC_MESSAGE_SET_LED);
if (ledTimer < 0) {
return -1;
}

return 0;
}

int finalizeUtils(void)
{
// Tell thread to stop and wait
IOS_SendMessage(asyncMessageQueue, ASYNC_MESSAGE_STOP_THREAD, IOS_MESSAGE_FLAGS_NONE);
IOS_JoinThread(asyncThreadHandle, NULL);

IOS_DestroyTimer(ledTimer);
IOS_DestroyMessageQueue(asyncMessageQueue);

return 0;
}

uint32_t kernRead32(uint32_t address)
{
return IOS_Syscall0x81(0, address, 0);
Expand Down Expand Up @@ -101,7 +172,7 @@ int SMC_ReadSystemEventFlag(uint8_t* flag)
return bspRead("SMC", 0, "SystemEventFlag", 1, flag);
}

int SMC_SetNotificationLED(uint8_t mask)
static int SMC_SetNotificationLED(uint8_t mask)
{
return bspWrite("SMC", 0, "NotificationLED", 1, &mask);
}
Expand All @@ -110,3 +181,23 @@ int SMC_SetODDPower(int power)
{
return bspWrite("SMC", 0, "ODDPower", 4, &power);
}

void setNotificationLED(uint8_t mask, uint32_t duration)
{
// Cancel any pending led updates
IOS_StopTimer(ledTimer);

if (currentLedMask == mask) {
return;
}

SMC_SetNotificationLED(mask);

if (duration) {
// Don't update the current LED mask and tell the async thread to restore the current LED mask
// after the specified duration
IOS_RestartTimer(ledTimer, duration * 1000, 0);
} else {
currentLedMask = mask;
}
}
8 changes: 6 additions & 2 deletions ios_mcp/source/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ enum {
NOTIF_LED_BLUE = 1 << 5,
};

int initializeUtils(void);

int finalizeUtils(void);

uint32_t kernRead32(uint32_t address);

void kernWrite32(uint32_t address, uint32_t value);
Expand All @@ -69,6 +73,6 @@ int DISPLAY_ReadDCConfig(DC_Config* config);

int SMC_ReadSystemEventFlag(uint8_t* flag);

int SMC_SetNotificationLED(uint8_t mask);

int SMC_SetODDPower(int power);

void setNotificationLED(uint8_t mask, uint32_t duration);
2 changes: 1 addition & 1 deletion ios_mcp/source/wupserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ void wupserver_init(void)
if (!serverRunning) {
serverSocket = -1;

threadId = IOS_CreateThread(wupserver_thread, NULL, threadStack + sizeof(threadStack), sizeof(threadStack), IOS_GetThreadPriority(0), 0);
threadId = IOS_CreateThread(wupserver_thread, NULL, threadStack + sizeof(threadStack), sizeof(threadStack), IOS_GetThreadPriority(0), IOS_THREAD_FLAGS_NONE);
if(threadId >= 0) {
IOS_StartThread(threadId);
serverRunning = 1;
Expand Down

0 comments on commit 2203a92

Please sign in to comment.