//Pascal &or the FreePascal use of nintendo 2ds, 3ds regime // // Copyright (c) 2013, 2015, 2017 Kenneth Dwayne Lee Bsc. // all rights reserved. // {$ifdef 3dsintf} {* * @file uds.h * @brief UDS(NWMUDS) local-WLAN service. https://3dbrew.org/wiki/NWM_Services } {/ Maximum number of nodes(devices) that can be connected to the network. } const UDS_MAXNODES = 16; {/ Broadcast value for NetworkNodeID / alias for all NetworkNodeIDs. } UDS_BROADCAST_NETWORKNODEID = $FFFF; {/ NetworkNodeID for the host(the first node). } UDS_HOST_NETWORKNODEID = $1; {/ Default recv_buffer_size that can be used for udsBind() input / code which uses udsBind() internally. } UDS_DEFAULT_RECVBUFSIZE = $2E30; {/ Max size of user data-frames. } UDS_DATAFRAME_MAXSIZE = $5C6; {/ 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). } function UDS_CHECK_SENDTO_FATALERROR(x : longint) : longint; {/ Node info struct. } {UDS version of the FriendCodeSeed. } {This is the first 0x18-bytes from this config block: https://www.3dbrew.org/wiki/Config_Savegame#0x000A0000_Block } {Unknown, normally zero. Set to 0x0 with the output from udsScanBeacons(). } /// Node info struct untested in pascal. udsNodeInfo = record uds_friendcodeseed :u64;//UDS version of the FriendCodeSeed. usercfg array[0x18] of u8;//This is the first 0x18-bytes from this config block: https://www.3dbrew.org/wiki/Config_Savegame#0x000A0000_Block username array[0..9] of u16; unk_x1c:u16;//Unknown, normally zero. Set to 0x0 with the output from udsScanBeacons(). flag:u8;//"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?" pad_x1f:u8;//Unknown, normally zero. //The rest of this is initialized by NWM-module. NetworkNodeID:u16; pad_x22:u16;//Unknown, normally zero? word_x24:u32;//Normally zero? end; PudsNodeInfo = ^udsNodeInfo; {The rest of this is initialized by NWM-module. } {Unknown, normally zero? } {Normally zero? } in member_list *) {/ Connection status struct. } udsConnectionStatus = record status : u32; unk_x4 : u32; cur_NetworkNodeID : u16; unk_xa : u16; unk_xc : array [0..7] of u32; total_nodes : u8; max_nodes : u8; node_bitmask : u16; //"This is a bitmask of NetworkNodeIDs: bit0 for NetworkNodeID 0x1(host), bit1 for NetworkNodeID 0x2(first original client), and so on."in member_list *) end; PudsConnectionStatus = ^udsConnectionStatus; type udsNetworkStruct = record host_macaddress: array[0..5] of u8; 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. u8 pad_x7; 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. unk_x9 :array[0..2] of u8; oui_value:array[0..2] of u8;;//"This is the OUI value for use with the beacon tags. Normally this is 001F32." oui_type:u8;//"OUI type (21/0x15)" wlancommID:u32; //Unique local-WLAN communications ID for each application. id8:u8; //Additional ID that can be used by the application for different types of networks. unk_x15:u8; attributes: u16; //See the UDSNETATTR enum values below. networkID:u32; u8 total_nodes:u8; u8 max_nodes:u8; u8 unk_x1e:u8; u8 unk_x1f:u8; u8 unk_x20:array[0..32] of u8; appdata_size:u8; appdata:array[0..199] of u8; end; PudsNetworkStruct = ^udsNetworkStruct; udsBindContext = record BindNodeID : u32; event : Handle; spectator : boolean; end; PudsBindContext = ^udsBindContext; {/ General NWM input structure used for AP scanning. } {Not initialized by dlp. } nwmScanInputStruct = record unk_x0 : u16; unk_x2 : u16; unk_x4 : u16; unk_x6 : u16; mac_address : array[0..5] of u8; unk_xe : array[0..37] of u8; end; {/ General NWM output structure from AP scanning. } {"Max output size, from the command request." } {"Total amount of output data written relative to struct+0. 0xC when there's no entries." } {"Total entries, 0 for none. " } {The entries start here. } nwmBeaconDataReplyHeader = record maxsize : u32; size : u32; total_entries : u32; end; {/ General NWM output structure from AP scanning, for each entry. } {"Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size." } {Wifi channel for the AP. } {"AP MAC address." } {"Value 0x1C(size of this header and/or offset to the actual beacon data)." } {The actual beacon data starts here. } nwmBeaconDataReplyEntry = record size : u32; unk_x4 : u8; channel : u8; unk_x6 : u8; unk_x7 : u8; mac_address : array[0..5] of u8; unk_xe : array[0..5] of u8; unk_x14 : u32; val_x1c : u32; end; {/ Output structure generated from host scanning output. } udsNetworkScanInfo = record datareply_entry : nwmBeaconDataReplyEntry; network : udsNetworkStruct; nodes : array[0..(UDS_MAXNODES)-1] of udsNodeInfo; end; PudsNetworkScanInfo = ^udsNetworkScanInfo; udsConnectionType = (UDSCONTYPE_Client := $1, UDSCONTYPE_Spectator := $2); {* * @brief Initializes UDS. * @param sharedmem_size This must be 0x1000-byte aligned. * @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. } function udsInit(sharedmem_size:size_t; username:pcchar):s32;cdecl;external; {/ Exits UDS. } procedure udsExit;cdecl;external; {* * @brief Generates a NodeInfo struct with data loaded from system-config. * @param nodeinfo Output NodeInfo struct. * @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. } function udsGenerateNodeInfo(nodeinfo:PudsNodeInfo; username:pcchar):s32;cdecl;external; {* * @brief Loads the UTF-16 username stored in the input NodeInfo struct, converted to UTF-8. * @param nodeinfo Input NodeInfo struct. * @param username This is the output UTF-8 string. Max len is 10 characters without NUL-terminator. } function udsGetNodeInfoUsername(nodeinfo:PudsNodeInfo; username:pcchar):s32;cdecl;external; {* * @brief Checks whether a NodeInfo struct was initialized by NWM-module(not any output from udsGenerateNodeInfo()). * @param nodeinfo Input NodeInfo struct. } function udsCheckNodeInfoInitialized(nodeinfo:PudsNodeInfo):boolean;cdecl;external; {* * @brief Generates a default NetworkStruct for creating networks. * @param network The output struct. * @param wlancommID Unique local-WLAN communications ID for each application. * @param id8 Additional ID that can be used by the application for different types of networks. * @param max_nodes Maximum number of nodes(devices) that can be connected to the network, including the host. } procedure udsGenerateDefaultNetworkStruct(network:PudsNetworkStruct; wlancommID:u32; id8:u8; max_nodes:u8);cdecl;external; {* * @brief Scans for networks via beacon-scanning. * @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. * @param maxsize Max size of the buffer. * @Param networks Ptr where the allocated udsNetworkScanInfo array buffer is written. The allocsize is sizeof(udsNetworkScanInfo)*total_networks. * @Param total_networks Total number of networks stored under the networks buffer. * @param wlancommID Unique local-WLAN communications ID for each application. * @param id8 Additional ID that can be used by the application for different types of networks. * @param host_macaddress When set, this code will only return network info from the specified host MAC address. * @connected When not connected to a network this *must* be false. When connected to a network this *must* be true. } function udsScanBeacons(outbuf:pointer; maxsize:size_t; networks:PPudsNetworkScanInfo; total_networks:Psize_t; wlancommID:u32; id8:u8; host_macaddress:Pu8; connected:boolean):s32;cdecl;external; {* * @brief This can be used by the host to set the appdata contained in the broadcasted beacons. * @param buf Appdata buffer. * @param size Size of the input appdata. } function udsSetApplicationData(buf:pointer; size:size_t):s32;cdecl;external; {* * @brief This can be used while on a network(host/client) to get the appdata from the current beacon. * @param buf Appdata buffer. * @param size Max size of the output buffer. * @param actual_size If set, the actual size of the appdata written into the buffer is stored here. } function udsGetApplicationData(buf:pointer; size:size_t; actual_size:Psize_t):s32;cdecl;external; {* * @brief This can be used with a NetworkStruct, from udsScanBeacons() mainly, for getting the appdata. * @param buf Appdata buffer. * @param size Max size of the output buffer. * @param actual_size If set, the actual size of the appdata written into the buffer is stored here. } function udsGetNetworkStructApplicationData(network:PudsNetworkStruct; buf:pointer; size:size_t; actual_size:Psize_t):s32;cdecl;external; {* * @brief Create a bind. * @param bindcontext The output bind context. * @param NetworkNodeID This is the NetworkNodeID which this bind can receive data from. * @param spectator False for a regular bind, true for a spectator. * @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. * @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. } function udsBind(bindcontext:PudsBindContext; NetworkNodeID:u16; spectator:boolean; data_channel:u8; recv_buffer_size:u32):s32;cdecl;external; {* * @brief Remove a bind. * @param bindcontext The bind context. } function udsUnbind(bindcontext:PudsBindContext):s32;cdecl;external; {* * @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(). * @return Always true. However if wait=false, this will return false if the event wasn't signaled. * @param bindcontext The bind context. * @param nextEvent Whether to discard the current event and wait for the next event. * @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. } function udsWaitDataAvailable(bindcontext:PudsBindContext; nextEvent:boolean; wait:boolean):boolean;cdecl;external; {* * @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. * @param bindcontext Bind context. * @param buf Output receive buffer. * @param size Size of the buffer. * @param actual_size If set, the actual size written into the output buffer is stored here. This is zero when no data was received. * @param src_NetworkNodeID If set, the source NetworkNodeID is written here. This is zero when no data was received. } function udsPullPacket(bindcontext:PudsBindContext; buf:pointer; size:size_t; actual_size:Psize_t; src_NetworkNodeID:Pu16):s32;cdecl;external; {* * @brief Sends data over the network. * @param dst_NetworkNodeID Destination NetworkNodeID. * @param data_channel See udsBind(). * @param flags Send flags, see the UDS_SENDFLAG enum values. * @param buf Input send buffer. * @param size Size of the buffer. } function udsSendTo(dst_NetworkNodeID:u16; data_channel:u8; flags:u8; buf:pointer; size:size_t):s32;cdecl;external; {* * @brief Gets the wifi channel currently being used. * @param channel Output channel. } function udsGetChannel(channel:Pu8):s32;cdecl;external; {* * @brief Starts hosting a new network. * @param network The NetworkStruct, you can use udsGenerateDefaultNetworkStruct() for generating this. * @param passphrase Raw input passphrase buffer. * @param passphrase_size Size of the passphrase buffer. * @param context Optional output bind context which will be created for this host, with NetworkNodeID=UDS_BROADCAST_NETWORKNODEID. * @param data_channel This is the data_channel value which will be passed to udsBind() internally. * @param recv_buffer_size This is the recv_buffer_size value which will be passed to udsBind() internally. } function udsCreateNetwork(network:PudsNetworkStruct; passphrase:pointer; passphrase_size:size_t; context:PudsBindContext; data_channel:u8; recv_buffer_size:u32):s32;cdecl;external; {* * @brief Connect to a network. * @param network The NetworkStruct, you can use udsScanBeacons() for this. * @param passphrase Raw input passphrase buffer. * @param passphrase_size Size of the passphrase buffer. * @param context Optional output bind context which will be created for this host. * @param recv_NetworkNodeID This is the NetworkNodeID passed to udsBind() internally. * @param connection_type Type of connection, see the udsConnectionType enum values. * @param data_channel This is the data_channel value which will be passed to udsBind() internally. * @param recv_buffer_size This is the recv_buffer_size value which will be passed to udsBind() internally. } function udsConnectNetwork(network:PudsNetworkStruct; passphrase:pointer; passphrase_size:size_t; context:PudsBindContext; recv_NetworkNodeID:u16; connection_type:udsConnectionType; data_channel:u8; recv_buffer_size:u32):s32;cdecl;external; {* * @brief Stop hosting the network. } function udsDestroyNetwork:s32;cdecl;external; {* * @brief Disconnect this client device from the network. } function udsDisconnectNetwork:s32;cdecl;external; {* * @brief This can be used by the host to force-disconnect client(s). * @param NetworkNodeID Target NetworkNodeID. UDS_BROADCAST_NETWORKNODEID can be used to disconnect all clients. } function udsEjectClient(NetworkNodeID:u16):s32;cdecl;external; {* * @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. } function udsEjectSpectator:s32;cdecl;external; {* * @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. * @param bitmask Bitmask to clear/set in the attributes. See the UDSNETATTR enum values. * @param flag When false, bit-clear, otherwise bit-set. } function udsUpdateNetworkAttribute(bitmask:u16; flag:boolean):s32;cdecl;external; {* * @brief This uses udsUpdateNetworkAttribute() for (un)blocking new connections to this host. * @param block When true, block the specified connection types(bitmask set). Otherwise allow them(bitmask clear). * @param clients When true, (un)block regular clients. * @param flag When true, update UDSNETATTR_x4. Normally this should be false. } function udsSetNewConnectionsBlocked(block:boolean; clients:boolean; flag:boolean):s32;cdecl;external; {* * @brief This uses udsUpdateNetworkAttribute() for unblocking new spectator connections to this host. See udsEjectSpectator() for blocking new spectators. } function udsAllowSpectators:s32;cdecl;external; {* * @brief This loads the current ConnectionStatus struct. * @param output Output ConnectionStatus struct. } function udsGetConnectionStatus(output:PudsConnectionStatus):s32;cdecl;external; {* * @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. * @return Always true. However if wait=false, this will return false if the event wasn't signaled. * @param nextEvent Whether to discard the current event and wait for the next event. * @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. } function udsWaitConnectionStatusEvent(nextEvent:boolean; wait:booleane):boolean;cdecl;external; {* * @brief This loads a NodeInfo struct for the specified NetworkNodeID. The broadcast alias can't be used with this. * @param NetworkNodeID Target NetworkNodeID. * @param output Output NodeInfo struct. } function udsGetNodeInformation(NetworkNodeID:u16; output:PudsNodeInfo):s32;cdecl;external; {$endif 3dsintf} {$ifdef 3dsimpl} function UDS_CHECK_SENDTO_FATALERROR(x : longint) : longint; begin UDS_CHECK_SENDTO_FATALERROR:=((R_FAILED(x)) and (@(x)))<>$C86113F0; end; {$endif 3dsimpl}