Skip to content

Commit 7ed3008

Browse files
committed
Added code for using dlp::clnt
1 parent 607f1d1 commit 7ed3008

File tree

5 files changed

+381
-0
lines changed

5 files changed

+381
-0
lines changed

libctru/include/3ds.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ extern "C" {
7979
#include <3ds/services/loader.h>
8080
#include <3ds/services/y2r.h>
8181
#include <3ds/services/mcuhwc.h>
82+
#include <3ds/services/dlpclnt.h>
8283

8384
#include <3ds/gpu/gx.h>
8485
#include <3ds/gpu/gpu.h>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#include <3ds/types.h>
2+
#include <3ds/result.h>
3+
#include <3ds/svc.h>
4+
#include <3ds/srv.h>
5+
#include <3ds/synchronization.h>
6+
#include <3ds/services/cfgu.h>
7+
#include <3ds/services/ndm.h>
8+
#include <3ds/ipc.h>
9+
10+
typedef struct {
11+
u32 uniqueId;
12+
u32 revision;
13+
u8 macAddr[6];
14+
} dlpTitleInfo;
15+
16+
Result dlpClntInit(void);
17+
18+
void dlpClntExit(void);
19+
20+
bool dlpClntWaitForEvent(bool nextEvent, bool wait);
21+
22+
u64 dlpCreateChildTid(u32 uniqueId, u32 revision);
23+
24+
Result DLPCLNT_Initialize(size_t sharedMemSize, u8 maxScanTitles, size_t unk, Handle sharedmemHandle, Handle eventHandle);
25+
26+
Result DLPCLNT_Finalize(void);
27+
28+
//DLPCLNT_GetEventDesc();
29+
30+
Result DLPCLNT_GetChannel(u16* channel);
31+
32+
Result DLPCLNT_StartScan(u16 channel, u8* macAddr);
33+
34+
Result DLPCLNT_StopScan(void);
35+
/*
36+
DLPCLNT_GetServerInfo();
37+
38+
DLPCLNT_GetTitleInfo();
39+
*/
40+
Result DLPCLNT_GetTitleInfoInOrder(void* buf, size_t size, size_t* actual_size);
41+
/*
42+
DLPCLNT_DeleteScanInfo();
43+
*/
44+
Result DLPCLNT_PrepareForSystemDownload(u8* macAddr, u32 uniqueId, u32 revision);
45+
/*
46+
DLPCLNT_StartSystemDownload();
47+
*/
48+
Result DLPCLNT_StartTitleDownload(u8* macAddr, u32 uniqueId, u32 revision);
49+
50+
Result DLPCLNT_GetMyStatus(u32* status);
51+
/*
52+
DLPCLNT_GetConnectingNodes();
53+
54+
DLPCLNT_GetNodeInfo();
55+
*/
56+
Result DLPCLNT_GetWirelessRebootPassphrase(void* buf);
57+
58+
Result DLPCLNT_StopSession(void);
59+
/*
60+
DLPCLNT_GetCupVersion();
61+
62+
DLPCLNT_GetDupAvailability();*/

libctru/include/3ds/services/ns.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ Result NS_TerminateTitle(void);
3333
*/
3434
Result NS_LaunchApplicationFIRM(u64 titleid, u32 flags);
3535

36+
Result NS_SetWirelessRebootInfo(u8* macAddr, u8* passphrase);
37+
3638
/**
3739
* @brief Reboots to a title.
3840
* @param mediatype Mediatype of the title.

libctru/source/services/dlpclnt.c

Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
#include <malloc.h>
2+
#include <string.h>
3+
#include <3ds/types.h>
4+
#include <3ds/result.h>
5+
#include <3ds/svc.h>
6+
#include <3ds/srv.h>
7+
#include <3ds/synchronization.h>
8+
#include <3ds/services/dlpclnt.h>
9+
#include <3ds/services/cfgu.h>
10+
#include <3ds/services/ndm.h>
11+
#include <3ds/ipc.h>
12+
13+
14+
Handle dlpClntHandle;
15+
Handle dlpClntMemHandle;
16+
u8* dlpClntMemAddr;
17+
size_t dlpClntMemSize;
18+
Handle dlpClntEventHandle;
19+
20+
static int dlpClntRefCount;
21+
22+
u32 ndm_state;
23+
24+
Result dlpClntInit() {
25+
Result ret = 0;
26+
ndm_state = 0;
27+
28+
if (AtomicPostIncrement(&dlpClntRefCount)) return 0;
29+
30+
ret = ndmuInit();
31+
if (R_FAILED(ret))goto end;
32+
33+
ndm_state = 1;
34+
ret = NDMU_EnterExclusiveState(NDM_EXCLUSIVE_STATE_LOCAL_COMMUNICATIONS);
35+
if (R_FAILED(ret))goto end;
36+
37+
ndm_state = 2;
38+
39+
dlpClntMemSize = 0x232000;
40+
dlpClntMemAddr = memalign(0x1000, dlpClntMemSize);
41+
if (dlpClntMemAddr == NULL) {
42+
ret = -1;
43+
goto end;
44+
}
45+
46+
ret = svcCreateMemoryBlock(&dlpClntMemHandle, (u32)dlpClntMemAddr, dlpClntMemSize, 0x0, MEMPERM_READ | MEMPERM_WRITE);
47+
if (R_FAILED(ret))goto end;
48+
49+
ret = svcCreateEvent(&dlpClntEventHandle, RESET_ONESHOT);
50+
if (R_FAILED(ret))goto end;
51+
52+
ret = srvGetServiceHandle(&dlpClntHandle, "dlp:CLNT");
53+
if (R_FAILED(ret))goto end;
54+
55+
ret = DLPCLNT_Initialize(dlpClntMemSize, 0x10, 0x200000, dlpClntMemHandle, dlpClntEventHandle);
56+
if (R_FAILED(ret)) {
57+
svcCloseHandle(dlpClntHandle);
58+
dlpClntHandle = 0;
59+
goto end;
60+
}
61+
62+
return ret;
63+
end:
64+
dlpClntExit();
65+
return ret;
66+
}
67+
68+
void dlpClntExit() {
69+
if (AtomicDecrement(&dlpClntRefCount)) return;
70+
71+
if (dlpClntHandle)
72+
{
73+
DLPCLNT_Finalize();
74+
svcCloseHandle(dlpClntHandle);
75+
dlpClntHandle = 0;
76+
}
77+
78+
if (ndm_state) {
79+
if (ndm_state == 2)NDMU_LeaveExclusiveState();
80+
ndmuExit();
81+
ndm_state = 0;
82+
}
83+
84+
if (dlpClntEventHandle) {
85+
svcCloseHandle(dlpClntMemHandle);
86+
dlpClntMemHandle = 0;
87+
}
88+
89+
if (dlpClntMemHandle)
90+
{
91+
svcCloseHandle(dlpClntMemHandle);
92+
dlpClntMemHandle = 0;
93+
}
94+
95+
dlpClntMemAddr = NULL;
96+
dlpClntMemSize = 0;
97+
}
98+
99+
bool dlpClntWaitForEvent(bool nextEvent, bool wait) {
100+
bool ret = true;
101+
u64 delayvalue = U64_MAX;
102+
103+
if (!wait)delayvalue = 0;
104+
105+
if (nextEvent)svcClearEvent(dlpClntEventHandle);
106+
107+
if (svcWaitSynchronization(dlpClntEventHandle, delayvalue) != 0 && !wait)ret = false;
108+
109+
if (!nextEvent)svcClearEvent(dlpClntEventHandle);
110+
111+
return ret;
112+
}
113+
114+
u64 dlpCreateChildTid(u32 uniqueId, u32 revision) {
115+
u64 tid = 0;
116+
if (uniqueId) {
117+
tid = (u64)0x40001 << 32;
118+
tid |= revision | ((uniqueId & 0xff0fffff) << 8);
119+
}
120+
return tid;
121+
}
122+
123+
Result DLPCLNT_Initialize(size_t sharedMemSize, u8 maxScanTitles, size_t unk, Handle sharedMemHandle, Handle eventHandle) {
124+
u32* cmdbuf = getThreadCommandBuffer();
125+
126+
cmdbuf[0] = IPC_MakeHeader(0x1,3,3); // 0x100C3
127+
cmdbuf[1] = sharedMemSize;
128+
cmdbuf[2] = maxScanTitles;
129+
cmdbuf[3] = unk;
130+
cmdbuf[4] = IPC_Desc_SharedHandles(2);
131+
cmdbuf[5] = sharedMemHandle;
132+
cmdbuf[6] = eventHandle;
133+
134+
Result ret = 0;
135+
if (R_FAILED(ret = svcSendSyncRequest(dlpClntHandle)))return ret;
136+
137+
return cmdbuf[1];
138+
}
139+
140+
Result DLPCLNT_Finalize() {
141+
u32* cmdbuf = getThreadCommandBuffer();
142+
143+
cmdbuf[0] = IPC_MakeHeader(0x2,0,0); // 0x20000
144+
145+
Result ret = 0;
146+
if (R_FAILED(ret = svcSendSyncRequest(dlpClntHandle)))return ret;
147+
148+
return cmdbuf[1];
149+
}
150+
151+
Result DLPCLNT_GetChannel(u16* channel) {
152+
u32* cmdbuf = getThreadCommandBuffer();
153+
154+
cmdbuf[0] = IPC_MakeHeader(0x4,0,0); // 0x40000
155+
156+
Result ret = 0;
157+
if (R_FAILED(ret = svcSendSyncRequest(dlpClntHandle)))return ret;
158+
159+
*channel = cmdbuf[2];
160+
161+
return cmdbuf[1];
162+
}
163+
164+
Result DLPCLNT_StartScan(u16 channel, u8* macAddr) {
165+
u32* cmdbuf = getThreadCommandBuffer();
166+
167+
cmdbuf[0] = IPC_MakeHeader(0x5,6,0); // 0x50180
168+
cmdbuf[1] = channel;
169+
cmdbuf[2] = 0; // tidLow filter
170+
cmdbuf[3] = 0; // tidHigh filter
171+
if (macAddr) {
172+
memcpy(cmdbuf + 4, macAddr, 6);
173+
}
174+
else {
175+
cmdbuf[4] = 0; // mac address filter
176+
cmdbuf[5] = 0;
177+
}
178+
cmdbuf[6] = 0; // unknown state filter
179+
180+
Result ret = 0;
181+
if (R_FAILED(ret = svcSendSyncRequest(dlpClntHandle)))return ret;
182+
183+
return cmdbuf[1];
184+
}
185+
186+
Result DLPCLNT_StopScan() {
187+
u32* cmdbuf = getThreadCommandBuffer();
188+
189+
cmdbuf[0] = IPC_MakeHeader(0x6,0,0); // 0x60000
190+
191+
Result ret = 0;
192+
if (R_FAILED(ret = svcSendSyncRequest(dlpClntHandle)))return ret;
193+
194+
return cmdbuf[1];
195+
}
196+
197+
Result DLPCLNT_GetTitleInfoInOrder(void* buf, size_t size, size_t* actual_size) {
198+
u32* cmdbuf = getThreadCommandBuffer();
199+
u32 saved_threadstorage[2];
200+
201+
cmdbuf[0] = IPC_MakeHeader(0x9,1,0); // 0x90040
202+
cmdbuf[1] = 0; // 0 = Iterate?, 1 = Don't Iterate?
203+
204+
u32* staticbufs = getThreadStaticBuffers();
205+
saved_threadstorage[0] = staticbufs[0];
206+
saved_threadstorage[1] = staticbufs[1];
207+
208+
staticbufs[0] = IPC_Desc_StaticBuffer(size, 0);
209+
staticbufs[1] = (u32)buf;
210+
211+
Result ret = 0;
212+
ret = svcSendSyncRequest(dlpClntHandle);
213+
214+
staticbufs[0] = saved_threadstorage[0];
215+
staticbufs[1] = saved_threadstorage[1];
216+
217+
if (R_FAILED(ret))return ret;
218+
219+
ret = cmdbuf[1];
220+
221+
if (R_SUCCEEDED(ret))
222+
{
223+
if (actual_size)*actual_size = cmdbuf[2];
224+
}
225+
226+
return ret;
227+
}
228+
229+
Result DLPCLNT_PrepareForSystemDownload(u8* macAddr, u32 uniqueId, u32 revision) {
230+
u32* cmdbuf = getThreadCommandBuffer();
231+
232+
u64 tid = dlpCreateChildTid(uniqueId, revision);
233+
234+
cmdbuf[0] = IPC_MakeHeader(0xB,4,0); // 0xB0100
235+
memcpy(cmdbuf + 1, macAddr, 6);
236+
cmdbuf[3] = tid & 0xFFFFFFFF;
237+
cmdbuf[4] = tid >> 32;
238+
239+
Result ret = 0;
240+
if (R_FAILED(ret = svcSendSyncRequest(dlpClntHandle)))return ret;
241+
242+
return cmdbuf[1];
243+
}
244+
245+
Result DLPCLNT_StartTitleDownload(u8* macAddr, u32 uniqueId, u32 revision) {
246+
u32* cmdbuf = getThreadCommandBuffer();
247+
248+
u64 tid = dlpCreateChildTid(uniqueId, revision);
249+
250+
cmdbuf[0] = IPC_MakeHeader(0xD,4,0); // 0xD0100
251+
memcpy(cmdbuf + 1, macAddr, 6);
252+
cmdbuf[3] = tid & 0xFFFFFFFF;
253+
cmdbuf[4] = tid >> 32;
254+
255+
Result ret = 0;
256+
if (R_FAILED(ret = svcSendSyncRequest(dlpClntHandle)))return ret;
257+
258+
return cmdbuf[1];
259+
}
260+
261+
Result DLPCLNT_GetMyStatus(u32* status) {
262+
u32* cmdbuf = getThreadCommandBuffer();
263+
264+
cmdbuf[0] = IPC_MakeHeader(0xE,0,0); // 0xE00000
265+
266+
Result ret = 0;
267+
if (R_FAILED(ret = svcSendSyncRequest(dlpClntHandle)))return ret;
268+
269+
memcpy(status, cmdbuf + 2, sizeof(u32) * 3);
270+
271+
return cmdbuf[1];
272+
}
273+
274+
Result DLPCLNT_GetWirelessRebootPassphrase(void* buf) {
275+
u32* cmdbuf = getThreadCommandBuffer();
276+
277+
cmdbuf[0] = IPC_MakeHeader(0x11,0,0); // 0x110000
278+
279+
Result ret = 0;
280+
if (R_FAILED(ret = svcSendSyncRequest(dlpClntHandle)))return ret;
281+
282+
memcpy(buf, cmdbuf + 2, 9);
283+
284+
return cmdbuf[1];
285+
}
286+
287+
Result DLPCLNT_StopSession(void) {
288+
u32* cmdbuf = getThreadCommandBuffer();
289+
290+
cmdbuf[0] = IPC_MakeHeader(0x12,0,0); // 0x120000
291+
292+
Result ret = 0;
293+
if (R_FAILED(ret = svcSendSyncRequest(dlpClntHandle)))return ret;
294+
295+
return cmdbuf[1];
296+
}

0 commit comments

Comments
 (0)