mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 12:32:40 +02:00
pdmqry: Updated for new-ipc and updated for using AccountUid. Renamed pdmqryGetUserPlayedApplications to pdmqryQueryRecentlyPlayedApplication. Renamed pdmqryGetUserAccountEvent to pdmqryGetRecentlyPlayedApplicationUpdateEvent. Minor param name adjustment.
This commit is contained in:
parent
39288a832e
commit
1b610070f5
@ -6,7 +6,8 @@
|
||||
*/
|
||||
#pragma once
|
||||
#include "../types.h"
|
||||
#include "../services/sm.h"
|
||||
#include "../sf/service.h"
|
||||
#include "../services/acc.h"
|
||||
#include "../kernel/event.h"
|
||||
|
||||
/// PlayEventType
|
||||
@ -132,7 +133,7 @@ typedef struct {
|
||||
|
||||
/// AccountEvent
|
||||
typedef struct {
|
||||
union { u128 userID; } PACKED; ///< userID.
|
||||
AccountUid userID; ///< \ref AccountUid
|
||||
u32 entryindex; ///< Entry index.
|
||||
u8 pad[4]; ///< Padding.
|
||||
u64 timestampUser; ///< See PdmPlayEvent::timestampUser.
|
||||
@ -182,10 +183,10 @@ Result pdmqryQueryPlayStatisticsByApplicationId(u64 titleID, PdmPlayStatistics *
|
||||
/**
|
||||
* @brief Gets \ref PdmPlayStatistics for the specified titleID and account userID.
|
||||
* @param[in] titleID Application titleID.
|
||||
* @param[in] userID Account userID.
|
||||
* @param[in] userID \ref AccountUid
|
||||
* @param[out] stats \ref PdmPlayStatistics
|
||||
*/
|
||||
Result pdmqryQueryPlayStatisticsByApplicationIdAndUserAccountId(u64 titleID, u128 userID, PdmPlayStatistics *stats);
|
||||
Result pdmqryQueryPlayStatisticsByApplicationIdAndUserAccountId(u64 titleID, AccountUid *userID, PdmPlayStatistics *stats);
|
||||
|
||||
/**
|
||||
* @brief Gets \ref PdmLastPlayTime for the specified titles.
|
||||
@ -226,39 +227,39 @@ Result pdmqryQueryAccountEvent(u32 entryindex, PdmAccountEvent *events, s32 coun
|
||||
* @brief Gets a list of \ref PdmAccountPlayEvent.
|
||||
* @note Only available with [4.0.0+].
|
||||
* @param[in] entryindex Start entry index.
|
||||
* @param[in] userID Account userID.
|
||||
* @param[in] userID \ref AccountUid
|
||||
* @param[out] events Output \ref PdmAccountPlayEvent array.
|
||||
* @param[in] count Max entries in the output array.
|
||||
* @param[out] total_out Total output entries.
|
||||
*/
|
||||
Result pdmqryQueryAccountPlayEvent(u32 entryindex, u128 userID, PdmAccountPlayEvent *events, s32 count, s32 *total_out);
|
||||
Result pdmqryQueryAccountPlayEvent(u32 entryindex, AccountUid *userID, PdmAccountPlayEvent *events, s32 count, s32 *total_out);
|
||||
|
||||
/**
|
||||
* @brief Gets range fields which can then be used with \ref pdmqryQueryAccountPlayEvent.
|
||||
* @param[in] userID Account userID.
|
||||
* @param[in] userID \ref AccountUid
|
||||
* @param[out] total_entries Total entries.
|
||||
* @param[out] start_entryindex Start entry index.
|
||||
* @param[out] end_entryindex End entry index.
|
||||
*/
|
||||
Result pdmqryGetAvailableAccountPlayEventRange(u128 userID, u32 *total_entries, u32 *start_entryindex, u32 *end_entryindex);
|
||||
Result pdmqryGetAvailableAccountPlayEventRange(AccountUid *userID, u32 *total_entries, u32 *start_entryindex, u32 *end_entryindex);
|
||||
|
||||
/**
|
||||
* @brief Gets a list of titles played by the specified user.
|
||||
* @note Only available with [6.0.0+].
|
||||
* @param[in] userID Account userID.
|
||||
* @param[in] userID \ref AccountUid
|
||||
* @param[out] titleIDs Output titleID array.
|
||||
* @param[in] count Max entries in the output array.
|
||||
* @param[out] total_out Total output entries.
|
||||
*/
|
||||
Result pdmqryGetUserPlayedApplications(u128 userID, u64 *titleIDs, size_t count, u32 *total_out);
|
||||
Result pdmqryQueryRecentlyPlayedApplication(AccountUid *userID, u64 *titleIDs, size_t count, u32 *total_out);
|
||||
|
||||
/**
|
||||
* @brief Gets an Event which is signaled when logging a new \ref PdmPlayEvent which would be available via \ref pdmqryQueryAccountEvent, where PdmPlayEvent::eventData::account::type is 0.
|
||||
* @note Only available with [6.0.0+].
|
||||
* @note The Event must be closed by the user once finished with it.
|
||||
* @param[out] event_out Output Event with autoclear=false.
|
||||
* @param[out] out_event Output Event with autoclear=false.
|
||||
*/
|
||||
Result pdmqryGetUserAccountEvent(Event* event_out);
|
||||
Result pdmqryGetRecentlyPlayedApplicationUpdateEvent(Event* out_event);
|
||||
|
||||
/**
|
||||
* @brief Helper function which converts a Play timestamp from the Pdm*Event structs to POSIX.
|
||||
|
@ -1,193 +1,75 @@
|
||||
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
||||
#include "service_guard.h"
|
||||
#include <string.h>
|
||||
#include "types.h"
|
||||
#include "result.h"
|
||||
#include "arm/atomics.h"
|
||||
#include "kernel/ipc.h"
|
||||
#include "kernel/event.h"
|
||||
#include "services/sm.h"
|
||||
#include "services/pdm.h"
|
||||
#include "services/acc.h"
|
||||
#include "runtime/hosversion.h"
|
||||
|
||||
static Service g_pdmqrySrv;
|
||||
static u64 g_pdmqryRefCnt;
|
||||
|
||||
Result pdmqryInitialize(void) {
|
||||
atomicIncrement64(&g_pdmqryRefCnt);
|
||||
NX_GENERATE_SERVICE_GUARD(pdmqry);
|
||||
|
||||
if (serviceIsActive(&g_pdmqrySrv))
|
||||
return 0;
|
||||
|
||||
Result rc = smGetService(&g_pdmqrySrv, "pdm:qry");
|
||||
|
||||
if (R_FAILED(rc)) pdmqryExit();
|
||||
|
||||
return rc;
|
||||
Result _pdmqryInitialize(void) {
|
||||
return smGetService(&g_pdmqrySrv, "pdm:qry");
|
||||
}
|
||||
|
||||
void pdmqryExit(void) {
|
||||
if (atomicDecrement64(&g_pdmqryRefCnt) == 0)
|
||||
serviceClose(&g_pdmqrySrv);
|
||||
void _pdmqryCleanup(void) {
|
||||
serviceClose(&g_pdmqrySrv);
|
||||
}
|
||||
|
||||
Service* pdmqryGetServiceSession(void) {
|
||||
return &g_pdmqrySrv;
|
||||
}
|
||||
|
||||
static Result _pdmqryQueryEvent(u64 cmd_id, u32 entryindex, void* events, size_t entrysize, s32 count, s32 *total_out) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
static Result _pdmCmdGetEvent(Service* srv, Event* out_event, bool autoclear, u32 cmd_id) {
|
||||
Handle event = INVALID_HANDLE;
|
||||
Result rc = serviceDispatch(srv, cmd_id,
|
||||
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
|
||||
.out_handles = &event,
|
||||
);
|
||||
|
||||
ipcAddRecvBuffer(&c, events, count*entrysize, BufferType_Normal);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
u32 entryindex;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_pdmqrySrv, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = cmd_id;
|
||||
raw->entryindex = entryindex;
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_pdmqrySrv);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
s32 total_out;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_pdmqrySrv, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc) && total_out) *total_out = resp->total_out;
|
||||
}
|
||||
if (R_SUCCEEDED(rc))
|
||||
eventLoadRemote(out_event, event, autoclear);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static Result _pdmqryQueryEvent(u32 cmd_id, u32 entryindex, void* events, size_t entrysize, s32 count, s32 *total_out) {
|
||||
return serviceDispatchInOut(&g_pdmqrySrv, cmd_id, entryindex, *total_out,
|
||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
||||
.buffers = { { events, count*entrysize } },
|
||||
);
|
||||
}
|
||||
|
||||
Result pdmqryQueryApplicationEvent(u32 entryindex, PdmApplicationEvent *events, s32 count, s32 *total_out) {
|
||||
return _pdmqryQueryEvent(0, entryindex, events, sizeof(PdmApplicationEvent), count, total_out);
|
||||
}
|
||||
|
||||
Result pdmqryQueryPlayStatisticsByApplicationId(u64 titleID, PdmPlayStatistics *stats) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
u64 titleID;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_pdmqrySrv, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 4;
|
||||
raw->titleID = titleID;
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_pdmqrySrv);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
PdmPlayStatistics stats;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_pdmqrySrv, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc) && stats) memcpy(stats, &resp->stats, sizeof(resp->stats));
|
||||
}
|
||||
|
||||
return rc;
|
||||
return serviceDispatchInOut(&g_pdmqrySrv, 4, titleID, *stats);
|
||||
}
|
||||
|
||||
Result pdmqryQueryPlayStatisticsByApplicationIdAndUserAccountId(u64 titleID, u128 userID, PdmPlayStatistics *stats) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
Result pdmqryQueryPlayStatisticsByApplicationIdAndUserAccountId(u64 titleID, AccountUid *userID, PdmPlayStatistics *stats) {
|
||||
const struct {
|
||||
u64 titleID;
|
||||
union { u128 userID; } PACKED;
|
||||
} *raw;
|
||||
AccountUid userID;
|
||||
} in = { titleID, *userID };
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_pdmqrySrv, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 5;
|
||||
raw->titleID = titleID;
|
||||
raw->userID = userID;
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_pdmqrySrv);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
PdmPlayStatistics stats;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_pdmqrySrv, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc) && stats) memcpy(stats, &resp->stats, sizeof(resp->stats));
|
||||
}
|
||||
|
||||
return rc;
|
||||
return serviceDispatchInOut(&g_pdmqrySrv, 5, in, *stats);
|
||||
}
|
||||
|
||||
Result pdmqryQueryLastPlayTime(PdmLastPlayTime *playtimes, const u64 *titleIDs, s32 count, s32 *total_out) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
ipcAddSendBuffer(&c, titleIDs, count*sizeof(u64), BufferType_Normal);
|
||||
ipcAddRecvBuffer(&c, playtimes, count*sizeof(PdmLastPlayTime), BufferType_Normal);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_pdmqrySrv, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 7;
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_pdmqrySrv);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
s32 total_out;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_pdmqrySrv, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc) && total_out) *total_out = resp->total_out;
|
||||
}
|
||||
|
||||
return rc;
|
||||
return serviceDispatchOut(&g_pdmqrySrv, 7, *total_out,
|
||||
.buffer_attrs = {
|
||||
SfBufferAttr_HipcMapAlias | SfBufferAttr_Out,
|
||||
SfBufferAttr_HipcMapAlias | SfBufferAttr_In,
|
||||
},
|
||||
.buffers = {
|
||||
{ playtimes, count*sizeof(PdmLastPlayTime) },
|
||||
{ titleIDs, count*sizeof(u64) },
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Result pdmqryQueryPlayEvent(u32 entryindex, PdmPlayEvent *events, s32 count, s32 *total_out) {
|
||||
@ -195,41 +77,18 @@ Result pdmqryQueryPlayEvent(u32 entryindex, PdmPlayEvent *events, s32 count, s32
|
||||
}
|
||||
|
||||
Result pdmqryGetAvailablePlayEventRange(u32 *total_entries, u32 *start_entryindex, u32 *end_entryindex) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_pdmqrySrv, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 9;
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_pdmqrySrv);
|
||||
u32 total_entries;
|
||||
u32 start_entryindex;
|
||||
u32 end_entryindex;
|
||||
} out;
|
||||
|
||||
Result rc = serviceDispatchOut(&g_pdmqrySrv, 9, out);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
u32 total_entries;
|
||||
u32 start_entryindex;
|
||||
u32 end_entryindex;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_pdmqrySrv, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc) && total_entries) *total_entries = resp->total_entries;
|
||||
if (R_SUCCEEDED(rc) && start_entryindex) *start_entryindex = resp->start_entryindex;
|
||||
if (R_SUCCEEDED(rc) && end_entryindex) *end_entryindex = resp->end_entryindex;
|
||||
if (total_entries) *total_entries = out.total_entries;
|
||||
if (start_entryindex) *start_entryindex = out.start_entryindex;
|
||||
if (end_entryindex) *end_entryindex = out.end_entryindex;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -237,173 +96,54 @@ Result pdmqryQueryAccountEvent(u32 entryindex, PdmAccountEvent *events, s32 coun
|
||||
return _pdmqryQueryEvent(10, entryindex, events, sizeof(PdmAccountEvent), count, total_out);
|
||||
}
|
||||
|
||||
Result pdmqryQueryAccountPlayEvent(u32 entryindex, u128 userID, PdmAccountPlayEvent *events, s32 count, s32 *total_out) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
Result pdmqryQueryAccountPlayEvent(u32 entryindex, AccountUid *userID, PdmAccountPlayEvent *events, s32 count, s32 *total_out) {
|
||||
if (hosversionBefore(4,0,0))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
|
||||
ipcAddRecvBuffer(&c, events, count*sizeof(PdmAccountPlayEvent), BufferType_Normal);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
const struct {
|
||||
u32 entryindex;
|
||||
u32 pad;
|
||||
union { u128 userID; } PACKED;
|
||||
} *raw;
|
||||
AccountUid userID;
|
||||
} in = { entryindex, *userID };
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_pdmqrySrv, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 11;
|
||||
raw->entryindex = entryindex;
|
||||
raw->userID = userID;
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_pdmqrySrv);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
s32 total_out;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_pdmqrySrv, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc) && total_out) *total_out = resp->total_out;
|
||||
}
|
||||
|
||||
return rc;
|
||||
return serviceDispatchInOut(&g_pdmqrySrv, 11, in, *total_out,
|
||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
||||
.buffers = { { events, count*sizeof(PdmAccountPlayEvent) } },
|
||||
);
|
||||
}
|
||||
|
||||
Result pdmqryGetAvailableAccountPlayEventRange(u128 userID, u32 *total_entries, u32 *start_entryindex, u32 *end_entryindex) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
Result pdmqryGetAvailableAccountPlayEventRange(AccountUid *userID, u32 *total_entries, u32 *start_entryindex, u32 *end_entryindex) {
|
||||
if (hosversionBefore(4,0,0))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
u128 userID;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_pdmqrySrv, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 12;
|
||||
raw->userID = userID;
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_pdmqrySrv);
|
||||
u32 total_entries;
|
||||
u32 start_entryindex;
|
||||
u32 end_entryindex;
|
||||
} out;
|
||||
|
||||
Result rc = serviceDispatchInOut(&g_pdmqrySrv, 12, *userID, out);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
u32 total_entries;
|
||||
u32 start_entryindex;
|
||||
u32 end_entryindex;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_pdmqrySrv, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc) && total_entries) *total_entries = resp->total_entries;
|
||||
if (R_SUCCEEDED(rc) && start_entryindex) *start_entryindex = resp->start_entryindex;
|
||||
if (R_SUCCEEDED(rc) && end_entryindex) *end_entryindex = resp->end_entryindex;
|
||||
if (total_entries) *total_entries = out.total_entries;
|
||||
if (start_entryindex) *start_entryindex = out.start_entryindex;
|
||||
if (end_entryindex) *end_entryindex = out.end_entryindex;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result pdmqryGetUserPlayedApplications(u128 userID, u64 *titleIDs, size_t count, u32 *total_out) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
Result pdmqryQueryRecentlyPlayedApplication(AccountUid *userID, u64 *titleIDs, size_t count, u32 *total_out) {
|
||||
if (hosversionBefore(6,0,0))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
|
||||
ipcAddRecvBuffer(&c, titleIDs, count*sizeof(u64), BufferType_Normal);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
u128 userID;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_pdmqrySrv, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 14;
|
||||
raw->userID = userID;
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_pdmqrySrv);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
u32 total_out;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_pdmqrySrv, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc) && total_out) *total_out = resp->total_out;
|
||||
}
|
||||
|
||||
return rc;
|
||||
return serviceDispatchInOut(&g_pdmqrySrv, 14, *userID, *total_out,
|
||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
||||
.buffers = { { titleIDs, count*sizeof(u64) } },
|
||||
);
|
||||
}
|
||||
|
||||
Result pdmqryGetUserAccountEvent(Event* event_out) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
Result pdmqryGetRecentlyPlayedApplicationUpdateEvent(Event* out_event) {
|
||||
if (hosversionBefore(6,0,0))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_pdmqrySrv, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 15;
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_pdmqrySrv);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_pdmqrySrv, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
eventLoadRemote(event_out, r.Handles[0], false);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
return _pdmCmdGetEvent(&g_pdmqrySrv, out_event, false, 15);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user