1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     Parent.cpp
4 
5   Copyright (C)2009-2012 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 47228 $
14  *---------------------------------------------------------------------------*/
15 
16 #include <string.h>
17 #include <nn.h>
18 #include <nn/fs.h>
19 #include <nn/dlp.h>
20 #include <nn/types.h>
21 #include <nn/dbg.h>
22 #include <nn/nstd/nstd_String.h>
23 
24 #include <nn/os/os_Memory.h>
25 #include <nn/os/os_MemoryTypes.h>
26 #include <nn/fnd/fnd_ExpHeap.h>
27 
28 #include <nn/gx.h>
29 
30 #include "dlpDemo.h"
31 #include "demo.h"
32 
33 enum ParentState
34 {
35     NOT_INITIALIZED,    // Uninitialized state
36     MASTER,             // Communicate as Master
37     ERROR               // Entered sleep or Wi-Fi OFF mode
38 };
39 
40 const int           GL_MEMORY_SIZE = 0x800000;
41 
42 struct NodeData
43 {
44     u16     nodeId;     //
45     char    name[11];   //
46     NN_PADDING3;
47 };
48 
49 
50 static u16          s_NodeNum;
51 static NodeData     s_NodeData[nn::uds::NODE_MAX];
52 
DoParent(u16 childNum,const char passphrase[])53 void DoParent(u16 childNum, const char passphrase[])
54 {
55     DLP_DEBUG_PRINT("Parent start\n");
56 
57     nn::Result                          result;
58     nn::uds::EndpointDescriptor         ed;
59     ParentState                         state = NOT_INITIALIZED;
60     uptr                                heapForGx;
61     nn::os::Event                       statusUpdateEvent;
62     size_t                              sendCount;
63     char                                tmpPassphrase[nn::dlp::MAX_CHILD_UDS_PASSPHRASE_LENGTH];
64 
65     static demo::RenderSystemDrawing    s_RenderSystem;
66     static nn::fnd::ExpHeap             s_AppHeap;
67     static bit8                         s_UdsReceiveBuffer[4096*20] NN_ATTRIBUTE_ALIGN(4096);
68 
69     nn::nstd::MemCpy(tmpPassphrase, passphrase, sizeof(tmpPassphrase));
70     tmpPassphrase[nn::dlp::MAX_CHILD_UDS_PASSPHRASE_LENGTH - 1] = '\0';
71 
72    // Initialize hid
73     NN_UTIL_PANIC_IF_FAILED(nn::hid::Initialize());
74 
75     // Create heap
76     s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(),
77                         nn::os::GetDeviceMemorySize() );
78     heapForGx = reinterpret_cast<uptr>(s_AppHeap.Allocate(GL_MEMORY_SIZE));
79 
80     // Allocates 8 MB memory in FCRAM for graphics
81     s_RenderSystem.Initialize(heapForGx, GL_MEMORY_SIZE);
82 
83     s_RenderSystem.SetClearColor(NN_GX_DISPLAY0, 0.0f, 0.0f, 0.0f, 0.0f);
84     s_RenderSystem.SetClearColor(NN_GX_DISPLAY1, 0.0f, 0.0f, 0.0f, 0.0f);
85 
86     nn::hid::PadReader padReader;
87     nn::hid::PadStatus padStatus;
88 
89     while(true)
90     {
91         s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
92         s_RenderSystem.Clear();
93         s_RenderSystem.SetFontSize(FONT_SIZE);
94         s_RenderSystem.SetColor(1.0f, 1.0f, 1.0f);
95 
96         padReader.ReadLatest(&padStatus);
97 
98         switch( state )
99         {
100         case NOT_INITIALIZED:
101             {
102                 s_RenderSystem.DrawText(0, 0, "Create network");
103                 s_NodeNum = 0;
104                 sendCount = 0;
105                 ::std::memset(s_NodeData, 0, sizeof(s_NodeData));
106 
107                 if ((result = nn::uds::Initialize( &statusUpdateEvent, s_UdsReceiveBuffer, sizeof(s_UdsReceiveBuffer))).IsFailure())
108                 {
109                     DLP_DEBUG_POINT;
110                 }
111 
112                 DLP_DEBUG_PRINT("Passphrase : %s \n", tmpPassphrase);
113                 if ((result = nn::uds::CreateNetwork(SUB_ID, childNum + 1, nn::uds::CreateLocalCommunicationId(UNIQUE_ID_SAMPLEDEMOS_DLP), tmpPassphrase, strlen(tmpPassphrase))).IsFailure())
114                 {
115                     DLP_DEBUG_POINT;
116                 }
117                 if ((result = nn::uds::CreateEndpoint(&ed)).IsFailure())
118                 {
119                     DLP_DEBUG_POINT;
120                 }
121 
122                 if (result.IsFailure())
123                 {
124                     DLP_DEBUG_POINT;
125                     NN_DBG_PRINT_RESULT(result);
126                     state = ERROR;
127                 }
128                 else
129                 {
130                     DLP_DEBUG_POINT;
131                     state = MASTER;
132                 }
133             } break;
134 
135         case MASTER:
136             {
137                 if (statusUpdateEvent.WaitOne(nn::fnd::TimeSpan::FromSeconds(0)))
138                 {
139                     nn::uds::ConnectionStatus connectionStatus;
140                     NN_UTIL_PANIC_IF_FAILED(nn::uds::GetConnectionStatus(&connectionStatus));
141 
142                     if( connectionStatus.nowState != nn::uds::STATE_MASTER)
143                     {
144                         DLP_DEBUG_PRINT("Leave Network (Reason:%d)\n", connectionStatus.disconnectReason);
145                         state = ERROR;
146                     }
147                     else
148                     {
149                         DLP_DEBUG_POINT;
150 
151                         for(int i = 0;i < nn::uds::NODE_MAX; i++) //List all nodes
152                         {
153                             if( connectionStatus.updateNodeBitmap&(0x0001 << i ) )
154                             {
155                                 if( connectionStatus.nodeIdList[i] != 0 ) //New connection
156                                 {
157                                     nn::uds::NodeInformation nodeInfo;
158 
159                                     if(nn::uds::GetNodeInformation( &nodeInfo, connectionStatus.nodeIdList[i] ).IsSuccess())
160                                     {
161                                         DLP_DEBUG_POINT;
162                                         //Get name
163                                         char name[12];
164                                         if( nodeInfo.userName.isNgUserName == true )
165                                         {
166                                             // If the user name is a profanity word, change to ***********
167                                             std::memset(name, '*', 11);
168                                         }
169                                         else
170                                         {
171                                             std::wcstombs(name, nodeInfo.userName.userName, 11);
172                                         }
173                                         name[11] = NULL;
174                                         s_NodeData[i].nodeId = connectionStatus.nodeIdList[i];
175                                         std::memcpy(s_NodeData[i].name, name, sizeof(name));
176                                         DLP_DEBUG_PRINT("Connect! ID:%d, name:%s\n", connectionStatus.nodeIdList[i], name);
177                                         s_NodeNum ++;
178                                     }
179                                     else
180                                     {
181                                         DLP_DEBUG_POINT;
182                                         state = ERROR;
183                                         break;
184                                     }
185                                 }
186                                 else //Disconnect
187                                 {
188                                     DLP_DEBUG_PRINT("Disconnect! ID:%d\n", s_NodeData[i].nodeId);
189                                     state = ERROR;
190                                     break;
191                                 }
192                             }
193                         }
194                     }
195                 }
196 
197                 s_RenderSystem.DrawText(0, 0, "Node num : %2d/%2d", s_NodeNum, childNum + 1);
198                 s_RenderSystem.DrawText(0, 1 * FONT_SIZE, "------------------------------------------");
199 
200                 int j = 0;
201                 for (int i = 0; i < nn::uds::NODE_MAX; i++)
202                 {
203                     if (s_NodeData[i].nodeId)
204                     {
205                         s_RenderSystem.DrawText(0, (2 + j) * FONT_SIZE, "%02d : %s", s_NodeData[i].nodeId, s_NodeData[i].name);
206                         j ++;
207                     }
208 
209                 }
210             } break;
211 
212         case ERROR:  // If the system enters sleep or Wi-Fi OFF mode during this, UDS must be initialized again.
213             {
214                 s_RenderSystem.DrawText(0, 0, "(Error) Press A to restart");
215                 if(padStatus.trigger & nn::hid::BUTTON_A)
216                 {
217                     DLP_DEBUG_POINT;
218                     nn::uds::CTR::DestroyEndpoint(&ed);
219                     nn::uds::DestroyNetwork();
220                     nn::uds::Finalize();
221                     state = NOT_INITIALIZED;
222                 }
223             }break;
224         }
225 
226         s_RenderSystem.SwapBuffers();
227 
228         //Display the communication status
229         s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
230         s_RenderSystem.Clear();
231 
232         if (state == MASTER)
233         {
234             if (s_NodeNum >= (childNum + 1))
235             {
236                 if (nn::uds::SendTo(ed, &sendCount, sizeof(sendCount), nn::uds::BROADCAST_NODE_ID, 1, nn::uds::NO_WAIT).IsSuccess())
237                 {
238                     sendCount ++;
239                 }
240                 s_RenderSystem.DrawText(0, 0, "Sending packet : %08x", sendCount);
241 
242             }
243         }
244 
245         s_RenderSystem.SwapBuffers();
246         s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
247 
248     }
249 }
250 
251 
252