PSC (Power State Control) provides services related to power state changes in the system.

Concept

psc:m allows a process to register a module that depends on power management in some way. A client calls GetPmModule to receive an IPmModule (Power Managed Module), and then calls IPmModule->Initialize(module_id, module_dependency_list) where module_id is the ModuleId enum member for the client, and the dependency list is an array of module IDs for the modules that this depends on. Initialize() returns an event handle that the client can wait on to be notified of a power state change.

psc:c allows a module to the power state controller for the system (in practice, AM is the only client to the controller). IPmControl->DispatchRequest() is used notify all IPmModules of a state change.

For example, FS registers itself as an IPmModule with dependencies on pinmux, gpio, pcv, tma, and initializes the SD card once those dependencies have registered..

It then does (basically) the following pseudocode (actual code located at .text + 0xB2DB0 in 6.0.0 FS):

   while (true) {
       Fs_IPmModule->WaitSignaled();
       
       Fs_IPmModule->GetRequest(&state);
       switch (state) {
           case WakingUp:
               /* hardware devices are woken up here */
           case GoingToSleep:
               /* hardware devices are put to sleep here */
           case ShuttingDown:
               /* hardware devices are turned off here */
       }
       
       Fs_IPmModule->Acknowledge(state);
   }

psc:c

This is "nn::psc::sf::IPmControl".

Cmd Name
0 Initialize
1 DispatchRequest
2 GetResult
3 GetState
4 Cancel
5 [1.0.0-6.2.0] PrintModuleInformation
6 GetModuleInformation
10 [9.0.0+]
11 [9.0.0+]

psc:m

This is "nn::psc::sf::IPmService".

Cmd Name Notes
0 GetPmModule Returns an #IPmModule.

IPmModule

This is "nn::psc::sf::IPmModule".

Cmd Name
0 Initialize
1 GetRequest
2 Acknowledge
3 Finalize
4 [5.1.0+] AcknowledgeEx

psc:l

This was added with [9.0.0+].

Cmd Name
0
1
2
3
4

srepo:u, srepo:a

These are "nn::srepo::detail::ipc::ISrepoService".

These were added with [5.0.0+].

Cmd Name
10100
10101 [6.0.0+]
10200 [6.0.0+]
10201 [6.0.0+]
11000 [6.0.0+]
11001 [6.0.0+]
11002 [6.0.0+]
11003 [6.0.0+]
11004 [6.0.0+]
11100 [6.0.0+]
11200 [6.0.0+]
11300 [6.0.0+]
11400 [6.0.0+]
11500 [6.0.0+]
11600 [6.0.0+]
11601 [6.0.0+]
11602 [6.0.0+]
11700 [6.0.0+]
11800 [6.0.0+]
11801 [6.0.0+]
11810 [8.0.0+]
11811 [8.0.0+]
12000 [8.0.0+]
12001 [8.0.0+]
13000 [8.0.0+]
13001 [8.0.0+]
20100
20200
20300 [6.0.0+]
20400 [6.0.0+]
20401 [6.0.0+]
20402 [7.0.0+]
20500 [8.0.0+]

Cmd13000

Takes a type-0x5 input buffer, no output.

[9.0.0+] No input, returns a total of 0xC-bytes of output, an #IUnknown0, and a handle.

IUnknown0

Added with [9.0.0+].

Cmd Name
0

Cmd0: no input, returns a total of 8-bytes of output.

ovln:rcv

This is "nn::ovln::IReceiverService".

Cmd Name
0 OpenReceiver

IReceiver

This is "nn::ovln::IReceiver".

Cmd Name
0 AddSource
1 RemoveSource
2 GetReceiveEventHandle
3 Receive
4 ReceiveWithTick

ovln:snd

This is "nn::ovln::ISenderService".

Cmd Name
0 OpenSender

ISender

This is "nn::ovln::ISender".

Cmd Name
0 Send
1 GetUnreceivedMessageCount

time:m

This is "nn::timesrv::detail::service::ITimeServiceManager".

This was added with [9.0.0+].

