/*---------------------------------------------------------------------------* Project: Horizon File: Updater.cpp Copyright 2009 Nintendo. 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$ *---------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include namespace ConsoleRestore { using namespace ES_NAMESPACE; using namespace EC_NAMESPACE; /* ------------------------------------------------------------------- GetCustomerSupportCode -------------------------------------------------------------------- */ #define NIM_UPDATER_RESULT_CHECK(result) \ do { \ if (result.IsFailure()) \ { \ ECCustomerSupportCode csc; \ NN_UTIL_PANIC_IF_FAILED( \ nn::nim::Updater::GetCustomerSupportCode(&csc)); \ NN_LOG("CSCode: %d\n", csc); \ nn::dbg::PrintResult(result); \ s_Result = result; \ goto LABEL_FINALIZE; \ } \ } while(0) namespace { nn::Result s_Result = nn::ResultSuccess(); bool s_updateFinished = false; const size_t UPDATER_THREAD_STACK_SIZE = 0x1000; nn::os::Thread s_UpdaterThread; nn::os::StackBuffer s_UpdaterThreadStack; u64 s_Progress = 0; } nn::Result PrintNetworkSetting() { nn::ac::NetworkSetting networkSetting; NN_UTIL_RETURN_IF_FAILED(nn::ac::LoadNetworkSetting(0, networkSetting)); NN_LOG("SSID: %s\n", networkSetting.wireless.essidSecurity.ssid); NN_LOG("DNS : %d.%d.%d.%d\n", networkSetting.ip.dns[0][0], networkSetting.ip.dns[0][1], networkSetting.ip.dns[0][2], networkSetting.ip.dns[0][3]); return nn::ResultSuccess(); } nn::Result ConnectNetwork() { nn::Result result = nn::ResultSuccess(); nn::ac::Config config; result = nn::ac::CreateDefaultConfig(&config); NN_UTIL_RETURN_IF_FAILED(result); result = nn::ac::ConnectWithoutEula(config); NN_UTIL_RETURN_IF_FAILED(result); NN_LOG("Success nn::ac::ConnectWithoutEula\n"); NN_UTIL_RETURN_IF_FAILED(PrintNetworkSetting()); return nn::ResultSuccess(); } nn::Result InitializeInternal() { nn::Result result = nn::ResultSuccess(); result = nn::ac::InitializeInternal(); NN_UTIL_RETURN_IF_FAILED(result); result = ConnectNetwork(); NN_UTIL_RETURN_IF_FAILED(result); return nn::ResultSuccess(); } nn::Result FinalizeInternal() { nn::Result result = nn::ResultSuccess(); nn::ac::CloseAll(); result = nn::ac::FinalizeInternal(); NN_UTIL_RETURN_IF_FAILED(result); return nn::ResultSuccess(); } void UpdateThreadFunc() { nn::Result result; NN_LOG("********************UpdateThreadFunc Start********************\n"); nn::cfg::CTR::init::Initialize(); nn::cfg::CfgCountryCode country; nn::cfg::CfgRegionCode region; const char *regionStr; const char *countryStr; NN_UNUSED_VAR(regionStr); NN_UNUSED_VAR(countryStr); country = nn::cfg::GetCountry(); region = nn::cfg::GetRegion(); countryStr = nn::cfg::GetCountryCodeA2(country); regionStr = nn::cfg::GetRegionCodeA3(region); NN_LOG("[Updater] country:%2d:%s\n", country, countryStr); NN_LOG("[Updater] region :%2d:%s\n", region, regionStr); /* ------------------------------------------------------------------- Initialize -------------------------------------------------------------------- */ NN_LOG("[Updater] nn::nim::InitializeForUpdater\n"); result = nn::nim::InitializeForUpdater(); NIM_UPDATER_RESULT_CHECK(result); NN_LOG("[Updater] InitializeInternal\n"); result = InitializeInternal(); NIM_UPDATER_RESULT_CHECK(result); /* ------------------------------------------------------------------- StartNetworkUpdate -------------------------------------------------------------------- */ NN_LOG("[Updater] nn::nim::Updater::StartNetworkUpdate()\n"); result = nn::nim::Updater::StartNetworkUpdate(); NIM_UPDATER_RESULT_CHECK(result); /* ------------------------------------------------------------------- GetProgress -------------------------------------------------------------------- */ NN_LOG("[Updater] nn::nim::Updater::GetProgress()\n"); while(true) { nn::nim::NetworkUpdateProgress progress; NIM_UPDATER_RESULT_CHECK(nn::nim::Updater::GetProgress(&progress)); NIM_UPDATER_RESULT_CHECK(progress.lastResult); NN_LOG("\x1b[1A\x1b[K"); NN_LOG("Downloading %2lld/%2lld %8lld/%8lld (%d)\n", progress.downloadedTitleNum, progress.totalTitleNum, progress.currentDownloadedSize, progress.currentTotalSize, progress.state); // ゼロ除算を防ぐ if(progress.totalTitleNum == 0) { progress.totalTitleNum++; progress.downloadedTitleNum++; } if(progress.state > nn::nim::CTR::NUP_STATE_CHECKING) { s_Progress = progress.downloadedTitleNum * 100 / progress.totalTitleNum; } if (progress.state == nn::nim::NUP_STATE_NO_NEED) { NN_LOG("[Updater] No need to NetworkUpdate\n"); s_Progress = 100; break; } if (progress.state == nn::nim::NUP_STATE_FINISHED) { NN_LOG("[Updater] Finished NetworkUpdate\n"); s_Progress = 100; break; } nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(300)); } LABEL_FINALIZE: /* ------------------------------------------------------------------- Finalize -------------------------------------------------------------------- */ NN_LOG("[Updater] nn::nim::FinalizeForUpdater\n"); result = nn::nim::FinalizeForUpdater(); NIM_UPDATER_RESULT_CHECK(result); result = FinalizeInternal(); NIM_UPDATER_RESULT_CHECK(result); NN_LOG("[Updater] Finish nim Updater demo.\n"); s_updateFinished = true; } void StartFGNetworkUpdate() { NN_LOG("Start FGNetworkUpdate\n"); s_updateFinished = false; s_Result = nn::ResultSuccess(); s_UpdaterThread.Start(UpdateThreadFunc, s_UpdaterThreadStack); } bool IsUpdaterThreadStateValid() { return s_UpdaterThread.IsValid(); } void FinishFGNetworkUpdate() { NN_LOG("Finalize FGNetworkUpdate\n"); s_UpdaterThread.Join(); } bool IsNetworkUpdateFinished() { return s_updateFinished; } u32 GetUpdateProgress() { return s_Progress; } nn::Result GetUpdateResult() { return s_Result; } }