Added varioues UDS structs and enums+defines. Implemented udsGenerateDefaultNetworkStruct(). Implemented code for creating+destroying networks. Implemented code for binds. Implemented udsSendTo().
This commit is contained in:
parent
ed53bcf4a8
commit
9aa9d32e11
@ -11,6 +11,64 @@ typedef struct {
|
||||
u32 words_x20[2];//Not initialized by DLP-sysmodule.
|
||||
} udsNodeInfo;
|
||||
|
||||
/// Network struct stored as big-endian.
|
||||
typedef struct {
|
||||
u8 host_macaddress[6];
|
||||
u8 unk_x6[2];
|
||||
|
||||
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.
|
||||
|
||||
u8 unk_x9[3];
|
||||
|
||||
u8 oui_value[3];//"This is the OUI value for use with the beacon tags. Normally this is 001F32. "
|
||||
u8 oui_type;//"OUI type (21/0x15)"
|
||||
|
||||
u32 wlancommID;//Unique local-WLAN communications ID for each application.
|
||||
u8 id8;//Additional ID that can be used by the application for different types of networks.
|
||||
u8 unk_x15;
|
||||
|
||||
u16 attributes;//See the UDSNETATTR enum values below.
|
||||
u8 unk_x18[5];
|
||||
|
||||
u8 max_nodes;
|
||||
u8 unk_x1e;
|
||||
u8 unk_x1f;
|
||||
u8 unk_x20[0x1f];
|
||||
|
||||
u8 appdata_size;
|
||||
u8 appdata[0xc8];
|
||||
} udsNetworkStruct;
|
||||
|
||||
typedef struct {
|
||||
u32 BindNodeID;
|
||||
Handle event;
|
||||
} udsBindContext;
|
||||
|
||||
enum {
|
||||
UDSNETATTR_DisableConnectClients = BIT(1), //When set new Clients are not allowed to connect.
|
||||
UDSNETATTR_DisableConnectSpectators = BIT(2), //When set new Spectators are (probably) not allowed to connect.
|
||||
UDSNETATTR_Default = BIT(15), //Unknown what this bit is for.
|
||||
};
|
||||
|
||||
enum {
|
||||
UDS_SENDFLAG_Default = BIT(0), //Unknown what this bit is for.
|
||||
UDS_SENDFLAG_Broadcast = BIT(1) //When set, broadcast the data frame even when UDS_BROADCAST_NETWORKNODEID isn't used. Needs verified.
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
UDSCONTYPE_Client = 0x1,
|
||||
UDSCONTYPE_Spectator = 0x2
|
||||
} udsConnectionType;
|
||||
|
||||
/// Maximum number of nodes(devices) that can be connected to the network.
|
||||
#define UDS_MAXNODES 16
|
||||
|
||||
/// Broadcast value for NetworkNodeID / alias for all NetworkNodeIDs.
|
||||
#define UDS_BROADCAST_NETWORKNODEID 0xFFFF
|
||||
|
||||
/// Default value that can be used for udsSendTo() input8.
|
||||
#define UDS_SEND_INPUT8_DEFAULT 0x2
|
||||
|
||||
/**
|
||||
* @brief Initializes UDS.
|
||||
* @param sharedmem_size This must be 0x1000-byte aligned.
|
||||
@ -33,3 +91,49 @@ Result udsGenerateNodeInfo(udsNodeInfo *nodeinfo, const uint8_t *username);
|
||||
*/
|
||||
Result udsGetNodeInfoUsername(udsNodeInfo *nodeinfo, uint8_t *username);
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
void udsGenerateDefaultNetworkStruct(udsNetworkStruct *network, u32 wlancommID, u8 id8, u8 max_nodes);
|
||||
|
||||
/**
|
||||
* @brief Create a bind.
|
||||
* @param bindcontext The output bind context.
|
||||
* @param NetworkNodeID This is the NetworkNodeID which this bind can receive data from.
|
||||
*/
|
||||
Result udsBind(udsBindContext *bindcontext, u16 NetworkNodeID);
|
||||
|
||||
/**
|
||||
* @brief Remove a bind.
|
||||
* @param bindcontext The bind context.
|
||||
*/
|
||||
Result udsUnbind(udsBindContext *bindcontext);
|
||||
|
||||
/**
|
||||
* @brief Sends data over the network.
|
||||
* @param dst_NetworkNodeID Destination NetworkNodeID.
|
||||
* @param input8 UDS_SEND_INPUT8_DEFAULT can be used for this. It's unknown what this field is actually for.
|
||||
* @param flags Send flags, see the UDS_SENDFLAG enum values.
|
||||
* @param buf Input send buffer.
|
||||
* @param size Size of the buffer.
|
||||
*/
|
||||
Result udsSendTo(u16 dst_NetworkNodeID, u8 input8, u8 flags, void* buf, size_t size);
|
||||
|
||||
/**
|
||||
* @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 bindcontext Output bind context which will be created for this host, with NetworkNodeID=UDS_BROADCAST_NETWORKNODEID.
|
||||
*/
|
||||
Result udsCreateNetwork(udsNetworkStruct *network, void* passphrase, size_t passphrase_size, udsBindContext *bindcontext);
|
||||
|
||||
/**
|
||||
* @brief Stop hosting the network.
|
||||
*/
|
||||
Result udsDestroyNetwork(void);
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <3ds/types.h>
|
||||
#include <3ds/result.h>
|
||||
#include <3ds/svc.h>
|
||||
@ -22,10 +23,18 @@ static Handle __uds_sharedmem_handle;
|
||||
|
||||
static Handle __uds_connectionstatus_event;
|
||||
|
||||
static u32 bind_allocbitmask;
|
||||
|
||||
static Result uds_Initialize(u32 sharedmem_size, const uint8_t *username);
|
||||
static Result udsipc_InitializeWithVersion(udsNodeInfo *nodeinfo, Handle sharedmem_handle, u32 sharedmem_size, Handle *eventhandle);
|
||||
static Result udsipc_Shutdown(void);
|
||||
|
||||
static Result udsipc_BeginHostingNetwork(udsNetworkStruct *network, void* passphrase, size_t passphrase_size);
|
||||
static Result udsipc_SetProbeResponseParam(u32 oui, s8 data);
|
||||
|
||||
static Result udsipc_Bind(udsBindContext *bindcontext, u32 input0, u8 input1, u16 NetworkNodeID);
|
||||
static Result udsipc_Unbind(udsBindContext *bindcontext);
|
||||
|
||||
Result udsInit(u32 sharedmem_size, const uint8_t *username)
|
||||
{
|
||||
Result ret=0;
|
||||
@ -69,6 +78,8 @@ Result udsInit(u32 sharedmem_size, const uint8_t *username)
|
||||
AtomicDecrement(&__uds_refcount);
|
||||
}
|
||||
|
||||
bind_allocbitmask = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -151,6 +162,28 @@ Result udsGetNodeInfoUsername(udsNodeInfo *nodeinfo, uint8_t *username)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void udsGenerateDefaultNetworkStruct(udsNetworkStruct *network, u32 wlancommID, u8 id8, u8 max_nodes)
|
||||
{
|
||||
u8 oui_value[3] = {0x00, 0x1f, 0x32};
|
||||
|
||||
memset(network, 0, sizeof(udsNetworkStruct));
|
||||
|
||||
network->initialized_flag = 1;
|
||||
|
||||
memcpy(network->oui_value, oui_value, 3);
|
||||
network->oui_type = 21;
|
||||
|
||||
network->wlancommID = htonl(wlancommID);
|
||||
network->id8 = id8;
|
||||
|
||||
network->attributes = UDSNETATTR_Default;
|
||||
|
||||
if(max_nodes > UDS_MAXNODES)max_nodes = UDS_MAXNODES;
|
||||
network->max_nodes = max_nodes;
|
||||
|
||||
network->unk_x1f = 1;
|
||||
}
|
||||
|
||||
static Result uds_Initialize(u32 sharedmem_size, const uint8_t *username)
|
||||
{
|
||||
Result ret=0;
|
||||
@ -195,6 +228,23 @@ static Result uds_Initialize(u32 sharedmem_size, const uint8_t *username)
|
||||
return ret;
|
||||
}
|
||||
|
||||
Result udsCreateNetwork(udsNetworkStruct *network, void* passphrase, size_t passphrase_size, udsBindContext *context)
|
||||
{
|
||||
Result ret=0;
|
||||
|
||||
ret = udsipc_SetProbeResponseParam(0x00210080, 0);
|
||||
if(R_FAILED(ret))return ret;
|
||||
|
||||
ret = udsipc_BeginHostingNetwork(network, passphrase, passphrase_size);
|
||||
if(R_FAILED(ret))return ret;
|
||||
|
||||
ret = udsBind(context, UDS_BROADCAST_NETWORKNODEID);
|
||||
|
||||
if(R_FAILED(ret))udsDestroyNetwork();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Result udsipc_InitializeWithVersion(udsNodeInfo *nodeinfo, Handle sharedmem_handle, u32 sharedmem_size, Handle *eventhandle)
|
||||
{
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
@ -230,3 +280,140 @@ static Result udsipc_Shutdown(void)
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result udsDestroyNetwork(void)
|
||||
{
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0]=IPC_MakeHeader(0x8,0,0); // 0x80000
|
||||
|
||||
Result ret=0;
|
||||
if(R_FAILED(ret=svcSendSyncRequest(__uds_servhandle)))return ret;
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result udsBind(udsBindContext *bindcontext, u16 NetworkNodeID)
|
||||
{
|
||||
u32 pos;
|
||||
|
||||
memset(bindcontext, 0, sizeof(udsBindContext));
|
||||
|
||||
for(pos=0; pos<UDS_MAXNODES; pos++)
|
||||
{
|
||||
if((bind_allocbitmask & BIT(pos)) == 0)break;
|
||||
}
|
||||
if(pos==UDS_MAXNODES)return -1;
|
||||
|
||||
bind_allocbitmask |= BIT(pos);
|
||||
|
||||
bindcontext->BindNodeID = (pos+1)<<1;
|
||||
|
||||
return udsipc_Bind(bindcontext, 0x2e30, 0xf3, NetworkNodeID);
|
||||
}
|
||||
|
||||
Result udsUnbind(udsBindContext *bindcontext)
|
||||
{
|
||||
Result ret=0;
|
||||
|
||||
if(bindcontext->event)
|
||||
{
|
||||
svcCloseHandle(bindcontext->event);
|
||||
}
|
||||
|
||||
ret = udsipc_Unbind(bindcontext);
|
||||
|
||||
bind_allocbitmask &= ~BIT((bindcontext->BindNodeID>>1) - 1);
|
||||
|
||||
memset(bindcontext, 0, sizeof(udsBindContext));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Result udsipc_Bind(udsBindContext *bindcontext, u32 input0, u8 input1, u16 NetworkNodeID)//input0 and input1 are unknown.
|
||||
{
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0]=IPC_MakeHeader(0x12,4,0); // 0x120100
|
||||
cmdbuf[1]=bindcontext->BindNodeID;
|
||||
cmdbuf[2]=input0;
|
||||
cmdbuf[3]=input1;
|
||||
cmdbuf[4]=NetworkNodeID;
|
||||
|
||||
Result ret=0;
|
||||
if(R_FAILED(ret=svcSendSyncRequest(__uds_servhandle)))return ret;
|
||||
ret = cmdbuf[1];
|
||||
|
||||
if(R_SUCCEEDED(ret))
|
||||
{
|
||||
bindcontext->event = cmdbuf[3];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Result udsipc_Unbind(udsBindContext *bindcontext)
|
||||
{
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0]=IPC_MakeHeader(0x13,1,0); // 0x130040
|
||||
cmdbuf[1]=bindcontext->BindNodeID;
|
||||
|
||||
Result ret=0;
|
||||
if(R_FAILED(ret=svcSendSyncRequest(__uds_servhandle)))return ret;
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result udsSendTo(u16 dst_NetworkNodeID, u8 input8, u8 flags, void* buf, size_t size)
|
||||
{
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
|
||||
u32 aligned_size = (size+0x3) & ~0x3;
|
||||
|
||||
cmdbuf[0]=IPC_MakeHeader(0x17,6,2); // 0x170182
|
||||
cmdbuf[1]=0x1;//Unused
|
||||
cmdbuf[2]=dst_NetworkNodeID;
|
||||
cmdbuf[3]=input8;
|
||||
cmdbuf[4]=aligned_size>>2;
|
||||
cmdbuf[5]=size;
|
||||
cmdbuf[6]=flags;
|
||||
cmdbuf[7]=IPC_Desc_StaticBuffer(aligned_size, 5);
|
||||
cmdbuf[8]=(u32)buf;
|
||||
|
||||
Result ret=0;
|
||||
if(R_FAILED(ret=svcSendSyncRequest(__uds_servhandle)))return ret;
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
static Result udsipc_BeginHostingNetwork(udsNetworkStruct *network, void* passphrase, size_t passphrase_size)
|
||||
{
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0]=IPC_MakeHeader(0x1D,1,4); // 0x1D0044
|
||||
cmdbuf[1]=passphrase_size;
|
||||
cmdbuf[2]=IPC_Desc_StaticBuffer(sizeof(udsNetworkStruct), 1);
|
||||
cmdbuf[3]=(u32)network;
|
||||
cmdbuf[4]=IPC_Desc_StaticBuffer(passphrase_size, 0);
|
||||
cmdbuf[5]=(u32)network;
|
||||
|
||||
Result ret=0;
|
||||
if(R_FAILED(ret=svcSendSyncRequest(__uds_servhandle)))return ret;
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
static Result udsipc_SetProbeResponseParam(u32 oui, s8 data)
|
||||
{
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0]=IPC_MakeHeader(0x21,2,0); // 0x210080
|
||||
cmdbuf[1]=oui;
|
||||
cmdbuf[2]=data;
|
||||
|
||||
Result ret=0;
|
||||
if(R_FAILED(ret=svcSendSyncRequest(__uds_servhandle)))return ret;
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user