/*---------------------------------------------------------------------------* Project: Horizon File: Parent.cpp Copyright (C)2009-2012 Nintendo Co., Ltd. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Rev: 47228 $ *---------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include #include "dlpDemo.h" #include "demo.h" enum ParentState { NOT_INITIALIZED, // Uninitialized state MASTER, // Communicate as Master ERROR // Entered sleep or Wi-Fi OFF mode }; const int GL_MEMORY_SIZE = 0x800000; struct NodeData { u16 nodeId; // char name[11]; // NN_PADDING3; }; static u16 s_NodeNum; static NodeData s_NodeData[nn::uds::NODE_MAX]; void DoParent(u16 childNum, const char passphrase[]) { DLP_DEBUG_PRINT("Parent start\n"); nn::Result result; nn::uds::EndpointDescriptor ed; ParentState state = NOT_INITIALIZED; uptr heapForGx; nn::os::Event statusUpdateEvent; size_t sendCount; char tmpPassphrase[nn::dlp::MAX_CHILD_UDS_PASSPHRASE_LENGTH]; static demo::RenderSystemDrawing s_RenderSystem; static nn::fnd::ExpHeap s_AppHeap; static bit8 s_UdsReceiveBuffer[4096*20] NN_ATTRIBUTE_ALIGN(4096); nn::nstd::MemCpy(tmpPassphrase, passphrase, sizeof(tmpPassphrase)); tmpPassphrase[nn::dlp::MAX_CHILD_UDS_PASSPHRASE_LENGTH - 1] = '\0'; // Initialize hid NN_UTIL_PANIC_IF_FAILED(nn::hid::Initialize()); // Create heap s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize() ); heapForGx = reinterpret_cast(s_AppHeap.Allocate(GL_MEMORY_SIZE)); // Allocates 8 MB memory in FCRAM for graphics s_RenderSystem.Initialize(heapForGx, GL_MEMORY_SIZE); s_RenderSystem.SetClearColor(NN_GX_DISPLAY0, 0.0f, 0.0f, 0.0f, 0.0f); s_RenderSystem.SetClearColor(NN_GX_DISPLAY1, 0.0f, 0.0f, 0.0f, 0.0f); nn::hid::PadReader padReader; nn::hid::PadStatus padStatus; while(true) { s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1); s_RenderSystem.Clear(); s_RenderSystem.SetFontSize(FONT_SIZE); s_RenderSystem.SetColor(1.0f, 1.0f, 1.0f); padReader.ReadLatest(&padStatus); switch( state ) { case NOT_INITIALIZED: { s_RenderSystem.DrawText(0, 0, "Create network"); s_NodeNum = 0; sendCount = 0; ::std::memset(s_NodeData, 0, sizeof(s_NodeData)); if ((result = nn::uds::Initialize( &statusUpdateEvent, s_UdsReceiveBuffer, sizeof(s_UdsReceiveBuffer))).IsFailure()) { DLP_DEBUG_POINT; } DLP_DEBUG_PRINT("Passphrase : %s \n", tmpPassphrase); if ((result = nn::uds::CreateNetwork(SUB_ID, childNum + 1, nn::uds::CreateLocalCommunicationId(UNIQUE_ID_SAMPLEDEMOS_DLP), tmpPassphrase, strlen(tmpPassphrase))).IsFailure()) { DLP_DEBUG_POINT; } if ((result = nn::uds::CreateEndpoint(&ed)).IsFailure()) { DLP_DEBUG_POINT; } if (result.IsFailure()) { DLP_DEBUG_POINT; NN_DBG_PRINT_RESULT(result); state = ERROR; } else { DLP_DEBUG_POINT; state = MASTER; } } break; case MASTER: { if (statusUpdateEvent.WaitOne(nn::fnd::TimeSpan::FromSeconds(0))) { nn::uds::ConnectionStatus connectionStatus; NN_UTIL_PANIC_IF_FAILED(nn::uds::GetConnectionStatus(&connectionStatus)); if( connectionStatus.nowState != nn::uds::STATE_MASTER) { DLP_DEBUG_PRINT("Leave Network (Reason:%d)\n", connectionStatus.disconnectReason); state = ERROR; } else { DLP_DEBUG_POINT; for(int i = 0;i < nn::uds::NODE_MAX; i++) //List all nodes { if( connectionStatus.updateNodeBitmap&(0x0001 << i ) ) { if( connectionStatus.nodeIdList[i] != 0 ) //New connection { nn::uds::NodeInformation nodeInfo; if(nn::uds::GetNodeInformation( &nodeInfo, connectionStatus.nodeIdList[i] ).IsSuccess()) { DLP_DEBUG_POINT; //Get name char name[12]; if( nodeInfo.userName.isNgUserName == true ) { // If the user name is a profanity word, change to *********** std::memset(name, '*', 11); } else { std::wcstombs(name, nodeInfo.userName.userName, 11); } name[11] = NULL; s_NodeData[i].nodeId = connectionStatus.nodeIdList[i]; std::memcpy(s_NodeData[i].name, name, sizeof(name)); DLP_DEBUG_PRINT("Connect! ID:%d, name:%s\n", connectionStatus.nodeIdList[i], name); s_NodeNum ++; } else { DLP_DEBUG_POINT; state = ERROR; break; } } else //Disconnect { DLP_DEBUG_PRINT("Disconnect! ID:%d\n", s_NodeData[i].nodeId); state = ERROR; break; } } } } } s_RenderSystem.DrawText(0, 0, "Node num : %2d/%2d", s_NodeNum, childNum + 1); s_RenderSystem.DrawText(0, 1 * FONT_SIZE, "------------------------------------------"); int j = 0; for (int i = 0; i < nn::uds::NODE_MAX; i++) { if (s_NodeData[i].nodeId) { s_RenderSystem.DrawText(0, (2 + j) * FONT_SIZE, "%02d : %s", s_NodeData[i].nodeId, s_NodeData[i].name); j ++; } } } break; case ERROR: // If the system enters sleep or Wi-Fi OFF mode during this, UDS must be initialized again. { s_RenderSystem.DrawText(0, 0, "(Error) Press A to restart"); if(padStatus.trigger & nn::hid::BUTTON_A) { DLP_DEBUG_POINT; nn::uds::CTR::DestroyEndpoint(&ed); nn::uds::DestroyNetwork(); nn::uds::Finalize(); state = NOT_INITIALIZED; } }break; } s_RenderSystem.SwapBuffers(); //Display the communication status s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); s_RenderSystem.Clear(); if (state == MASTER) { if (s_NodeNum >= (childNum + 1)) { if (nn::uds::SendTo(ed, &sendCount, sizeof(sendCount), nn::uds::BROADCAST_NODE_ID, 1, nn::uds::NO_WAIT).IsSuccess()) { sendCount ++; } s_RenderSystem.DrawText(0, 0, "Sending packet : %08x", sendCount); } } s_RenderSystem.SwapBuffers(); s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH); } }