]> Chaos Git - corbenik/ctrulib.git/commitdiff
Added varioues UDS structs and enums+defines. Implemented udsGenerateDefaultNetworkSt...
authoryellows8 <yellows8@users.noreply.github.com>
Mon, 4 Apr 2016 18:26:49 +0000 (14:26 -0400)
committeryellows8 <yellows8@users.noreply.github.com>
Mon, 4 Apr 2016 18:26:49 +0000 (14:26 -0400)
libctru/include/3ds/services/uds.h
libctru/source/services/uds.c

index fc3f864dd3dde5fc2b9a65268ddacf41892966f0..97666d949537bd3c6efd148f11979de2de8853cb 100644 (file)
@@ -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);
+
index b41dfd3e1e1197bb4510f41c4416111198040835..a76df522734d473c3b71d39ab46c5a19f02eb1d6 100644 (file)
@@ -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];
+}
+