diff --git a/.appveyor.yml b/.appveyor.yml
index bf7d74102..8f35dc7b5 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -60,3 +60,5 @@ test_script:
artifacts:
- path: release
name: release
+- path: build\bin\AppPackages
+ name: app
diff --git a/.gitignore b/.gitignore
index 36ea568b8..6c2aa02e4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,6 +23,8 @@ config.log
config.status
doc/Doxyfile
doc/html
+etc/visual-studio/BundleArtifacts
+etc/visual-studio/Generated Files
include/openthread-config.h
include/openthread-config.h.in
include/stamp-h1
diff --git a/etc/visual-studio/Assets/LockScreenLogo.scale-200.png b/etc/visual-studio/Assets/LockScreenLogo.scale-200.png
new file mode 100644
index 000000000..1e1671875
Binary files /dev/null and b/etc/visual-studio/Assets/LockScreenLogo.scale-200.png differ
diff --git a/etc/visual-studio/Assets/SplashScreen.scale-200.png b/etc/visual-studio/Assets/SplashScreen.scale-200.png
new file mode 100644
index 000000000..9f918754e
Binary files /dev/null and b/etc/visual-studio/Assets/SplashScreen.scale-200.png differ
diff --git a/etc/visual-studio/Assets/Square150x150Logo.scale-200.png b/etc/visual-studio/Assets/Square150x150Logo.scale-200.png
new file mode 100644
index 000000000..e46fa0436
Binary files /dev/null and b/etc/visual-studio/Assets/Square150x150Logo.scale-200.png differ
diff --git a/etc/visual-studio/Assets/Square44x44Logo.scale-200.png b/etc/visual-studio/Assets/Square44x44Logo.scale-200.png
new file mode 100644
index 000000000..81f252c34
Binary files /dev/null and b/etc/visual-studio/Assets/Square44x44Logo.scale-200.png differ
diff --git a/etc/visual-studio/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/etc/visual-studio/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
new file mode 100644
index 000000000..4b07c7d5d
Binary files /dev/null and b/etc/visual-studio/Assets/Square44x44Logo.targetsize-24_altform-unplated.png differ
diff --git a/etc/visual-studio/Assets/StoreLogo.png b/etc/visual-studio/Assets/StoreLogo.png
new file mode 100644
index 000000000..61d6a334b
Binary files /dev/null and b/etc/visual-studio/Assets/StoreLogo.png differ
diff --git a/etc/visual-studio/Assets/Wide310x150Logo.scale-200.png b/etc/visual-studio/Assets/Wide310x150Logo.scale-200.png
new file mode 100644
index 000000000..41130667c
Binary files /dev/null and b/etc/visual-studio/Assets/Wide310x150Logo.scale-200.png differ
diff --git a/etc/visual-studio/OpenThread.vcxproj b/etc/visual-studio/OpenThread.vcxproj
new file mode 100644
index 000000000..1c4de0dc6
--- /dev/null
+++ b/etc/visual-studio/OpenThread.vcxproj
@@ -0,0 +1,107 @@
+
+
+
+
+ {f8c22844-9b93-4978-80df-8af2b37a7abb}
+ Thread
+ en-US
+ 14.0
+ true
+ Windows Store
+ 10.0.10586.0
+ 10.0.10240.0
+ 10.0
+
+
+
+ Application
+ true
+ v140
+
+
+ Application
+ false
+ true
+ v140
+ true
+
+
+
+
+
+
+
+
+ ..\..\examples\apps\windows\OpenThread_TemporaryKey.pfx
+
+
+ ..\..\build\obj\$(Platform)\$(Configuration)\$(ProjectName)\
+ ..\..\build\bin\$(Platform)\$(Configuration)\app\
+ True
+ ..\..\build\bin\AppPackages\
+ Never
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+ %(AdditionalIncludeDirectories);
+ ..\..\examples\apps\windows;
+ ..\..\include;
+
+
+
+
+ %(AdditionalDependencies);
+ ..\..\build\bin\$(Platform)\$(Configuration)\dll\otApi.lib;
+
+
+
+
+
+
+ ..\..\examples\apps\windows\App.xaml
+
+
+ ..\..\examples\apps\windows\MainPage.xaml
+
+
+
+
+ Designer
+
+
+ Designer
+
+
+
+
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\..\examples\apps\windows\App.xaml
+
+
+ ..\..\examples\apps\windows\MainPage.xaml
+
+
+ Create
+
+
+
+
+
+
\ No newline at end of file
diff --git a/etc/visual-studio/OpenThread.vcxproj.filters b/etc/visual-studio/OpenThread.vcxproj.filters
new file mode 100644
index 000000000..ac15ec70e
--- /dev/null
+++ b/etc/visual-studio/OpenThread.vcxproj.filters
@@ -0,0 +1,57 @@
+
+
+
+
+ f8c22844-9b93-4978-80df-8af2b37a7abb
+
+
+ cf539bf1-44af-4a06-be13-5941f6ac2623
+ bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/etc/visual-studio/openthread.sln b/etc/visual-studio/openthread.sln
index 825fdfd2c..d76e83ddc 100644
--- a/etc/visual-studio/openthread.sln
+++ b/etc/visual-studio/openthread.sln
@@ -48,6 +48,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "otLwf", "otLwf.vcxproj", "{
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "otApi", "otApi.vcxproj", "{ED0EA262-C222-42C7-98D3-E70C72978ED2}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenThread", "OpenThread.vcxproj", "{F8C22844-9B93-4978-80DF-8AF2B37A7ABB}"
+ ProjectSection(ProjectDependencies) = postProject
+ {ED0EA262-C222-42C7-98D3-E70C72978ED2} = {ED0EA262-C222-42C7-98D3-E70C72978ED2}
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
@@ -240,6 +245,24 @@ Global
{ED0EA262-C222-42C7-98D3-E70C72978ED2}.Release|x64.Build.0 = Release|x64
{ED0EA262-C222-42C7-98D3-E70C72978ED2}.Release|x86.ActiveCfg = Release|Win32
{ED0EA262-C222-42C7-98D3-E70C72978ED2}.Release|x86.Build.0 = Release|Win32
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Debug|ARM.ActiveCfg = Debug|ARM
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Debug|ARM.Build.0 = Debug|ARM
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Debug|ARM.Deploy.0 = Debug|ARM
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Debug|x64.ActiveCfg = Debug|x64
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Debug|x64.Build.0 = Debug|x64
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Debug|x64.Deploy.0 = Debug|x64
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Debug|x86.ActiveCfg = Debug|Win32
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Debug|x86.Build.0 = Debug|Win32
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Debug|x86.Deploy.0 = Debug|Win32
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Release|ARM.ActiveCfg = Release|ARM
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Release|ARM.Build.0 = Release|ARM
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Release|ARM.Deploy.0 = Release|ARM
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Release|x64.ActiveCfg = Release|x64
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Release|x64.Build.0 = Release|x64
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Release|x64.Deploy.0 = Release|x64
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Release|x86.ActiveCfg = Release|Win32
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Release|x86.Build.0 = Release|Win32
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Release|x86.Deploy.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -259,5 +282,6 @@ Global
{9EEF9DCD-EA8F-4154-BD02-AB2B31CEC324} = {76EA541E-CAB1-4DB5-A39F-E3DB2A78CDDD}
{3F1F7F6C-2A33-4635-9880-08FC5BC4E435} = {61E8A4A0-8138-49DB-97B4-3BEC87C8E133}
{ED0EA262-C222-42C7-98D3-E70C72978ED2} = {61E8A4A0-8138-49DB-97B4-3BEC87C8E133}
+ {F8C22844-9B93-4978-80DF-8AF2B37A7ABB} = {76EA541E-CAB1-4DB5-A39F-E3DB2A78CDDD}
EndGlobalSection
EndGlobal
diff --git a/examples/apps/windows/App.xaml b/examples/apps/windows/App.xaml
new file mode 100644
index 000000000..45bbb4ff7
--- /dev/null
+++ b/examples/apps/windows/App.xaml
@@ -0,0 +1,35 @@
+
+
+
+
diff --git a/examples/apps/windows/App.xaml.cpp b/examples/apps/windows/App.xaml.cpp
new file mode 100644
index 000000000..8fffb144d
--- /dev/null
+++ b/examples/apps/windows/App.xaml.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2016, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "pch.h"
+#include "MainPage.xaml.h"
+
+using namespace Thread;
+
+using namespace Platform;
+using namespace Windows::ApplicationModel;
+using namespace Windows::ApplicationModel::Activation;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Controls::Primitives;
+using namespace Windows::UI::Xaml::Data;
+using namespace Windows::UI::Xaml::Input;
+using namespace Windows::UI::Xaml::Interop;
+using namespace Windows::UI::Xaml::Media;
+using namespace Windows::UI::Xaml::Navigation;
+
+///
+/// Initializes the singleton application object. This is the first line of authored code
+/// executed, and as such is the logical equivalent of main() or WinMain().
+///
+App::App()
+{
+ InitializeComponent();
+ Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending);
+}
+
+///
+/// Invoked when the application is launched normally by the end user. Other entry points
+/// will be used such as when the application is launched to open a specific file.
+///
+/// Details about the launch request and process.
+void App::OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e)
+{
+#if _DEBUG
+ // Show graphics profiling information while debugging.
+ if (IsDebuggerPresent())
+ {
+ // Display the current frame rate counters
+ DebugSettings->EnableFrameRateCounter = true;
+ }
+#endif
+ auto rootFrame = dynamic_cast(Window::Current->Content);
+
+ // Do not repeat app initialization when the Window already has content,
+ // just ensure that the window is active
+ if (rootFrame == nullptr)
+ {
+ // Create a Frame to act as the navigation context and associate it with
+ // a SuspensionManager key
+ rootFrame = ref new Frame();
+
+ rootFrame->NavigationFailed += ref new Windows::UI::Xaml::Navigation::NavigationFailedEventHandler(this, &App::OnNavigationFailed);
+
+ if (e->PreviousExecutionState == ApplicationExecutionState::Terminated)
+ {
+ // TODO: Restore the saved session state only when appropriate, scheduling the
+ // final launch steps after the restore is complete
+ }
+
+ if (e->PrelaunchActivated == false)
+ {
+ if (rootFrame->Content == nullptr)
+ {
+ // When the navigation stack isn't restored navigate to the first page,
+ // configuring the new page by passing required information as a navigation
+ // parameter
+ rootFrame->Navigate(TypeName(MainPage::typeid), e->Arguments);
+ }
+ // Place the frame in the current Window
+ Window::Current->Content = rootFrame;
+ // Ensure the current window is active
+ Window::Current->Activate();
+ }
+ }
+ else
+ {
+ if (e->PrelaunchActivated == false)
+ {
+ if (rootFrame->Content == nullptr)
+ {
+ // When the navigation stack isn't restored navigate to the first page,
+ // configuring the new page by passing required information as a navigation
+ // parameter
+ rootFrame->Navigate(TypeName(MainPage::typeid), e->Arguments);
+ }
+ // Ensure the current window is active
+ Window::Current->Activate();
+ }
+ }
+}
+
+///
+/// Invoked when application execution is being suspended. Application state is saved
+/// without knowing whether the application will be terminated or resumed with the contents
+/// of memory still intact.
+///
+/// The source of the suspend request.
+/// Details about the suspend request.
+void App::OnSuspending(Object^ sender, SuspendingEventArgs^ e)
+{
+ (void) sender; // Unused parameter
+ (void) e; // Unused parameter
+
+ //TODO: Save application state and stop any background activity
+}
+
+///
+/// Invoked when Navigation to a certain page fails
+///
+/// The Frame which failed navigation
+/// Details about the navigation failure
+void App::OnNavigationFailed(Platform::Object ^sender, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs ^e)
+{
+ throw ref new FailureException("Failed to load Page " + e->SourcePageType.Name);
+}
diff --git a/examples/apps/windows/App.xaml.h b/examples/apps/windows/App.xaml.h
new file mode 100644
index 000000000..52ef3aab5
--- /dev/null
+++ b/examples/apps/windows/App.xaml.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "App.g.h"
+
+namespace Thread
+{
+ ///
+ /// Provides application-specific behavior to supplement the default Application class.
+ ///
+ ref class App sealed
+ {
+ protected:
+ virtual void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e) override;
+
+ internal:
+ App();
+
+ private:
+ void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ e);
+ void OnNavigationFailed(Platform::Object ^sender, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs ^e);
+ };
+}
diff --git a/examples/apps/windows/MainPage.xaml b/examples/apps/windows/MainPage.xaml
new file mode 100644
index 000000000..4bfb3503e
--- /dev/null
+++ b/examples/apps/windows/MainPage.xaml
@@ -0,0 +1,285 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/apps/windows/MainPage.xaml.cpp b/examples/apps/windows/MainPage.xaml.cpp
new file mode 100644
index 000000000..3975baaa1
--- /dev/null
+++ b/examples/apps/windows/MainPage.xaml.cpp
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 2016, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "pch.h"
+#include "MainPage.xaml.h"
+
+using namespace Thread;
+
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Controls::Primitives;
+using namespace Windows::UI::Xaml::Data;
+using namespace Windows::UI::Xaml::Input;
+using namespace Windows::UI::Xaml::Media;
+using namespace Windows::UI::Xaml::Navigation;
+
+MainPage^ MainPage::Current = nullptr;
+
+#define GUID_FORMAT L"{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}"
+#define GUID_ARG(guid) guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]
+
+#define MAC8_FORMAT L"%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X"
+#define MAC8_ARG(mac) mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], mac[6], mac[7]
+
+PCWSTR ToString(otDeviceRole role)
+{
+ switch (role)
+ {
+ case kDeviceRoleOffline: return L"Offline";
+ case kDeviceRoleDisabled: return L"Disabled";
+ case kDeviceRoleDetached: return L"Disconnected";
+ case kDeviceRoleChild: return L"Connected - Child";
+ case kDeviceRoleRouter: return L"Connected - Router";
+ case kDeviceRoleLeader: return L"Connected - Leader";
+ }
+
+ return L"Unknown Role State";
+}
+
+void OTCALL
+ThreadDeviceAvailabilityCallback(
+ bool /* aAdded */,
+ const GUID* /* aDeviceGuid */,
+ _In_ void* /* aContext */
+ )
+{
+ // Trigger the interface list to update
+ MainPage::Current->Dispatcher->RunAsync(
+ Windows::UI::Core::CoreDispatcherPriority::Normal,
+ ref new Windows::UI::Core::DispatchedHandler(
+ [=]() {
+ MainPage::Current->BuildInterfaceList();
+ }
+ )
+ );
+}
+
+void OTCALL
+ThreadStateChangeCallback(
+ uint32_t aFlags,
+ _In_ void* /* aContext */
+ )
+{
+ if ((aFlags & OT_NET_ROLE) != 0)
+ {
+ // Trigger the interface list to update
+ MainPage::Current->Dispatcher->RunAsync(
+ Windows::UI::Core::CoreDispatcherPriority::Normal,
+ ref new Windows::UI::Core::DispatchedHandler(
+ [=]() {
+ MainPage::Current->BuildInterfaceList();
+ }
+ )
+ );
+ }
+}
+
+MainPage::MainPage()
+{
+ InitializeComponent();
+
+ MainPage::Current = this;
+ _isFullScreen = false;
+
+ _apiInstance = nullptr;
+ InterfaceConfigCancelButton->Click +=
+ ref new RoutedEventHandler(
+ [=](Platform::Object^, RoutedEventArgs^) {
+ InterfaceConfiguration->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
+ }
+ );
+ InterfaceConfigOkButton->Click +=
+ ref new RoutedEventHandler(
+ [=](Platform::Object^, RoutedEventArgs^) {
+ InterfaceConfiguration->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
+ ConnectNetwork(_currentInterface);
+ }
+ );
+ InterfaceDetailsCloseButton->Click +=
+ ref new RoutedEventHandler(
+ [=](Platform::Object^, RoutedEventArgs^) {
+ InterfaceDetails->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
+ }
+ );
+}
+
+void MainPage::OnNavigatedTo(NavigationEventArgs^ e)
+{
+ Window::Current->CoreWindow->VisibilityChanged += ref new TypedEventHandler(this, &MainPage::OnVisibilityChanged);
+
+ SizeChanged += ref new SizeChangedEventHandler(this, &MainPage::OnWindowSizeChanged);
+ Loaded += ref new RoutedEventHandler(this, &MainPage::OnLoaded);
+ Unloaded += ref new RoutedEventHandler(this, &MainPage::OnUnloaded);
+
+ _isVisible = Window::Current->CoreWindow->Visible;
+}
+
+void MainPage::OnLoaded(Object^ sender, RoutedEventArgs^ e)
+{
+ // Initialize api handle
+ _apiInstance = otApiInit();
+ if (_apiInstance)
+ {
+ // Register for device availability callbacks
+ otSetDeviceAvailabilityChangedCallback(ApiInstance, ThreadDeviceAvailabilityCallback, nullptr);
+
+ // Build the initial list
+ BuildInterfaceList();
+ }
+}
+
+void MainPage::OnUnloaded(Object^ sender, RoutedEventArgs^ e)
+{
+ // Unregister for callbacks
+ otSetDeviceAvailabilityChangedCallback(ApiInstance, nullptr, nullptr);
+
+ // Clean up api handle
+ otApiFinalize(ApiInstance);
+ _apiInstance = nullptr;
+}
+
+void MainPage::OnResuming()
+{
+}
+
+void MainPage::OnWindowSizeChanged(Object^ sender, SizeChangedEventArgs^ args)
+{
+ _windowSize = args->NewSize;
+}
+
+void MainPage::OnVisibilityChanged(Windows::UI::Core::CoreWindow^ coreWindow, Windows::UI::Core::VisibilityChangedEventArgs^ args)
+{
+ // The Visible property is toggled when the app enters and exits minimized state.
+ // But obscuring the app with another window does not change Visible state, oddly enough.
+ _isVisible = args->Visible;
+}
+
+void MainPage::ShowInterfaceDetails(Platform::Guid InterfaceGuid)
+{
+ if (ApiInstance == nullptr) return;
+
+ GUID deviceGuid = InterfaceGuid;
+ auto device = otInstanceInit(ApiInstance, &deviceGuid);
+
+ auto extendedAddress = otGetExtendedAddress(device);
+ if (extendedAddress)
+ {
+ WCHAR szMac[256] = { 0 };
+ swprintf_s(szMac, 256, MAC8_FORMAT, MAC8_ARG(extendedAddress));
+ InterfaceMacAddress->Text = ref new String(szMac);
+
+ otFreeMemory(extendedAddress);
+ }
+ else
+ {
+ InterfaceMacAddress->Text = L"ERROR";
+ }
+
+ auto ml_eid = otGetMeshLocalEid(device);
+ if (ml_eid)
+ {
+ WCHAR szAddress[46] = { 0 };
+ RtlIpv6AddressToStringW((const PIN6_ADDR)ml_eid, szAddress);
+ InterfaceML_EID->Text = ref new String(szAddress);
+
+ otFreeMemory(ml_eid);
+ }
+ else
+ {
+ InterfaceML_EID->Text = L"ERROR";
+ }
+
+ auto rloc16 = otGetRloc16(device);
+ WCHAR szRloc[16] = { 0 };
+ swprintf_s(szRloc, 16, L"%4x", rloc16);
+ InterfaceRLOC->Text = ref new String(szRloc);
+
+ if (otGetDeviceRole(device) > kDeviceRoleChild)
+ {
+ uint8_t index = 0;
+ otChildInfo childInfo;
+ while (kThreadError_None == otGetChildInfoByIndex(device, index, &childInfo))
+ {
+ index++;
+ }
+
+ WCHAR szText[64] = { 0 };
+ swprintf_s(szText, 64, L"%d", index);
+ InterfaceChildren->Text = ref new String(szText);
+
+ InterfaceNeighbors->Text = L"unknown";
+
+ InterfaceNeighbors->Visibility = Windows::UI::Xaml::Visibility::Visible;
+ InterfaceNeighborsText->Visibility = Windows::UI::Xaml::Visibility::Visible;
+ InterfaceChildren->Visibility = Windows::UI::Xaml::Visibility::Visible;
+ InterfaceChildrenText->Visibility = Windows::UI::Xaml::Visibility::Visible;
+ }
+
+ // Show the details
+ InterfaceDetails->Visibility = Windows::UI::Xaml::Visibility::Visible;
+
+ otFreeMemory(device);
+}
+
+UIElement^ MainPage::CreateNewInterface(Platform::Guid InterfaceGuid)
+{
+ GUID deviceGuid = InterfaceGuid;
+
+ auto device = otInstanceInit(ApiInstance, &deviceGuid);
+ auto deviceRole = otGetDeviceRole(device);
+
+ WCHAR szText[256] = { 0 };
+ swprintf_s(szText, 256, L"%s\r\n\t" GUID_FORMAT L"\r\n\t%s",
+ L"openthread interface", // TODO ...
+ GUID_ARG(deviceGuid),
+ ::ToString(deviceRole));
+
+ auto InterfaceStackPanel = ref new StackPanel();
+ InterfaceStackPanel->Orientation = Orientation::Horizontal;
+
+ auto InterfaceTextBlock = ref new TextBlock();
+ InterfaceTextBlock->Text = ref new String(szText);
+ InterfaceTextBlock->FontSize = 16;
+ InterfaceTextBlock->Margin = Thickness(10);
+ InterfaceTextBlock->TextWrapping = TextWrapping::Wrap;
+ InterfaceStackPanel->Children->Append(InterfaceTextBlock);
+
+ if (deviceRole == kDeviceRoleDisabled)
+ {
+ auto ConnectButton = ref new Button();
+ ConnectButton->Content = ref new String(L"Connect");
+ ConnectButton->Click +=
+ ref new RoutedEventHandler(
+ [=](Platform::Object^, RoutedEventArgs^) {
+ _currentInterface = InterfaceGuid;
+ InterfaceConfiguration->Visibility = Windows::UI::Xaml::Visibility::Visible;
+ }
+ );
+ InterfaceStackPanel->Children->Append(ConnectButton);
+ }
+ else
+ {
+ auto DetailsButton = ref new Button();
+ DetailsButton->Content = ref new String(L"Details");
+ DetailsButton->Click +=
+ ref new RoutedEventHandler(
+ [=](Platform::Object^, RoutedEventArgs^) {
+ ShowInterfaceDetails(InterfaceGuid);
+ }
+ );
+ InterfaceStackPanel->Children->Append(DetailsButton);
+
+ auto DisconnectButton = ref new Button();
+ DisconnectButton->Content = ref new String(L"Disconnect");
+ DisconnectButton->Click +=
+ ref new RoutedEventHandler(
+ [=](Platform::Object^, RoutedEventArgs^) {
+ DisconnectNetwork(InterfaceGuid);
+ }
+ );
+ InterfaceStackPanel->Children->Append(DisconnectButton);
+ }
+
+ // Register for callbacks on the device
+ otSetStateChangedCallback(device, ThreadStateChangeCallback, nullptr);
+
+ // Cache the device
+ _devices.push_back(device);
+
+ return InterfaceStackPanel;
+}
+
+void MainPage::BuildInterfaceList()
+{
+ if (ApiInstance == nullptr) return;
+
+ // Clear all existing children
+ InterfaceList->Items->Clear();
+
+ // Clean up devices
+ for each (auto device in _devices)
+ {
+ // Unregister for callbacks for the device
+ otSetStateChangedCallback((otInstance*)device, nullptr, nullptr);
+
+ // Free the device
+ otFreeMemory(device);
+ }
+ _devices.clear();
+
+ // Enumerate the new device list
+ auto deviceList = otEnumerateDevices(ApiInstance);
+ if (deviceList)
+ {
+ // Dump the results to the console
+ for (DWORD dwIndex = 0; dwIndex < deviceList->aDevicesLength; dwIndex++)
+ {
+ InterfaceList->Items->Append(
+ CreateNewInterface(deviceList->aDevices[dwIndex]));
+ }
+
+ otFreeMemory(deviceList);
+ }
+}
+
+void MainPage::ConnectNetwork(Platform::Guid InterfaceGuid)
+{
+ if (ApiInstance == nullptr) return;
+
+ GUID deviceGuid = InterfaceGuid;
+ auto device = otInstanceInit(ApiInstance, &deviceGuid);
+
+ //
+ // Configure
+ //
+
+ otNetworkName networkName = {};
+ wcstombs(networkName.m8, InterfaceConfigName->Text->Data(), sizeof(networkName.m8));
+ otSetNetworkName(device, networkName.m8);
+
+ otMasterKey masterKey = {};
+ wcstombs((char*)masterKey.m8, InterfaceConfigKey->Text->Data(), sizeof(masterKey.m8));
+ otSetMasterKey(device, masterKey.m8, sizeof(masterKey.m8));
+
+ otSetChannel(device, (uint8_t)InterfaceConfigChannel->Value);
+ otSetMaxAllowedChildren(device, (uint8_t)InterfaceConfigMaxChildren->Value);
+
+ otSetPanId(device, 0x4567);
+
+ //
+ // Bring up the interface and start the Thread logic
+ //
+
+ otInterfaceUp(device);
+
+ otThreadStart(device);
+
+ // Cleanup
+ otFreeMemory(device);
+}
+
+void MainPage::DisconnectNetwork(Platform::Guid InterfaceGuid)
+{
+ if (ApiInstance == nullptr) return;
+
+ GUID deviceGuid = InterfaceGuid;
+ auto device = otInstanceInit(ApiInstance, &deviceGuid);
+
+ //
+ // Start the Thread logic and the interface
+ //
+
+ otThreadStop(device);
+
+ otInterfaceDown(device);
+
+ // Cleanup
+ otFreeMemory(device);
+}
diff --git a/examples/apps/windows/MainPage.xaml.h b/examples/apps/windows/MainPage.xaml.h
new file mode 100644
index 000000000..549337d46
--- /dev/null
+++ b/examples/apps/windows/MainPage.xaml.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2016, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "MainPage.g.h"
+
+namespace Thread
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public ref class MainPage sealed
+ {
+ public:
+ MainPage();
+
+ void OnResuming();
+
+ void BuildInterfaceList();
+
+ void ConnectNetwork(Platform::Guid InterfaceGuid);
+ void ShowInterfaceDetails(Platform::Guid InterfaceGuid);
+ void DisconnectNetwork(Platform::Guid InterfaceGuid);
+
+ protected:
+ virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
+
+ private:
+
+ void OnLoaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ void OnUnloaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+
+ void OnWindowSizeChanged(Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ args);
+ void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ coreWindow, Windows::UI::Core::VisibilityChangedEventArgs^ args);
+
+ UIElement^ CreateNewInterface(Platform::Guid InterfaceGuid);
+
+ bool _isVisible;
+ bool _isFullScreen;
+
+ Windows::Foundation::Size _windowSize;
+
+ void *_apiInstance;
+ #define ApiInstance ((otApiInstance*)_apiInstance)
+
+ std::vector _devices;
+
+ Platform::Guid _currentInterface;
+
+ internal:
+ static MainPage^ Current;
+
+ };
+}
diff --git a/examples/apps/windows/OpenThread_TemporaryKey.pfx b/examples/apps/windows/OpenThread_TemporaryKey.pfx
new file mode 100644
index 000000000..46b475578
Binary files /dev/null and b/examples/apps/windows/OpenThread_TemporaryKey.pfx differ
diff --git a/examples/apps/windows/Package.appxmanifest b/examples/apps/windows/Package.appxmanifest
new file mode 100644
index 000000000..c2dbaca76
--- /dev/null
+++ b/examples/apps/windows/Package.appxmanifest
@@ -0,0 +1,30 @@
+
+
+
+
+
+ OpenThread
+ OpenThread
+ Assets\StoreLogo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/apps/windows/pch.cpp b/examples/apps/windows/pch.cpp
new file mode 100644
index 000000000..34894818c
--- /dev/null
+++ b/examples/apps/windows/pch.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "pch.h"
diff --git a/examples/apps/windows/pch.h b/examples/apps/windows/pch.h
new file mode 100644
index 000000000..66b2b5dee
--- /dev/null
+++ b/examples/apps/windows/pch.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#define _CRT_SECURE_NO_WARNINGS
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#define OTDLL 1
+#include
+#include
+#include
+
+#include "App.xaml.h"