Cmd Name
0 #GetUserStaticService
5 #GetAdminStaticService
6 #GetRepairStaticService
9 #GetManufactureStaticService
10 #SetupStandardSteadyClock
11 #SetupStandardLocalSystemClock
12 #SetupStandardNetworkSystemClock
13 #SetupStandardUserSystemClock
14 #SetupTimeZoneManager
15 #SetupEphemeralNetworkSystemClock
50
51
52
60 GetStandardUserSystemClockAutomaticCorrectionEvent
100 #SetStandardSteadyClockRtcOffset
200 GetAlarmRegistrationEvent
201 #UpdateSteadyAlarms
202

GetUserStaticService

Returns an #IStaticService.

This is used for the wrapped instance of "time:u" in glue.

GetAdminStaticService

Returns an #IStaticService.

This is used for the wrapped instance of "time:a" in glue.

GetRepairStaticService

Returns an #IStaticService.

This is used for the wrapped instance of "time:r" in glue.

GetManufactureStaticService

Returns an #IStaticService.

This seems unused.

SetupStandardSteadyClock

Takes an input rtc_clock_source UUID, an input rtc_offset s64, an input internal_offset s64, an input test_offset s64 and a is_rtc_reset_detected bool. No output.

SetupStandardLocalSystemClock

Takes an input #SystemClockContext and an input #PosixTime. No output.

SetupStandardNetworkSystemClock

Takes an input #SystemClockContext and an input sufficient_accuracy_minutes u64. No output.

SetupStandardUserSystemClock

Takes an input automatic_correction bool and an input #SteadyClockTimePoint. No output.

SetupTimeZoneManager

Takes an input #LocationName, an input #SteadyClockTimePoint, an input total_location_name_count u32, an input #TimeZoneRuleVersion and a type-0x21 input buffer containing a TimeZoneBinary. No output.

SetupEphemeralNetworkSystemClock

No input, no output.

SetStandardSteadyClockRtcOffset

An input rtc_offset s64, no output.

UpdateSteadyAlarms

No input, no output.

time:al

This is "nn::timesrv::detail::service::IAlarmService".

This was added with [9.0.0+].

Cmd Name
0
1

Cmd0/cmd1: no input, returns an #ISteadyClockAlarm.

ISteadyClockAlarm

This is "nn::timesrv::detail::service::ISteadyClockAlarm".

This was added with [9.0.0+].

Cmd Name
0 GetWakeUpEvent
1 Enable
2 Disable
3 IsEnabled
10
11

Cmd10

Opens a session for psc:l and returns it's interface.

Cmd11

Close the session opened by #Cmd10 when the alarm is disabled.

time:p

This is "nn::timesrv::detail::service::IPowerStateRequestHandler".

This was added with [9.0.0+].

Cmd Name
0
1

time:su, time:s

These are "nn::timesrv::detail::service::IStaticService".

These were added with [9.0.0+].

Cmd Name Notes
0 GetStandardUserSystemClock Returns an #ISystemClock.
1 GetStandardNetworkSystemClock Returns an #ISystemClock.
2 GetStandardSteadyClock Returns an #ISteadyClock.
3 GetTimeZoneService Returns an #ITimeZoneService.
4 GetStandardLocalSystemClock Returns an #ISystemClock.
5 [4.0.0+] GetEphemeralNetworkSystemClock Returns an #ISystemClock.
20 [6.0.0+] GetSharedMemoryNativeHandle
30 [6.0.0-8.1.0] GetStandardNetworkClockOperationEventReadableHandle
31 [6.0.0-8.1.0] GetEphemeralNetworkClockOperationEventReadableHandle
50 [4.0.0+] SetStandardSteadyClockInternalOffset
51 [9.0.0+] GetStandardSteadyClockRtcValue
100 IsStandardUserSystemClockAutomaticCorrectionEnabled
101 SetStandardUserSystemClockAutomaticCorrectionEnabled
102 [5.0.0+] GetStandardUserSystemClockInitialYear
200 [3.0.0+] IsStandardNetworkSystemClockAccuracySufficient
201 [6.0.0+] GetStandardUserSystemClockAutomaticCorrectionUpdatedTime
300 [4.0.0+] CalculateMonotonicSystemClockBaseTimePoint
400 [4.0.0+] GetClockSnapshot
401 [4.0.0+] GetClockSnapshotFromSystemClockContext
500 [4.0.0+] CalculateStandardUserSystemClockDifferenceByUser
501 [4.0.0+] CalculateSpanBetween

ISteadyClock

