Changes

Jump to navigation Jump to search
8,682 bytes added ,  19:09, 18 May 2022
no edit summary
Line 79: Line 79:  
|-
 
|-
 
| 83 || [6.0.0+] [[#IsFirmwareUpdateAvailableForSixAxisSensor]]
 
| 83 || [6.0.0+] [[#IsFirmwareUpdateAvailableForSixAxisSensor]]
 +
|-
 +
| 84 || [13.0.0+] EnableSixAxisSensorUnalteredPassthrough
 +
|-
 +
| 85 || [13.0.0+] IsSixAxisSensorUnalteredPassthroughEnabled
 +
|-
 +
| 86 || [13.0.0+] StoreSixAxisSensorCalibrationParameter
 +
|-
 +
| 87 || [13.0.0+] LoadSixAxisSensorCalibrationParameter
 +
|-
 +
| 88 || [13.0.0+] GetSixAxisSensorIcInformation
 +
|-
 +
| 89 || [13.0.0+] ResetIsSixAxisSensorDeviceNewlyAssigned
 
|-
 
|-
 
| 91 || [[#ActivateGesture]]
 
| 91 || [[#ActivateGesture]]
Line 726: Line 738:     
== GetPalmaOperationInfo ==
 
== GetPalmaOperationInfo ==
Takes a [[#PalmaConnectionHandle]], a type-0x6 output buffer, returns an output u64.
+
Takes a [[#PalmaConnectionHandle]], a type-0x6 output buffer, returns an output u64 [[#PalmaOperationType]].
    
sdknso passes [[#PalmaOperationInfo]]+0x8 size 0x140 for the output buffer. [5.1.0+] After using the cmd successfully, [[#GetPalmaOperationResult]] is used.
 
sdknso passes [[#PalmaOperationInfo]]+0x8 size 0x140 for the output buffer. [5.1.0+] After using the cmd successfully, [[#GetPalmaOperationResult]] is used.
Line 735: Line 747:  
Takes an input [[#PalmaConnectionHandle]], an u64 (exposed by sdknso as an u16), no output.
 
Takes an input [[#PalmaConnectionHandle]], an u64 (exposed by sdknso as an u16), no output.
   −
See [[#hidGetPalmaOperationInfo]].
+
See [[#GetPalmaOperationInfo]].
    
== SetPalmaFrModeType ==
 
== SetPalmaFrModeType ==
 
Takes an input [[#PalmaConnectionHandle]], an u64 [[#PalmaFrModeType]], no output.
 
Takes an input [[#PalmaConnectionHandle]], an u64 [[#PalmaFrModeType]], no output.
   −
See [[#hidGetPalmaOperationInfo]].
+
See [[#GetPalmaOperationInfo]].
    
== ReadPalmaStep ==
 
== ReadPalmaStep ==
 
Takes an input [[#PalmaConnectionHandle]], no output.
 
Takes an input [[#PalmaConnectionHandle]], no output.
   −
See [[#hidGetPalmaOperationInfo]].
+
See [[#GetPalmaOperationInfo]].
    
[[#EnablePalmaStep]] should be used before this.
 
[[#EnablePalmaStep]] should be used before this.
Line 752: Line 764:  
Takes an input bool, a [[#PalmaConnectionHandle]], no output.
 
Takes an input bool, a [[#PalmaConnectionHandle]], no output.
   −
See [[#hidGetPalmaOperationInfo]].
+
See [[#GetPalmaOperationInfo]].
    
== ResetPalmaStep ==
 
== ResetPalmaStep ==
 
Takes an input [[#PalmaConnectionHandle]], no output.
 
Takes an input [[#PalmaConnectionHandle]], no output.
   −
See [[#hidGetPalmaOperationInfo]].
+
See [[#GetPalmaOperationInfo]].
    
== ReadPalmaApplicationSection ==
 
== ReadPalmaApplicationSection ==
Line 764: Line 776:  
sdknso exposes the first u64 as a s32. sdknso will Abort if the input value for the second u64 is >0x100.
 
sdknso exposes the first u64 as a s32. sdknso will Abort if the input value for the second u64 is >0x100.
   −
See [[#hidGetPalmaOperationInfo]].
+
See [[#GetPalmaOperationInfo]].
    
== WritePalmaApplicationSection ==
 
== WritePalmaApplicationSection ==
Line 771: Line 783:  
sdknso exposes the first u64 as a s32. Data is copied from the input [[#PalmaApplicationSectionAccessBuffer]] with the specified size.
 
sdknso exposes the first u64 as a s32. Data is copied from the input [[#PalmaApplicationSectionAccessBuffer]] with the specified size.
   −
See [[#hidGetPalmaOperationInfo]].
+
See [[#GetPalmaOperationInfo]].
    
== ReadPalmaUniqueCode ==
 
== ReadPalmaUniqueCode ==
 
Takes an input [[#PalmaConnectionHandle]], no output.
 
Takes an input [[#PalmaConnectionHandle]], no output.
   −
See [[#hidGetPalmaOperationInfo]].
+
See [[#GetPalmaOperationInfo]].
    
== SetPalmaUniqueCodeInvalid ==
 
== SetPalmaUniqueCodeInvalid ==
 
Takes an input [[#PalmaConnectionHandle]], no output.
 
Takes an input [[#PalmaConnectionHandle]], no output.
   −
See [[#hidGetPalmaOperationInfo]].
+
See [[#GetPalmaOperationInfo]].
    
== WritePalmaActivityEntry ==
 
== WritePalmaActivityEntry ==
Line 788: Line 800:  
sdknso exposes the first u64 as an u16, while the rest are exposed as [[#PalmaActivityEntry]].
 
sdknso exposes the first u64 as an u16, while the rest are exposed as [[#PalmaActivityEntry]].
   −
See [[#hidGetPalmaOperationInfo]].
+
See [[#GetPalmaOperationInfo]].
    
== WritePalmaRgbLedPatternEntry ==
 
== WritePalmaRgbLedPatternEntry ==
Line 795: Line 807:  
sdknso exposes the u64 as an u16.
 
sdknso exposes the u64 as an u16.
   −
See [[#hidGetPalmaOperationInfo]].
+
See [[#GetPalmaOperationInfo]].
    
== WritePalmaWaveEntry ==
 
== WritePalmaWaveEntry ==
Line 804: Line 816:  
Note that the sysmodule will not properly close the TransferMemory handle if the [[#PalmaConnectionHandle]] is invalid.
 
Note that the sysmodule will not properly close the TransferMemory handle if the [[#PalmaConnectionHandle]] is invalid.
   −
See [[#hidGetPalmaOperationInfo]].
+
See [[#GetPalmaOperationInfo]].
    
== SetPalmaDataBaseIdentificationVersion ==
 
== SetPalmaDataBaseIdentificationVersion ==
 
Takes an input s32, a [[#PalmaConnectionHandle]], no output.
 
Takes an input s32, a [[#PalmaConnectionHandle]], no output.
   −
See [[#hidGetPalmaOperationInfo]].
+
See [[#GetPalmaOperationInfo]].
    
== GetPalmaDataBaseIdentificationVersion ==
 
== GetPalmaDataBaseIdentificationVersion ==
 
Takes an input [[#PalmaConnectionHandle]], no output.
 
Takes an input [[#PalmaConnectionHandle]], no output.
   −
See [[#hidGetPalmaOperationInfo]].
+
See [[#GetPalmaOperationInfo]].
    
== SuspendPalmaFeature ==
 
== SuspendPalmaFeature ==
 
Takes an input "nn::util::BitFlagSet<32, [[#PalmaFeature]]>", a [[#PalmaConnectionHandle]], no output.
 
Takes an input "nn::util::BitFlagSet<32, [[#PalmaFeature]]>", a [[#PalmaConnectionHandle]], no output.
   −
See [[#hidGetPalmaOperationInfo]].
+
See [[#GetPalmaOperationInfo]].
    
== GetPalmaOperationResult ==
 
== GetPalmaOperationResult ==
Line 829: Line 841:  
Takes an input u16, a [[#PalmaConnectionHandle]], no output.
 
Takes an input u16, a [[#PalmaConnectionHandle]], no output.
   −
See [[#hidGetPalmaOperationInfo]].
+
See [[#GetPalmaOperationInfo]].
    
== ResetPalmaPlayLog ==
 
== ResetPalmaPlayLog ==
 
Takes an input u16, a [[#PalmaConnectionHandle]], no output.
 
Takes an input u16, a [[#PalmaConnectionHandle]], no output.
   −
See [[#hidGetPalmaOperationInfo]].
+
See [[#GetPalmaOperationInfo]].
    
== SetIsPalmaAllConnectable ==
 
== SetIsPalmaAllConnectable ==
 
Takes a PID, a bool, an [[AM_services|AppletResourceUserId]], no output.
 
Takes a PID, a bool, an [[AM_services|AppletResourceUserId]], no output.
 +
 +
The sysmodule also calls the code which eventually runs from this, from various other funcs internally (bool value varies).
 +
 +
This updates various state. If needed, this uses either [[BTM_services|StartBleScanForGeneral]] or [[BTM_services|StopBleScanForGeneral]].
    
== SetIsPalmaPairedConnectable ==
 
== SetIsPalmaPairedConnectable ==
 
Takes a PID, a bool, an [[AM_services|AppletResourceUserId]], no output.
 
Takes a PID, a bool, an [[AM_services|AppletResourceUserId]], no output.
 +
 +
The actual cmd impl ignores the PID/AppletResourceUserId.
 +
 +
This code is also called by another func internally by the sysmodule, where flag = {whether bit6 in a field is set} (presumably [[#NpadStyleSet]]). This is eventually called from various funcs, including [[#SetSupportedNpadStyleSet]].
 +
 +
This updates various state. If needed, this uses either [[BTM_services|StartBleScanForPairedDevice]] or [[BTM_services|StopBleScanForPairedDevice]].
    
== PairPalma ==
 
== PairPalma ==
 
Takes an input [[#PalmaConnectionHandle]], no output.
 
Takes an input [[#PalmaConnectionHandle]], no output.
 +
 +
This eventually uses [[BTM_services#BlePairDevice|BlePairDevice]] if needed, and updates state.
    
== SetPalmaBoostMode ==
 
== SetPalmaBoostMode ==
Line 886: Line 910:     
== IAppletResource ==
 
== IAppletResource ==
 +
This is "nn::hid::IAppletResource".
 +
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 931: Line 957:  
|-
 
|-
 
| 14 || [11.0.0+] ProcessTouchScreenAutoTune
 
| 14 || [11.0.0+] ProcessTouchScreenAutoTune
 +
|-
 +
| 15 || [13.0.0+] ForceStopTouchScreenManagement
 +
|-
 +
| 16 || [13.0.0+] ForceRestartTouchScreenManagement
 +
|-
 +
| 17 || [13.0.0+] IsTouchScreenManaged
 
|-
 
|-
 
| 20 || [[#DeactivateMouse]]
 
| 20 || [[#DeactivateMouse]]
Line 966: Line 998:  
| 112 || UnsetHomeButtonAutoPilotState
 
| 112 || UnsetHomeButtonAutoPilotState
 
|-
 
|-
| 120 || DeactivateSleepButton
+
| 120 || [[#DeactivateSleepButton]]
 
|-
 
|-
| 121 || SetSleepButtonAutoPilotState
+
| 121 || [[#SetSleepButtonAutoPilotState]]
 
|-
 
|-
| 122 || UnsetSleepButtonAutoPilotState
+
| 122 || [[#UnsetSleepButtonAutoPilotState]]
 
|-
 
|-
 
| 123 || [1.0.0-9.2.0] DeactivateInputDetector
 
| 123 || [1.0.0-9.2.0] DeactivateInputDetector
Line 1,097: Line 1,129:  
|-
 
|-
 
| 249 || [11.0.0+] ConnectUniquePad
 
| 249 || [11.0.0+] ConnectUniquePad
 +
|-
 +
| 250 || [12.0.0+] IsVirtual
 +
|-
 +
| 251 || [12.0.0+] GetAnalogStickModuleParam
 
|-
 
|-
 
| 301 || [5.0.0-8.1.0] [[#GetAbstractedPadHandles]]
 
| 301 || [5.0.0-8.1.0] [[#GetAbstractedPadHandles]]
Line 1,151: Line 1,187:  
|-
 
|-
 
| 600 || [10.0.0+] ConvertPadState
 
| 600 || [10.0.0+] ConvertPadState
 +
|-
 +
| 650 || [12.0.0+] AddButtonPlayData
 +
|-
 +
| 651 || [12.0.0+] StartButtonPlayData
 +
|-
 +
| 652 || [12.0.0+] StopButtonPlayData
 
|-
 
|-
 
| 2000 || [10.0.0+] DeactivateDigitizer
 
| 2000 || [10.0.0+] DeactivateDigitizer
Line 1,204: Line 1,246:     
This just returns 0.
 
This just returns 0.
 +
 +
== DeactivateSleepButton ==
 +
No input/output.
 +
 +
== SetSleepButtonAutoPilotState ==
 +
Takes an input [[#SleepButtonAutoPilotState]], no output.
 +
 +
== UnsetSleepButtonAutoPilotState ==
 +
No input/output.
    
== StartFirmwareUpdate ==
 
== StartFirmwareUpdate ==
Line 1,310: Line 1,361:  
== AttachHdlsWorkBuffer ==
 
== AttachHdlsWorkBuffer ==
 
Takes an input TransferMemory handle and an u64 for the TransferMemory size, no output.
 
Takes an input TransferMemory handle and an u64 for the TransferMemory size, no output.
 +
 +
[13.0.0+] Now additionally returns an output [[#HdlsSessionId]].
    
Official user-processes use TransferMemory size=0x1000 and permissions=RW.
 
Official user-processes use TransferMemory size=0x1000 and permissions=RW.
Line 1,319: Line 1,372:  
== ReleaseHdlsWorkBuffer ==
 
== ReleaseHdlsWorkBuffer ==
 
No input/output.
 
No input/output.
 +
 +
[13.0.0+] Takes an input [[#HdlsSessionId]], no output.
    
== DumpHdlsNpadAssignmentState ==
 
== DumpHdlsNpadAssignmentState ==
 
No input/output.
 
No input/output.
 +
 +
[13.0.0+] Takes an input [[#HdlsSessionId]], no output.
    
After using this cmd, the output [[#HdlsNpadAssignment]] is located at tmem+0.
 
After using this cmd, the output [[#HdlsNpadAssignment]] is located at tmem+0.
Line 1,327: Line 1,384:  
== DumpHdlsStates ==
 
== DumpHdlsStates ==
 
No input/output.
 
No input/output.
 +
 +
[13.0.0+] Takes an input [[#HdlsSessionId]], no output.
    
After using this cmd, the output [[#HdlsStateList]] struct is located at tmem+0.
 
After using this cmd, the output [[#HdlsStateList]] struct is located at tmem+0.
Line 1,332: Line 1,391:  
== ApplyHdlsNpadAssignmentState ==
 
== ApplyHdlsNpadAssignmentState ==
 
Takes an input u8 bool, no output.
 
Takes an input u8 bool, no output.
 +
 +
[13.0.0+] Takes an input bool and a [[#HdlsSessionId]], no output.
    
Prior to using this cmd, the input [[#HdlsNpadAssignment]] is written to tmem+0 by the user-process.
 
Prior to using this cmd, the input [[#HdlsNpadAssignment]] is written to tmem+0 by the user-process.
Line 1,337: Line 1,398:  
== ApplyHdlsStateList ==
 
== ApplyHdlsStateList ==
 
No input/output.
 
No input/output.
 +
 +
[13.0.0+] Takes an input [[#HdlsSessionId]], no output.
    
Prior to using this cmd, the input [[#HdlsStateList]] is written to tmem+0 by the user-process.
 
Prior to using this cmd, the input [[#HdlsStateList]] is written to tmem+0 by the user-process.
Line 1,448: Line 1,511:  
|-
 
|-
 
| 326 || [10.0.0+] GetUniquePadAppletDetailedUiType
 
| 326 || [10.0.0+] GetUniquePadAppletDetailedUiType
 +
|-
 +
| 327 || [14.0.0+] GetAbstractedPadIdDataFromNpad
 +
|-
 +
| 328 || [14.0.0+] AttachAbstractedPadToNpad
 +
|-
 +
| 329 || [14.0.0+] DetachAbstractedPadAll
 +
|-
 +
| 330 || [14.0.0+] CheckAbstractedPadConnection
 
|-
 
|-
 
| 500 || SetAppletResourceUserId
 
| 500 || SetAppletResourceUserId
Line 1,460: Line 1,531:  
|-
 
|-
 
| 505 || EnableAppletToGetSixAxisSensor
 
| 505 || EnableAppletToGetSixAxisSensor
 +
|-
 +
| 506 || [14.0.0+] EnableAppletToGetPadInput
 +
|-
 +
| 507 || [14.0.0+] EnableAppletToGetTouchScreen
 
|-
 
|-
 
| 510 || [[#SetVibrationMasterVolume]]
 
| 510 || [[#SetVibrationMasterVolume]]
Line 1,468: Line 1,543:  
|-
 
|-
 
| 513 || [3.0.0+] EndPermitVibrationSession
 
| 513 || [3.0.0+] EndPermitVibrationSession
 +
|-
 +
| 514 || [12.0.0+] SendVibrationNotificationPattern
 
|-
 
|-
 
| 520 || EnableHandheldHids
 
| 520 || EnableHandheldHids
Line 1,683: Line 1,760:  
| 1258 || [10.0.0+] [[#IsButtonConfigStorageRightEmpty]]
 
| 1258 || [10.0.0+] [[#IsButtonConfigStorageRightEmpty]]
 
|-
 
|-
| 1259 || [11.0.0+] [[#GetButtonConfigStorageEmbeddedDeprecated]] ([10.0.0-10.2.0] [[#GetButtonConfigStorageEmbeddedDeprecated|GetButtonConfigStorageEmbedded]])
+
| 1259 || [11.0.0-12.1.0] [[#GetButtonConfigStorageEmbeddedDeprecated]] ([10.0.0-10.2.0] [[#GetButtonConfigStorageEmbeddedDeprecated|GetButtonConfigStorageEmbedded]])
 
|-
 
|-
| 1260 || [11.0.0+] [[#GetButtonConfigStorageFullDeprecated]] ([10.0.0-10.2.0] [[#GetButtonConfigStorageFullDeprecated|GetButtonConfigStorageFull]])
+
| 1260 || [11.0.0-12.1.0] [[#GetButtonConfigStorageFullDeprecated]] ([10.0.0-10.2.0] [[#GetButtonConfigStorageFullDeprecated|GetButtonConfigStorageFull]])
 
|-
 
|-
| 1261 || [11.0.0+] [[#GetButtonConfigStorageLeftDeprecated]] ([10.0.0-10.2.0] [[#GetButtonConfigStorageLeftDeprecated|GetButtonConfigStorageLeft]])
+
| 1261 || [11.0.0-12.1.0] [[#GetButtonConfigStorageLeftDeprecated]] ([10.0.0-10.2.0] [[#GetButtonConfigStorageLeftDeprecated|GetButtonConfigStorageLeft]])
 
|-
 
|-
| 1262 || [11.0.0+] [[#GetButtonConfigStorageRightDeprecated]] ([10.0.0-10.2.0] [[#GetButtonConfigStorageRightDeprecated|GetButtonConfigStorageRight]])
+
| 1262 || [11.0.0-12.1.0] [[#GetButtonConfigStorageRightDeprecated]] ([10.0.0-10.2.0] [[#GetButtonConfigStorageRightDeprecated|GetButtonConfigStorageRight]])
 
|-
 
|-
| 1263 || [11.0.0+] [[#SetButtonConfigStorageEmbeddedDeprecated]] ([10.0.0-10.2.0] [[#SetButtonConfigStorageEmbeddedDeprecated|SetButtonConfigStorageEmbedded]])
+
| 1263 || [11.0.0-12.1.0] [[#SetButtonConfigStorageEmbeddedDeprecated]] ([10.0.0-10.2.0] [[#SetButtonConfigStorageEmbeddedDeprecated|SetButtonConfigStorageEmbedded]])
 
|-
 
|-
| 1264 || [11.0.0+] [[#SetButtonConfigStorageFullDeprecated]] ([10.0.0-10.2.0] [[#SetButtonConfigStorageFullDeprecated|SetButtonConfigStorageFull]])
+
| 1264 || [11.0.0-12.1.0] [[#SetButtonConfigStorageFullDeprecated]] ([10.0.0-10.2.0] [[#SetButtonConfigStorageFullDeprecated|SetButtonConfigStorageFull]])
 
|-
 
|-
| 1265 || [11.0.0+] [[#SetButtonConfigStorageLeftDeprecated]] ([10.0.0-10.2.0] [[#SetButtonConfigStorageLeftDeprecated|SetButtonConfigStorageLeft]])
+
| 1265 || [11.0.0-12.1.0] [[#SetButtonConfigStorageLeftDeprecated]] ([10.0.0-10.2.0] [[#SetButtonConfigStorageLeftDeprecated|SetButtonConfigStorageLeft]])
 
|-
 
|-
| 1266 || [11.0.0+] [[#SetButtonConfigStorageRightDeprecated]] ([10.0.0-10.2.0] [[#SetButtonConfigStorageRightDeprecated|SetButtonConfigStorageRight]])
+
| 1266 || [11.0.0-12.1.0] [[#SetButtonConfigStorageRightDeprecated]] ([10.0.0-10.2.0] [[#SetButtonConfigStorageRightDeprecated|SetButtonConfigStorageRight]])
 
|-
 
|-
 
| 1267 || [10.0.0+] [[#DeleteButtonConfigStorageEmbedded]]
 
| 1267 || [10.0.0+] [[#DeleteButtonConfigStorageEmbedded]]
Line 2,751: Line 2,828:  
! Cmd || Name
 
! Cmd || Name
 
|-
 
|-
| 0 || GetDataFormat
+
| 0 || [[#GetDataFormat]]
 
|-
 
|-
| 1 || SetDataFormat
+
| 1 || [[#SetDataFormat]]
 
|-
 
|-
| 2 || GetMcuState
+
| 2 || [[#GetMcuState]]
 
|-
 
|-
| 3 || SetMcuState
+
| 3 || [[#SetMcuState]]
 
|-
 
|-
| 4 || GetMcuVersionForNfc
+
| 4 || [[#GetMcuVersionForNfc]]
 
|-
 
|-
| 5 || CheckNfcDevicePower
+
| 5 || [[#CheckNfcDevicePower]]
 
|-
 
|-
| 6 || [5.0.0+] SetMcuStateImmediate
+
| 6 || [5.0.0+] [[#SetMcuStateImmediate]]
 
|-
 
|-
| 10 || SetNfcEvent
+
| 10 || [[#SetNfcEvent]]
 
|-
 
|-
| 11 || GetNfcInfo
+
| 11 || [[#GetNfcInfo]]
 
|-
 
|-
 
| 12 || StartNfcDiscovery
 
| 12 || StartNfcDiscovery
Line 2,798: Line 2,875:  
[5.0.0+] SetDataFormat, SetMcuState, and ClearMifareKey: now takes a total of 0xC-bytes of input instead of 0x10.
 
[5.0.0+] SetDataFormat, SetMcuState, and ClearMifareKey: now takes a total of 0xC-bytes of input instead of 0x10.
   −
[6.0.0+]: The buffer type used by GetNfcInfo is now 0x32 instead of 0x1A.
+
== GetDataFormat ==
 +
Takes an input 8-byte handle, returns an output u8.
 +
 
 +
== SetDataFormat ==
 +
Takes an input u8 and a 8-byte handle (4-byte alignment), no output.
 +
 
 +
== GetMcuState ==
 +
Takes an input 8-byte handle, returns an output u8.
 +
 
 +
== SetMcuState ==
 +
Takes an input u8 and a 8-byte handle (4-byte alignment), no output.
 +
 
 +
== GetMcuVersionForNfc ==
 +
Takes an input 8-byte handle, returns an output 0x20-byte struct.
 +
 
 +
== CheckNfcDevicePower ==
 +
Takes an input 8-byte handle, no output.
 +
 
 +
== SetMcuStateImmediate ==
 +
Takes an input u8 and a 8-byte handle (4-byte alignment), no output.
 +
 
 +
== SetNfcEvent ==
 +
Takes an input 8-byte handle, returns 2 output Event handles.
 +
 
 +
== GetNfcInfo ==
 +
Takes an input 8-byte handle and a type-0x1A output buffer.
 +
 
 +
[6.0.0+]: The buffer type is now 0x32 instead of 0x1A.
 +
 
 +
This buffer contains a 0x804-byte struct, for the NFC data sent in response to the various other cmds.
    
= hidbus =
 
= hidbus =
Line 2,843: Line 2,949:     
== GetBusHandle ==
 
== GetBusHandle ==
Takes an input u32 [[#NpadIdType]], an u64 [[#BusType]], an u64 [[AM_services|AppletResourceUserId]], returns an output u8 bool and a [[#BusHandle]].
+
Takes an input u32 [[#NpadIdType]], an u64 [[#BusType]] and an u64 [[AM_services|AppletResourceUserId]]. Returns an output bool '''HasHandle''' and a [[#BusHandle]].
   −
The bool indicates whether the [[#BusHandle]] is valid.
+
'''HasHandle''' indicates whether the [[#BusHandle]] is valid.
    
Official sw will assert when [[#BusHandle]] InternalIndex is >=0x11 (>=0x13 with [6.0.0+]). This same check is also done for all funcs using [[#BusHandle]] as input.
 
Official sw will assert when [[#BusHandle]] InternalIndex is >=0x11 (>=0x13 with [6.0.0+]). This same check is also done for all funcs using [[#BusHandle]] as input.
Line 2,852: Line 2,958:     
== IsExternalDeviceConnected ==
 
== IsExternalDeviceConnected ==
Takes an input [[#BusHandle]], returns an output u8 bool.
+
Takes an input [[#BusHandle]]. Returns an output bool '''IsAttached'''.
    
This is not used by sdknso.
 
This is not used by sdknso.
    
== Initialize ==
 
== Initialize ==
Takes an input [[#BusHandle]], an u64 [[AM_services|AppletResourceUserId]], no output.
+
Takes an input [[#BusHandle]] and an u64 [[AM_services|AppletResourceUserId]]. No output.
    
Prior to using this cmd, sdknso handles [[#GetSharedMemoryHandle|sharedmem]] mapping if not done previously.
 
Prior to using this cmd, sdknso handles [[#GetSharedMemoryHandle|sharedmem]] mapping if not done previously.
    
== Finalize ==
 
== Finalize ==
Takes an input [[#BusHandle]], an u64 [[AM_services|AppletResourceUserId]], no output.
+
Takes an input [[#BusHandle]] and an u64 [[AM_services|AppletResourceUserId]]. No output.
    
== EnableExternalDevice ==
 
== EnableExternalDevice ==
Takes an input u8 bool, a [[#BusHandle]], an u64, an u64 [[AM_services|AppletResourceUserId]], no output.
+
Takes an input bool '''IsEnabled''', a [[#BusHandle]], an u64 '''Version''' and an u64 [[AM_services|AppletResourceUserId]]. No output.
   −
sdknso passes value 0x38900050018 (0x3A600050018 with 7.x+) for the u64.
+
sdknso passes value 0x38900050018 (0x3A600050018 with 7.x+) for '''Version'''.
   −
The bool flag indicates whether to enable the device (true = enable, false = disable).  When false, this will use [[#DisableJoyPollingReceiveMode]] if needed.
+
'''IsEnabled''' indicates whether to enable the device (true = enable, false = disable).  When false, this will use [[#DisableJoyPollingReceiveMode]] if needed.
    
== GetExternalDeviceId ==
 
== GetExternalDeviceId ==
Takes an input [[#BusHandle]], returns an output u32 ExternalDeviceId.
+
Takes an input [[#BusHandle]]. Returns an output u32 '''DeviceId'''.
    
== SendCommandAsync ==
 
== SendCommandAsync ==
Takes a type-0x21 input buffer and a [[#BusHandle]], no output.
+
Takes a type-0x21 input buffer and a [[#BusHandle]]. No output.
    
== GetSendCommandAsynceResult ==
 
== GetSendCommandAsynceResult ==
Takes a type-0x22 output buffer and a [[#BusHandle]], returns an output u32.
+
Takes a type-0x22 output buffer and a [[#BusHandle]]. Returns an output u32 '''OutSize'''.
   −
Official sw copies the u32 to an output u64, for the actual output size.
+
Official sw copies '''OutSize''' to an output u64, for the actual output size.
    
== SetEventForSendCommandAsycResult ==
 
== SetEventForSendCommandAsycResult ==
Takes an input [[#BusHandle]], returns an output Event handle with EventClearMode=0.
+
Takes an input [[#BusHandle]]. Returns an output Event handle '''AttachmentDataReceiveEventHandle''' with EventClearMode=0.
    
Official sw with SendAndReceive clears this event (6.x+ sdknso), uses [[#SendCommandAsync]], waits on + clears this event, then uses [[#GetSendCommandAsynceResult]].
 
Official sw with SendAndReceive clears this event (6.x+ sdknso), uses [[#SendCommandAsync]], waits on + clears this event, then uses [[#GetSendCommandAsynceResult]].
    
== GetSharedMemoryHandle ==
 
== GetSharedMemoryHandle ==
No input, returns an output SharedMemory handle.
+
No input. Returns an output SharedMemory handle.
    
The SharedMemory is mapped with size 0x1000 and permissions=R--.
 
The SharedMemory is mapped with size 0x1000 and permissions=R--.
Line 2,920: Line 3,026:     
== EnableJoyPollingReceiveMode ==
 
== EnableJoyPollingReceiveMode ==
Takes a type-0x21 input buffer, a TransferMemory handle, an u32 tmem_size, an u32 [[#JoyPollingMode]], a [[#BusHandle]], no output.
+
Takes a type-0x21 input buffer, a TransferMemory handle, an u32 '''TransferMemorySize''', an u32 [[#JoyPollingMode]] and a [[#BusHandle]]. No output.
    
The TransferMemory is created with an user-specified output buffer, with permissions=R--.
 
The TransferMemory is created with an user-specified output buffer, with permissions=R--.
Line 2,989: Line 3,095:     
== DisableJoyPollingReceiveMode ==
 
== DisableJoyPollingReceiveMode ==
Takes an input [[#BusHandle]], no output.
+
Takes an input [[#BusHandle]]. No output.
    
== SetStatusManagerType ==
 
== SetStatusManagerType ==
Takes an input u32, no output.
+
Takes an input u32 [[#StatusManagerType]]. No output.
    
This is used by sdknso immediately after mapping [[#GetSharedMemoryHandle|sharedmem]] (before [[#Initialize]]) with hard-coded value 0x2.
 
This is used by sdknso immediately after mapping [[#GetSharedMemoryHandle|sharedmem]] (before [[#Initialize]]) with hard-coded value 0x2.
Line 4,364: Line 4,470:  
|-
 
|-
 
| 0x0
 
| 0x0
| 0x43F0 ([1.0.0-8.1.0] 0x4410)
+
| 0x43F8 ([9.0.0-12.1.0] 0x43F0, [1.0.0-8.1.0] 0x4410)
 
| [[#NpadInternalState]]
 
| [[#NpadInternalState]]
 
|}
 
|}
Line 4,511: Line 4,617:  
| 0x43EC ([1.0.0-8.1.0] 0x440C)
 
| 0x43EC ([1.0.0-8.1.0] 0x440C)
 
| 0x4
 
| 0x4
|  
+
| [[#NpadLagerType|LagerType]]
 +
|-
 +
| 0x43F0
 +
| 0x1 * 6
 +
| [13.0.0+] Array of [[#SixAxisSensorProperties]]
 
|}
 
|}
   Line 6,641: Line 6,751:  
|-
 
|-
 
| 29
 
| 29
|  
+
| Verification
 
|-
 
|-
 
| 30
 
| 30
 
| HandheldLeftB (Left B button on NES controllers in Handheld mode)
 
| HandheldLeftB (Left B button on NES controllers in Handheld mode)
 +
|-
 +
| 31
 +
| LagonCLeft (Left C button in N64 controller)
 +
|-
 +
| 32
 +
| LagonCUp (Up C button in N64 controller)
 +
|-
 +
| 33
 +
| LagonCRight (Right C button in N64 controller)
 +
|-
 +
| 34
 +
| LagonCDown (Down C button in N64 controller)
 
|}
 
|}
   Line 6,704: Line 6,826:  
| SNES controller
 
| SNES controller
 
|-
 
|-
| 10-28
+
| 10
 +
| NpadStyleLagon
 +
| N64 controller
 +
|-
 +
| 11
 +
| NpadStyleLager
 +
| Sega Genesis controller
 +
|-
 +
| 12-28
 
| Reserved
 
| Reserved
 
|
 
|
Line 7,017: Line 7,147:  
|-
 
|-
 
| 0x14000000 || Verification
 
| 0x14000000 || Verification
 +
|-
 +
| 0x15000000 || [13.0.0+] Lagon
 
|-
 
|-
 
| 0xFFFFFFFF || Unknown
 
| 0xFFFFFFFF || Unknown
Line 7,069: Line 7,201:  
|-
 
|-
 
| 20 || Verification
 
| 20 || Verification
 +
|-
 +
| 21 || [13.0.0+] Lagon
 
|}
 
|}
   Line 7,147: Line 7,281:  
|-
 
|-
 
| 3 || U
 
| 3 || U
 +
|}
 +
 +
= NpadLagerType =
 +
This is "nn::hid::NpadLagerType".
 +
 +
{| class="wikitable" border="1"
 +
!  Value
 +
!  Description
 +
|-
 +
| 0 || Invalid
 +
|-
 +
| 1 || J
 +
|-
 +
| 2 || E
 +
|-
 +
| 3 || U
 +
|}
 +
 +
= SixAxisSensorProperties =
 +
This is "nn::hid::server::SixAxisSensorProperties".
 +
 +
{| class="wikitable" border="1"
 +
|-
 +
! Bit
 +
! Description
 +
|-
 +
| 0
 +
| IsSixAxisSensorDeviceNewlyAssigned
 +
|-
 +
| 1
 +
| IsFirmwareUpdateAvailableForSixAxisSensor
 
|}
 
|}
   Line 7,253: Line 7,418:  
| Lucia
 
| Lucia
 
|-
 
|-
| 16-30
+
| 16
 +
| Lagon
 +
|-
 +
| 17
 +
| Lager
 +
|-
 +
| 18-30
 
| Reserved
 
| Reserved
 
|-
 
|-
Line 7,304: Line 7,475:  
!  [[#DeviceType|DeviceType]]
 
!  [[#DeviceType|DeviceType]]
 
!  [[#UniquePadType|UniquePadType]]
 
!  [[#UniquePadType|UniquePadType]]
 +
!  [[#AppletDetailedUiType|AppletDetailedUiType]]
 
!  Description
 
!  Description
 
|-
 
|-
| 1 || JoyRight, HandheldRight || JoyRight || Joy-Con right controller
+
| 1 || JoyRight, HandheldRight || RightController || JoyDual, JoyRightHorizontal, JoyRightVertical, JoyDualRightOnly, HandheldJoyConRightOnly, HandheldJoyConLeftJoyConRight, HandheldLarkHvc1JoyConRight, HandheldLarkNesLeftJoyConRight, HandheldNone || Joy-Con right controller (USB PID 0x2007)
 +
|-
 +
| 2 || JoyLeft, HandheldLeft || LeftController || JoyDual, JoyLeftHorizontal, JoyLeftVertical, JoyDualLeftOnly, HandheldJoyConLeftOnly, HandheldJoyConLeftJoyConRight, HandheldJoyConLeftLarkHvc2, HandheldJoyConLeftLarkNesRight, HandheldNone || Joy-Con left controller (USB PID 0x2006)
 +
|-
 +
| 3 || FullKey || FullKeyController || SwitchProController || Pro Controller (USB PID 0x2009)
 +
|-
 +
| 4 || JoyLeft || LeftController || || Reserved
 
|-
 
|-
| 2 || JoyLeft, HandheldLeft || JoyLeft || Joy-Con left controller
+
| 5 || JoyRight || RightController || || Reserved
 
|-
 
|-
| 3 || FullKey || FullKey || Pro Controller
+
| 6 || FullKey || FullKeyController || || Reserved
 
|-
 
|-
| 4 || JoyLeft || JoyLeft || Reserved
+
| 7 || LarkHvcLeft, HandheldLarkHvcLeft || LeftController || LarkHvc1, HandheldLarkHvc1Only, HandheldLarkHvc1JoyConRight, HandheldLarkHvc1LarkHvc2, HandheldLarkHvc1LarkNesRight, HandheldNone || Famicom left controller
 
|-
 
|-
| 5 || JoyRight || JoyRight || Reserved
+
| 8 || LarkHvcRight, HandheldLarkHvcRight || RightController || LarkHvc2, HandheldLarkHvc2Only, HandheldJoyConLeftLarkHvc2, HandheldLarkHvc1LarkHvc2, HandheldLarkNesLeftLarkHvc2, HandheldNone || Famicom right controller (with microphone)
 
|-
 
|-
| 6 || FullKey || FullKey || Reserved
+
| 9 || LarkNesLeft, HandheldLarkNesLeft || LeftController || LarkNesLeft, HandheldLarkNesLeftOnly, HandheldLarkNesLeftJoyConRight, HandheldLarkNesLeftLarkHvc2, HandheldLarkNesLeftLarkNesRight, HandheldNone || NES left controller
 
|-
 
|-
| 7 || LarkHvcLeft, HandheldLarkHvcLeft || JoyLeft || Famicom left controller
+
| 10 || LarkNesRight, HandheldLarkNesRight || RightController || LarkNesRight, HandheldLarkNesRightOnly, HandheldJoyConLeftLarkNesRight, HandheldLarkHvc1LarkNesRight, HandheldLarkNesLeftLarkNesRight, HandheldNone || NES right controller
 
|-
 
|-
| 8 || LarkHvcRight, HandheldLarkHvcRight || JoyRight || Famicom right controller (with microphone)
+
| 11 || Lucia || FullKeyController || LuciaU, LuciaJ, LuciaE || SNES controller (USB PID 0x2017)
 
|-
 
|-
| 9 || LarkNesLeft, HandheldLarkNesLeft || JoyLeft || NES left controller
+
| 12 || Palma || Embedded || Unknown || Poké Ball Plus controller
 
|-
 
|-
| 10 || LarkNesRight, HandheldLarkNesRight || JoyRight || NES right controller
+
| 13 || FullKey || FullKeyController || || Gc controller
 
|-
 
|-
| 11 || Lucia || FullKey || SNES controller
+
| 14 || HandheldLeft || LeftController || || Reserved
 
|-
 
|-
| 12 || Palma || Other || Poké Ball Plus controller
+
| 15 || FullKey || FullKeyController || || Reserved
 
|-
 
|-
| 13 || FullKey || FullKey || Gc controller
+
| 16 || FullKey || FullKeyController || || Reserved
 
|-
 
|-
| 14 || HandheldLeft || JoyLeft || Reserved
+
| 17 || DebugPad || DebugPadController || Verification || Debug controller
 
|-
 
|-
| 15 || FullKey || FullKey || Reserved
+
| 18 || HandheldRight || RightController || || Reserved
 
|-
 
|-
| 16 || FullKey || FullKey || Reserved
+
| 19 || System || Embedded || CompatibleProController || Third party Pro Controller
 
|-
 
|-
| 17 || DebugPad || DebugPad || Debug controller
+
| 20 || System || Embedded || CompatibleJoyCon, HandheldNone || Third party Joy-Con right controller
 
|-
 
|-
| 18 || HandheldRight || JoyRight || Reserved
+
| 21 || System || Embedded || CompatibleJoyCon, HandheldNone || Third party Joy-Con left controller
 
|-
 
|-
| 19 || System || Other || Unknown (has [[#NpadStyleTag|NpadFullKey]] style tag)
+
| 22 || Lagon || FullKeyController || Lagon || N64 controller (USB PID 0x2019)
 
|-
 
|-
| 20 || System || Other || Unknown (has [[#NpadStyleTag|NpadJoyDual]] style tag)
+
| 23 || ? || ? || ? || Joy-Con Charging Grip (USB PID 0x200E)
 
|-
 
|-
| 21 || System || Other || Unknown (has [[#NpadStyleTag|NpadJoyDual]] style tag)
+
| 24 || ? || ? || ? || Nintendo, USB PID 0x200F
 +
|-
 +
| 25 || ? || ? || ? || Nintendo, USB PID 0x2008
 +
|-
 +
| 26 || ? || ? || ? || Nintendo, USB PID 0x2018
 +
|-
 +
| 27 || ? || ? || ? || Nintendo, USB PID 0x201A
 +
|-
 +
| 28 || Lager || FullKeyController || || Sega Genesis controller (USB PID 0x201E)
 +
|-
 +
| 29 || ? || ? || ? || Nintendo, USB PID 0x201F
 
|}
 
|}
   Line 7,587: Line 7,775:  
| 14 || SuspendFeature
 
| 14 || SuspendFeature
 
|-
 
|-
| [[5.1.0]]+ 15 || ReadPlayLog
+
| 15 || [5.1.0+] ReadPlayLog
 
|-
 
|-
| [[5.1.0]]+ 16 || ResetPlayLog
+
| 16 || [5.1.0+] ResetPlayLog
 
|}
 
|}
   Line 7,816: Line 8,004:  
| 0x20
 
| 0x20
 
| [[#KeyboardKeySet|Keys]]
 
| [[#KeyboardKeySet|Keys]]
 +
|}
 +
 +
= SleepButtonAutoPilotState =
 +
This is "nn::hid::debug::SleepButtonAutoPilotState". This is a 0x8-byte struct with 8-byte alignment.
 +
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0 || 0x8 || Buttons (only bit0 is used)
 +
|}
 +
 +
= PowerInfo =
 +
This is "nn::hidtypes::PowerInfo".
 +
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0 || 0x4 || BatteryLevel
 +
|-
 +
| 0x4 || 0x4 || [[#PowerAttribute]]
 +
|}
 +
 +
= PowerAttribute =
 +
This is "nn::hidtypes::PowerAttribute". This is a 32-bit flag.
 +
 +
{| class="wikitable" border="1"
 +
!  Bits
 +
!  Description
 +
|-
 +
| 0
 +
| IsPowered
 +
|-
 +
| 1
 +
| IsCharging
 +
|}
 +
 +
= HdlsAttribute =
 +
This is "nn::hidtypes::HdlsAttribute". This is a 32-bit flag.
 +
 +
{| class="wikitable" border="1"
 +
!  Bits
 +
!  Description
 +
|-
 +
| 0
 +
| HasVirtualSixAxisSensorAcceleration
 +
|-
 +
| 1
 +
| HasVirtualSixAxisSensorAngle
 
|}
 
|}
    
= HdlsHandle =
 
= HdlsHandle =
 
This is "nn::hid::debug::HdlsHandle". This is a 0x8-byte struct with 8-byte alignment.
 
This is "nn::hid::debug::HdlsHandle". This is a 0x8-byte struct with 8-byte alignment.
 +
 +
= HdlsSessionId =
 +
This is "nn::hid::debug::detail::HdlsSessionId". This is a 0x8-byte struct with 8-byte alignment.
    
= HdlsNpadAssignment =
 
= HdlsNpadAssignment =
Line 7,892: Line 8,137:     
= HdlsDeviceInfo =
 
= HdlsDeviceInfo =
This is a 0x10-byte struct.
+
This is "nn::hid::debug::HdlsDeviceInfo". This is a 0x10-byte struct.
    
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 7,931: Line 8,176:     
= HdlsState =
 
= HdlsState =
This is a 0x24-byte struct.
+
This is "nn::hid::debug::HdlsState". This is a 0x24-byte struct.
    
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 7,949: Line 8,194:  
| 0x10 || 0x10(4*2*2) || Joystick data.
 
| 0x10 || 0x10(4*2*2) || Joystick data.
 
|-
 
|-
| 0x20 || 0x1 || Unused for input. Set with output from [[#DumpHdlsStates]] (zero in some cases).
+
| 0x20 || 0x1 || Indicator. Unused for input. Set with output from [[#DumpHdlsStates]] (zero in some cases).
 
|-
 
|-
 
| 0x21 || 0x3 || Padding
 
| 0x21 || 0x3 || Padding
 
|}
 
|}
   −
[9.0.0+]:
+
[9.0.0+] (0x28-bytes):
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
 
! Offset || Size || Description
 
! Offset || Size || Description
 
|-
 
|-
| 0x0 || 0x4 || BatteryLevel for the main PowerInfo.
+
| 0x0 || 0x8 || [[#PowerInfo]]
 +
|-
 +
| 0x8 || 0x8 || [[#NpadButton|Buttons]], masked with 0xfffffffff00fffff. See above table regarding HOME/Capture buttons.
 +
|-
 +
| 0x10 || 0x10(4*2*2) || Joystick data.
 +
|-
 +
| 0x20 || 0x1 || Indicator. Unused for input. Set with output from [[#DumpHdlsStates]] (zero in some cases).
 
|-
 
|-
| 0x4 || 0x4 || Flags. Used to set the main PowerInfo for [[#NpadSystemProperties]]. Bit0 -> IsPowered, bit1 -> IsCharging.
+
| 0x21 || 0x7 || Padding
 +
|}
 +
 
 +
[12.0.0+] (0x40-bytes):
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset || Size || Description
 +
|-
 +
| 0x0 || 0x8 || [[#PowerInfo]]
 
|-
 
|-
 
| 0x8 || 0x8 || [[#NpadButton|Buttons]], masked with 0xfffffffff00fffff. See above table regarding HOME/Capture buttons.
 
| 0x8 || 0x8 || [[#NpadButton|Buttons]], masked with 0xfffffffff00fffff. See above table regarding HOME/Capture buttons.
Line 7,967: Line 8,226:  
| 0x10 || 0x10(4*2*2) || Joystick data.
 
| 0x10 || 0x10(4*2*2) || Joystick data.
 
|-
 
|-
| 0x20 || 0x1 || Unused for input. Set with output from [[#DumpHdlsStates]] (zero in some cases).
+
| 0x20 || 0xC || VirtualSixAxisSensorAcceleration
 
|-
 
|-
| 0x21 || 0x3 || Padding
+
| 0x2C || 0xC || VirtualSixAxisSensorAngle
 +
|-
 +
| 0x38 || 0x4 || [[#HdlsAttribute]]
 +
|-
 +
| 0x3C || 0x1 || Indicator. Unused for input.
 +
|-
 +
| 0x3D || 0x3 || Padding
 
|}
 
|}
   Line 9,012: Line 9,277:  
| 1 || RightJoyRail
 
| 1 || RightJoyRail
 
|-
 
|-
| 2 || [6.0.0+] RightLarkRail (for microphone)
+
| 2 || [6.0.0+] InternalBus (for Lark microphone)
 
|}
 
|}
   Line 9,030: Line 9,295:     
Other values causes [[#EnableJoyPollingReceiveMode]] to assert.
 
Other values causes [[#EnableJoyPollingReceiveMode]] to assert.
 +
 +
= StatusManagerType =
 +
This is "nn::hidbus::detail::StatusManagerType".
 +
 +
{| class="wikitable" border="1"
 +
!  Value
 +
!  Description
 +
|-
 +
| 0 || None
 +
|-
 +
| 1 || 16
 +
|-
 +
| 2 || 32
 +
|}
    
= ExternalDevices =
 
= ExternalDevices =
Line 9,035: Line 9,314:  
* [[Ring-Con]]
 
* [[Ring-Con]]
 
* Famicom right controller (with microphone)
 
* Famicom right controller (with microphone)
 +
** [[#BusType]] is 2, ExternalDeviceId is 0x21. SendAndReceive is not used. EnableJoyPollingReceiveMode is used where the input buffer is an u32 with value 0, [[#JoyPollingMode]] = 2. GetJoyPollingReceivedData is used to get the output data.
 +
* Used by Starlink: Battle For Atlas.
 +
** [[#BusType]] is 1, ExternalDeviceId is 0x28. EnableJoyPollingReceiveMode is used where the input buffer is an u16 with value 0x09, [[#JoyPollingMode]] = 0. SendAndReceive is called from 1 func. GetJoyPollingReceivedData is used to determine whether to call the same func which calls SendAndReceive, which is only done if <code>out_size==0x4 && data[0]==0x09 && (data[1] & 1 == 1)</code>.
    
= RomFS =
 
= RomFS =
Line 9,081: Line 9,363:  
* [10.0.0+] '''TouchScreenConfiguration.csv'''
 
* [10.0.0+] '''TouchScreenConfiguration.csv'''
 
* [10.0.0+] '''TouchScreenFirmwareInfo.csv'''
 
* [10.0.0+] '''TouchScreenFirmwareInfo.csv'''
 +
* [13.0.0+] '''FTS_33000510.fts256'''
 +
* [13.0.0+] '''FTS_98000004.ftb'''
    
[[Category:Services]]
 
[[Category:Services]]

Navigation menu