diff --git a/sysmodules/rosalina/include/mcu.h b/sysmodules/rosalina/include/mcu.h new file mode 100644 index 00000000..7472853b --- /dev/null +++ b/sysmodules/rosalina/include/mcu.h @@ -0,0 +1,9 @@ +#include <3ds.h> + +Handle mcuhwcHandle; + +Result mcuInit(void); +Result mcuExit(void); +Result mcuReadRegister(u8 reg, u8* data, u32 size); +Result mcuWriteRegister(u8 reg, u8* data, u32 size); +Result mcuGetLEDState(u8* out); diff --git a/sysmodules/rosalina/include/menus/miscellaneous.h b/sysmodules/rosalina/include/menus/miscellaneous.h index c628c65b..fa8bbd45 100644 --- a/sysmodules/rosalina/include/menus/miscellaneous.h +++ b/sysmodules/rosalina/include/menus/miscellaneous.h @@ -35,6 +35,7 @@ void MiscellaneousMenu_SwitchBoot3dsxTargetTitle(void); void MiscellaneousMenu_ChangeMenuCombo(void); void MiscellaneousMenu_SaveSettings(void); void MiscellaneousMenu_InputRedirection(void); +void MiscellaneousMenu_ToggleLEDs(void); void MiscellaneousMenu_ToggleWireless(void); void MiscellaneousMenu_PowerOff(void); void MiscellaneousMenu_Reboot(void); diff --git a/sysmodules/rosalina/source/mcu.c b/sysmodules/rosalina/source/mcu.c new file mode 100644 index 00000000..ce3177ba --- /dev/null +++ b/sysmodules/rosalina/source/mcu.c @@ -0,0 +1,42 @@ +#include "mcu.h" + +Result mcuInit(void) +{ + return srvGetServiceHandle(&mcuhwcHandle, "mcu::HWC"); +} + +Result mcuExit(void) +{ + return svcCloseHandle(mcuhwcHandle); +} + +Result mcuReadRegister(u8 reg, u8* data, u32 size) +{ + u32* ipc = getThreadCommandBuffer(); + ipc[0] = 0x10082; + ipc[1] = reg; + ipc[2] = size; + ipc[3] = size << 4 | 0xC; + ipc[4] = (u32)data; + Result ret = svcSendSyncRequest(mcuhwcHandle); + if(ret < 0) return ret; + return ipc[1]; +} + +Result mcuWriteRegister(u8 reg, u8* data, u32 size) +{ + u32* ipc = getThreadCommandBuffer(); + ipc[0] = 0x20082; + ipc[1] = reg; + ipc[2] = size; + ipc[3] = size << 4 | 0xA; + ipc[4] = (u32)data; + Result ret = svcSendSyncRequest(mcuhwcHandle); + if(ret < 0) return ret; + return ipc[1]; +} + +Result mcuGetLEDState(u8* out) +{ + return mcuReadRegister(0x28, out, 1); +} diff --git a/sysmodules/rosalina/source/menu.c b/sysmodules/rosalina/source/menu.c index c320b772..cb8c0972 100644 --- a/sysmodules/rosalina/source/menu.c +++ b/sysmodules/rosalina/source/menu.c @@ -28,6 +28,7 @@ #include "menu.h" #include "draw.h" #include "fmt.h" +#include "mcu.h" #include "memory.h" #include "ifile.h" #include "menus.h" @@ -125,11 +126,10 @@ u32 waitCombo(void) static Result _MCUHWC_GetBatteryLevel(u8 *out) { - #define TRY(expr) if(R_FAILED(res = (expr))) { svcCloseHandle(mcuhwcHandle); return res; } + #define TRY(expr) if(R_FAILED(res = (expr))) { mcuExit(); return res; } Result res; - Handle mcuhwcHandle; - TRY(srvGetServiceHandle(&mcuhwcHandle, "mcu::HWC")); + TRY(mcuInit()); u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = 0x50000; diff --git a/sysmodules/rosalina/source/menus/miscellaneous.c b/sysmodules/rosalina/source/menus/miscellaneous.c index 797046df..f4fa47ab 100644 --- a/sysmodules/rosalina/source/menus/miscellaneous.c +++ b/sysmodules/rosalina/source/menus/miscellaneous.c @@ -27,6 +27,7 @@ #include <3ds.h> #include "menus/miscellaneous.h" #include "input_redirection.h" +#include "mcu.h" #include "memory.h" #include "draw.h" #include "hbloader.h" @@ -37,14 +38,15 @@ Menu miscellaneousMenu = { "Miscellaneous options menu", - .nbItems = 7, + .nbItems = 8, { { "Switch the hb. title to the current app.", METHOD, .method = &MiscellaneousMenu_SwitchBoot3dsxTargetTitle }, { "Change the menu combo", METHOD, .method = MiscellaneousMenu_ChangeMenuCombo }, { "Save settings", METHOD, .method = &MiscellaneousMenu_SaveSettings }, { "Start InputRedirection", METHOD, .method = &MiscellaneousMenu_InputRedirection }, + { "Toggle LEDs", METHOD, .method = &MiscellaneousMenu_ToggleLEDs }, { "Toggle Wireless", METHOD, .method = &MiscellaneousMenu_ToggleWireless }, - { "Power off", METHOD, .method = &MiscellaneousMenu_PowerOff }, + { "Power Off", METHOD, .method = &MiscellaneousMenu_PowerOff }, { "Reboot", METHOD, .method = &MiscellaneousMenu_Reboot }, } }; @@ -130,6 +132,7 @@ static void MiscellaneousMenu_ConvertComboToString(char *out, u32 combo) out[-1] = 0; } + void MiscellaneousMenu_ChangeMenuCombo(void) { char comboStrOrig[64], comboStr[64]; @@ -336,6 +339,40 @@ void MiscellaneousMenu_InputRedirection(void) while(!(waitInput() & BUTTON_B) && !terminationRequest); } +void MiscellaneousMenu_ToggleLEDs(void) +{ + Draw_Lock(); + Draw_ClearFramebuffer(); + Draw_FlushFramebuffer(); + Draw_Unlock(); + + do + { + Draw_Lock(); + Draw_DrawString(10, 10, COLOR_TITLE, "Miscellaneous options menu"); + Draw_DrawString(10, 30, COLOR_WHITE, "Press A to toggle, press B to go back."); + Draw_DrawString(10, 40, COLOR_RED, "NOTE: Entering sleep mode will reset the LED state!"); + + Draw_FlushFramebuffer(); + Draw_Unlock(); + + u32 pressed = waitInputWithTimeout(1000); + + if(pressed & BUTTON_A) + { + mcuInit(); + u8 result; + mcuGetLEDState(&result); + u8 value = ~result; + mcuWriteRegister(40, &value, 1); + mcuExit(); + } + else if(pressed & BUTTON_B) + return; + } + while(!terminationRequest); +} + void MiscellaneousMenu_ToggleWireless(void) { Draw_Lock();