This is "nn::timesrv::detail::service::ISteadyClock".

Cmd Name Notes
0 GetCurrentTimePoint No input, returns an output #SteadyClockTimePoint.
2 GetTestOffset No input, returns an output #TimeSpanType.
3 SetTestOffset Takes an input #TimeSpanType, no output.
100 [2.0.0+] GetRtcValue No input, returns an output s64.
101 [2.0.0+] IsRtcResetDetected No input, returns an output u8 bool.
102 [2.0.0+] GetSetupResultValue No input, returns an output u32.
200 [3.0.0+] GetInternalOffset No input, returns an output #TimeSpanType.
201 [3.0.0-3.0.2] SetInternalOffset Takes an input #TimeSpanType, no output.

SteadyClockTimePoint

Offset Size Description
0x0 0x8 A u64 representing a point in time.
0x8 0x10 An ID representing the clock source.

This is a 0x18-byte struct.

TimeSpanType

This is an u64.

ISystemClock

This is "nn::timesrv::detail::service::ISystemClock".

Cmd Name Notes
0 GetCurrentTime Returns an output #PosixTime.
1 SetCurrentTime Takes an input #PosixTime.
2 GetSystemClockContext Returns an output #SystemClockContext.
3 SetSystemClockContext Takes an input #SystemClockContext.
4 [9.0.0+] GetOperationEventReadableHandle

PosixTime

This is an s64 for UTC POSIX time.

SystemClockContext

This is an 0x20-byte struct.

Offset Size Description
0x0 0x8 a #PosixTime representing the system clock epoch.
0x8 0x18 a #SteadyClockTimePoint

ITimeZoneService

This is "nn::timesrv::detail::service::ITimeZoneService".

Cmd Name Notes
0 GetDeviceLocationName No input, returns an output #LocationName.
1 SetDeviceLocationName Takes an input #LocationName, no output.
2 GetTotalLocationNameCount No input, returns an output s32.
3 LoadLocationNameList
4 LoadTimeZoneRule Takes an input #LocationName and a type-0x16 output buffer for #TimeZoneRule, no output.
5 [2.0.0+] GetTimeZoneRuleVersion No input, returns an output #TimeZoneRuleVersion.
6 [5.0.0+] GetDeviceLocationNameAndUpdatedTime
7 [9.0.0+] SetDeviceLocationNameWithTimeZoneRule
8 [9.0.0+] ParseTimeZoneBinary
20 [9.0.0+] GetDeviceLocationNameOperationEventReadableHandle
100 ToCalendarTime Takes an input #PosixTime and a type-0x15 input buffer for #TimeZoneRule, returns an output #CalendarTime and #CalendarAdditionalInfo.
101 ToCalendarTimeWithMyRule Takes an input #PosixTime, returns an output #CalendarTime and #CalendarAdditionalInfo.
201 ToPosixTime Takes an input #CalendarTime, a type-0x15 input buffer for #TimeZoneRule, an type-0xA output buffer for #PosixTime array, and returns an output s32.
202 ToPosixTimeWithMyRule Takes an input #CalendarTime, an type-0xA output buffer for #PosixTime array, and returns an output s32.

LoadLocationNameList

Takes an input s32 LocationName_index and a type-0x6 output buffer for #LocationName, returns an output s32 for total output entries.

LocationName

This contains a TimeZone location string with a max size of 0x24 bytes.

TimeZoneRule

This is an 0x4000-byte struct. Official sw uses fixed-size 0x4000 for the buffer size with the above commands.

This is loaded from the TimeZoneBinary title with the specified LocationName under the zoneinfo/ directory, the content is then converted into this TimeZoneRule structure.

The files contained under zoneinfo/ directory are Tzif2 files without Tzif1 header and data at the begining of them (see RFC8536 for more information).

