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:
yellows8 2016-04-04 14:26:49 -04:00
parent ed53bcf4a8
commit 9aa9d32e11
2 changed files with 291 additions and 0 deletions

View File

@ -11,6 +11,64 @@ typedef struct {
u32 words_x20[2];//Not initialized by DLP-sysmodule. u32 words_x20[2];//Not initialized by DLP-sysmodule.
} udsNodeInfo; } 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. * @brief Initializes UDS.
* @param sharedmem_size This must be 0x1000-byte aligned. * @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); 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);

View File

@ -2,6 +2,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <malloc.h> #include <malloc.h>
#include <unistd.h> #include <unistd.h>
#include <arpa/inet.h>
#include <3ds/types.h> #include <3ds/types.h>
#include <3ds/result.h> #include <3ds/result.h>
#include <3ds/svc.h> #include <3ds/svc.h>
@ -22,10 +23,18 @@ static Handle __uds_sharedmem_handle;
static Handle __uds_connectionstatus_event; static Handle __uds_connectionstatus_event;
static u32 bind_allocbitmask;
static Result uds_Initialize(u32 sharedmem_size, const uint8_t *username); 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_InitializeWithVersion(udsNodeInfo *nodeinfo, Handle sharedmem_handle, u32 sharedmem_size, Handle *eventhandle);
static Result udsipc_Shutdown(void); 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 udsInit(u32 sharedmem_size, const uint8_t *username)
{ {
Result ret=0; Result ret=0;
@ -69,6 +78,8 @@ Result udsInit(u32 sharedmem_size, const uint8_t *username)
AtomicDecrement(&__uds_refcount); AtomicDecrement(&__uds_refcount);
} }
bind_allocbitmask = 0;
return ret; return ret;
} }
@ -151,6 +162,28 @@ Result udsGetNodeInfoUsername(udsNodeInfo *nodeinfo, uint8_t *username)
return 0; 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) static Result uds_Initialize(u32 sharedmem_size, const uint8_t *username)
{ {
Result ret=0; Result ret=0;
@ -195,6 +228,23 @@ static Result uds_Initialize(u32 sharedmem_size, const uint8_t *username)
return ret; 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) static Result udsipc_InitializeWithVersion(udsNodeInfo *nodeinfo, Handle sharedmem_handle, u32 sharedmem_size, Handle *eventhandle)
{ {
u32* cmdbuf=getThreadCommandBuffer(); u32* cmdbuf=getThreadCommandBuffer();
@ -230,3 +280,140 @@ static Result udsipc_Shutdown(void)
return cmdbuf[1]; 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];
}