mirror of
https://github.com/switchbrew/libnx.git
synced 2025-08-05 16:09:24 +02:00
set: Updated for new-ipc. Changed the type of the Language param for setMakeLanguage*() from s32 to SetLanguage. Added size_out param to setsysGetSettingsItemValue which was previously missing. Minor param name adjustment for setsysBindFatalDirtyFlagEvent. Improved docs.
This commit is contained in:
parent
c8550c378b
commit
1c334bafb9
@ -7,16 +7,16 @@
|
|||||||
* @copyright libnx Authors
|
* @copyright libnx Authors
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../result.h"
|
#include "../types.h"
|
||||||
#include "../kernel/event.h"
|
#include "../kernel/event.h"
|
||||||
#include "../services/sm.h"
|
#include "../sf/service.h"
|
||||||
|
|
||||||
#define SET_MAX_NAME_SIZE 0x48
|
#define SET_MAX_NAME_SIZE 0x48
|
||||||
#define SET_MAX_NICKNAME_SIZE 0x80
|
#define SET_MAX_NICKNAME_SIZE 0x80
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ColorSetId_Light=0,
|
ColorSetId_Light = 0,
|
||||||
ColorSetId_Dark=1
|
ColorSetId_Dark = 1,
|
||||||
} ColorSetId;
|
} ColorSetId;
|
||||||
|
|
||||||
/// IDs for Language.
|
/// IDs for Language.
|
||||||
@ -55,23 +55,23 @@ typedef enum {
|
|||||||
|
|
||||||
/// Command IDs for setsysGetFlag/setsysSetFlag.
|
/// Command IDs for setsysGetFlag/setsysSetFlag.
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SetSysFlag_LockScreen = 7,
|
SetSysFlag_LockScreen = 7,
|
||||||
SetSysFlag_ConsoleInformationUpload = 25,
|
SetSysFlag_ConsoleInformationUpload = 25,
|
||||||
SetSysFlag_AutomaticApplicationDownload = 27,
|
SetSysFlag_AutomaticApplicationDownload = 27,
|
||||||
SetSysFlag_Quest = 47,
|
SetSysFlag_Quest = 47,
|
||||||
SetSysFlag_Usb30Enable = 65,
|
SetSysFlag_Usb30Enable = 65,
|
||||||
SetSysFlag_NfcEnable = 69,
|
SetSysFlag_NfcEnable = 69,
|
||||||
SetSysFlag_WirelessLanEnable = 73,
|
SetSysFlag_WirelessLanEnable = 73,
|
||||||
SetSysFlag_BluetoothEnable = 88,
|
SetSysFlag_BluetoothEnable = 88,
|
||||||
SetSysFlag_AutoUpdateEnable = 95,
|
SetSysFlag_AutoUpdateEnable = 95, ///< [2.0.0+]
|
||||||
SetSysFlag_BatteryPercentage = 99,
|
SetSysFlag_BatteryPercentage = 99, ///< [2.0.0+]
|
||||||
SetSysFlag_ExternalRtcReset = 101,
|
SetSysFlag_ExternalRtcReset = 101, ///< [2.0.0+]
|
||||||
SetSysFlag_UsbFullKeyEnable = 103,
|
SetSysFlag_UsbFullKeyEnable = 103, ///< [3.0.0+]
|
||||||
SetSysFlag_BluetoothAfhEnable = 111,
|
SetSysFlag_BluetoothAfhEnable = 111, ///< [3.0.0+]
|
||||||
SetSysFlag_BluetoothBoostEnable = 113,
|
SetSysFlag_BluetoothBoostEnable = 113, ///< [3.0.0+]
|
||||||
SetSysFlag_InRepairProcessEnable = 115,
|
SetSysFlag_InRepairProcessEnable = 115, ///< [3.0.0+]
|
||||||
SetSysFlag_HeadphoneVolumeUpdate = 117,
|
SetSysFlag_HeadphoneVolumeUpdate = 117, ///< [3.0.0+]
|
||||||
SetSysFlag_RequiresRunRepairTimeReviser = 141,
|
SetSysFlag_RequiresRunRepairTimeReviser = 141, ///< [5.0.0+]
|
||||||
} SetSysFlag;
|
} SetSysFlag;
|
||||||
|
|
||||||
/// Structure returned by \ref setsysGetFirmwareVersion
|
/// Structure returned by \ref setsysGetFirmwareVersion
|
||||||
@ -94,11 +94,11 @@ Result setInitialize(void);
|
|||||||
void setExit(void);
|
void setExit(void);
|
||||||
Service* setGetServiceSession(void);
|
Service* setGetServiceSession(void);
|
||||||
|
|
||||||
/// Converts LanguageCode to Language.
|
/// Converts LanguageCode to \ref SetLanguage.
|
||||||
Result setMakeLanguage(u64 LanguageCode, s32 *Language);
|
Result setMakeLanguage(u64 LanguageCode, SetLanguage *Language);
|
||||||
|
|
||||||
/// Converts Language to LanguageCode.
|
/// Converts \ref SetLanguage to LanguageCode.
|
||||||
Result setMakeLanguageCode(s32 Language, u64 *LanguageCode);
|
Result setMakeLanguageCode(SetLanguage Language, u64 *LanguageCode);
|
||||||
|
|
||||||
/// Gets the current system LanguageCode.
|
/// Gets the current system LanguageCode.
|
||||||
/// Normally this should be used instead of \ref setGetLanguageCode.
|
/// Normally this should be used instead of \ref setGetLanguageCode.
|
||||||
@ -143,8 +143,9 @@ Result setsysGetSettingsItemValueSize(const char *name, const char *item_key, u6
|
|||||||
* @param item_key Item key string.
|
* @param item_key Item key string.
|
||||||
* @param value_out Pointer to output the value to.
|
* @param value_out Pointer to output the value to.
|
||||||
* @param value_out_size Size of the value_out buffer.
|
* @param value_out_size Size of the value_out buffer.
|
||||||
|
* @param size_out Total size which was copied to value_out.
|
||||||
*/
|
*/
|
||||||
Result setsysGetSettingsItemValue(const char *name, const char *item_key, void *value_out, size_t value_out_size);
|
Result setsysGetSettingsItemValue(const char *name, const char *item_key, void *value_out, size_t value_out_size, u64 *size_out);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the system's serial number.
|
* @brief Gets the system's serial number.
|
||||||
@ -174,9 +175,9 @@ Result setsysGetFirmwareVersion(SetSysFirmwareVersion *out);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets an event that settings will signal on flag change.
|
* @brief Gets an event that settings will signal on flag change.
|
||||||
* @param out Event to bind. Output event will have autoclear=false.
|
* @param out_event Event to bind. Output event will have autoclear=false.
|
||||||
*/
|
*/
|
||||||
Result setsysBindFatalDirtyFlagEvent(Event *out);
|
Result setsysBindFatalDirtyFlagEvent(Event *out_event);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the settings flags that have changed.
|
* @brief Gets the settings flags that have changed.
|
||||||
|
@ -29,7 +29,7 @@ static u32 g_nacpLanguageTable[15] = {
|
|||||||
Result nacpGetLanguageEntry(NacpStruct* nacp, NacpLanguageEntry** langentry) {
|
Result nacpGetLanguageEntry(NacpStruct* nacp, NacpLanguageEntry** langentry) {
|
||||||
Result rc=0;
|
Result rc=0;
|
||||||
u64 LanguageCode=0;
|
u64 LanguageCode=0;
|
||||||
s32 Language=0;
|
SetLanguage Language=0;
|
||||||
NacpLanguageEntry *entry = NULL;
|
NacpLanguageEntry *entry = NULL;
|
||||||
u32 i=0;
|
u32 i=0;
|
||||||
|
|
||||||
|
@ -1,24 +1,12 @@
|
|||||||
/**
|
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
||||||
* @file set.h
|
|
||||||
* @brief Settings services IPC wrapper.
|
|
||||||
* @author plutoo
|
|
||||||
* @author yellows8
|
|
||||||
* @copyright libnx Authors
|
|
||||||
*/
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "types.h"
|
#include "service_guard.h"
|
||||||
#include "result.h"
|
|
||||||
#include "arm/atomics.h"
|
|
||||||
#include "kernel/ipc.h"
|
|
||||||
#include "runtime/hosversion.h"
|
#include "runtime/hosversion.h"
|
||||||
#include "services/set.h"
|
#include "services/set.h"
|
||||||
#include "services/sm.h"
|
|
||||||
#include "services/applet.h"
|
#include "services/applet.h"
|
||||||
|
|
||||||
static Service g_setSrv;
|
static Service g_setSrv;
|
||||||
static Service g_setsysSrv;
|
static Service g_setsysSrv;
|
||||||
static u64 g_refCnt;
|
|
||||||
static u64 g_refCntSys;
|
|
||||||
|
|
||||||
static bool g_setLanguageCodesInitialized;
|
static bool g_setLanguageCodesInitialized;
|
||||||
static u64 g_setLanguageCodes[0x40];
|
static u64 g_setLanguageCodes[0x40];
|
||||||
@ -26,50 +14,83 @@ static s32 g_setLanguageCodesTotal;
|
|||||||
|
|
||||||
static Result _setMakeLanguageCode(s32 Language, u64 *LanguageCode);
|
static Result _setMakeLanguageCode(s32 Language, u64 *LanguageCode);
|
||||||
|
|
||||||
Result setInitialize(void)
|
NX_GENERATE_SERVICE_GUARD(set);
|
||||||
{
|
|
||||||
atomicIncrement64(&g_refCnt);
|
|
||||||
|
|
||||||
if (serviceIsActive(&g_setSrv))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
Result _setInitialize(void) {
|
||||||
g_setLanguageCodesInitialized = 0;
|
g_setLanguageCodesInitialized = 0;
|
||||||
|
|
||||||
return smGetService(&g_setSrv, "set");
|
return smGetService(&g_setSrv, "set");
|
||||||
}
|
}
|
||||||
|
|
||||||
void setExit(void)
|
void _setCleanup(void) {
|
||||||
{
|
serviceClose(&g_setSrv);
|
||||||
if (atomicDecrement64(&g_refCnt) == 0) {
|
|
||||||
serviceClose(&g_setSrv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Service* setGetServiceSession(void) {
|
Service* setGetServiceSession(void) {
|
||||||
return &g_setSrv;
|
return &g_setSrv;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setsysInitialize(void)
|
NX_GENERATE_SERVICE_GUARD(setsys);
|
||||||
{
|
|
||||||
atomicIncrement64(&g_refCntSys);
|
|
||||||
|
|
||||||
if (serviceIsActive(&g_setsysSrv))
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized);
|
|
||||||
|
|
||||||
|
Result _setsysInitialize(void) {
|
||||||
return smGetService(&g_setsysSrv, "set:sys");
|
return smGetService(&g_setsysSrv, "set:sys");
|
||||||
}
|
}
|
||||||
|
|
||||||
void setsysExit(void)
|
void _setsysCleanup(void) {
|
||||||
{
|
serviceClose(&g_setsysSrv);
|
||||||
if (atomicDecrement64(&g_refCntSys) == 0) {
|
|
||||||
serviceClose(&g_setsysSrv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Service* setsysGetServiceSession(void) {
|
Service* setsysGetServiceSession(void) {
|
||||||
return &g_setsysSrv;
|
return &g_setsysSrv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Result _setCmdGetHandle(Service* srv, Handle* handle_out, u32 cmd_id) {
|
||||||
|
return serviceDispatch(srv, cmd_id,
|
||||||
|
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
|
||||||
|
.out_handles = handle_out,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _setCmdGetEvent(Service* srv, Event* out_event, bool autoclear, u32 cmd_id) {
|
||||||
|
Handle tmp_handle = INVALID_HANDLE;
|
||||||
|
Result rc = 0;
|
||||||
|
|
||||||
|
rc = _setCmdGetHandle(srv, &tmp_handle, cmd_id);
|
||||||
|
if (R_SUCCEEDED(rc)) eventLoadRemote(out_event, tmp_handle, autoclear);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _setCmdNoInOut64(Service* srv, u64 *out, u32 cmd_id) {
|
||||||
|
return serviceDispatchOut(srv, cmd_id, *out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _setCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) {
|
||||||
|
return serviceDispatchOut(srv, cmd_id, *out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _setCmdNoInOutU8(Service* srv, u8 *out, u32 cmd_id) {
|
||||||
|
return serviceDispatchOut(srv, cmd_id, *out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _setCmdNoInOutBool(Service* srv, bool *out, u32 cmd_id) {
|
||||||
|
u8 tmp=0;
|
||||||
|
Result rc = _setCmdNoInOutU8(srv, &tmp, cmd_id);
|
||||||
|
if (R_SUCCEEDED(rc) && out) *out = tmp!=0;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _setCmdInU8NoOut(Service* srv, u8 inval, u64 cmd_id) {
|
||||||
|
return serviceDispatchIn(srv, cmd_id, inval);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _setCmdInBoolNoOut(Service* srv, bool inval, u32 cmd_id) {
|
||||||
|
return _setCmdInU8NoOut(srv, inval!=0, cmd_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _setCmdInU32NoOut(Service* srv, u32 inval, u32 cmd_id) {
|
||||||
|
return serviceDispatchIn(srv, cmd_id, inval);
|
||||||
|
}
|
||||||
|
|
||||||
static Result setInitializeLanguageCodesCache(void) {
|
static Result setInitializeLanguageCodesCache(void) {
|
||||||
if (g_setLanguageCodesInitialized) return 0;
|
if (g_setLanguageCodesInitialized) return 0;
|
||||||
Result rc = 0;
|
Result rc = 0;
|
||||||
@ -84,7 +105,7 @@ static Result setInitializeLanguageCodesCache(void) {
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setMakeLanguage(u64 LanguageCode, s32 *Language) {
|
Result setMakeLanguage(u64 LanguageCode, SetLanguage *Language) {
|
||||||
Result rc = setInitializeLanguageCodesCache();
|
Result rc = setInitializeLanguageCodesCache();
|
||||||
if (R_FAILED(rc)) return rc;
|
if (R_FAILED(rc)) return rc;
|
||||||
|
|
||||||
@ -100,7 +121,7 @@ Result setMakeLanguage(u64 LanguageCode, s32 *Language) {
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setMakeLanguageCode(s32 Language, u64 *LanguageCode) {
|
Result setMakeLanguageCode(SetLanguage Language, u64 *LanguageCode) {
|
||||||
Result rc = setInitializeLanguageCodesCache();
|
Result rc = setInitializeLanguageCodesCache();
|
||||||
if (R_FAILED(rc)) return rc;
|
if (R_FAILED(rc)) return rc;
|
||||||
|
|
||||||
@ -126,43 +147,10 @@ Result setGetSystemLanguage(u64 *LanguageCode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result setGetLanguageCode(u64 *LanguageCode) {
|
Result setGetLanguageCode(u64 *LanguageCode) {
|
||||||
IpcCommand c;
|
return _setCmdNoInOut64(&g_setSrv, LanguageCode, 0);
|
||||||
ipcInitialize(&c);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
|
||||||
} *raw;
|
|
||||||
|
|
||||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
||||||
|
|
||||||
raw->magic = SFCI_MAGIC;
|
|
||||||
raw->cmd_id = 0;
|
|
||||||
|
|
||||||
Result rc = serviceIpcDispatch(&g_setSrv);
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
IpcParsedCommand r;
|
|
||||||
ipcParse(&r);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
u64 LanguageCode;
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
rc = resp->result;
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc) && LanguageCode) *LanguageCode = resp->LanguageCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setGetAvailableLanguageCodes(s32 *total_entries, u64 *LanguageCodes, size_t max_entries) {
|
Result setGetAvailableLanguageCodes(s32 *total_entries, u64 *LanguageCodes, size_t max_entries) {
|
||||||
IpcCommand c;
|
|
||||||
ipcInitialize(&c);
|
|
||||||
|
|
||||||
Result rc=0;
|
Result rc=0;
|
||||||
bool new_cmd = hosversionAtLeast(4,0,0);
|
bool new_cmd = hosversionAtLeast(4,0,0);
|
||||||
|
|
||||||
@ -175,260 +163,38 @@ Result setGetAvailableLanguageCodes(s32 *total_entries, u64 *LanguageCodes, size
|
|||||||
if (max_entries > (size_t)tmptotal) max_entries = (size_t)tmptotal;
|
if (max_entries > (size_t)tmptotal) max_entries = (size_t)tmptotal;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t bufsize = max_entries*sizeof(u64);
|
return serviceDispatchOut(&g_setSrv, new_cmd ? 5 : 1, *total_entries,
|
||||||
|
.buffer_attrs = { (new_cmd ? SfBufferAttr_HipcMapAlias : SfBufferAttr_HipcPointer) | SfBufferAttr_Out },
|
||||||
if (!new_cmd) {
|
.buffers = { { LanguageCodes, max_entries*sizeof(u64) } },
|
||||||
ipcAddRecvStatic(&c, LanguageCodes, bufsize, 0);
|
);
|
||||||
}
|
|
||||||
else {
|
|
||||||
ipcAddRecvBuffer(&c, LanguageCodes, bufsize, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
|
||||||
} *raw;
|
|
||||||
|
|
||||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
||||||
|
|
||||||
raw->magic = SFCI_MAGIC;
|
|
||||||
raw->cmd_id = new_cmd ? 5 : 1;
|
|
||||||
|
|
||||||
rc = serviceIpcDispatch(&g_setSrv);
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
IpcParsedCommand r;
|
|
||||||
ipcParse(&r);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
s32 total_entries;
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
rc = resp->result;
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc) && total_entries) *total_entries = resp->total_entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result _setMakeLanguageCode(s32 Language, u64 *LanguageCode) {
|
static Result _setMakeLanguageCode(s32 Language, u64 *LanguageCode) {
|
||||||
IpcCommand c;
|
return serviceDispatchInOut(&g_setSrv, 2, Language, *LanguageCode);
|
||||||
ipcInitialize(&c);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
|
||||||
s32 Language;
|
|
||||||
} *raw;
|
|
||||||
|
|
||||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
||||||
|
|
||||||
raw->magic = SFCI_MAGIC;
|
|
||||||
raw->cmd_id = 2;
|
|
||||||
raw->Language = Language;
|
|
||||||
|
|
||||||
Result rc = serviceIpcDispatch(&g_setSrv);
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
IpcParsedCommand r;
|
|
||||||
ipcParse(&r);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
u64 LanguageCode;
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
rc = resp->result;
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc) && LanguageCode) *LanguageCode = resp->LanguageCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setGetAvailableLanguageCodeCount(s32 *total) {
|
Result setGetAvailableLanguageCodeCount(s32 *total) {
|
||||||
IpcCommand c;
|
Result rc = _setCmdNoInOutU32(&g_setSrv, (u32*)total, hosversionAtLeast(4,0,0) ? 6 : 3);
|
||||||
ipcInitialize(&c);
|
if (R_SUCCEEDED(rc) && total && *total < 0) *total = 0;
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
|
||||||
} *raw;
|
|
||||||
|
|
||||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
||||||
|
|
||||||
raw->magic = SFCI_MAGIC;
|
|
||||||
raw->cmd_id = hosversionAtLeast(4,0,0) ? 6 : 3;
|
|
||||||
|
|
||||||
Result rc = serviceIpcDispatch(&g_setSrv);
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
IpcParsedCommand r;
|
|
||||||
ipcParse(&r);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
s32 total;
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
rc = resp->result;
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc) && total) {
|
|
||||||
*total = resp->total;
|
|
||||||
if (*total < 0) *total = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setGetRegionCode(SetRegion *out) {
|
Result setGetRegionCode(SetRegion *out) {
|
||||||
IpcCommand c;
|
s32 code=0;
|
||||||
ipcInitialize(&c);
|
Result rc = _setCmdNoInOutU32(&g_setSrv, (u32*)&code, 4);
|
||||||
|
if (R_SUCCEEDED(rc) && out) *out = code;
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
|
||||||
} *raw;
|
|
||||||
|
|
||||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
||||||
|
|
||||||
raw->magic = SFCI_MAGIC;
|
|
||||||
raw->cmd_id = 4;
|
|
||||||
|
|
||||||
Result rc = serviceIpcDispatch(&g_setSrv);
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
IpcParsedCommand r;
|
|
||||||
ipcParse(&r);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
s32 RegionCode;
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
rc = resp->result;
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc) && out) *out = resp->RegionCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setsysGetColorSetId(ColorSetId *out)
|
Result setsysGetColorSetId(ColorSetId *out) {
|
||||||
{
|
u32 color_set=0;
|
||||||
IpcCommand c;
|
Result rc = _setCmdNoInOutU32(&g_setsysSrv, &color_set, 23);
|
||||||
ipcInitialize(&c);
|
if (R_SUCCEEDED(rc) && out) *out = color_set;
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
|
||||||
} *raw;
|
|
||||||
|
|
||||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
||||||
|
|
||||||
raw->magic = SFCI_MAGIC;
|
|
||||||
raw->cmd_id = 23;
|
|
||||||
|
|
||||||
Result rc = serviceIpcDispatch(&g_setsysSrv);
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
IpcParsedCommand r;
|
|
||||||
ipcParse(&r);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
u32 color_set;
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
*out = resp->color_set;
|
|
||||||
rc = resp->result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setsysSetColorSetId(ColorSetId id)
|
Result setsysSetColorSetId(ColorSetId id) {
|
||||||
{
|
return _setCmdInU32NoOut(&g_setsysSrv, id, 24);
|
||||||
IpcCommand c;
|
|
||||||
ipcInitialize(&c);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
|
||||||
s32 id;
|
|
||||||
} *raw;
|
|
||||||
|
|
||||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
||||||
|
|
||||||
raw->magic = SFCI_MAGIC;
|
|
||||||
raw->cmd_id = 24;
|
|
||||||
raw->id = id;
|
|
||||||
|
|
||||||
Result rc = serviceIpcDispatch(&g_setsysSrv);
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
IpcParsedCommand r;
|
|
||||||
ipcParse(&r);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
rc = resp->result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result setsysGetSettingsItemValue(const char *name, const char *item_key, void *value_out, size_t value_out_size) {
|
|
||||||
char send_name[SET_MAX_NAME_SIZE];
|
|
||||||
char send_item_key[SET_MAX_NAME_SIZE];
|
|
||||||
|
|
||||||
memset(send_name, 0, SET_MAX_NAME_SIZE);
|
|
||||||
memset(send_item_key, 0, SET_MAX_NAME_SIZE);
|
|
||||||
strncpy(send_name, name, SET_MAX_NAME_SIZE-1);
|
|
||||||
strncpy(send_item_key, item_key, SET_MAX_NAME_SIZE-1);
|
|
||||||
|
|
||||||
IpcCommand c;
|
|
||||||
ipcInitialize(&c);
|
|
||||||
ipcAddSendStatic(&c, send_name, SET_MAX_NAME_SIZE, 0);
|
|
||||||
ipcAddSendStatic(&c, send_item_key, SET_MAX_NAME_SIZE, 0);
|
|
||||||
ipcAddRecvBuffer(&c, value_out, value_out_size, 0);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
|
||||||
} *raw;
|
|
||||||
|
|
||||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
||||||
|
|
||||||
raw->magic = SFCI_MAGIC;
|
|
||||||
raw->cmd_id = 38;
|
|
||||||
|
|
||||||
Result rc = serviceIpcDispatch(&g_setsysSrv);
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
IpcParsedCommand r;
|
|
||||||
ipcParse(&r);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
rc = resp->result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setsysGetSettingsItemValueSize(const char *name, const char *item_key, u64 *size_out) {
|
Result setsysGetSettingsItemValueSize(const char *name, const char *item_key, u64 *size_out) {
|
||||||
@ -439,178 +205,66 @@ Result setsysGetSettingsItemValueSize(const char *name, const char *item_key, u6
|
|||||||
memset(send_item_key, 0, SET_MAX_NAME_SIZE);
|
memset(send_item_key, 0, SET_MAX_NAME_SIZE);
|
||||||
strncpy(send_name, name, SET_MAX_NAME_SIZE-1);
|
strncpy(send_name, name, SET_MAX_NAME_SIZE-1);
|
||||||
strncpy(send_item_key, item_key, SET_MAX_NAME_SIZE-1);
|
strncpy(send_item_key, item_key, SET_MAX_NAME_SIZE-1);
|
||||||
|
|
||||||
|
return serviceDispatchOut(&g_setsysSrv, 37, *size_out,
|
||||||
|
.buffer_attrs = {
|
||||||
|
SfBufferAttr_HipcPointer | SfBufferAttr_In,
|
||||||
|
SfBufferAttr_HipcPointer | SfBufferAttr_In,
|
||||||
|
},
|
||||||
|
.buffers = {
|
||||||
|
{ send_name, SET_MAX_NAME_SIZE },
|
||||||
|
{ send_item_key, SET_MAX_NAME_SIZE },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result setsysGetSettingsItemValue(const char *name, const char *item_key, void *value_out, size_t value_out_size, u64 *size_out) {
|
||||||
|
char send_name[SET_MAX_NAME_SIZE];
|
||||||
|
char send_item_key[SET_MAX_NAME_SIZE];
|
||||||
|
|
||||||
IpcCommand c;
|
memset(send_name, 0, SET_MAX_NAME_SIZE);
|
||||||
ipcInitialize(&c);
|
memset(send_item_key, 0, SET_MAX_NAME_SIZE);
|
||||||
ipcAddSendStatic(&c, send_name, SET_MAX_NAME_SIZE, 0);
|
strncpy(send_name, name, SET_MAX_NAME_SIZE-1);
|
||||||
ipcAddSendStatic(&c, send_item_key, SET_MAX_NAME_SIZE, 0);
|
strncpy(send_item_key, item_key, SET_MAX_NAME_SIZE-1);
|
||||||
|
|
||||||
struct {
|
return serviceDispatchOut(&g_setsysSrv, 38, *size_out,
|
||||||
u64 magic;
|
.buffer_attrs = {
|
||||||
u64 cmd_id;
|
SfBufferAttr_HipcPointer | SfBufferAttr_In,
|
||||||
} *raw;
|
SfBufferAttr_HipcPointer | SfBufferAttr_In,
|
||||||
|
SfBufferAttr_HipcMapAlias | SfBufferAttr_Out,
|
||||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
},
|
||||||
|
.buffers = {
|
||||||
raw->magic = SFCI_MAGIC;
|
{ send_name, SET_MAX_NAME_SIZE },
|
||||||
raw->cmd_id = 37;
|
{ send_item_key, SET_MAX_NAME_SIZE },
|
||||||
|
{ value_out, value_out_size },
|
||||||
Result rc = serviceIpcDispatch(&g_setsysSrv);
|
},
|
||||||
|
);
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
IpcParsedCommand r;
|
|
||||||
ipcParse(&r);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
u64 size;
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
rc = resp->result;
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc) && size_out) *size_out = resp->size;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setsysGetSerialNumber(char *serial) {
|
Result setsysGetSerialNumber(char *serial) {
|
||||||
IpcCommand c;
|
char out[0x18]={0};
|
||||||
ipcInitialize(&c);
|
|
||||||
|
|
||||||
if (serial) memset(serial, 0, 0x19);
|
Result rc = serviceDispatchOut(&g_setsysSrv, 68, out);
|
||||||
|
if (R_SUCCEEDED(rc) && serial) {
|
||||||
struct {
|
memcpy(serial, out, 0x18);
|
||||||
u64 magic;
|
serial[0x18]=0;
|
||||||
u64 cmd_id;
|
|
||||||
} *raw;
|
|
||||||
|
|
||||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
||||||
|
|
||||||
raw->magic = SFCI_MAGIC;
|
|
||||||
raw->cmd_id = 68;
|
|
||||||
|
|
||||||
Result rc = serviceIpcDispatch(&g_setsysSrv);
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
IpcParsedCommand r;
|
|
||||||
ipcParse(&r);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
char serial[0x18];
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
rc = resp->result;
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc) && serial)
|
|
||||||
memcpy(serial, resp->serial, 0x18);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setsysGetFlag(SetSysFlag flag, bool *out) {
|
Result setsysGetFlag(SetSysFlag flag, bool *out) {
|
||||||
IpcCommand c;
|
return _setCmdNoInOutBool(&g_setsysSrv, out, flag);
|
||||||
ipcInitialize(&c);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
|
||||||
} *raw;
|
|
||||||
|
|
||||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
||||||
|
|
||||||
raw->magic = SFCI_MAGIC;
|
|
||||||
raw->cmd_id = flag;
|
|
||||||
|
|
||||||
Result rc = serviceIpcDispatch(&g_setsysSrv);
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
IpcParsedCommand r;
|
|
||||||
ipcParse(&r);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
u8 flag;
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
*out = resp->flag;
|
|
||||||
rc = resp->result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setsysSetFlag(SetSysFlag flag, bool enable) {
|
Result setsysSetFlag(SetSysFlag flag, bool enable) {
|
||||||
IpcCommand c;
|
return _setCmdInBoolNoOut(&g_setsysSrv, enable, flag + 1);
|
||||||
ipcInitialize(&c);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
|
||||||
u8 flag;
|
|
||||||
} *raw;
|
|
||||||
|
|
||||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
||||||
|
|
||||||
raw->magic = SFCI_MAGIC;
|
|
||||||
raw->cmd_id = flag + 1;
|
|
||||||
raw->flag = enable;
|
|
||||||
|
|
||||||
Result rc = serviceIpcDispatch(&g_setsysSrv);
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
IpcParsedCommand r;
|
|
||||||
ipcParse(&r);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
u8 flag;
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
rc = resp->result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result _setsysGetFirmwareVersionImpl(SetSysFirmwareVersion *out, u32 cmd_id) {
|
static Result _setsysGetFirmwareVersionImpl(SetSysFirmwareVersion *out, u32 cmd_id) {
|
||||||
IpcCommand c;
|
return serviceDispatch(&g_setsysSrv, cmd_id,
|
||||||
ipcInitialize(&c);
|
.buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_Out },
|
||||||
ipcAddRecvStatic(&c, out, sizeof(*out), 0);
|
.buffers = { { out, sizeof(*out) } },
|
||||||
|
);
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
|
||||||
} *raw;
|
|
||||||
|
|
||||||
raw = serviceIpcPrepareHeader(&g_setsysSrv, &c, sizeof(*raw));
|
|
||||||
|
|
||||||
raw->magic = SFCI_MAGIC;
|
|
||||||
raw->cmd_id = cmd_id;
|
|
||||||
|
|
||||||
Result rc = serviceIpcDispatch(&g_setsysSrv);
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
IpcParsedCommand r;
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
} *resp;
|
|
||||||
|
|
||||||
serviceIpcParse(&g_setsysSrv, &r, sizeof(*resp));
|
|
||||||
resp = r.Raw;
|
|
||||||
|
|
||||||
rc = resp->result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setsysGetFirmwareVersion(SetSysFirmwareVersion *out) {
|
Result setsysGetFirmwareVersion(SetSysFirmwareVersion *out) {
|
||||||
@ -622,143 +276,35 @@ Result setsysGetFirmwareVersion(SetSysFirmwareVersion *out) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setsysBindFatalDirtyFlagEvent(Event *out) {
|
Result setsysBindFatalDirtyFlagEvent(Event *out_event) {
|
||||||
IpcCommand c;
|
return _setCmdGetEvent(&g_setsysSrv, out_event, false, 93);
|
||||||
ipcInitialize(&c);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
|
||||||
} *raw;
|
|
||||||
|
|
||||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
||||||
|
|
||||||
raw->magic = SFCI_MAGIC;
|
|
||||||
raw->cmd_id = 93;
|
|
||||||
|
|
||||||
Result rc = serviceIpcDispatch(&g_setsysSrv);
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
IpcParsedCommand r;
|
|
||||||
ipcParse(&r);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
rc = resp->result;
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
eventLoadRemote(out, r.Handles[0], false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setsysGetFatalDirtyFlags(u64 *flags_0, u64 *flags_1) {
|
Result setsysGetFatalDirtyFlags(u64 *flags_0, u64 *flags_1) {
|
||||||
IpcCommand c;
|
|
||||||
ipcInitialize(&c);
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u64 magic;
|
u64 flags_0;
|
||||||
u64 cmd_id;
|
u64 flags_1;
|
||||||
} *raw;
|
} out;
|
||||||
|
|
||||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
||||||
|
|
||||||
raw->magic = SFCI_MAGIC;
|
|
||||||
raw->cmd_id = 94;
|
|
||||||
|
|
||||||
Result rc = serviceIpcDispatch(&g_setsysSrv);
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
IpcParsedCommand r;
|
|
||||||
ipcParse(&r);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
u64 flags_0;
|
|
||||||
u64 flags_1;
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
rc = resp->result;
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
*flags_0 = resp->flags_0;
|
|
||||||
*flags_1 = resp->flags_1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Result rc = serviceDispatchOut(&g_setsysSrv, 94, out);
|
||||||
|
if (R_SUCCEEDED(rc) && flags_0) *flags_0 = out.flags_0;
|
||||||
|
if (R_SUCCEEDED(rc) && flags_1) *flags_1 = out.flags_1;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setsysGetDeviceNickname(char* nickname) {
|
Result setsysGetDeviceNickname(char* nickname) {
|
||||||
IpcCommand c;
|
return serviceDispatch(&g_setsysSrv, 77,
|
||||||
ipcInitialize(&c);
|
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
||||||
|
.buffers = { { nickname, SET_MAX_NICKNAME_SIZE } },
|
||||||
ipcAddRecvBuffer(&c, nickname, SET_MAX_NICKNAME_SIZE, BufferType_Normal);
|
);
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
|
||||||
} *raw;
|
|
||||||
|
|
||||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
||||||
|
|
||||||
raw->magic = SFCI_MAGIC;
|
|
||||||
raw->cmd_id = 77;
|
|
||||||
|
|
||||||
Result rc = serviceIpcDispatch(&g_setsysSrv);
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
IpcParsedCommand r;
|
|
||||||
ipcParse(&r);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
rc = resp->result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result setsysSetDeviceNickname(const char* nickname) {
|
Result setsysSetDeviceNickname(const char* nickname) {
|
||||||
char send_nickname[SET_MAX_NICKNAME_SIZE] = {0};
|
char send_nickname[SET_MAX_NICKNAME_SIZE] = {0};
|
||||||
strncpy(send_nickname, nickname, SET_MAX_NICKNAME_SIZE-1);
|
strncpy(send_nickname, nickname, SET_MAX_NICKNAME_SIZE-1);
|
||||||
|
|
||||||
IpcCommand c;
|
return serviceDispatch(&g_setsysSrv, 78,
|
||||||
ipcInitialize(&c);
|
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
|
||||||
ipcAddSendBuffer(&c, send_nickname, SET_MAX_NICKNAME_SIZE, 0);
|
.buffers = { { send_nickname, SET_MAX_NICKNAME_SIZE } },
|
||||||
|
);
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
|
||||||
} *raw;
|
|
||||||
|
|
||||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
|
||||||
|
|
||||||
raw->magic = SFCI_MAGIC;
|
|
||||||
raw->cmd_id = 78;
|
|
||||||
|
|
||||||
Result rc = serviceIpcDispatch(&g_setsysSrv);
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
IpcParsedCommand r;
|
|
||||||
ipcParse(&r);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
rc = resp->result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user