The conversion of a Tzif2 file to a TimeZoneRule structure is based on tz database code with some custom modifications (Leap seconds aren't handled, no usage of "posixrules" and Tzif1 support stripped out).

Offset Size Description
0x0 0x4 timecnt
0x4 0x4 typecnt
0x8 0x4 charcnt
0xC 0x1 goback
0xD 0x1 goahead
0xE 0x2 Padding
0x10 0x8 * 1000 ats
0x1f50 0x1 * 1000 types
0x2338 0x10 * 128 ttis (time type information), struct ttinfo[1000]
0x2b38 0x1 * 512 chars
0x2d38 0x4 defaulttype
0x2d3c 0x12c4 Reserved / Unused

ttinfo

This is an 0x10-byte struct. Represent a Time Type Information used in #TimeZoneRule.

Offset Size Description
0x0 0x4 tt_gmtoff
0x4 0x1 tt_isdst
0x5 0x3 Padding
0x8 0x4 tt_abbrind
0xC 0x1 tt_ttisstd
0xD 0x1 tt_ttisgmt
0xE 0x2 Padding

TimeZoneRuleVersion

This is an u128.

CalendarTime

Offset Size Description
0x0 0x2 Year
0x2 0x1 Month
0x3 0x1 Day
0x4 0x1 Hour
0x5 0x1 Minute
0x6 0x1 Second
0x7 0x1 Padding / unknown?

This is an 0x8-byte struct.

CalendarAdditionalInfo

Offset Size Description
0x0 0x4 0-based day-of-week.
0x4 0x4 0-based day-of-year.
0x8 0x8 Timezone name string.
0x10 0x4 0 = no DST, 1 = DST.
0x14 0x4 s32 seconds relative to UTC for this timezone.

This is an 0x18-byte struct. This stores timezone info.

ins:r

This is "nn::ins::IReceiverManager".

This was added with [9.0.0+].

Cmd Name
0
1

Cmd0

Takes an input u32 InsID. Returns an u64.

Cmd1

Takes an input u32 InsID and an input u64 (unused, official software passes struct pointer). Returns an output Event handle with autoclear disabled.

ins:s

This is "nn::ins::ISenderManager".

This was added with [9.0.0+].

Cmd Name
0

Cmd0

Takes an input u32 InsID and an input u64 (unused, official software passes struct pointer). Returns an output Event handle with autoclear disabled.

PSC Module IDs

ID Module
0x03
0x04 PmModuleId_Usb
0x05 PmModuleId_Ethernet
0x06 PmModuleId_Fgm
0x07 PmModuleId_PcvClock
0x08 PmModuleId_PcvVoltage
0x09 PmModuleId_Gpio
0x0A PmModuleId_Pinmux
0x0B PmModuleId_Uart
0x0C PmModuleId_I2c
0x0D PmModuleId_I2cPcv
0x0E PmModuleId_Spi
0x0F PmModuleId_Pwm
0x10 PmModuleId_Psm
0x11 PmModuleId_Tc
0x12 PmModuleId_Omm
0x13 PmModuleId_Pcie
0x14 PmModuleId_Lbl
0x15 PmModuleId_Display
0x18 PmModuleId_Hid
0x19 PmModuleId_WlanSockets
0x1B PmModuleId_Fs
0x1C PmModuleId_Audio
0x1E PmModuleId_TmaHostIo
0x1F PmModuleId_Bluetooth
0x20 PmModuleId_Bpc
0x21 PmModuleId_Fan
0x22 PmModuleId_Pcm
0x23 PmModuleId_Nfc
0x24 PmModuleId_Apm
0x25 PmModuleId_Btm
0x26 PmModuleId_Nifm
0x27 PmModuleId_GpioLow
0x28 PmModuleId_Npns
0x29 PmModuleId_Lm
0x2A PmModuleId_Bcat
0x2B PmModuleId_Time
0x2C PmModuleId_Pctl
0x2D PmModuleId_Erpt
0x2E PmModuleId_Eupld
0x2F PmModuleId_Friends
0x30 PmModuleId_Bgtc
0x31 PmModuleId_Account
0x32 PmModuleId_Sasbus
0x33 PmModuleId_Ntc
0x34 PmModuleId_Idle
0x35 PmModuleId_Tcap
0x36 PmModuleId_PsmLow
0x37 PmModuleId_Ndd
0x65 PmModuleId_Nvservices
0x7F PmModuleId_Spsm

Power Management States

ID Name Description
Awake 0 Everything is awake.
ReadyAwaken 1 Preparing to transition to awake.
ReadySleep 2 Preparing to transition to sleep.
ReadySleepCritical 3 Critical services are ready to sleep.
ReadyAwakenCritical 4 Critical services are ready to wake up.
ReadyShutdown 5 Preparing to transition to shutdown.