libctru  v2.4.1
uds.h
Go to the documentation of this file.
1 /**
2  * @file uds.h
3  * @brief UDS(NWMUDS) local-WLAN service. https://3dbrew.org/wiki/NWM_Services
4  */
5 #pragma once
6 
7 /// Maximum number of nodes(devices) that can be connected to the network.
8 #define UDS_MAXNODES 16
9 
10 /// Broadcast value for NetworkNodeID / alias for all NetworkNodeIDs.
11 #define UDS_BROADCAST_NETWORKNODEID 0xFFFF
12 
13 /// NetworkNodeID for the host(the first node).
14 #define UDS_HOST_NETWORKNODEID 0x1
15 
16 /// Default recv_buffer_size that can be used for udsBind() input / code which uses udsBind() internally.
17 #define UDS_DEFAULT_RECVBUFSIZE 0x2E30
18 
19 /// Max size of user data-frames.
20 #define UDS_DATAFRAME_MAXSIZE 0x5C6
21 
22 /// Check whether a fatal udsSendTo error occured(some error(s) from udsSendTo() can be ignored, but the frame won't be sent when that happens).
23 #define UDS_CHECK_SENDTO_FATALERROR(x) (R_FAILED(x) && x!=0xC86113F0)
24 
25 /// Node info struct.
26 typedef struct {
27  u64 uds_friendcodeseed;//UDS version of the FriendCodeSeed.
28 
29  union {
30  u8 usercfg[0x18];//This is the first 0x18-bytes from this config block: https://www.3dbrew.org/wiki/Config_Savegame#0x000A0000_Block
31 
32  struct {
33  u16 username[10];
34 
35  u16 unk_x1c;//Unknown, normally zero. Set to 0x0 with the output from udsScanBeacons().
36  u8 flag;//"u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?"
37  u8 pad_x1f;//Unknown, normally zero.
38  };
39  };
40 
41  //The rest of this is initialized by NWM-module.
42  u16 NetworkNodeID;
43  u16 pad_x22;//Unknown, normally zero?
44  u32 word_x24;//Normally zero?
45 } udsNodeInfo;
46 
47 /// Connection status struct.
48 typedef struct {
49  u32 status;
50  u32 unk_x4;
51  u16 cur_NetworkNodeID;//"u16 NetworkNodeID for this device."
52  u16 unk_xa;
53  u32 unk_xc[0x20>>2];
54 
55  u8 total_nodes;
56  u8 max_nodes;
57  u16 node_bitmask;//"This is a bitmask of NetworkNodeIDs: bit0 for NetworkNodeID 0x1(host), bit1 for NetworkNodeID 0x2(first original client), and so on."
59 
60 /// Network struct stored as big-endian.
61 typedef struct {
62  u8 host_macaddress[6];
63  u8 channel;//Wifi channel for this network. If you want to create a network on a specific channel instead of the system selecting it, you can set this to a non-zero channel value.
64  u8 pad_x7;
65 
66  u8 initialized_flag;//Must be non-zero otherwise NWM-module will use zeros internally instead of the actual field data, for most/all(?) of the fields in this struct.
67 
68  u8 unk_x9[3];
69 
70  u8 oui_value[3];//"This is the OUI value for use with the beacon tags. Normally this is 001F32."
71  u8 oui_type;//"OUI type (21/0x15)"
72 
73  u32 wlancommID;//Unique local-WLAN communications ID for each application.
74  u8 id8;//Additional ID that can be used by the application for different types of networks.
75  u8 unk_x15;
76 
77  u16 attributes;//See the UDSNETATTR enum values below.
78 
79  u32 networkID;
80 
81  u8 total_nodes;
82  u8 max_nodes;
83  u8 unk_x1e;
84  u8 unk_x1f;
85  u8 unk_x20[0x1f];
86 
87  u8 appdata_size;
88  u8 appdata[0xc8];
90 
91 typedef struct {
92  u32 BindNodeID;
93  Handle event;
94  bool spectator;
96 
97 /// General NWM input structure used for AP scanning.
98 typedef struct {
99  u16 unk_x0;
100  u16 unk_x2;
101  u16 unk_x4;
102  u16 unk_x6;
103 
104  u8 mac_address[6];
105 
106  u8 unk_xe[0x26];//Not initialized by dlp.
108 
109 /// General NWM output structure from AP scanning.
110 typedef struct {
111  u32 maxsize;//"Max output size, from the command request."
112  u32 size;//"Total amount of output data written relative to struct+0. 0xC when there's no entries."
113  u32 total_entries;//"Total entries, 0 for none. "
114 
115  //The entries start here.
117 
118 /// General NWM output structure from AP scanning, for each entry.
119 typedef struct {
120  u32 size;//"Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size."
121  u8 unk_x4;
122  u8 channel;//Wifi channel for the AP.
123  u8 unk_x6;
124  u8 unk_x7;
125  u8 mac_address[6];//"AP MAC address."
126  u8 unk_xe[6];
127  u32 unk_x14;
128  u32 val_x1c;//"Value 0x1C(size of this header and/or offset to the actual beacon data)."
129 
130  //The actual beacon data starts here.
132 
133 /// Output structure generated from host scanning output.
134 typedef struct {
135  nwmBeaconDataReplyEntry datareply_entry;
136  udsNetworkStruct network;
137  udsNodeInfo nodes[UDS_MAXNODES];
139 
140 enum {
141  UDSNETATTR_DisableConnectSpectators = BIT(0), //When set new Spectators are not allowed to connect.
142  UDSNETATTR_DisableConnectClients = BIT(1), //When set new Clients are not allowed to connect.
143  UDSNETATTR_x4 = BIT(2), //Unknown what this bit is for.
144  UDSNETATTR_Default = BIT(15), //Unknown what this bit is for.
145 };
146 
147 enum {
148  UDS_SENDFLAG_Default = BIT(0), //Unknown what this bit is for.
149  UDS_SENDFLAG_Broadcast = BIT(1) //When set, broadcast the data frame via the destination MAC address even when UDS_BROADCAST_NETWORKNODEID isn't used.
150 };
151 
152 typedef enum {
153  UDSCONTYPE_Client = 0x1,
154  UDSCONTYPE_Spectator = 0x2
155 } udsConnectionType;
156 
157 /**
158  * @brief Initializes UDS.
159  * @param sharedmem_size This must be 0x1000-byte aligned.
160  * @param username Optional custom UTF-8 username(converted to UTF-16 internally) that other nodes on the UDS network can use. If not set the username from system-config is used. Max len is 10 characters without NUL-terminator.
161  */
162 Result udsInit(size_t sharedmem_size, const char *username);
163 
164 /// Exits UDS.
165 void udsExit(void);
166 
167 /**
168  * @brief Generates a NodeInfo struct with data loaded from system-config.
169  * @param nodeinfo Output NodeInfo struct.
170  * @param username If set, this is the UTF-8 string to convert for use in the struct. Max len is 10 characters without NUL-terminator.
171  */
172 Result udsGenerateNodeInfo(udsNodeInfo *nodeinfo, const char *username);
173 
174 /**
175  * @brief Loads the UTF-16 username stored in the input NodeInfo struct, converted to UTF-8.
176  * @param nodeinfo Input NodeInfo struct.
177  * @param username This is the output UTF-8 string. Max len is 10 characters without NUL-terminator.
178  */
179 Result udsGetNodeInfoUsername(const udsNodeInfo *nodeinfo, char *username);
180 
181 /**
182  * @brief Checks whether a NodeInfo struct was initialized by NWM-module(not any output from udsGenerateNodeInfo()).
183  * @param nodeinfo Input NodeInfo struct.
184  */
186 
187 /**
188  * @brief Generates a default NetworkStruct for creating networks.
189  * @param network The output struct.
190  * @param wlancommID Unique local-WLAN communications ID for each application.
191  * @param id8 Additional ID that can be used by the application for different types of networks.
192  * @param max_nodes Maximum number of nodes(devices) that can be connected to the network, including the host.
193  */
194 void udsGenerateDefaultNetworkStruct(udsNetworkStruct *network, u32 wlancommID, u8 id8, u8 max_nodes);
195 
196 /**
197  * @brief Scans for networks via beacon-scanning.
198  * @param outbuf Buffer which will be used by the beacon-scanning command and for the data parsing afterwards. Normally there's no need to use the contents of this buffer once this function returns.
199  * @param maxsize Max size of the buffer.
200  * @Param networks Ptr where the allocated udsNetworkScanInfo array buffer is written. The allocsize is sizeof(udsNetworkScanInfo)*total_networks.
201  * @Param total_networks Total number of networks stored under the networks buffer.
202  * @param wlancommID Unique local-WLAN communications ID for each application.
203  * @param id8 Additional ID that can be used by the application for different types of networks.
204  * @param host_macaddress When set, this code will only return network info from the specified host MAC address.
205  * @connected When not connected to a network this *must* be false. When connected to a network this *must* be true.
206  */
207 Result udsScanBeacons(void *outbuf, size_t maxsize, udsNetworkScanInfo **networks, size_t *total_networks, u32 wlancommID, u8 id8, const u8 *host_macaddress, bool connected);
208 
209 /**
210  * @brief This can be used by the host to set the appdata contained in the broadcasted beacons.
211  * @param buf Appdata buffer.
212  * @param size Size of the input appdata.
213  */
214 Result udsSetApplicationData(const void *buf, size_t size);
215 
216 /**
217  * @brief This can be used while on a network(host/client) to get the appdata from the current beacon.
218  * @param buf Appdata buffer.
219  * @param size Max size of the output buffer.
220  * @param actual_size If set, the actual size of the appdata written into the buffer is stored here.
221  */
222 Result udsGetApplicationData(void *buf, size_t size, size_t *actual_size);
223 
224 /**
225  * @brief This can be used with a NetworkStruct, from udsScanBeacons() mainly, for getting the appdata.
226  * @param buf Appdata buffer.
227  * @param size Max size of the output buffer.
228  * @param actual_size If set, the actual size of the appdata written into the buffer is stored here.
229  */
230 Result udsGetNetworkStructApplicationData(const udsNetworkStruct *network, void *buf, size_t size, size_t *actual_size);
231 
232 /**
233  * @brief Create a bind.
234  * @param bindcontext The output bind context.
235  * @param NetworkNodeID This is the NetworkNodeID which this bind can receive data from.
236  * @param spectator False for a regular bind, true for a spectator.
237  * @param data_channel This is an arbitrary value to use for data-frame filtering. This bind will only receive data frames which contain a matching data_channel value, which was specified by udsSendTo(). The data_channel must be non-zero.
238  * @param recv_buffer_size Size of the buffer under sharedmem used for temporarily storing received data-frames which are then loaded by udsPullPacket(). The system requires this to be >=0x5F4. UDS_DEFAULT_RECVBUFSIZE can be used for this.
239  */
240 Result udsBind(udsBindContext *bindcontext, u16 NetworkNodeID, bool spectator, u8 data_channel, u32 recv_buffer_size);
241 
242 /**
243  * @brief Remove a bind.
244  * @param bindcontext The bind context.
245  */
247 
248 /**
249  * @brief Waits for the bind event to occur, or checks if the event was signaled. This event is signaled every time new data is available via udsPullPacket().
250  * @return Always true. However if wait=false, this will return false if the event wasn't signaled.
251  * @param bindcontext The bind context.
252  * @param nextEvent Whether to discard the current event and wait for the next event.
253  * @param wait When true this will not return until the event is signaled. When false this checks if the event was signaled without waiting for it.
254  */
255 bool udsWaitDataAvailable(const udsBindContext *bindcontext, bool nextEvent, bool wait);
256 
257 /**
258  * @brief Receives data over the network. This data is loaded from the recv_buffer setup by udsBind(). When a node disconnects, this will still return data from that node until there's no more frames from that node in the recv_buffer.
259  * @param bindcontext Bind context.
260  * @param buf Output receive buffer.
261  * @param size Size of the buffer.
262  * @param actual_size If set, the actual size written into the output buffer is stored here. This is zero when no data was received.
263  * @param src_NetworkNodeID If set, the source NetworkNodeID is written here. This is zero when no data was received.
264  */
265 Result udsPullPacket(const udsBindContext *bindcontext, void *buf, size_t size, size_t *actual_size, u16 *src_NetworkNodeID);
266 
267 /**
268  * @brief Sends data over the network.
269  * @param dst_NetworkNodeID Destination NetworkNodeID.
270  * @param data_channel See udsBind().
271  * @param flags Send flags, see the UDS_SENDFLAG enum values.
272  * @param buf Input send buffer.
273  * @param size Size of the buffer.
274  */
275 Result udsSendTo(u16 dst_NetworkNodeID, u8 data_channel, u8 flags, const void *buf, size_t size);
276 
277 /**
278  * @brief Gets the wifi channel currently being used.
279  * @param channel Output channel.
280  */
282 
283 /**
284  * @brief Starts hosting a new network.
285  * @param network The NetworkStruct, you can use udsGenerateDefaultNetworkStruct() for generating this.
286  * @param passphrase Raw input passphrase buffer.
287  * @param passphrase_size Size of the passphrase buffer.
288  * @param context Optional output bind context which will be created for this host, with NetworkNodeID=UDS_BROADCAST_NETWORKNODEID.
289  * @param data_channel This is the data_channel value which will be passed to udsBind() internally.
290  * @param recv_buffer_size This is the recv_buffer_size value which will be passed to udsBind() internally.
291  */
292 Result udsCreateNetwork(const udsNetworkStruct *network, const void *passphrase, size_t passphrase_size, udsBindContext *context, u8 data_channel, u32 recv_buffer_size);
293 
294 /**
295  * @brief Connect to a network.
296  * @param network The NetworkStruct, you can use udsScanBeacons() for this.
297  * @param passphrase Raw input passphrase buffer.
298  * @param passphrase_size Size of the passphrase buffer.
299  * @param context Optional output bind context which will be created for this host.
300  * @param recv_NetworkNodeID This is the NetworkNodeID passed to udsBind() internally.
301  * @param connection_type Type of connection, see the udsConnectionType enum values.
302  * @param data_channel This is the data_channel value which will be passed to udsBind() internally.
303  * @param recv_buffer_size This is the recv_buffer_size value which will be passed to udsBind() internally.
304  */
305 Result udsConnectNetwork(const udsNetworkStruct *network, const void *passphrase, size_t passphrase_size, udsBindContext *context, u16 recv_NetworkNodeID, udsConnectionType connection_type, u8 data_channel, u32 recv_buffer_size);
306 
307 /**
308  * @brief Stop hosting the network.
309  */
311 
312 /**
313  * @brief Disconnect this client device from the network.
314  */
316 
317 /**
318  * @brief This can be used by the host to force-disconnect client(s).
319  * @param NetworkNodeID Target NetworkNodeID. UDS_BROADCAST_NETWORKNODEID can be used to disconnect all clients.
320  */
321 Result udsEjectClient(u16 NetworkNodeID);
322 
323 /**
324  * @brief This can be used by the host to force-disconnect the spectators. Afterwards new spectators will not be allowed to connect until udsAllowSpectators() is used.
325  */
327 
328 /**
329  * @brief This can be used by the host to update the network attributes. If bitmask 0x4 is clear in the input bitmask, this clears that bit in the value before actually writing the value into state. Normally you should use the below wrapper functions.
330  * @param bitmask Bitmask to clear/set in the attributes. See the UDSNETATTR enum values.
331  * @param flag When false, bit-clear, otherwise bit-set.
332  */
334 
335 /**
336  * @brief This uses udsUpdateNetworkAttribute() for (un)blocking new connections to this host.
337  * @param block When true, block the specified connection types(bitmask set). Otherwise allow them(bitmask clear).
338  * @param clients When true, (un)block regular clients.
339  * @param flag When true, update UDSNETATTR_x4. Normally this should be false.
340  */
341 Result udsSetNewConnectionsBlocked(bool block, bool clients, bool flag);
342 
343 /**
344  * @brief This uses udsUpdateNetworkAttribute() for unblocking new spectator connections to this host. See udsEjectSpectator() for blocking new spectators.
345  */
347 
348 /**
349  * @brief This loads the current ConnectionStatus struct.
350  * @param output Output ConnectionStatus struct.
351  */
353 
354 /**
355  * @brief Waits for the ConnectionStatus event to occur, or checks if the event was signaled. This event is signaled when the data from udsGetConnectionStatus() was updated internally.
356  * @return Always true. However if wait=false, this will return false if the event wasn't signaled.
357  * @param nextEvent Whether to discard the current event and wait for the next event.
358  * @param wait When true this will not return until the event is signaled. When false this checks if the event was signaled without waiting for it.
359  */
360 bool udsWaitConnectionStatusEvent(bool nextEvent, bool wait);
361 
362 /**
363  * @brief This loads a NodeInfo struct for the specified NetworkNodeID. The broadcast alias can't be used with this.
364  * @param NetworkNodeID Target NetworkNodeID.
365  * @param output Output NodeInfo struct.
366  */
367 Result udsGetNodeInformation(u16 NetworkNodeID, udsNodeInfo *output);
368 
General NWM output structure from AP scanning, for each entry.
Definition: uds.h:119
General NWM output structure from AP scanning.
Definition: uds.h:110
General NWM input structure used for AP scanning.
Definition: uds.h:98
Definition: uds.h:91
Connection status struct.
Definition: uds.h:48
Output structure generated from host scanning output.
Definition: uds.h:134
Network struct stored as big-endian.
Definition: uds.h:61
Node info struct.
Definition: uds.h:26
#define BIT(n)
Creates a bitmask from a bit number.
Definition: types.h:47
uint64_t u64
64-bit unsigned integer
Definition: types.h:24
uint8_t u8
would be nice if newlib had this already
Definition: types.h:21
u32 Handle
Resource handle.
Definition: types.h:41
s32 Result
Function result.
Definition: types.h:42
uint16_t u16
16-bit unsigned integer
Definition: types.h:22
uint32_t u32
32-bit unsigned integer
Definition: types.h:23
Result udsUnbind(udsBindContext *bindcontext)
Remove a bind.
void udsExit(void)
Exits UDS.
Result udsPullPacket(const udsBindContext *bindcontext, void *buf, size_t size, size_t *actual_size, u16 *src_NetworkNodeID)
Receives data over the network.
Result udsCreateNetwork(const udsNetworkStruct *network, const void *passphrase, size_t passphrase_size, udsBindContext *context, u8 data_channel, u32 recv_buffer_size)
Starts hosting a new network.
Result udsSendTo(u16 dst_NetworkNodeID, u8 data_channel, u8 flags, const void *buf, size_t size)
Sends data over the network.
Result udsScanBeacons(void *outbuf, size_t maxsize, udsNetworkScanInfo **networks, size_t *total_networks, u32 wlancommID, u8 id8, const u8 *host_macaddress, bool connected)
Scans for networks via beacon-scanning.
Result udsBind(udsBindContext *bindcontext, u16 NetworkNodeID, bool spectator, u8 data_channel, u32 recv_buffer_size)
Create a bind.
Result udsDisconnectNetwork(void)
Disconnect this client device from the network.
bool udsWaitConnectionStatusEvent(bool nextEvent, bool wait)
Waits for the ConnectionStatus event to occur, or checks if the event was signaled.
Result udsDestroyNetwork(void)
Stop hosting the network.
Result udsSetNewConnectionsBlocked(bool block, bool clients, bool flag)
This uses udsUpdateNetworkAttribute() for (un)blocking new connections to this host.
Result udsEjectSpectator(void)
This can be used by the host to force-disconnect the spectators.
Result udsConnectNetwork(const udsNetworkStruct *network, const void *passphrase, size_t passphrase_size, udsBindContext *context, u16 recv_NetworkNodeID, udsConnectionType connection_type, u8 data_channel, u32 recv_buffer_size)
Connect to a network.
Result udsGetChannel(u8 *channel)
Gets the wifi channel currently being used.
Result udsSetApplicationData(const void *buf, size_t size)
This can be used by the host to set the appdata contained in the broadcasted beacons.
bool udsWaitDataAvailable(const udsBindContext *bindcontext, bool nextEvent, bool wait)
Waits for the bind event to occur, or checks if the event was signaled.
Result udsAllowSpectators(void)
This uses udsUpdateNetworkAttribute() for unblocking new spectator connections to this host.
Result udsInit(size_t sharedmem_size, const char *username)
Initializes UDS.
Result udsGetConnectionStatus(udsConnectionStatus *output)
This loads the current ConnectionStatus struct.
bool udsCheckNodeInfoInitialized(const udsNodeInfo *nodeinfo)
Checks whether a NodeInfo struct was initialized by NWM-module(not any output from udsGenerateNodeInf...
Result udsGetNodeInformation(u16 NetworkNodeID, udsNodeInfo *output)
This loads a NodeInfo struct for the specified NetworkNodeID.
Result udsGetApplicationData(void *buf, size_t size, size_t *actual_size)
This can be used while on a network(host/client) to get the appdata from the current beacon.
Result udsGetNodeInfoUsername(const udsNodeInfo *nodeinfo, char *username)
Loads the UTF-16 username stored in the input NodeInfo struct, converted to UTF-8.
Result udsGetNetworkStructApplicationData(const udsNetworkStruct *network, void *buf, size_t size, size_t *actual_size)
This can be used with a NetworkStruct, from udsScanBeacons() mainly, for getting the appdata.
Result udsEjectClient(u16 NetworkNodeID)
This can be used by the host to force-disconnect client(s).
Result udsGenerateNodeInfo(udsNodeInfo *nodeinfo, const char *username)
Generates a NodeInfo struct with data loaded from system-config.
Result udsUpdateNetworkAttribute(u16 bitmask, bool flag)
This can be used by the host to update the network attributes.
void udsGenerateDefaultNetworkStruct(udsNetworkStruct *network, u32 wlancommID, u8 id8, u8 max_nodes)
Generates a default NetworkStruct for creating networks.
#define UDS_MAXNODES
Maximum number of nodes(devices) that can be connected to the network.
Definition: uds.h:8