diff --git a/etc/visual-studio/openthread.sln b/etc/visual-studio/openthread.sln
index 9b5a1cdce..bb79d12d3 100644
--- a/etc/visual-studio/openthread.sln
+++ b/etc/visual-studio/openthread.sln
@@ -46,6 +46,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "drivers", "drivers", "{61E8
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "otLwf", "otLwf.vcxproj", "{3F1F7F6C-2A33-4635-9880-08FC5BC4E435}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "otApi", "otApi.vcxproj", "{ED0EA262-C222-42C7-98D3-E70C72978ED2}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -166,6 +168,14 @@ Global
{3F1F7F6C-2A33-4635-9880-08FC5BC4E435}.Release|x86.ActiveCfg = Release|Win32
{3F1F7F6C-2A33-4635-9880-08FC5BC4E435}.Release|x86.Build.0 = Release|Win32
{3F1F7F6C-2A33-4635-9880-08FC5BC4E435}.Release|x86.Deploy.0 = Release|Win32
+ {ED0EA262-C222-42C7-98D3-E70C72978ED2}.Debug|x64.ActiveCfg = Debug|x64
+ {ED0EA262-C222-42C7-98D3-E70C72978ED2}.Debug|x64.Build.0 = Debug|x64
+ {ED0EA262-C222-42C7-98D3-E70C72978ED2}.Debug|x86.ActiveCfg = Debug|Win32
+ {ED0EA262-C222-42C7-98D3-E70C72978ED2}.Debug|x86.Build.0 = Debug|Win32
+ {ED0EA262-C222-42C7-98D3-E70C72978ED2}.Release|x64.ActiveCfg = Release|x64
+ {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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -184,5 +194,6 @@ Global
{B4C744EC-B662-46C6-A076-FB58FA8FDF1B} = {76EA541E-CAB1-4DB5-A39F-E3DB2A78CDDD}
{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}
EndGlobalSection
EndGlobal
diff --git a/etc/visual-studio/otApi.vcxproj b/etc/visual-studio/otApi.vcxproj
new file mode 100644
index 000000000..62ae8086f
--- /dev/null
+++ b/etc/visual-studio/otApi.vcxproj
@@ -0,0 +1,200 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {ED0EA262-C222-42C7-98D3-E70C72978ED2}
+ Win32Proj
+ otApi
+ $(LatestTargetPlatformVersion)
+
+
+
+ DynamicLibrary
+ true
+ WindowsApplicationForDrivers10.0
+ Unicode
+
+
+ DynamicLibrary
+ false
+ WindowsApplicationForDrivers10.0
+ true
+ Unicode
+
+
+ DynamicLibrary
+ true
+ WindowsApplicationForDrivers10.0
+ Unicode
+ false
+
+
+ DynamicLibrary
+ false
+ WindowsApplicationForDrivers10.0
+ true
+ Unicode
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ ..\..\build\bin\$(Platform)\$(Configuration)\dll\
+ ..\..\build\obj\$(Platform)\$(Configuration)\$(ProjectName)\
+ C:\Program Files (x86)\Microsoft Visual Studio 14.0\Team Tools\Static Analysis Tools\Rule Sets\NativeRecommendedRules.ruleset
+ true
+
+
+ true
+ ..\..\build\bin\$(Platform)\$(Configuration)\dll\
+ ..\..\build\obj\$(Platform)\$(Configuration)\$(ProjectName)\
+ C:\Program Files (x86)\Microsoft Visual Studio 14.0\Team Tools\Static Analysis Tools\Rule Sets\NativeRecommendedRules.ruleset
+ true
+
+
+ false
+ ..\..\build\bin\$(Platform)\$(Configuration)\dll\
+ ..\..\build\obj\$(Platform)\$(Configuration)\$(ProjectName)\
+ C:\Program Files (x86)\Microsoft Visual Studio 14.0\Team Tools\Static Analysis Tools\Rule Sets\NativeRecommendedRules.ruleset
+ true
+
+
+ false
+ ..\..\build\bin\$(Platform)\$(Configuration)\dll\
+ ..\..\build\obj\$(Platform)\$(Configuration)\$(ProjectName)\
+ C:\Program Files (x86)\Microsoft Visual Studio 14.0\Team Tools\Static Analysis Tools\Rule Sets\NativeRecommendedRules.ruleset
+ true
+
+
+
+ NotUsing
+ Level3
+ Disabled
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;OTAPI_EXPORTS;%(PreprocessorDefinitions)
+ true
+ ..\..\include;..\..\examples\drivers\windows\include;..\..\examples\drivers\windows\otApi;%(AdditionalIncludeDirectories)
+ precomp.h
+ true
+ ..\..\include\platform\logging-windows.h
+ otApi
+ true
+
+
+ Windows
+ true
+ ntdll.lib;iphlpapi.lib;%(AdditionalDependencies)
+
+
+
+
+ NotUsing
+ Level3
+ Disabled
+ _DEBUG;_WINDOWS;_USRDLL;OTAPI_EXPORTS;%(PreprocessorDefinitions)
+ true
+ ..\..\include;..\..\examples\drivers\windows\include;..\..\examples\drivers\windows\otApi;%(AdditionalIncludeDirectories)
+ precomp.h
+ true
+ ..\..\include\platform\logging-windows.h
+ otApi
+ true
+
+
+ Windows
+ true
+ ntdll.lib;iphlpapi.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ NotUsing
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;OTAPI_EXPORTS;%(PreprocessorDefinitions)
+ true
+ ..\..\include;..\..\examples\drivers\windows\include;..\..\examples\drivers\windows\otApi;%(AdditionalIncludeDirectories)
+ precomp.h
+ true
+ ..\..\include\platform\logging-windows.h
+ otApi
+ true
+
+
+ Windows
+ true
+ true
+ true
+ ntdll.lib;iphlpapi.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ NotUsing
+ MaxSpeed
+ true
+ true
+ NDEBUG;_WINDOWS;_USRDLL;OTAPI_EXPORTS;%(PreprocessorDefinitions)
+ true
+ ..\..\include;..\..\examples\drivers\windows\include;..\..\examples\drivers\windows\otApi;%(AdditionalIncludeDirectories)
+ precomp.h
+ true
+ ..\..\include\platform\logging-windows.h
+ otApi
+ true
+
+
+ Windows
+ true
+ true
+ true
+ ntdll.lib;iphlpapi.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/etc/visual-studio/otApi.vcxproj.filters b/etc/visual-studio/otApi.vcxproj.filters
new file mode 100644
index 000000000..ce2de0616
--- /dev/null
+++ b/etc/visual-studio/otApi.vcxproj.filters
@@ -0,0 +1,30 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/examples/apps/cli/main.c b/examples/apps/cli/main.c
index 6400f03a7..b0c99faac 100644
--- a/examples/apps/cli/main.c
+++ b/examples/apps/cli/main.c
@@ -35,6 +35,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/examples/apps/ncp/main.c b/examples/apps/ncp/main.c
index a5496e0e0..97dfe1d98 100644
--- a/examples/apps/ncp/main.c
+++ b/examples/apps/ncp/main.c
@@ -35,6 +35,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/examples/drivers/windows/otApi/dllmain.cpp b/examples/drivers/windows/otApi/dllmain.cpp
new file mode 100644
index 000000000..63d2326c1
--- /dev/null
+++ b/examples/drivers/windows/otApi/dllmain.cpp
@@ -0,0 +1,58 @@
+/*
+ * 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 "precomp.h"
+#include "dllmain.tmh"
+
+BOOL
+__stdcall
+DllMain(
+ HINSTANCE hinstDll,
+ DWORD dwReason,
+ LPVOID /* lpvReserved */
+ )
+{
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(hinstDll);
+ WPP_INIT_TRACING(L"otApi");
+ break;
+
+ case DLL_PROCESS_DETACH:
+ WPP_CLEANUP();
+ break;
+
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ break;
+ }
+
+ return TRUE;
+}
+
diff --git a/examples/drivers/windows/otApi/otApi.cpp b/examples/drivers/windows/otApi/otApi.cpp
new file mode 100644
index 000000000..be7595169
--- /dev/null
+++ b/examples/drivers/windows/otApi/otApi.cpp
@@ -0,0 +1,3490 @@
+/*
+ * 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 "precomp.h"
+#include "otApi.tmh"
+
+//#define DEBUG_ASYNC_IO
+
+using namespace std;
+
+// The maximum time we will wait for an overlapped result. Essentially, the maximum
+// amount of time each synchronous IOCTL should take.
+const DWORD c_MaxOverlappedWaitTimeMS = 10 * 1000;
+
+// Version string returned by the API
+const char c_Version[] = "Windows"; // TODO - What should we really put here?
+
+template
+class otCallback
+{
+public:
+ RTL_REFERENCE_COUNT CallbackRefCount;
+ HANDLE CallbackCompleteEvent;
+ GUID InterfaceGuid;
+ CallbackT Callback;
+ PVOID CallbackContext;
+
+ otCallback(
+ CallbackT _Callback,
+ PVOID _CallbackContext
+ ) :
+ CallbackRefCount(1),
+ CallbackCompleteEvent(CreateEvent(nullptr, FALSE, FALSE, nullptr)),
+ Callback(_Callback),
+ CallbackContext(_CallbackContext)
+ {
+ }
+
+ otCallback(
+ const GUID& _InterfaceGuid,
+ CallbackT _Callback,
+ PVOID _CallbackContext
+ ) :
+ CallbackRefCount(1),
+ CallbackCompleteEvent(CreateEvent(nullptr, FALSE, FALSE, nullptr)),
+ InterfaceGuid(_InterfaceGuid),
+ Callback(_Callback),
+ CallbackContext(_CallbackContext)
+ {
+ }
+
+ ~otCallback()
+ {
+ if (CallbackCompleteEvent) CloseHandle(CallbackCompleteEvent);
+ }
+
+ void AddRef()
+ {
+ RtlIncrementReferenceCount(&CallbackRefCount);
+ }
+
+ void Release(bool waitForShutdown = false)
+ {
+ if (RtlDecrementReferenceCount(&CallbackRefCount))
+ {
+ // Set completion event if there are no more refs
+ SetEvent(CallbackCompleteEvent);
+ }
+
+ if (waitForShutdown)
+ {
+ WaitForSingleObject(CallbackCompleteEvent, INFINITE);
+ }
+ }
+};
+
+typedef otCallback otApiDeviceAvailabilityCallback;
+typedef otCallback otApiActiveScanCallback;
+typedef otCallback otApiEnergyScanCallback;
+typedef otCallback otApiStateChangeCallback;
+typedef otCallback otApiCommissionerEnergyReportCallback;
+typedef otCallback otApiCommissionerPanIdConflictCallback;
+
+typedef struct otApiInstance
+{
+ // Handle to the driver
+ HANDLE DeviceHandle;
+
+ // Async IO variables
+ OVERLAPPED Overlapped;
+ PTP_WAIT ThreadpoolWait;
+
+ // Notification variables
+ CRITICAL_SECTION CallbackLock;
+ OTLWF_NOTIFICATION NotificationBuffer;
+
+ // Callbacks
+ otApiDeviceAvailabilityCallback* DeviceAvailabilityCallbacks;
+ vector ActiveScanCallbacks;
+ vector EnergyScanCallbacks;
+ vector DiscoverCallbacks;
+ vector StateChangedCallbacks;
+ vector CommissionerEnergyReportCallbacks;
+ vector CommissionerPanIdConflictCallbacks;
+
+ // Constructor
+ otApiInstance() :
+ DeviceHandle(INVALID_HANDLE_VALUE),
+ Overlapped({0}),
+ ThreadpoolWait(nullptr),
+ DeviceAvailabilityCallbacks(nullptr)
+ {
+ InitializeCriticalSection(&CallbackLock);
+ }
+
+ ~otApiInstance()
+ {
+ DeleteCriticalSection(&CallbackLock);
+ }
+
+ // Helper function to set a callback
+ template
+ bool
+ SetCallback(
+ vector*> &Callbacks,
+ const GUID& InterfaceGuid,
+ CallbackT Callback,
+ PVOID CallbackContext
+ )
+ {
+ bool alreadyExists = false;
+ otCallback* CallbackToRelease = nullptr;
+
+ EnterCriticalSection(&CallbackLock);
+
+ if (Callback == nullptr)
+ {
+ for (size_t i = 0; i < Callbacks.size(); i++)
+ {
+ if (Callbacks[i]->InterfaceGuid == InterfaceGuid)
+ {
+ CallbackToRelease = Callbacks[i];
+ Callbacks.erase(Callbacks.begin() + i);
+ break;
+ }
+ }
+ }
+ else
+ {
+ for (size_t i = 0; i < Callbacks.size(); i++)
+ {
+ if (Callbacks[i]->InterfaceGuid == InterfaceGuid)
+ {
+ alreadyExists = true;
+ break;
+ }
+ }
+
+ if (!alreadyExists)
+ {
+ Callbacks.push_back(new otCallback(InterfaceGuid, Callback, CallbackContext));
+ }
+ }
+
+ LeaveCriticalSection(&CallbackLock);
+
+ if (CallbackToRelease)
+ {
+ CallbackToRelease->Release(true);
+ delete CallbackToRelease;
+ }
+
+ return !alreadyExists;
+ }
+
+} otApiInstance;
+
+typedef struct otInstance
+{
+ otApiInstance *ApiHandle; // Pointer to the Api handle
+ NET_IFINDEX InterfaceIndex; // Interface Index
+ NET_LUID InterfaceLuid; // Interface Luid
+ GUID InterfaceGuid; // Interface guid
+ ULONG CompartmentID; // Interface Compartment ID
+
+} otInstance;
+
+// otpool wait callback for async IO completion
+VOID CALLBACK
+otIoComplete(
+ _Inout_ PTP_CALLBACK_INSTANCE Instance,
+ _Inout_opt_ PVOID Context,
+ _Inout_ PTP_WAIT Wait,
+ _In_ TP_WAIT_RESULT WaitResult
+ );
+
+OTAPI
+otApiInstance *
+OTCALL
+otApiInit(
+ )
+{
+ DWORD dwError = ERROR_SUCCESS;
+ otApiInstance *aApitInstance = nullptr;
+
+ otLogFuncEntry();
+
+ aApitInstance = new(std::nothrow)otApiInstance();
+ if (aApitInstance == nullptr)
+ {
+ dwError = GetLastError();
+ otLogWarnApi("Failed to allocate otApiInstance");
+ goto error;
+ }
+
+ // Open the pipe to the OpenThread driver
+ aApitInstance->DeviceHandle =
+ CreateFile(
+ OTLWF_IOCLT_PATH,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ nullptr, // no SECURITY_ATTRIBUTES structure
+ OPEN_EXISTING, // No special create flags
+ FILE_FLAG_OVERLAPPED, // Allow asynchronous requests
+ nullptr
+ );
+ if (aApitInstance->DeviceHandle == INVALID_HANDLE_VALUE)
+ {
+ dwError = GetLastError();
+ otLogCritApi("CreateFile failed, %!WINERROR!", dwError);
+ goto error;
+ }
+
+ // Create event for completion of async IO
+ aApitInstance->Overlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
+ if (aApitInstance->Overlapped.hEvent == nullptr)
+ {
+ dwError = GetLastError();
+ otLogCritApi("CreateEvent (Overlapped.hEvent) failed, %!WINERROR!", dwError);
+ goto error;
+ }
+
+ // Create the otpool wait
+ aApitInstance->ThreadpoolWait =
+ CreateThreadpoolWait(
+ otIoComplete,
+ aApitInstance,
+ nullptr
+ );
+ if (aApitInstance->ThreadpoolWait == nullptr)
+ {
+ dwError = GetLastError();
+ otLogCritApi("CreateThreadpoolWait failed, %!WINERROR!", dwError);
+ goto error;
+ }
+
+ // Start the otpool waiting on the overlapped event
+ SetThreadpoolWait(aApitInstance->ThreadpoolWait, aApitInstance->Overlapped.hEvent, nullptr);
+
+#ifdef DEBUG_ASYNC_IO
+ otLogDebgApi("Querying for 1st notification");
+#endif
+
+ // Request first notification asynchronously
+ if (!DeviceIoControl(
+ aApitInstance->DeviceHandle,
+ IOCTL_OTLWF_QUERY_NOTIFICATION,
+ nullptr, 0,
+ &aApitInstance->NotificationBuffer, sizeof(OTLWF_NOTIFICATION),
+ nullptr,
+ &aApitInstance->Overlapped))
+ {
+ dwError = GetLastError();
+ if (dwError != ERROR_IO_PENDING)
+ {
+ otLogCritApi("DeviceIoControl for first notification failed, %!WINERROR!", dwError);
+ goto error;
+ }
+ dwError = ERROR_SUCCESS;
+ }
+
+error:
+
+ if (dwError != ERROR_SUCCESS)
+ {
+ otApiFinalize(aApitInstance);
+ aApitInstance = nullptr;
+ }
+
+ otLogFuncExit();
+
+ return aApitInstance;
+}
+
+OTAPI
+void
+OTCALL
+otApiFinalize(
+ _In_ otApiInstance *aApitInstance
+)
+{
+ if (aApitInstance == nullptr) return;
+
+ otLogFuncEntry();
+
+ // If we never got the handle, nothing left to clean up
+ if (aApitInstance->DeviceHandle != INVALID_HANDLE_VALUE)
+ {
+ //
+ // Make sure we unregister callbacks
+ //
+
+ EnterCriticalSection(&aApitInstance->CallbackLock);
+
+ otApiDeviceAvailabilityCallback* DeviceAvailabilityCallbacks = aApitInstance->DeviceAvailabilityCallbacks;
+ aApitInstance->DeviceAvailabilityCallbacks = nullptr;
+
+ vector ActiveScanCallbacks(aApitInstance->ActiveScanCallbacks);
+ aApitInstance->ActiveScanCallbacks.clear();
+
+ vector EnergyScanCallbacks(aApitInstance->EnergyScanCallbacks);
+ aApitInstance->EnergyScanCallbacks.clear();
+
+ vector DiscoverCallbacks(aApitInstance->DiscoverCallbacks);
+ aApitInstance->DiscoverCallbacks.clear();
+
+ vector StateChangedCallbacks(aApitInstance->StateChangedCallbacks);
+ aApitInstance->StateChangedCallbacks.clear();
+
+ vector CommissionerEnergyReportCallbacks(aApitInstance->CommissionerEnergyReportCallbacks);
+ aApitInstance->CommissionerEnergyReportCallbacks.clear();
+
+ vector CommissionerPanIdConflictCallbacks(aApitInstance->CommissionerPanIdConflictCallbacks);
+ aApitInstance->CommissionerPanIdConflictCallbacks.clear();
+
+ #ifdef DEBUG_ASYNC_IO
+ otLogDebgApi("Clearing Threadpool Wait");
+ #endif
+
+ // Clear the threadpool wait to prevent further waits from being scheduled
+ PTP_WAIT tpWait = aApitInstance->ThreadpoolWait;
+ aApitInstance->ThreadpoolWait = nullptr;
+
+ LeaveCriticalSection(&aApitInstance->CallbackLock);
+
+ // Clear all callbacks
+ if (DeviceAvailabilityCallbacks)
+ {
+ DeviceAvailabilityCallbacks->Release(true);
+ delete DeviceAvailabilityCallbacks;
+ }
+ for (size_t i = 0; i < ActiveScanCallbacks.size(); i++)
+ {
+ ActiveScanCallbacks[i]->Release(true);
+ delete ActiveScanCallbacks[i];
+ }
+ for (size_t i = 0; i < EnergyScanCallbacks.size(); i++)
+ {
+ EnergyScanCallbacks[i]->Release(true);
+ delete EnergyScanCallbacks[i];
+ }
+ for (size_t i = 0; i < DiscoverCallbacks.size(); i++)
+ {
+ DiscoverCallbacks[i]->Release(true);
+ delete DiscoverCallbacks[i];
+ }
+ for (size_t i = 0; i < StateChangedCallbacks.size(); i++)
+ {
+ StateChangedCallbacks[i]->Release(true);
+ delete StateChangedCallbacks[i];
+ }
+ for (size_t i = 0; i < CommissionerEnergyReportCallbacks.size(); i++)
+ {
+ CommissionerEnergyReportCallbacks[i]->Release(true);
+ delete CommissionerEnergyReportCallbacks[i];
+ }
+ for (size_t i = 0; i < CommissionerPanIdConflictCallbacks.size(); i++)
+ {
+ CommissionerPanIdConflictCallbacks[i]->Release(true);
+ delete CommissionerPanIdConflictCallbacks[i];
+ }
+
+ // Clean up threadpool wait
+ if (tpWait)
+ {
+ #ifdef DEBUG_ASYNC_IO
+ otLogDebgApi("Waiting for outstanding threadpool callbacks to compelte");
+ #endif
+
+ // Cancel any queued waits and wait for any outstanding calls to compelte
+ WaitForThreadpoolWaitCallbacks(tpWait, TRUE);
+
+ #ifdef DEBUG_ASYNC_IO
+ otLogDebgApi("Cancelling any pending IO");
+ #endif
+
+ // Cancel any async IO
+ CancelIoEx(aApitInstance->DeviceHandle, &aApitInstance->Overlapped);
+
+ // Free the threadpool wait
+ CloseThreadpoolWait(tpWait);
+ }
+
+ // Clean up overlapped event
+ if (aApitInstance->Overlapped.hEvent)
+ {
+ CloseHandle(aApitInstance->Overlapped.hEvent);
+ }
+
+ // Close the device handle
+ CloseHandle(aApitInstance->DeviceHandle);
+ }
+
+ delete aApitInstance;
+
+ otLogFuncExit();
+}
+
+OTAPI
+void
+OTCALL
+otFreeMemory(
+ _In_ const void *mem
+ )
+{
+ free((void*)mem);
+}
+
+// Handles cleanly invoking the register callback
+VOID
+ProcessNotification(
+ _In_ otApiInstance *aApitInstance,
+ _In_ POTLWF_NOTIFICATION Notif
+ )
+{
+ if (Notif->NotifType == OTLWF_NOTIF_DEVICE_AVAILABILITY)
+ {
+ otCallback* Callback = nullptr;
+
+ EnterCriticalSection(&aApitInstance->CallbackLock);
+
+ if (aApitInstance->DeviceAvailabilityCallbacks != nullptr)
+ {
+ aApitInstance->DeviceAvailabilityCallbacks->AddRef();
+ Callback = aApitInstance->DeviceAvailabilityCallbacks;
+ }
+
+ LeaveCriticalSection(&aApitInstance->CallbackLock);
+
+ // Invoke the callback outside the lock and release ref when done
+ if (Callback)
+ {
+ Callback->Callback(
+ Notif->DeviceAvailabilityPayload.Available != FALSE,
+ &Notif->InterfaceGuid,
+ Callback->CallbackContext);
+
+ Callback->Release();
+ }
+ }
+ else if (Notif->NotifType == OTLWF_NOTIF_STATE_CHANGE)
+ {
+ otCallback* Callback = nullptr;
+
+ EnterCriticalSection(&aApitInstance->CallbackLock);
+
+ for (size_t i = 0; i < aApitInstance->StateChangedCallbacks.size(); i++)
+ {
+ if (aApitInstance->StateChangedCallbacks[i]->InterfaceGuid == Notif->InterfaceGuid)
+ {
+ aApitInstance->StateChangedCallbacks[i]->AddRef();
+ Callback = aApitInstance->StateChangedCallbacks[i];
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&aApitInstance->CallbackLock);
+
+ // Invoke the callback outside the lock and release ref when done
+ if (Callback)
+ {
+ Callback->Callback(
+ Notif->StateChangePayload.Flags,
+ Callback->CallbackContext);
+
+ Callback->Release();
+ }
+ }
+ else if (Notif->NotifType == OTLWF_NOTIF_DISCOVER)
+ {
+ otCallback* Callback = nullptr;
+
+ EnterCriticalSection(&aApitInstance->CallbackLock);
+
+ for (size_t i = 0; i < aApitInstance->DiscoverCallbacks.size(); i++)
+ {
+ if (aApitInstance->DiscoverCallbacks[i]->InterfaceGuid == Notif->InterfaceGuid)
+ {
+ aApitInstance->DiscoverCallbacks[i]->AddRef();
+ Callback = aApitInstance->DiscoverCallbacks[i];
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&aApitInstance->CallbackLock);
+
+ // Invoke the callback outside the lock and release ref when done
+ if (Callback)
+ {
+ Callback->Callback(
+ Notif->DiscoverPayload.Valid ? &Notif->DiscoverPayload.Results : nullptr,
+ Callback->CallbackContext);
+
+ Callback->Release();
+ }
+ }
+ else if (Notif->NotifType == OTLWF_NOTIF_ACTIVE_SCAN)
+ {
+ otCallback* Callback = nullptr;
+
+ EnterCriticalSection(&aApitInstance->CallbackLock);
+
+ for (size_t i = 0; i < aApitInstance->ActiveScanCallbacks.size(); i++)
+ {
+ if (aApitInstance->ActiveScanCallbacks[i]->InterfaceGuid == Notif->InterfaceGuid)
+ {
+ aApitInstance->ActiveScanCallbacks[i]->AddRef();
+ Callback = aApitInstance->ActiveScanCallbacks[i];
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&aApitInstance->CallbackLock);
+
+ // Invoke the callback outside the lock and release ref when done
+ if (Callback)
+ {
+ Callback->Callback(
+ Notif->ActiveScanPayload.Valid ? &Notif->ActiveScanPayload.Results : nullptr,
+ Callback->CallbackContext);
+
+ Callback->Release();
+ }
+ }
+ else if (Notif->NotifType == OTLWF_NOTIF_ENERGY_SCAN)
+ {
+ otCallback* Callback = nullptr;
+
+ EnterCriticalSection(&aApitInstance->CallbackLock);
+
+ for (size_t i = 0; i < aApitInstance->EnergyScanCallbacks.size(); i++)
+ {
+ if (aApitInstance->EnergyScanCallbacks[i]->InterfaceGuid == Notif->InterfaceGuid)
+ {
+ aApitInstance->EnergyScanCallbacks[i]->AddRef();
+ Callback = aApitInstance->EnergyScanCallbacks[i];
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&aApitInstance->CallbackLock);
+
+ // Invoke the callback outside the lock and release ref when done
+ if (Callback)
+ {
+ Callback->Callback(
+ Notif->EnergyScanPayload.Valid ? &Notif->EnergyScanPayload.Results : nullptr,
+ Callback->CallbackContext);
+
+ Callback->Release();
+ }
+ }
+ else if (Notif->NotifType == OTLWF_NOTIF_COMMISSIONER_ENERGY_REPORT)
+ {
+ otCallback* Callback = nullptr;
+
+ EnterCriticalSection(&aApitInstance->CallbackLock);
+
+ for (size_t i = 0; i < aApitInstance->CommissionerEnergyReportCallbacks.size(); i++)
+ {
+ if (aApitInstance->CommissionerEnergyReportCallbacks[i]->InterfaceGuid == Notif->InterfaceGuid)
+ {
+ aApitInstance->CommissionerEnergyReportCallbacks[i]->AddRef();
+ Callback = aApitInstance->CommissionerEnergyReportCallbacks[i];
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&aApitInstance->CallbackLock);
+
+ // Invoke the callback outside the lock and release ref when done
+ if (Callback)
+ {
+ Callback->Callback(
+ Notif->CommissionerEnergyReportPayload.ChannelMask,
+ Notif->CommissionerEnergyReportPayload.EnergyList,
+ Notif->CommissionerEnergyReportPayload.EnergyListLength,
+ Callback->CallbackContext);
+
+ Callback->Release();
+ }
+ }
+ else if (Notif->NotifType == OTLWF_NOTIF_COMMISSIONER_PANID_QUERY)
+ {
+ otCallback* Callback = nullptr;
+
+ EnterCriticalSection(&aApitInstance->CallbackLock);
+
+ for (size_t i = 0; i < aApitInstance->CommissionerPanIdConflictCallbacks.size(); i++)
+ {
+ if (aApitInstance->CommissionerPanIdConflictCallbacks[i]->InterfaceGuid == Notif->InterfaceGuid)
+ {
+ aApitInstance->CommissionerPanIdConflictCallbacks[i]->AddRef();
+ Callback = aApitInstance->CommissionerPanIdConflictCallbacks[i];
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&aApitInstance->CallbackLock);
+
+ // Invoke the callback outside the lock and release ref when done
+ if (Callback)
+ {
+ Callback->Callback(
+ Notif->CommissionerPanIdQueryPayload.PanId,
+ Notif->CommissionerPanIdQueryPayload.ChannelMask,
+ Callback->CallbackContext);
+
+ Callback->Release();
+ }
+ }
+ else
+ {
+ // Unexpected notif type
+ }
+}
+
+// Threadpool wait callback for async IO completion
+VOID CALLBACK
+otIoComplete(
+ _Inout_ PTP_CALLBACK_INSTANCE /* Instance */,
+ _Inout_opt_ PVOID Context,
+ _Inout_ PTP_WAIT /* Wait */,
+ _In_ TP_WAIT_RESULT /* WaitResult */
+ )
+{
+#ifdef DEBUG_ASYNC_IO
+ otLogFuncEntry();
+#endif
+
+ otApiInstance *aApitInstance = (otApiInstance*)Context;
+ if (aApitInstance == nullptr) return;
+
+ // Get the result of the IO operation
+ DWORD dwBytesTransferred = 0;
+ if (!GetOverlappedResult(
+ aApitInstance->DeviceHandle,
+ &aApitInstance->Overlapped,
+ &dwBytesTransferred,
+ FALSE))
+ {
+ DWORD dwError = GetLastError();
+ otLogCritApi("GetOverlappedResult for notification failed, %!WINERROR!", dwError);
+ }
+ else
+ {
+ otLogDebgApi("Received successful callback for notification, type=%d",
+ aApitInstance->NotificationBuffer.NotifType);
+
+ // Invoke the callback if set
+ ProcessNotification(aApitInstance, &aApitInstance->NotificationBuffer);
+
+ // Try to get the threadpool wait to see if we are allowed to continue processing notifications
+ EnterCriticalSection(&aApitInstance->CallbackLock);
+ PTP_WAIT tpWait = aApitInstance->ThreadpoolWait;
+ LeaveCriticalSection(&aApitInstance->CallbackLock);
+
+ if (tpWait)
+ {
+ // Start waiting for next notification
+ SetThreadpoolWait(tpWait, aApitInstance->Overlapped.hEvent, nullptr);
+
+#ifdef DEBUG_ASYNC_IO
+ otLogDebgApi("Querying for next notification");
+#endif
+
+ // Request next notification
+ if (!DeviceIoControl(
+ aApitInstance->DeviceHandle,
+ IOCTL_OTLWF_QUERY_NOTIFICATION,
+ nullptr, 0,
+ &aApitInstance->NotificationBuffer, sizeof(OTLWF_NOTIFICATION),
+ nullptr,
+ &aApitInstance->Overlapped))
+ {
+ DWORD dwError = GetLastError();
+ if (dwError != ERROR_IO_PENDING)
+ {
+ otLogCritApi("DeviceIoControl for new notification failed, %!WINERROR!", dwError);
+ }
+ }
+ }
+ }
+
+#ifdef DEBUG_ASYNC_IO
+ otLogFuncExit();
+#endif
+}
+
+DWORD
+SendIOCTL(
+ _In_ otApiInstance *aApitInstance,
+ _In_ DWORD dwIoControlCode,
+ _In_reads_bytes_opt_(nInBufferSize) LPVOID lpInBuffer,
+ _In_ DWORD nInBufferSize,
+ _Out_writes_bytes_opt_(nOutBufferSize) LPVOID lpOutBuffer,
+ _In_ DWORD nOutBufferSize
+ )
+{
+ DWORD dwError = ERROR_SUCCESS;
+ OVERLAPPED Overlapped = { 0 };
+ DWORD dwBytesReturned = 0;
+
+ Overlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
+ if (Overlapped.hEvent == nullptr)
+ {
+ dwError = GetLastError();
+ otLogCritApi("CreateEvent (Overlapped.hEvent) failed, %!WINERROR!", dwError);
+ goto error;
+ }
+
+ // Send the IOCTL the OpenThread driver
+ if (!DeviceIoControl(
+ aApitInstance->DeviceHandle,
+ dwIoControlCode,
+ lpInBuffer, nInBufferSize,
+ lpOutBuffer, nOutBufferSize,
+ nullptr,
+ &Overlapped))
+ {
+ dwError = GetLastError();
+ if (dwError != ERROR_IO_PENDING)
+ {
+ otLogCritApi("DeviceIoControl(0x%x) failed, %!WINERROR!", dwIoControlCode, dwError);
+ goto error;
+ }
+ dwError = ERROR_SUCCESS;
+ }
+
+ // Get the result of the IO operation
+ if (!GetOverlappedResultEx(
+ aApitInstance->DeviceHandle,
+ &Overlapped,
+ &dwBytesReturned,
+ c_MaxOverlappedWaitTimeMS,
+ FALSE
+ ))
+ {
+ dwError = GetLastError();
+ if (dwError == WAIT_TIMEOUT)
+ {
+ dwError = ERROR_TIMEOUT;
+ CancelIoEx(aApitInstance->DeviceHandle, &Overlapped);
+ }
+ otLogCritApi("GetOverlappedResult failed, %!WINERROR!", dwError);
+ goto error;
+ }
+
+ if (dwBytesReturned != nOutBufferSize)
+ {
+ dwError = ERROR_INVALID_DATA;
+ otLogCritApi("GetOverlappedResult returned invalid output size, expected=%u actual=%u",
+ nOutBufferSize, dwBytesReturned);
+ goto error;
+ }
+
+error:
+
+ if (Overlapped.hEvent)
+ {
+ CloseHandle(Overlapped.hEvent);
+ }
+
+ return dwError;
+}
+
+__pragma(pack(push,1))
+template
+struct PackedBuffer2
+{
+ T1 data1; T2 data2;
+ PackedBuffer2(const T1 &d1, const T2 &d2) : data1(d1), data2(d2) { }
+};
+template
+struct PackedBuffer3
+{
+ T1 data1; T2 data2; T3 data3;
+ PackedBuffer3(const T1 &d1, const T2 &d2, const T3 &d3) : data1(d1), data2(d2), data3(d3) { }
+};
+template
+struct PackedBuffer4
+{
+ T1 data1; T2 data2; T3 data3; T4 data4;
+ PackedBuffer4(const T1 &d1, const T2 &d2, const T3 &d3, const T4 &d4) : data1(d1), data2(d2), data3(d3), data4(d4) { }
+};
+template
+struct PackedBuffer5
+{
+ T1 data1; T2 data2; T3 data3; T4 data4; T5 data5;
+ PackedBuffer5(const T1 &d1, const T2 &d2, const T3 &d3, const T4 &d4, const T5 &d5) : data1(d1), data2(d2), data3(d3), data4(d4), data5(d5) { }
+};
+template
+struct PackedBuffer6
+{
+ T1 data1; T2 data2; T3 data3; T4 data4; T5 data5; T6 data6;
+ PackedBuffer6(const T1 &d1, const T2 &d2, const T3 &d3, const T4 &d4, const T5 &d5, const T6 &d6) : data1(d1), data2(d2), data3(d3), data4(d4), data5(d5), data6(d6) { }
+};
+ __pragma(pack(pop))
+
+template
+DWORD
+QueryIOCTL(
+ _In_ otInstance *aInstance,
+ _In_ DWORD dwIoControlCode,
+ _In_ const in *input,
+ _Out_ out* output
+ )
+{
+ PackedBuffer2 Buffer(aInstance->InterfaceGuid, *input);
+ return SendIOCTL(aInstance->ApiHandle, dwIoControlCode, &Buffer, sizeof(Buffer), output, sizeof(out));
+}
+
+template
+DWORD
+QueryIOCTL(
+ _In_ otInstance *aInstance,
+ _In_ DWORD dwIoControlCode,
+ _Out_ out* output
+ )
+{
+ return SendIOCTL(aInstance->ApiHandle, dwIoControlCode, &aInstance->InterfaceGuid, sizeof(GUID), output, sizeof(out));
+}
+
+template
+DWORD
+SetIOCTL(
+ _In_ otInstance *aInstance,
+ _In_ DWORD dwIoControlCode,
+ _In_ const in* input
+ )
+{
+ PackedBuffer2 Buffer(aInstance->InterfaceGuid, *input);
+ return SendIOCTL(aInstance->ApiHandle, dwIoControlCode, &Buffer, sizeof(Buffer), nullptr, 0);
+}
+
+template
+DWORD
+SetIOCTL(
+ _In_ otInstance *aInstance,
+ _In_ DWORD dwIoControlCode,
+ _In_ const in input
+ )
+{
+ PackedBuffer2 Buffer(aInstance->InterfaceGuid, input);
+ return SendIOCTL(aInstance->ApiHandle, dwIoControlCode, &Buffer, sizeof(Buffer), nullptr, 0);
+}
+
+DWORD
+SetIOCTL(
+ _In_ otInstance *aInstance,
+ _In_ DWORD dwIoControlCode
+ )
+{
+ return SendIOCTL(aInstance->ApiHandle, dwIoControlCode, &aInstance->InterfaceGuid, sizeof(GUID), nullptr, 0);
+}
+
+ThreadError
+DwordToThreadError(
+ DWORD dwError
+ )
+{
+ if (((int)dwError) > 0)
+ {
+ return kThreadError_Error;
+ }
+ else
+ {
+ return (ThreadError)(-(int)dwError);
+ }
+}
+
+OTAPI
+void
+OTCALL
+otSetDeviceAvailabilityChangedCallback(
+ _In_ otApiInstance *aApitInstance,
+ _In_ otDeviceAvailabilityChangedCallback aCallback,
+ _In_ void *aCallbackContext
+ )
+{
+ otApiDeviceAvailabilityCallback* CallbackToRelease = nullptr;
+
+ EnterCriticalSection(&aApitInstance->CallbackLock);
+
+ if (aApitInstance->DeviceAvailabilityCallbacks != nullptr)
+ {
+ CallbackToRelease = aApitInstance->DeviceAvailabilityCallbacks;
+ aApitInstance->DeviceAvailabilityCallbacks = nullptr;
+ }
+
+ if (aCallback != nullptr)
+ {
+ aApitInstance->DeviceAvailabilityCallbacks =
+ new otApiDeviceAvailabilityCallback(aCallback, aCallbackContext);
+ }
+
+ LeaveCriticalSection(&aApitInstance->CallbackLock);
+
+ if (CallbackToRelease)
+ {
+ CallbackToRelease->Release(true);
+ delete CallbackToRelease;
+ }
+}
+
+OTAPI
+otDeviceList*
+OTCALL
+otEnumerateDevices(
+ _In_ otApiInstance *aApitInstance
+ )
+{
+ DWORD dwError = ERROR_SUCCESS;
+ OVERLAPPED Overlapped = { 0 };
+ DWORD dwBytesReturned = 0;
+ otDeviceList* pDeviceList = nullptr;
+ DWORD cbDeviceList = sizeof(otDeviceList);
+
+ otLogFuncEntry();
+
+ Overlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
+ if (Overlapped.hEvent == nullptr)
+ {
+ dwError = GetLastError();
+ otLogCritApi("CreateEvent (Overlapped.hEvent) failed, %!WINERROR!", dwError);
+ goto error;
+ }
+
+ pDeviceList = (otDeviceList*)malloc(cbDeviceList);
+ if (pDeviceList == nullptr)
+ {
+ otLogWarnApi("Failed to allocate otDeviceList of %u bytes.", cbDeviceList);
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto error;
+ }
+ RtlZeroMemory(pDeviceList, cbDeviceList);
+
+ // Query in a loop to account for it changing between calls
+ while (true)
+ {
+ // Send the IOCTL to query the interfaces
+ if (!DeviceIoControl(
+ aApitInstance->DeviceHandle,
+ IOCTL_OTLWF_ENUMERATE_DEVICES,
+ nullptr, 0,
+ pDeviceList, cbDeviceList,
+ nullptr,
+ &Overlapped))
+ {
+ dwError = GetLastError();
+ if (dwError != ERROR_IO_PENDING)
+ {
+ otLogCritApi("DeviceIoControl(IOCTL_OTLWF_ENUMERATE_DEVICES) failed, %!WINERROR!", dwError);
+ goto error;
+ }
+ dwError = ERROR_SUCCESS;
+ }
+
+ // Get the result of the IO operation
+ if (!GetOverlappedResultEx(
+ aApitInstance->DeviceHandle,
+ &Overlapped,
+ &dwBytesReturned,
+ c_MaxOverlappedWaitTimeMS,
+ TRUE))
+ {
+ dwError = GetLastError();
+ if (dwError == WAIT_TIMEOUT)
+ {
+ dwError = ERROR_TIMEOUT;
+ CancelIoEx(aApitInstance->DeviceHandle, &Overlapped);
+ }
+ otLogCritApi("GetOverlappedResult for notification failed, %!WINERROR!", dwError);
+ goto error;
+ }
+
+ // Calculate the expected size of the full buffer
+ cbDeviceList =
+ FIELD_OFFSET(otDeviceList, aDevices) +
+ pDeviceList->aDevicesLength * sizeof(otDeviceList::aDevices);
+
+ // Make sure they returned a complete buffer
+ if (dwBytesReturned != sizeof(otDeviceList::aDevicesLength)) break;
+
+ // If we get here that means we didn't have a big enough buffer
+ // Reallocate a new buffer
+ free(pDeviceList);
+ pDeviceList = (otDeviceList*)malloc(cbDeviceList);
+ if (pDeviceList == nullptr)
+ {
+ otLogCritApi("Failed to allocate otDeviceList of %u bytes.", cbDeviceList);
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto error;
+ }
+ RtlZeroMemory(pDeviceList, cbDeviceList);
+ }
+
+error:
+
+ if (dwError != ERROR_SUCCESS)
+ {
+ free(pDeviceList);
+ pDeviceList = nullptr;
+ }
+
+ if (Overlapped.hEvent)
+ {
+ CloseHandle(Overlapped.hEvent);
+ }
+
+ otLogFuncExitMsg("%d devices", pDeviceList == nullptr ? -1 : (int)pDeviceList->aDevicesLength);
+
+ return pDeviceList;
+}
+
+OTAPI
+otInstance *
+OTCALL
+otInstanceInit(
+ _In_ otApiInstance *aApitInstance,
+ _In_ const GUID *aDeviceGuid
+ )
+{
+ otInstance *aInstance = nullptr;
+
+ OTLWF_DEVICE Result = {0};
+ if (aApitInstance &&
+ SendIOCTL(
+ aApitInstance,
+ IOCTL_OTLWF_QUERY_DEVICE,
+ (LPVOID)aDeviceGuid,
+ sizeof(GUID),
+ &Result,
+ sizeof(Result)
+ ) == ERROR_SUCCESS)
+ {
+ aInstance = (otInstance*)malloc(sizeof(otInstance));
+ if (aInstance)
+ {
+ aInstance->ApiHandle = aApitInstance;
+ aInstance->InterfaceGuid = *aDeviceGuid;
+ aInstance->CompartmentID = Result.CompartmentID;
+
+ if (ConvertInterfaceGuidToLuid(aDeviceGuid, &aInstance->InterfaceLuid) != ERROR_SUCCESS ||
+ ConvertInterfaceLuidToIndex(&aInstance->InterfaceLuid, &aInstance->InterfaceIndex) != ERROR_SUCCESS)
+ {
+ otLogCritApi("Failed to convert interface guid to index!");
+ free(aInstance);
+ aInstance = nullptr;
+ }
+ }
+ }
+
+ return aInstance;
+}
+
+OTAPI
+GUID
+OTCALL
+otGetDeviceGuid(
+ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return {};
+ return aInstance->InterfaceGuid;
+}
+
+OTAPI
+uint32_t
+OTCALL
+otGetDeviceIfIndex(
+ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return (uint32_t)-1;
+ return aInstance->InterfaceIndex;
+}
+
+OTAPI
+uint32_t
+OTCALL
+otGetCompartmentId(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return (uint32_t)-1;
+ return aInstance->CompartmentID;
+}
+
+OTAPI
+const char *
+OTCALL
+otGetVersionString()
+{
+ char* szVersion = (char*)malloc(sizeof(c_Version));
+ if (szVersion)
+ {
+ memcpy_s(szVersion, sizeof(c_Version), c_Version, sizeof(c_Version));
+ }
+ return szVersion;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otInterfaceUp(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_INTERFACE, (BOOLEAN)TRUE));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otInterfaceDown(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_INTERFACE, (BOOLEAN)FALSE));
+}
+
+OTAPI
+bool
+OTCALL
+otIsInterfaceUp(
+ _In_ otInstance *aInstance
+ )
+{
+ BOOLEAN Result = FALSE;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_INTERFACE, &Result);
+ return Result != FALSE;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otThreadStart(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_THREAD, (BOOLEAN)TRUE));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otThreadStop(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_THREAD, (BOOLEAN)FALSE));
+}
+
+OTAPI
+bool
+OTCALL
+otIsSingleton(
+ _In_ otInstance *aInstance
+ )
+{
+ BOOLEAN Result = FALSE;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_SINGLETON, &Result);
+ return Result != FALSE;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otActiveScan(
+ _In_ otInstance *aInstance,
+ uint32_t aScanChannels,
+ uint16_t aScanDuration,
+ otHandleActiveScanResult aCallback,
+ _In_ void *aCallbackContext
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+
+ aInstance->ApiHandle->SetCallback(
+ aInstance->ApiHandle->ActiveScanCallbacks,
+ aInstance->InterfaceGuid, aCallback, aCallbackContext
+ );
+
+ PackedBuffer3 Buffer(aInstance->InterfaceGuid, aScanChannels, aScanDuration);
+ return DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_ACTIVE_SCAN, &Buffer, sizeof(Buffer), nullptr, 0));
+}
+
+OTAPI
+bool
+OTCALL
+otIsActiveScanInProgress(
+ _In_ otInstance *aInstance
+ )
+{
+ BOOLEAN Result = FALSE;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_ACTIVE_SCAN, &Result);
+ return Result != FALSE;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otEnergyScan(
+ _In_ otInstance *aInstance,
+ uint32_t aScanChannels,
+ uint16_t aScanDuration,
+ _In_ otHandleEnergyScanResult aCallback,
+ _In_ void *aCallbackContext
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+
+ aInstance->ApiHandle->SetCallback(
+ aInstance->ApiHandle->EnergyScanCallbacks,
+ aInstance->InterfaceGuid, aCallback, aCallbackContext
+ );
+
+ PackedBuffer3 Buffer(aInstance->InterfaceGuid, aScanChannels, aScanDuration);
+ return DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_ENERGY_SCAN, &Buffer, sizeof(Buffer), nullptr, 0));
+}
+
+OTAPI
+bool
+OTCALL
+otIsEnergyScanInProgress(
+ _In_ otInstance *aInstance
+ )
+{
+ BOOLEAN Result = FALSE;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_ENERGY_SCAN, &Result);
+ return Result != FALSE;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otDiscover(
+ _In_ otInstance *aInstance,
+ uint32_t aScanChannels,
+ uint16_t aScanDuration,
+ uint16_t aPanid,
+ otHandleActiveScanResult aCallback,
+ void *aCallbackContext
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+
+ aInstance->ApiHandle->SetCallback(
+ aInstance->ApiHandle->DiscoverCallbacks,
+ aInstance->InterfaceGuid, aCallback, aCallbackContext
+ );
+
+ PackedBuffer4 Buffer(aInstance->InterfaceGuid, aScanChannels, aScanDuration, aPanid);
+ return DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_DISCOVER, &Buffer, sizeof(Buffer), nullptr, 0));
+}
+
+OTAPI
+bool
+OTCALL
+otIsDiscoverInProgress(
+ _In_ otInstance *aInstance
+ )
+{
+ BOOLEAN Result = FALSE;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_DISCOVER, &Result);
+ return Result != FALSE;
+}
+
+OTAPI
+uint8_t
+OTCALL
+otGetChannel(
+ _In_ otInstance *aInstance
+ )
+{
+ uint8_t Result = 0xFF;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_CHANNEL, &Result);
+ return Result;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSetChannel(
+ _In_ otInstance *aInstance,
+ uint8_t aChannel
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_CHANNEL, aChannel));
+}
+
+OTAPI
+uint8_t
+OTCALL
+otGetMaxAllowedChildren(
+ _In_ otInstance *aInstance
+ )
+{
+ uint8_t Result = 0;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_MAX_CHILDREN, &Result);
+ return Result;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSetMaxAllowedChildren(
+ _In_ otInstance *aInstance,
+ uint8_t aMaxChildren
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_MAX_CHILDREN, aMaxChildren));
+}
+
+OTAPI
+uint32_t
+OTCALL
+otGetChildTimeout(
+ _In_ otInstance *aInstance
+ )
+{
+ uint32_t Result = 0;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_CHILD_TIMEOUT, &Result);
+ return Result;
+}
+
+OTAPI
+void
+OTCALL
+otSetChildTimeout(
+ _In_ otInstance *aInstance,
+ uint32_t aTimeout
+ )
+{
+ if (aInstance == nullptr) return;
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_CHILD_TIMEOUT, aTimeout);
+}
+
+OTAPI
+const
+uint8_t *
+OTCALL
+otGetExtendedAddress(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return nullptr;
+
+ otExtAddress *Result = (otExtAddress*)malloc(sizeof(otExtAddress));
+ if (Result && QueryIOCTL(aInstance, IOCTL_OTLWF_OT_EXTENDED_ADDRESS, Result) != ERROR_SUCCESS)
+ {
+ free(Result);
+ Result = nullptr;
+ }
+ return (uint8_t*)Result;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSetExtendedAddress(
+ _In_ otInstance *aInstance,
+ const otExtAddress *aExtendedAddress
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_EXTENDED_ADDRESS, aExtendedAddress));
+}
+
+OTAPI
+const uint8_t *
+OTCALL
+otGetExtendedPanId(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return nullptr;
+
+ otExtendedPanId *Result = (otExtendedPanId*)malloc(sizeof(otExtendedPanId));
+ if (Result && QueryIOCTL(aInstance, IOCTL_OTLWF_OT_EXTENDED_PANID, Result) != ERROR_SUCCESS)
+ {
+ free(Result);
+ Result = nullptr;
+ }
+ return (uint8_t*)Result;
+}
+
+OTAPI
+void
+OTCALL
+otSetExtendedPanId(
+ _In_ otInstance *aInstance,
+ const uint8_t *aExtendedPanId
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_EXTENDED_PANID, (const otExtendedPanId*)aExtendedPanId);
+}
+
+OTAPI
+void
+OTCALL
+otGetFactoryAssignedIeeeEui64(
+ _In_ otInstance *aInstance,
+ _Out_ otExtAddress *aEui64
+)
+{
+ if (aInstance == nullptr) return;
+ (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_FACTORY_EUI64, aEui64);
+}
+
+OTAPI
+void
+OTCALL
+otGetHashMacAddress(
+ _In_ otInstance *aInstance,
+ _Out_ otExtAddress *aHashMacAddress
+ )
+{
+ if (aInstance == nullptr) return;
+ (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_HASH_MAC_ADDRESS, aHashMacAddress);
+}
+
+OTAPI
+ThreadError
+OTCALL
+otGetLeaderRloc(
+ _In_ otInstance *aInstance,
+ _Out_ otIp6Address *aLeaderRloc
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(QueryIOCTL(aInstance, IOCTL_OTLWF_OT_LEADER_RLOC, aLeaderRloc));
+}
+
+OTAPI
+otLinkModeConfig
+OTCALL
+otGetLinkMode(
+ _In_ otInstance *aInstance
+ )
+{
+ otLinkModeConfig Result = {0};
+ static_assert(sizeof(otLinkModeConfig) == 4, "The size of otLinkModeConfig should be 4 bytes");
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_LINK_MODE, &Result);
+ return Result;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSetLinkMode(
+ _In_ otInstance *aInstance,
+ otLinkModeConfig aConfig
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ static_assert(sizeof(otLinkModeConfig) == 4, "The size of otLinkModeConfig should be 4 bytes");
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_LINK_MODE, aConfig));
+}
+
+OTAPI
+const uint8_t *
+OTCALL
+otGetMasterKey(
+ _In_ otInstance *aInstance,
+ _Out_ uint8_t *aKeyLength
+ )
+{
+ if (aInstance == nullptr || aKeyLength == nullptr) return nullptr;
+
+ *aKeyLength = 0;
+
+ struct otMasterKeyAndLength
+ {
+ otMasterKey Key;
+ uint8_t Length;
+ };
+ otMasterKeyAndLength *Result = (otMasterKeyAndLength*)malloc(sizeof(otMasterKeyAndLength));
+ if (Result == nullptr) return nullptr;
+ if (QueryIOCTL(aInstance, IOCTL_OTLWF_OT_MASTER_KEY, Result) != ERROR_SUCCESS)
+ {
+ free(Result);
+ return nullptr;
+ }
+ else
+ {
+ *aKeyLength = Result->Length;
+ }
+ return (uint8_t*)Result;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSetMasterKey(
+ _In_ otInstance *aInstance,
+ const uint8_t *aKey,
+ uint8_t aKeyLength
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+
+ BYTE Buffer[sizeof(GUID) + sizeof(otMasterKey) + sizeof(uint8_t)];
+ memcpy_s(Buffer, sizeof(Buffer), &aInstance->InterfaceGuid, sizeof(GUID));
+ memcpy_s(Buffer + sizeof(GUID), sizeof(Buffer) - sizeof(GUID), aKey, aKeyLength);
+ memcpy_s(Buffer + sizeof(GUID) + sizeof(otMasterKey), sizeof(Buffer) - sizeof(GUID) - sizeof(otMasterKey), &aKeyLength, sizeof(aKeyLength));
+
+ return DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_MASTER_KEY, Buffer, sizeof(Buffer), nullptr, 0));
+}
+
+OTAPI
+int8_t
+OTCALL
+otGetMaxTransmitPower(
+ _In_ otInstance *aInstance
+ )
+{
+ int8_t Result = 0;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_MAX_TRANSMIT_POWER, &Result);
+ return Result;
+}
+
+OTAPI
+void
+OTCALL
+otSetMaxTransmitPower(
+ _In_ otInstance *aInstance,
+ int8_t aPower
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_MAX_TRANSMIT_POWER, aPower);
+}
+
+OTAPI
+const otIp6Address *
+OTCALL
+otGetMeshLocalEid(
+ _In_ otInstance *aInstance
+ )
+{
+ otIp6Address *Result = (otIp6Address*)malloc(sizeof(otIp6Address));
+ if (Result && QueryIOCTL(aInstance, IOCTL_OTLWF_OT_MESH_LOCAL_EID, Result) != ERROR_SUCCESS)
+ {
+ free(Result);
+ Result = nullptr;
+ }
+ return Result;
+}
+
+OTAPI
+const uint8_t *
+OTCALL
+otGetMeshLocalPrefix(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return nullptr;
+
+ otMeshLocalPrefix *Result = (otMeshLocalPrefix*)malloc(sizeof(otMeshLocalPrefix));
+ if (Result && QueryIOCTL(aInstance, IOCTL_OTLWF_OT_MESH_LOCAL_PREFIX, Result) != ERROR_SUCCESS)
+ {
+ free(Result);
+ Result = nullptr;
+ }
+ return (uint8_t*)Result;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSetMeshLocalPrefix(
+ _In_ otInstance *aInstance,
+ const uint8_t *aMeshLocalPrefix
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_MESH_LOCAL_PREFIX, (const otMeshLocalPrefix*)aMeshLocalPrefix));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otGetNetworkDataLeader(
+ _In_ otInstance *aInstance,
+ bool aStable,
+ _Out_ uint8_t *aData,
+ _Out_ uint8_t *aDataLength
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ UNREFERENCED_PARAMETER(aInstance);
+ UNREFERENCED_PARAMETER(aStable);
+ UNREFERENCED_PARAMETER(aData);
+ UNREFERENCED_PARAMETER(aDataLength);
+ return kThreadError_NotImplemented; // TODO
+}
+
+OTAPI
+ThreadError
+OTCALL
+otGetNetworkDataLocal(
+ _In_ otInstance *aInstance,
+ bool aStable,
+ _Out_ uint8_t *aData,
+ _Out_ uint8_t *aDataLength
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ UNREFERENCED_PARAMETER(aInstance);
+ UNREFERENCED_PARAMETER(aStable);
+ UNREFERENCED_PARAMETER(aData);
+ UNREFERENCED_PARAMETER(aDataLength);
+ return kThreadError_NotImplemented; // TODO
+}
+
+OTAPI
+const char *
+OTCALL
+otGetNetworkName(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return nullptr;
+
+ otNetworkName *Result = (otNetworkName*)malloc(sizeof(otNetworkName));
+ if (Result && QueryIOCTL(aInstance, IOCTL_OTLWF_OT_NETWORK_NAME, Result) != ERROR_SUCCESS)
+ {
+ free(Result);
+ Result = nullptr;
+ }
+ return (char*)Result;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSetNetworkName(
+ _In_ otInstance *aInstance,
+ _In_ const char *aNetworkName
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+
+ otNetworkName Buffer = {0};
+ strcpy_s(Buffer.m8, sizeof(Buffer), aNetworkName);
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_NETWORK_NAME, (const otNetworkName*)&Buffer));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otGetNextOnMeshPrefix(
+ _In_ otInstance *aInstance,
+ bool _aLocal,
+ _Inout_ otNetworkDataIterator *aIterator,
+ _Out_ otBorderRouterConfig *aConfig
+ )
+{
+ if (aInstance == nullptr || aConfig == nullptr) return kThreadError_InvalidArgs;
+
+ BOOLEAN aLocal = _aLocal ? TRUE : FALSE;
+ PackedBuffer3 InBuffer(aInstance->InterfaceGuid, aLocal, *aIterator);
+ BYTE OutBuffer[sizeof(uint8_t) + sizeof(otBorderRouterConfig)];
+
+ ThreadError aError =
+ DwordToThreadError(
+ SendIOCTL(
+ aInstance->ApiHandle,
+ IOCTL_OTLWF_OT_NEXT_ON_MESH_PREFIX,
+ &InBuffer, sizeof(InBuffer),
+ OutBuffer, sizeof(OutBuffer)));
+
+ if (aError == kThreadError_None)
+ {
+ memcpy(aIterator, OutBuffer, sizeof(uint8_t));
+ memcpy(aConfig, OutBuffer + sizeof(uint8_t), sizeof(otBorderRouterConfig));
+ }
+ else
+ {
+ ZeroMemory(aConfig, sizeof(otBorderRouterConfig));
+ }
+
+ return aError;
+}
+
+OTAPI
+otPanId
+OTCALL
+otGetPanId(
+ _In_ otInstance *aInstance
+ )
+{
+ otPanId Result = {0};
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_PAN_ID, &Result);
+ return Result;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSetPanId(
+ _In_ otInstance *aInstance,
+ otPanId aPanId
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_PAN_ID, aPanId));
+}
+
+OTAPI
+bool
+OTCALL
+otIsRouterRoleEnabled(
+ _In_ otInstance *aInstance
+ )
+{
+ BOOLEAN Result = {0};
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_ROUTER_ROLL_ENABLED, &Result);
+ return Result != FALSE;
+}
+
+OTAPI
+void
+OTCALL
+otSetRouterRoleEnabled(
+ _In_ otInstance *aInstance,
+ bool aEnabled
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_ROUTER_ROLL_ENABLED, (BOOLEAN)aEnabled);
+}
+
+OTAPI
+otShortAddress
+OTCALL
+otGetShortAddress(
+ _In_ otInstance *aInstance
+ )
+{
+ otShortAddress Result = {0};
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_SHORT_ADDRESS, &Result);
+ return Result;
+}
+
+BOOL
+GetAdapterAddresses(
+ PIP_ADAPTER_ADDRESSES * ppIAA
+)
+{
+ PIP_ADAPTER_ADDRESSES pIAA = NULL;
+ DWORD len = 0;
+ DWORD flags;
+
+ flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
+ if (GetAdaptersAddresses(AF_INET6, flags, NULL, NULL, &len) != ERROR_BUFFER_OVERFLOW)
+ return FALSE;
+
+ pIAA = (PIP_ADAPTER_ADDRESSES)malloc(len);
+ if (pIAA) {
+ GetAdaptersAddresses(AF_INET6, flags, NULL, pIAA, &len);
+ *ppIAA = pIAA;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+OTAPI
+const otNetifAddress *
+OTCALL
+otGetUnicastAddresses(
+ _In_ otInstance *aInstance
+ )
+{
+ otLogFuncEntry();
+ if (aInstance == nullptr)
+ {
+ otLogFuncExit();
+ return nullptr;
+ }
+
+ // Put the current thead in the correct compartment
+ bool RevertCompartmentOnExit = false;
+ ULONG OriginalCompartmentID = GetCurrentThreadCompartmentId();
+ if (OriginalCompartmentID != aInstance->CompartmentID)
+ {
+ DWORD dwError = ERROR_SUCCESS;
+ if ((dwError = SetCurrentThreadCompartmentId(aInstance->CompartmentID)) != ERROR_SUCCESS)
+ {
+ otLogCritApi("SetCurrentThreadCompartmentId failed, %!WINERROR!", dwError);
+ return nullptr;
+ }
+ RevertCompartmentOnExit = true;
+ }
+
+ otNetifAddress *addrs = nullptr;
+ ULONG AddrCount = 0;
+
+ // Query the current adapter addresses and format them in the proper output format
+ PIP_ADAPTER_ADDRESSES pIAAList;
+ if (GetAdapterAddresses(&pIAAList))
+ {
+ // Loop through all the interfaces
+ for (auto pIAA = pIAAList; pIAA != nullptr; pIAA = pIAA->Next)
+ {
+ // Look for the right interface
+ if (pIAA->Ipv6IfIndex != aInstance->InterfaceIndex) continue;
+
+ // Look through all unicast addresses
+ for (auto pUnicastAddr = pIAA->FirstUnicastAddress;
+ pUnicastAddr != nullptr;
+ pUnicastAddr = pUnicastAddr->Next)
+ {
+ AddrCount++;
+ }
+
+ break;
+ }
+
+ // If we didn't find any addresses, just break out
+ if (AddrCount == 0) goto error;
+
+ // Allocate the addresses
+ addrs = (otNetifAddress*)malloc(AddrCount * sizeof(otNetifAddress));
+ if (addrs == nullptr)
+ {
+ otLogWarnApi("Not enough memory to alloc otNetifAddress array");
+ goto error;
+ }
+ ZeroMemory(addrs, AddrCount * sizeof(otNetifAddress));
+
+ // Initialize the next pointers
+ for (ULONG i = 0; i < AddrCount; i++)
+ {
+ addrs[i].mNext = (i + 1 == AddrCount) ? nullptr : &addrs[i + 1];
+ }
+
+ AddrCount = 0;
+
+ // Loop through all the interfaces
+ for (auto pIAA = pIAAList; pIAA != nullptr; pIAA = pIAA->Next)
+ {
+ // Look for the right interface
+ if (pIAA->Ipv6IfIndex != aInstance->InterfaceIndex) continue;
+
+ // Look through all unicast addresses
+ for (auto pUnicastAddr = pIAA->FirstUnicastAddress;
+ pUnicastAddr != nullptr;
+ pUnicastAddr = pUnicastAddr->Next)
+ {
+ LPSOCKADDR_IN6 pAddr = (LPSOCKADDR_IN6)pUnicastAddr->Address.lpSockaddr;
+
+ // Copy the necessary parameters
+ memcpy(&addrs[AddrCount].mAddress, &pAddr->sin6_addr, sizeof(pAddr->sin6_addr));
+ addrs[AddrCount].mPreferredLifetime = pUnicastAddr->PreferredLifetime;
+ addrs[AddrCount].mValidLifetime = pUnicastAddr->ValidLifetime;
+ addrs[AddrCount].mPrefixLength = pUnicastAddr->OnLinkPrefixLength;
+
+ AddrCount++;
+ }
+
+ break;
+ }
+
+ error:
+ free(pIAAList);
+ }
+ else
+ {
+ otLogCritApi("GetAdapterAddresses failed!");
+ }
+
+ // Revert the comparment if necessary
+ if (RevertCompartmentOnExit)
+ {
+ (VOID)SetCurrentThreadCompartmentId(OriginalCompartmentID);
+ }
+
+ otLogFuncExitMsg("%d addrs", AddrCount);
+ return addrs;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otAddUnicastAddress(
+ _In_ otInstance *aInstance,
+ const otNetifAddress *aAddress
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+
+ // Put the current thead in the correct compartment
+ bool RevertCompartmentOnExit = false;
+ ULONG OriginalCompartmentID = GetCurrentThreadCompartmentId();
+ if (OriginalCompartmentID != aInstance->CompartmentID)
+ {
+ DWORD dwError = ERROR_SUCCESS;
+ if ((dwError = SetCurrentThreadCompartmentId(aInstance->CompartmentID)) != ERROR_SUCCESS)
+ {
+ otLogCritApi("SetCurrentThreadCompartmentId failed, %!WINERROR!", dwError);
+ return kThreadError_Failed;
+ }
+ RevertCompartmentOnExit = true;
+ }
+
+ MIB_UNICASTIPADDRESS_ROW newRow;
+ InitializeUnicastIpAddressEntry(&newRow);
+
+ newRow.InterfaceIndex = aInstance->InterfaceIndex;
+ newRow.InterfaceLuid = aInstance->InterfaceLuid;
+ newRow.Address.si_family = AF_INET6;
+ newRow.Address.Ipv6.sin6_family = AF_INET6;
+
+ static_assert(sizeof(IN6_ADDR) == sizeof(otIp6Address), "Windows and OpenThread IPv6 Addr Structs must be same size");
+
+ memcpy(&newRow.Address.Ipv6.sin6_addr, &aAddress->mAddress, sizeof(IN6_ADDR));
+ newRow.OnLinkPrefixLength = aAddress->mPrefixLength;
+ newRow.PreferredLifetime = aAddress->mPreferredLifetime;
+ newRow.ValidLifetime = aAddress->mValidLifetime;
+ newRow.PrefixOrigin = IpPrefixOriginOther; // Derived from network XPANID
+ newRow.SkipAsSource = FALSE; // Allow automatic binding to this address (default)
+
+ if (IN6_IS_ADDR_LINKLOCAL(&newRow.Address.Ipv6.sin6_addr))
+ {
+ newRow.SuffixOrigin = IpSuffixOriginLinkLayerAddress; // Derived from Extended MAC address
+ }
+ else
+ {
+ newRow.SuffixOrigin = IpSuffixOriginRandom; // Was created randomly
+ }
+
+ DWORD dwError = CreateUnicastIpAddressEntry(&newRow);
+
+ // Revert the comparment if necessary
+ if (RevertCompartmentOnExit)
+ {
+ (VOID)SetCurrentThreadCompartmentId(OriginalCompartmentID);
+ }
+
+ if (dwError != ERROR_SUCCESS)
+ {
+ otLogCritApi("CreateUnicastIpAddressEntry failed %!WINERROR!", dwError);
+ return kThreadError_Failed;
+ }
+
+ return kThreadError_None;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otRemoveUnicastAddress(
+ _In_ otInstance *aInstance,
+ const otIp6Address *aAddress
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+
+ // Put the current thead in the correct compartment
+ bool RevertCompartmentOnExit = false;
+ ULONG OriginalCompartmentID = GetCurrentThreadCompartmentId();
+ if (OriginalCompartmentID != aInstance->CompartmentID)
+ {
+ DWORD dwError = ERROR_SUCCESS;
+ if ((dwError = SetCurrentThreadCompartmentId(aInstance->CompartmentID)) != ERROR_SUCCESS)
+ {
+ otLogCritApi("SetCurrentThreadCompartmentId failed, %!WINERROR!", dwError);
+ return kThreadError_Failed;
+ }
+ RevertCompartmentOnExit = true;
+ }
+
+ MIB_UNICASTIPADDRESS_ROW deleteRow;
+ InitializeUnicastIpAddressEntry(&deleteRow);
+
+ deleteRow.InterfaceIndex = aInstance->InterfaceIndex;
+ deleteRow.InterfaceLuid = aInstance->InterfaceLuid;
+ deleteRow.Address.si_family = AF_INET6;
+
+ memcpy(&deleteRow.Address.Ipv6.sin6_addr, aAddress, sizeof(IN6_ADDR));
+
+ DWORD dwError = DeleteUnicastIpAddressEntry(&deleteRow);
+
+ // Revert the comparment if necessary
+ if (RevertCompartmentOnExit)
+ {
+ (VOID)SetCurrentThreadCompartmentId(OriginalCompartmentID);
+ }
+
+ if (dwError != ERROR_SUCCESS)
+ {
+ otLogCritApi("DeleteUnicastIpAddressEntry failed %!WINERROR!", dwError);
+ return kThreadError_Failed;
+ }
+
+ return kThreadError_None;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSetStateChangedCallback(
+ _In_ otInstance *aInstance,
+ _In_ otStateChangedCallback aCallback,
+ _In_ void *aContext
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ bool success =
+ aInstance->ApiHandle->SetCallback(
+ aInstance->ApiHandle->StateChangedCallbacks,
+ aInstance->InterfaceGuid, aCallback, aContext
+ );
+ return success ? kThreadError_None : kThreadError_Already;
+}
+
+OTAPI
+void
+OTCALL
+otRemoveStateChangeCallback(
+ _In_ otInstance *aInstance,
+ _In_ otStateChangedCallback /* aCallback */,
+ _In_ void *aContext
+ )
+{
+ if (aInstance == nullptr) return;
+ aInstance->ApiHandle->SetCallback(
+ aInstance->ApiHandle->StateChangedCallbacks,
+ aInstance->InterfaceGuid, (otStateChangedCallback)nullptr, aContext
+ );
+}
+
+OTAPI
+ThreadError
+OTCALL
+otGetActiveDataset(
+ _In_ otInstance *aInstance,
+ _Out_ otOperationalDataset *aDataset
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(QueryIOCTL(aInstance, IOCTL_OTLWF_OT_ACTIVE_DATASET, aDataset));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSetActiveDataset(
+ _In_ otInstance *aInstance,
+ const otOperationalDataset *aDataset
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_ACTIVE_DATASET, aDataset));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otGetPendingDataset(
+ _In_ otInstance *aInstance,
+ _Out_ otOperationalDataset *aDataset
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(QueryIOCTL(aInstance, IOCTL_OTLWF_OT_PENDING_DATASET, aDataset));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSetPendingDataset(
+ _In_ otInstance *aInstance,
+ const otOperationalDataset *aDataset
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_PENDING_DATASET, aDataset));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSendActiveGet(
+ _In_ otInstance *aInstance,
+ const uint8_t *aTlvTypes,
+ uint8_t aLength,
+ _In_opt_ const otIp6Address *aAddress
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ if (aTlvTypes == nullptr && aLength != 0) return kThreadError_InvalidArgs;
+
+ DWORD BufferSize = sizeof(GUID) + sizeof(uint8_t) + aLength;
+ PBYTE Buffer = (PBYTE)malloc(BufferSize);
+ if (Buffer == nullptr) return kThreadError_NoBufs;
+
+ memcpy_s(Buffer, BufferSize, &aInstance->InterfaceGuid, sizeof(GUID));
+ memcpy_s(Buffer + sizeof(GUID), BufferSize - sizeof(GUID), &aLength, sizeof(aLength));
+ if (aLength > 0)
+ memcpy_s(Buffer + sizeof(GUID) + sizeof(uint8_t), BufferSize - sizeof(GUID) - sizeof(uint8_t), aTlvTypes, aLength);
+
+ // TODO - include aAddress
+ UNREFERENCED_PARAMETER(aAddress);
+
+ ThreadError result =
+ DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_SEND_ACTIVE_GET, Buffer, BufferSize, nullptr, 0));
+
+ free(Buffer);
+ return result;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSendActiveSet(
+ _In_ otInstance *aInstance,
+ const otOperationalDataset *aDataset,
+ const uint8_t *aTlvs,
+ uint8_t aLength
+ )
+{
+ if (aInstance == nullptr || aDataset == nullptr) return kThreadError_InvalidArgs;
+ if (aTlvs == nullptr && aLength != 0) return kThreadError_InvalidArgs;
+
+ DWORD BufferSize = sizeof(GUID) + sizeof(otOperationalDataset) + sizeof(uint8_t) + aLength;
+ PBYTE Buffer = (PBYTE)malloc(BufferSize);
+ if (Buffer == nullptr) return kThreadError_NoBufs;
+
+ memcpy_s(Buffer, BufferSize, &aInstance->InterfaceGuid, sizeof(GUID));
+ memcpy_s(Buffer + sizeof(GUID), BufferSize - sizeof(GUID), aDataset, sizeof(otOperationalDataset));
+ memcpy_s(Buffer + sizeof(GUID) + sizeof(otOperationalDataset), BufferSize - sizeof(GUID) - sizeof(otOperationalDataset), &aLength, sizeof(aLength));
+ if (aLength > 0)
+ memcpy_s(Buffer + sizeof(GUID) + sizeof(otOperationalDataset) + sizeof(uint8_t), BufferSize - sizeof(GUID) - sizeof(otOperationalDataset) - sizeof(uint8_t), aTlvs, aLength);
+
+ ThreadError result =
+ DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_SEND_ACTIVE_SET, Buffer, BufferSize, nullptr, 0));
+
+ free(Buffer);
+ return result;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSendPendingGet(
+ _In_ otInstance *aInstance,
+ const uint8_t *aTlvTypes,
+ uint8_t aLength,
+ _In_opt_ const otIp6Address *aAddress
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ if (aTlvTypes == nullptr && aLength != 0) return kThreadError_InvalidArgs;
+
+ DWORD BufferSize = sizeof(GUID) + sizeof(uint8_t) + aLength;
+ PBYTE Buffer = (PBYTE)malloc(BufferSize);
+ if (Buffer == nullptr) return kThreadError_NoBufs;
+
+ memcpy_s(Buffer, BufferSize, &aInstance->InterfaceGuid, sizeof(GUID));
+ memcpy_s(Buffer + sizeof(GUID), BufferSize - sizeof(GUID), &aLength, sizeof(aLength));
+ if (aLength > 0)
+ memcpy_s(Buffer + sizeof(GUID) + sizeof(uint8_t), BufferSize - sizeof(GUID) - sizeof(uint8_t), aTlvTypes, aLength);
+
+ // TODO - include aAddress
+ UNREFERENCED_PARAMETER(aAddress);
+
+ ThreadError result =
+ DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_SEND_PENDING_GET, Buffer, BufferSize, nullptr, 0));
+
+ free(Buffer);
+ return result;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSendPendingSet(
+ _In_ otInstance *aInstance,
+ const otOperationalDataset *aDataset,
+ const uint8_t *aTlvs,
+ uint8_t aLength
+ )
+{
+ if (aInstance == nullptr || aDataset == nullptr) return kThreadError_InvalidArgs;
+ if (aTlvs == nullptr && aLength != 0) return kThreadError_InvalidArgs;
+
+ DWORD BufferSize = sizeof(GUID) + sizeof(otOperationalDataset) + sizeof(uint8_t) + aLength;
+ PBYTE Buffer = (PBYTE)malloc(BufferSize);
+ if (Buffer == nullptr) return kThreadError_NoBufs;
+
+ memcpy_s(Buffer, BufferSize, &aInstance->InterfaceGuid, sizeof(GUID));
+ memcpy_s(Buffer + sizeof(GUID), BufferSize - sizeof(GUID), aDataset, sizeof(otOperationalDataset));
+ memcpy_s(Buffer + sizeof(GUID) + sizeof(otOperationalDataset), BufferSize - sizeof(GUID) - sizeof(otOperationalDataset), &aLength, sizeof(aLength));
+ if (aLength > 0)
+ memcpy_s(Buffer + sizeof(GUID) + sizeof(otOperationalDataset) + sizeof(uint8_t), BufferSize - sizeof(GUID) - sizeof(otOperationalDataset) - sizeof(uint8_t), aTlvs, aLength);
+
+ ThreadError result =
+ DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_SEND_PENDING_SET, Buffer, BufferSize, nullptr, 0));
+
+ free(Buffer);
+ return result;
+}
+
+OTAPI
+uint32_t
+OTCALL
+otGetPollPeriod(
+ _In_ otInstance *aInstance
+ )
+{
+ uint32_t Result = 0;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_POLL_PERIOD, &Result);
+ return Result;
+}
+
+OTAPI
+void
+OTCALL
+otSetPollPeriod(
+ _In_ otInstance *aInstance,
+ uint32_t aPollPeriod
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_POLL_PERIOD, aPollPeriod);
+}
+
+OTAPI
+uint8_t
+OTCALL
+otGetLocalLeaderWeight(
+ _In_ otInstance *aInstance
+ )
+{
+ uint8_t Result = 0;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_LOCAL_LEADER_WEIGHT, &Result);
+ return Result;
+}
+
+OTAPI
+void
+OTCALL
+otSetLocalLeaderWeight(
+ _In_ otInstance *aInstance,
+ uint8_t aWeight
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_LOCAL_LEADER_WEIGHT, aWeight);
+}
+
+OTAPI
+uint32_t
+OTCALL
+otGetLocalLeaderPartitionId(
+ _In_ otInstance *aInstance
+ )
+{
+ uint32_t Result = 0;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_LOCAL_LEADER_PARTITION_ID, &Result);
+ return Result;
+}
+
+OTAPI
+void
+OTCALL
+otSetLocalLeaderPartitionId(
+ _In_ otInstance *aInstance,
+ uint32_t aPartitionId
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_LOCAL_LEADER_PARTITION_ID, aPartitionId);
+}
+
+OTAPI
+uint16_t
+OTCALL
+otGetJoinerUdpPort(
+ _In_ otInstance *aInstance
+)
+{
+ uint16_t Result = 0;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_JOINER_UDP_PORT, &Result);
+ return Result;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSetJoinerUdpPort(
+ _In_ otInstance *aInstance,
+ uint16_t aJoinerUdpPort
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_JOINER_UDP_PORT, aJoinerUdpPort));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otAddBorderRouter(
+ _In_ otInstance *aInstance,
+ const otBorderRouterConfig *aConfig
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_ADD_BORDER_ROUTER, aConfig));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otRemoveBorderRouter(
+ _In_ otInstance *aInstance,
+ const otIp6Prefix *aPrefix
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_REMOVE_BORDER_ROUTER, aPrefix));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otAddExternalRoute(
+ _In_ otInstance *aInstance,
+ const otExternalRouteConfig *aConfig
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_ADD_EXTERNAL_ROUTE, aConfig));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otRemoveExternalRoute(
+ _In_ otInstance *aInstance,
+ const otIp6Prefix *aPrefix
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_REMOVE_EXTERNAL_ROUTE, aPrefix));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSendServerData(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_SEND_SERVER_DATA));
+}
+
+OTAPI
+uint32_t
+OTCALL
+otGetContextIdReuseDelay(
+ _In_ otInstance *aInstance
+ )
+{
+ uint32_t Result = 0;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_CONTEXT_ID_REUSE_DELAY, &Result);
+ return Result;
+}
+
+OTAPI
+void
+OTCALL
+otSetContextIdReuseDelay(
+ _In_ otInstance *aInstance,
+ uint32_t aDelay
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_CONTEXT_ID_REUSE_DELAY, aDelay);
+}
+
+OTAPI
+uint32_t
+OTCALL
+otGetKeySequenceCounter(
+ _In_ otInstance *aInstance
+ )
+{
+ uint32_t Result = 0;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_KEY_SEQUENCE_COUNTER, &Result);
+ return Result;
+}
+
+OTAPI
+void
+OTCALL
+otSetKeySequenceCounter(
+ _In_ otInstance *aInstance,
+ uint32_t aKeySequenceCounter
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_KEY_SEQUENCE_COUNTER, aKeySequenceCounter);
+}
+
+OTAPI
+uint32_t
+OTCALL
+otGetKeySwitchGuardTime(
+ _In_ otInstance *aInstance
+ )
+{
+ uint32_t Result = 0;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_KEY_SWITCH_GUARDTIME, &Result);
+ return Result;
+}
+
+OTAPI
+void
+OTCALL
+otSetKeySwitchGuardTime(
+ _In_ otInstance *aInstance,
+ uint32_t aKeySwitchGuardTime
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_KEY_SWITCH_GUARDTIME, aKeySwitchGuardTime);
+}
+
+OTAPI
+uint8_t
+OTCALL
+otGetNetworkIdTimeout(
+ _In_ otInstance *aInstance
+ )
+{
+ uint8_t Result = 0;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_NETWORK_ID_TIMEOUT, &Result);
+ return Result;
+}
+
+OTAPI
+void
+OTCALL
+otSetNetworkIdTimeout(
+ _In_ otInstance *aInstance,
+ uint8_t aTimeout
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_NETWORK_ID_TIMEOUT, aTimeout);
+}
+
+OTAPI
+uint8_t
+OTCALL
+otGetRouterUpgradeThreshold(
+ _In_ otInstance *aInstance
+ )
+{
+ uint8_t Result = 0;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_ROUTER_UPGRADE_THRESHOLD, &Result);
+ return Result;
+}
+
+OTAPI
+void
+OTCALL
+otSetRouterUpgradeThreshold(
+ _In_ otInstance *aInstance,
+ uint8_t aThreshold
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_ROUTER_UPGRADE_THRESHOLD, aThreshold);
+}
+
+OTAPI
+uint8_t
+OTCALL
+otGetRouterDowngradeThreshold(
+ _In_ otInstance *aInstance
+ )
+{
+ uint8_t Result = 0;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_ROUTER_DOWNGRADE_THRESHOLD, &Result);
+ return Result;
+}
+
+OTAPI
+void
+OTCALL
+otSetRouterDowngradeThreshold(
+ _In_ otInstance *aInstance,
+ uint8_t aThreshold
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_ROUTER_DOWNGRADE_THRESHOLD, aThreshold);
+}
+
+OTAPI
+uint8_t
+OTCALL
+otGetRouterSelectionJitter(
+ _In_ otInstance *aInstance
+ )
+{
+ uint8_t Result = 0;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_ROUTER_SELECTION_JITTER, &Result);
+ return Result;
+}
+
+OTAPI
+void
+OTCALL
+otSetRouterSelectionJitter(
+ _In_ otInstance *aInstance,
+ uint8_t aRouterJitter
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_ROUTER_SELECTION_JITTER, aRouterJitter);
+}
+
+OTAPI
+ThreadError
+OTCALL
+otReleaseRouterId(
+ _In_ otInstance *aInstance,
+ uint8_t aRouterId
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_RELEASE_ROUTER_ID, aRouterId));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otAddMacWhitelist(
+ _In_ otInstance *aInstance,
+ const uint8_t *aExtAddr
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_ADD_MAC_WHITELIST, (const otExtAddress*)aExtAddr));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otAddMacWhitelistRssi(
+ _In_ otInstance *aInstance,
+ const uint8_t *aExtAddr,
+ int8_t aRssi
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+
+ PackedBuffer3 Buffer(aInstance->InterfaceGuid, *(otExtAddress*)aExtAddr, aRssi);
+ return DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_ADD_MAC_WHITELIST, &Buffer, sizeof(Buffer), nullptr, 0));
+}
+
+OTAPI
+void
+OTCALL
+otRemoveMacWhitelist(
+ _In_ otInstance *aInstance,
+ const uint8_t *aExtAddr
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_REMOVE_MAC_WHITELIST, (const otExtAddress*)aExtAddr);
+}
+
+OTAPI
+ThreadError
+OTCALL
+otGetMacWhitelistEntry(
+ _In_ otInstance *aInstance,
+ uint8_t aIndex,
+ _Out_ otMacWhitelistEntry *aEntry
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(QueryIOCTL(aInstance, IOCTL_OTLWF_OT_MAC_WHITELIST_ENTRY, &aIndex, aEntry));
+}
+
+OTAPI
+void
+OTCALL
+otClearMacWhitelist(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_CLEAR_MAC_WHITELIST);
+}
+
+OTAPI
+void
+OTCALL
+otDisableMacWhitelist(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_MAC_WHITELIST_ENABLED, (BOOLEAN)FALSE);
+}
+
+OTAPI
+void
+OTCALL
+otEnableMacWhitelist(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_MAC_WHITELIST_ENABLED, (BOOLEAN)TRUE);
+}
+
+OTAPI
+bool
+OTCALL
+otIsMacWhitelistEnabled(
+ _In_ otInstance *aInstance
+ )
+{
+ BOOLEAN Result = 0;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_MAC_WHITELIST_ENABLED, &Result);
+ return Result != FALSE;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otBecomeDetached(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_DEVICE_ROLE, (uint8_t)kDeviceRoleDetached));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otBecomeChild(
+ _In_ otInstance *aInstance,
+ otMleAttachFilter aFilter
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+
+ uint8_t Role = kDeviceRoleDetached;
+ uint8_t Filter = (uint8_t)aFilter;
+
+ PackedBuffer3 Buffer(aInstance->InterfaceGuid, Role, Filter);
+ return DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_DEVICE_ROLE, &Buffer, sizeof(Buffer), nullptr, 0));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otBecomeRouter(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_DEVICE_ROLE, (uint8_t)kDeviceRoleRouter));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otBecomeLeader(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_DEVICE_ROLE, (uint8_t)kDeviceRoleLeader));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otAddMacBlacklist(
+ _In_ otInstance *aInstance,
+ const uint8_t *aExtAddr
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_ADD_MAC_BLACKLIST, (const otExtAddress*)aExtAddr));
+}
+
+OTAPI
+void
+OTCALL
+otRemoveMacBlacklist(
+ _In_ otInstance *aInstance,
+ const uint8_t *aExtAddr
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_REMOVE_MAC_BLACKLIST, (const otExtAddress*)aExtAddr);
+}
+
+OTAPI
+ThreadError
+OTCALL
+otGetMacBlacklistEntry(
+ _In_ otInstance *aInstance,
+ uint8_t aIndex,
+ _Out_ otMacBlacklistEntry *aEntry
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(QueryIOCTL(aInstance, IOCTL_OTLWF_OT_MAC_BLACKLIST_ENTRY, &aIndex, aEntry));
+}
+
+OTAPI
+void
+OTCALL
+otClearMacBlacklist(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_CLEAR_MAC_BLACKLIST);
+}
+
+OTAPI
+void
+OTCALL
+otDisableMacBlacklist(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_MAC_BLACKLIST_ENABLED, (BOOLEAN)FALSE);
+}
+
+OTAPI
+void
+OTCALL
+otEnableMacBlacklist(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_MAC_BLACKLIST_ENABLED, (BOOLEAN)TRUE);
+}
+
+OTAPI
+bool
+OTCALL
+otIsMacBlacklistEnabled(
+ _In_ otInstance *aInstance
+ )
+{
+ BOOLEAN Result = 0;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_MAC_BLACKLIST_ENABLED, &Result);
+ return Result != FALSE;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otGetAssignLinkQuality(
+ _In_ otInstance *aInstance,
+ const uint8_t *aExtAddr,
+ _Out_ uint8_t *aLinkQuality
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(QueryIOCTL(aInstance, IOCTL_OTLWF_OT_ASSIGN_LINK_QUALITY, (otExtAddress*)aExtAddr, aLinkQuality));
+}
+
+OTAPI
+void
+OTCALL
+otSetAssignLinkQuality(
+ _In_ otInstance *aInstance,
+ const uint8_t *aExtAddr,
+ uint8_t aLinkQuality
+ )
+{
+ if (aInstance == nullptr) return;
+ PackedBuffer3 Buffer(aInstance->InterfaceGuid, *(otExtAddress*)aExtAddr, aLinkQuality);
+ (void)SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_ASSIGN_LINK_QUALITY, &Buffer, sizeof(Buffer), nullptr, 0);
+}
+
+OTAPI
+void
+OTCALL
+otPlatformReset(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_PLATFORM_RESET);
+}
+
+OTAPI
+ThreadError
+OTCALL
+otGetChildInfoById(
+ _In_ otInstance *aInstance,
+ uint16_t aChildId,
+ _Out_ otChildInfo *aChildInfo
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(QueryIOCTL(aInstance, IOCTL_OTLWF_OT_CHILD_INFO_BY_ID, &aChildId, aChildInfo));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otGetChildInfoByIndex(
+ _In_ otInstance *aInstance,
+ uint8_t aChildIndex,
+ _Out_ otChildInfo *aChildInfo
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(QueryIOCTL(aInstance, IOCTL_OTLWF_OT_CHILD_INFO_BY_INDEX, &aChildIndex, aChildInfo));
+}
+
+OTAPI
+otDeviceRole
+OTCALL
+otGetDeviceRole(
+ _In_ otInstance *aInstance
+ )
+{
+ uint8_t Result = kDeviceRoleOffline;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_DEVICE_ROLE, &Result);
+ return (otDeviceRole)Result;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otGetEidCacheEntry(
+ _In_ otInstance *aInstance,
+ uint8_t aIndex,
+ _Out_ otEidCacheEntry *aEntry
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(QueryIOCTL(aInstance, IOCTL_OTLWF_OT_EID_CACHE_ENTRY, &aIndex, aEntry));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otGetLeaderData(
+ _In_ otInstance *aInstance,
+ _Out_ otLeaderData *aLeaderData
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(QueryIOCTL(aInstance, IOCTL_OTLWF_OT_LEADER_DATA, aLeaderData));
+}
+
+OTAPI
+uint8_t
+OTCALL
+otGetLeaderRouterId(
+ _In_ otInstance *aInstance
+ )
+{
+ uint8_t Result = 0xFF;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_LEADER_ROUTER_ID, &Result);
+ return Result;
+}
+
+OTAPI
+uint8_t
+OTCALL
+otGetLeaderWeight(
+ _In_ otInstance *aInstance
+ )
+{
+ uint8_t Result = 0xFF;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_LEADER_WEIGHT, &Result);
+ return Result;
+}
+
+OTAPI
+uint8_t
+OTCALL
+otGetNetworkDataVersion(
+ _In_ otInstance *aInstance
+ )
+{
+ uint8_t Result = 0xFF;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_NETWORK_DATA_VERSION, &Result);
+ return Result;
+}
+
+OTAPI
+uint32_t
+OTCALL
+otGetPartitionId(
+ _In_ otInstance *aInstance
+ )
+{
+ uint32_t Result = 0xFFFFFFFF;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_PARTITION_ID, &Result);
+ return Result;
+}
+
+OTAPI
+uint16_t
+OTCALL
+otGetRloc16(
+ _In_ otInstance *aInstance
+ )
+{
+ uint16_t Result = 0xFFFF;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_RLOC16, &Result);
+ return Result;
+}
+
+OTAPI
+uint8_t
+OTCALL
+otGetRouterIdSequence(
+ _In_ otInstance *aInstance
+ )
+{
+ uint8_t Result = 0xFF;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_ROUTER_ID_SEQUENCE, &Result);
+ return Result;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otGetRouterInfo(
+ _In_ otInstance *aInstance,
+ uint16_t aRouterId,
+ _Out_ otRouterInfo *aRouterInfo
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(QueryIOCTL(aInstance, IOCTL_OTLWF_OT_ROUTER_INFO, &aRouterId, aRouterInfo));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otGetParentInfo(
+ _In_ otInstance *aInstance,
+ _Out_ otRouterInfo *aParentInfo
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ static_assert(sizeof(otRouterInfo) == 20, "The size of otRouterInfo should be 20 bytes");
+ return DwordToThreadError(QueryIOCTL(aInstance, IOCTL_OTLWF_OT_PARENT_INFO, aParentInfo));
+}
+
+OTAPI
+uint8_t
+OTCALL
+otGetStableNetworkDataVersion(
+ _In_ otInstance *aInstance
+ )
+{
+ uint8_t Result = 0xFF;
+ if (aInstance) (void)QueryIOCTL(aInstance, IOCTL_OTLWF_OT_STABLE_NETWORK_DATA_VERSION, &Result);
+ return Result;
+}
+
+OTAPI
+const otMacCounters*
+OTCALL
+otGetMacCounters(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return nullptr;
+
+ otMacCounters* aCounters = (otMacCounters*)malloc(sizeof(otMacCounters));
+ if (aCounters)
+ {
+ if (ERROR_SUCCESS != QueryIOCTL(aInstance, IOCTL_OTLWF_OT_MAC_COUNTERS, aCounters))
+ {
+ free(aCounters);
+ aCounters = nullptr;
+ }
+ }
+ return aCounters;
+}
+
+OTAPI
+bool
+OTCALL
+otIsIp6AddressEqual(
+ const otIp6Address *a,
+ const otIp6Address *b
+ )
+{
+ return memcmp(a->mFields.m8, b->mFields.m8, sizeof(otIp6Address)) == 0;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otIp6AddressFromString(
+ const char *str,
+ otIp6Address *address
+ )
+{
+ ThreadError error = kThreadError_None;
+ uint8_t *dst = reinterpret_cast(address->mFields.m8);
+ uint8_t *endp = reinterpret_cast(address->mFields.m8 + 15);
+ uint8_t *colonp = NULL;
+ uint16_t val = 0;
+ uint8_t count = 0;
+ bool first = true;
+ char ch;
+ uint8_t d;
+
+ memset(address->mFields.m8, 0, 16);
+
+ dst--;
+
+ for (;;)
+ {
+ ch = *str++;
+ d = ch & 0xf;
+
+ if (('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F'))
+ {
+ d += 9;
+ }
+ else if (ch == ':' || ch == '\0' || ch == ' ')
+ {
+ if (count)
+ {
+ if (dst + 2 > endp)
+ {
+ error = kThreadError_Parse;
+ goto exit;
+ }
+ *(dst + 1) = static_cast(val >> 8);
+ *(dst + 2) = static_cast(val);
+ dst += 2;
+ count = 0;
+ val = 0;
+ }
+ else if (ch == ':')
+ {
+ if (!(colonp == nullptr || first))
+ {
+ error = kThreadError_Parse;
+ goto exit;
+ }
+ colonp = dst;
+ }
+
+ if (ch == '\0' || ch == ' ')
+ {
+ break;
+ }
+
+ continue;
+ }
+ else
+ {
+ if (!('0' <= ch && ch <= '9'))
+ {
+ error = kThreadError_Parse;
+ goto exit;
+ }
+ }
+
+ first = false;
+ val = static_cast((val << 4) | d);
+ if (!(++count <= 4))
+ {
+ error = kThreadError_Parse;
+ goto exit;
+ }
+ }
+
+ while (colonp && dst > colonp)
+ {
+ *endp-- = *dst--;
+ }
+
+ while (endp > dst)
+ {
+ *endp-- = 0;
+ }
+
+exit:
+ return error;
+}
+
+OTAPI
+uint8_t
+OTCALL
+otIp6PrefixMatch(
+ const otIp6Address *aFirst,
+ const otIp6Address *aSecond
+ )
+{
+ uint8_t rval = 0;
+ uint8_t diff;
+
+ for (uint8_t i = 0; i < sizeof(otIp6Address); i++)
+ {
+ diff = aFirst->mFields.m8[i] ^ aSecond->mFields.m8[i];
+
+ if (diff == 0)
+ {
+ rval += 8;
+ }
+ else
+ {
+ while ((diff & 0x80) == 0)
+ {
+ rval++;
+ diff <<= 1;
+ }
+
+ break;
+ }
+ }
+
+ return rval;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSendDiagnosticGet(
+ _In_ otInstance *aInstance,
+ const otIp6Address *aDestination,
+ const uint8_t aTlvTypes[],
+ uint8_t aCount
+ )
+{
+ if (aInstance == nullptr || aDestination == nullptr) return kThreadError_InvalidArgs;
+ if (aTlvTypes == nullptr && aCount != 0) return kThreadError_InvalidArgs;
+
+ DWORD BufferSize = sizeof(GUID) + sizeof(otIp6Address) + sizeof(uint8_t) + aCount;
+ PBYTE Buffer = (PBYTE)malloc(BufferSize);
+ if (Buffer == nullptr) return kThreadError_NoBufs;
+
+ memcpy_s(Buffer, BufferSize, &aInstance->InterfaceGuid, sizeof(GUID));
+ memcpy_s(Buffer + sizeof(GUID), BufferSize - sizeof(GUID), aDestination, sizeof(otIp6Address));
+ memcpy_s(Buffer + sizeof(GUID) + sizeof(otIp6Address), BufferSize - sizeof(GUID) - sizeof(otIp6Address), &aCount, sizeof(aCount));
+ memcpy_s(Buffer + sizeof(GUID) + sizeof(otIp6Address) + sizeof(uint8_t), BufferSize - sizeof(GUID) - sizeof(otIp6Address) - sizeof(uint8_t), aTlvTypes, aCount);
+
+ ThreadError result =
+ DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_SEND_DIAGNOSTIC_GET, Buffer, BufferSize, nullptr, 0));
+
+ free(Buffer);
+ return result;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSendDiagnosticReset(
+ _In_ otInstance *aInstance,
+ const otIp6Address *aDestination,
+ const uint8_t aTlvTypes[],
+ uint8_t aCount
+ )
+{
+ if (aInstance == nullptr || aDestination == nullptr) return kThreadError_InvalidArgs;
+ if (aTlvTypes == nullptr && aCount != 0) return kThreadError_InvalidArgs;
+
+ DWORD BufferSize = sizeof(GUID) + sizeof(otIp6Address) + sizeof(uint8_t) + aCount;
+ PBYTE Buffer = (PBYTE)malloc(BufferSize);
+ if (Buffer == nullptr) return kThreadError_NoBufs;
+
+ memcpy_s(Buffer, BufferSize, &aInstance->InterfaceGuid, sizeof(GUID));
+ memcpy_s(Buffer + sizeof(GUID), BufferSize - sizeof(GUID), aDestination, sizeof(otIp6Address));
+ memcpy_s(Buffer + sizeof(GUID) + sizeof(otIp6Address), BufferSize - sizeof(GUID) - sizeof(otIp6Address), &aCount, sizeof(aCount));
+ memcpy_s(Buffer + sizeof(GUID) + sizeof(otIp6Address) + sizeof(uint8_t), BufferSize - sizeof(GUID) - sizeof(otIp6Address) - sizeof(uint8_t), aTlvTypes, aCount);
+
+ ThreadError result =
+ DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_SEND_DIAGNOSTIC_RESET, Buffer, BufferSize, nullptr, 0));
+
+ free(Buffer);
+ return result;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otCommissionerStart(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_COMMISIONER_START));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otCommissionerAddJoiner(
+ _In_ otInstance *aInstance,
+ const otExtAddress *aExtAddress,
+ const char *aPSKd
+ )
+{
+ if (aInstance == nullptr || aPSKd == nullptr) return kThreadError_InvalidArgs;
+
+ size_t aPSKdLength = strnlen(aPSKd, OPENTHREAD_PSK_MAX_LENGTH + 1);
+ if (aPSKdLength > OPENTHREAD_PSK_MAX_LENGTH)
+ {
+ return kThreadError_InvalidArgs;
+ }
+
+ uint8_t aExtAddressValid = aExtAddress ? 1 : 0;
+
+ const ULONG BufferLength = sizeof(GUID) + sizeof(uint8_t) + sizeof(otExtAddress) + (ULONG)aPSKdLength + 1;
+ BYTE Buffer[sizeof(GUID) + sizeof(uint8_t) + sizeof(otExtAddress) + OPENTHREAD_PSK_MAX_LENGTH + 1] = {0};
+ memcpy_s(Buffer, sizeof(Buffer), &aInstance->InterfaceGuid, sizeof(GUID));
+ memcpy_s(Buffer + sizeof(GUID), sizeof(Buffer) - sizeof(GUID), &aExtAddressValid, sizeof(aExtAddressValid));
+ if (aExtAddressValid)
+ memcpy_s(Buffer + sizeof(GUID) + sizeof(uint8_t), sizeof(Buffer) - sizeof(GUID) - sizeof(uint8_t), aExtAddress, sizeof(otExtAddress));
+ memcpy_s(Buffer + sizeof(GUID) + sizeof(uint8_t) + sizeof(otExtAddress), sizeof(Buffer) - sizeof(GUID) - sizeof(uint8_t) - sizeof(otExtAddress), aPSKd, aPSKdLength);
+
+ return DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_COMMISIONER_ADD_JOINER, Buffer, BufferLength, nullptr, 0));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otCommissionerRemoveJoiner(
+ _In_ otInstance *aInstance,
+ const otExtAddress *aExtAddress
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+
+ uint8_t aExtAddressValid = aExtAddress ? 1 : 0;
+
+ BYTE Buffer[sizeof(GUID) + sizeof(uint8_t) + sizeof(otExtAddress)] = {0};
+ memcpy_s(Buffer, sizeof(Buffer), &aInstance->InterfaceGuid, sizeof(GUID));
+ memcpy_s(Buffer + sizeof(GUID), sizeof(Buffer) - sizeof(GUID), &aExtAddressValid, sizeof(aExtAddressValid));
+ if (aExtAddressValid)
+ memcpy_s(Buffer + sizeof(GUID) + sizeof(uint8_t), sizeof(Buffer) - sizeof(GUID) - sizeof(uint8_t), aExtAddress, sizeof(otExtAddress));
+
+ return DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_COMMISIONER_REMOVE_JOINER, Buffer, sizeof(Buffer), nullptr, 0));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otCommissionerSetProvisioningUrl(
+ _In_ otInstance *aInstance,
+ const char *aProvisioningUrl
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+
+ size_t aProvisioningUrlLength = aProvisioningUrl ? strnlen(aProvisioningUrl, OPENTHREAD_PROV_URL_MAX_LENGTH + 1) : 0;
+ if (aProvisioningUrlLength > OPENTHREAD_PROV_URL_MAX_LENGTH)
+ {
+ return kThreadError_InvalidArgs;
+ }
+
+ const ULONG BufferLength = sizeof(GUID) + (ULONG)aProvisioningUrlLength + 1;
+ BYTE Buffer[sizeof(GUID) + OPENTHREAD_PROV_URL_MAX_LENGTH + 1] = {0};
+ memcpy_s(Buffer, sizeof(Buffer), &aInstance->InterfaceGuid, sizeof(GUID));
+ if (aProvisioningUrlLength > 0)
+ memcpy_s(Buffer + sizeof(GUID), sizeof(Buffer) - sizeof(GUID), aProvisioningUrl, aProvisioningUrlLength);
+
+ return DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_COMMISIONER_PROVISIONING_URL, Buffer, BufferLength, nullptr, 0));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otCommissionerAnnounceBegin(
+ otInstance *aInstance,
+ uint32_t aChannelMask,
+ uint8_t aCount,
+ uint16_t aPeriod,
+ const otIp6Address *aAddress
+ )
+{
+ if (aInstance == nullptr || aAddress == nullptr) return kThreadError_InvalidArgs;
+
+ PackedBuffer5 Buffer(aInstance->InterfaceGuid, aChannelMask, aCount, aPeriod, *aAddress);
+ return DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_COMMISIONER_ANNOUNCE_BEGIN, &Buffer, sizeof(Buffer), nullptr, 0));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otCommissionerStop(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_COMMISIONER_STOP));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otCommissionerEnergyScan(
+ _In_ otInstance *aInstance,
+ uint32_t aChannelMask,
+ uint8_t aCount,
+ uint16_t aPeriod,
+ uint16_t aScanDuration,
+ const otIp6Address *aAddress,
+ _In_ otCommissionerEnergyReportCallback aCallback,
+ _In_ void *aContext
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+
+ aInstance->ApiHandle->SetCallback(
+ aInstance->ApiHandle->CommissionerEnergyReportCallbacks,
+ aInstance->InterfaceGuid, aCallback, aContext
+ );
+
+ PackedBuffer6 Buffer(aInstance->InterfaceGuid, aChannelMask, aCount, aPeriod, aScanDuration, *aAddress);
+ return DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_COMMISSIONER_ENERGY_SCAN, &Buffer, sizeof(Buffer), nullptr, 0));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otCommissionerPanIdQuery(
+ _In_ otInstance *aInstance,
+ uint16_t aPanId,
+ uint32_t aChannelMask,
+ const otIp6Address *aAddress,
+ _In_ otCommissionerPanIdConflictCallback aCallback,
+ _In_ void *aContext
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+
+ aInstance->ApiHandle->SetCallback(
+ aInstance->ApiHandle->CommissionerPanIdConflictCallbacks,
+ aInstance->InterfaceGuid, aCallback, aContext
+ );
+
+ PackedBuffer4 Buffer(aInstance->InterfaceGuid, aPanId, aChannelMask, *aAddress);
+ return DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_COMMISSIONER_PANID_QUERY, &Buffer, sizeof(Buffer), nullptr, 0));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSendMgmtCommissionerGet(
+ _In_ otInstance *aInstance,
+ const uint8_t *aTlvs,
+ uint8_t aLength
+)
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ if (aTlvs == nullptr && aLength != 0) return kThreadError_InvalidArgs;
+
+ DWORD BufferSize = sizeof(GUID) + sizeof(uint8_t) + aLength;
+ PBYTE Buffer = (PBYTE)malloc(BufferSize);
+ if (Buffer == nullptr) return kThreadError_NoBufs;
+
+ memcpy_s(Buffer, BufferSize, &aInstance->InterfaceGuid, sizeof(GUID));
+ memcpy_s(Buffer + sizeof(GUID), BufferSize - sizeof(GUID), &aLength, sizeof(aLength));
+ if (aLength > 0)
+ memcpy_s(Buffer + sizeof(GUID) + sizeof(uint8_t), BufferSize - sizeof(GUID) - sizeof(uint8_t), aTlvs, aLength);
+
+ ThreadError result =
+ DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_SEND_MGMT_COMMISSIONER_GET, Buffer, BufferSize, nullptr, 0));
+
+ free(Buffer);
+ return result;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otSendMgmtCommissionerSet(
+ _In_ otInstance *aInstance,
+ const otCommissioningDataset *aDataset,
+ const uint8_t *aTlvs,
+ uint8_t aLength
+ )
+{
+ if (aInstance == nullptr || aDataset == nullptr) return kThreadError_InvalidArgs;
+ if (aTlvs == nullptr && aLength != 0) return kThreadError_InvalidArgs;
+
+ DWORD BufferSize = sizeof(GUID) + sizeof(otCommissioningDataset) + sizeof(uint8_t) + aLength;
+ PBYTE Buffer = (PBYTE)malloc(BufferSize);
+ if (Buffer == nullptr) return kThreadError_NoBufs;
+
+ memcpy_s(Buffer, BufferSize, &aInstance->InterfaceGuid, sizeof(GUID));
+ memcpy_s(Buffer + sizeof(GUID), BufferSize - sizeof(GUID), aDataset, sizeof(otCommissioningDataset));
+ memcpy_s(Buffer + sizeof(GUID) + sizeof(otCommissioningDataset), BufferSize - sizeof(GUID) - sizeof(otCommissioningDataset), &aLength, sizeof(aLength));
+ if (aLength > 0)
+ memcpy_s(Buffer + sizeof(GUID) + sizeof(otCommissioningDataset) + sizeof(uint8_t), BufferSize - sizeof(GUID) - sizeof(otCommissioningDataset) - sizeof(uint8_t), aTlvs, aLength);
+
+ ThreadError result =
+ DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_SEND_MGMT_COMMISSIONER_SET, Buffer, BufferSize, nullptr, 0));
+
+ free(Buffer);
+ return result;
+}
+
+OTAPI
+ThreadError
+OTCALL
+otJoinerStart(
+ _In_ otInstance *aInstance,
+ const char *aPSKd,
+ const char *aProvisioningUrl
+ )
+{
+ if (aInstance == nullptr || aPSKd == nullptr) return kThreadError_InvalidArgs;
+
+ otCommissionConfig config = {0};
+
+ size_t aPSKdLength = strlen(aPSKd);
+ size_t aProvisioningUrlLength = aProvisioningUrl == nullptr ? 0 : strlen(aProvisioningUrl);
+
+ if (aPSKdLength > OPENTHREAD_PSK_MAX_LENGTH ||
+ aProvisioningUrlLength > OPENTHREAD_PROV_URL_MAX_LENGTH)
+ {
+ return kThreadError_InvalidArgs;
+ }
+
+ memcpy_s(config.PSKd, sizeof(config.PSKd), aPSKd, aPSKdLength);
+ memcpy_s(config.ProvisioningUrl, sizeof(config.ProvisioningUrl), aProvisioningUrl, aProvisioningUrlLength);
+
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_JOINER_START, (const otCommissionConfig*)&config));
+}
+
+OTAPI
+ThreadError
+OTCALL
+otJoinerStop(
+ _In_ otInstance *aInstance
+ )
+{
+ if (aInstance == nullptr) return kThreadError_InvalidArgs;
+ return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_JOINER_STOP));
+}
diff --git a/examples/drivers/windows/otApi/precomp.h b/examples/drivers/windows/otApi/precomp.h
new file mode 100644
index 000000000..0e2419b63
--- /dev/null
+++ b/examples/drivers/windows/otApi/precomp.h
@@ -0,0 +1,31 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#pragma warning(disable:28301) // No annotations for first declaration of *
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// Define to export necessary functions
+#define OTDLL
+#define OTAPI EXTERN_C __declspec(dllexport)
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
diff --git a/examples/drivers/windows/otLwf/device.c b/examples/drivers/windows/otLwf/device.c
index 83f5f15d0..6bd72870f 100644
--- a/examples/drivers/windows/otLwf/device.c
+++ b/examples/drivers/windows/otLwf/device.c
@@ -175,6 +175,7 @@ otLwfDeviceClientCleanup(
}
// Free all pending notifications
+ NT_ASSERT(DeviceClient->NotificationSize <= OTLWF_MAX_PENDING_NOTIFICATIONS_PER_CLIENT);
for (UCHAR i = 0; i < DeviceClient->NotificationSize; i++)
{
UCHAR index = (DeviceClient->NotificationOffset + i) % OTLWF_MAX_PENDING_NOTIFICATIONS_PER_CLIENT;
@@ -515,6 +516,7 @@ otLwfIndicateNotification(
// If there are other pending notifications or we don't have a pending IRP saved
// then just go ahead and add the notification to the list
+ NT_ASSERT(DeviceClient->NotificationSize <= OTLWF_MAX_PENDING_NOTIFICATIONS_PER_CLIENT);
if (DeviceClient->NotificationSize != 0 ||
DeviceClient->PendingNotificationIRP == NULL
)
@@ -530,11 +532,15 @@ otLwfIndicateNotification(
{
LogWarning(DRIVER_IOCTL, "Dropping old notification!");
otLwfReleaseNotification(DeviceClient->PendingNotifications[DeviceClient->NotificationOffset]);
+ DeviceClient->NotificationOffset++;
+ }
+ else
+ {
+ DeviceClient->NotificationSize++;
}
// Copy the notification to the next space
DeviceClient->PendingNotifications[Index] = NotifEntry;
- DeviceClient->NotificationSize++;
}
else
{
diff --git a/examples/drivers/windows/otLwf/filter.c b/examples/drivers/windows/otLwf/filter.c
index 74f8a2e5b..4fb65702f 100644
--- a/examples/drivers/windows/otLwf/filter.c
+++ b/examples/drivers/windows/otLwf/filter.c
@@ -523,8 +523,11 @@ Return Value:
--*/
{
- NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
- PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
+ NTSTATUS NtStatus = STATUS_SUCCESS;
+ NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
+ PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
+ NL_INTERFACE_KEY key = {0};
+ NL_INTERFACE_RW interfaceRw;
PNDIS_RESTART_GENERAL_ATTRIBUTES NdisGeneralAttributes;
PNDIS_RESTART_ATTRIBUTES NdisRestartAttributes;
@@ -554,6 +557,28 @@ Return Value:
//
NdisGeneralAttributes->LookaheadSize = 128;
}
+
+ key.Luid = pFilter->InterfaceLuid;
+ NlInitializeInterfaceRw(&interfaceRw);
+ interfaceRw.DadTransmits = 0;
+ interfaceRw.SendUnsolicitedNeighborAdvertisementOnDad = FALSE;
+
+ NtStatus =
+ NsiSetAllParameters(
+ NsiActive,
+ NsiSetDefault,
+ &NPI_MS_IPV6_MODULEID,
+ NlInterfaceObject,
+ &key,
+ sizeof(key),
+ &interfaceRw,
+ sizeof(interfaceRw));
+ if (!NT_SUCCESS(NtStatus))
+ {
+ LogError(DRIVER_DEFAULT, "NsiSetAllParameters (NlInterfaceObject) failed, %!STATUS!", NtStatus);
+ NdisStatus = NDIS_STATUS_FAILURE;
+ goto exit;
+ }
//
// Enable the data path
@@ -567,6 +592,8 @@ Return Value:
otLwfNotifyDeviceAvailabilityChange(pFilter, TRUE);
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! arrival, Filter=%p", &pFilter->InterfaceGuid, pFilter);
+exit:
+
//
// Ensure the state is Paused if restart failed.
//
diff --git a/examples/drivers/windows/otLwf/nsihelper.h b/examples/drivers/windows/otLwf/nsihelper.h
index 5c6dc30ea..c3831995e 100644
--- a/examples/drivers/windows/otLwf/nsihelper.h
+++ b/examples/drivers/windows/otLwf/nsihelper.h
@@ -47,6 +47,17 @@ typedef enum _NSI_STORE {
NsiBootFirmwareTable
} NSI_STORE;
+typedef enum _NSI_SET_ACTION {
+ NsiSetDefault,
+ NsiSetCreateOnly,
+ NsiSetCreateOrSet,
+ NsiSetDelete,
+ NsiSetReset,
+ NsiSetClear,
+ NsiSetCreateOrSetWithReference,
+ NsiSetDeleteWithReference,
+} NSI_SET_ACTION;
+
typedef enum _NSI_STRUCT_TYPE {
NsiStructRw,
NsiStructRoDynamic,
@@ -54,6 +65,160 @@ typedef enum _NSI_STRUCT_TYPE {
NsiMaximumStructType
} NSI_STRUCT_TYPE;
+typedef struct _NL_INTERFACE_KEY {
+ IF_LUID Luid;
+} NL_INTERFACE_KEY, *PNL_INTERFACE_KEY;
+
+typedef enum _NL_TYPE_OF_INTERFACE {
+ InterfaceAllowAll = 0,
+ InterfaceDisallowUnicast,
+ InterfaceDisallowMulticast,
+ InterfaceDisallowAll,
+ InterfaceUnchanged = -1
+} NL_TYPE_OF_INTERFACE;
+
+typedef enum _NL_DOMAIN_NETWORK_LOCATION {
+ DomainNetworkLocationRemote = 0, // connect to a domain network remotely via DA i.e. outside corp network.
+ DomainNetworkCategoryLink = 1, // connect to a domain network directly i.e. inside corp network.
+ DomainNetworkUnchanged = -1
+} NL_DOMAIN_NETWORK_LOCATION;
+
+typedef enum _NL_DOMAIN_TYPE {
+ DomainTypeNonDomainNetwork = 0, // connected to non-domain network.
+ DomainTypeDomainNetwork = 1, // connected to a network that has active directory.
+ DomainTypeDomainAuthenticated = 2, // connected to AD network and machine is authenticated against it.
+ DomainTypeUnchanged = -1
+} NL_DOMAIN_TYPE;
+
+typedef enum _NL_INTERFACE_ECN_CAPABILITY {
+ NlInterfaceEcnUnchanged = -1,
+ NlInterfaceEcnDisabled = 0,
+ NlInterfaceEcnUseEct1 = 1,
+ NlInterfaceEcnUseEct0 = 2,
+ NlInterfaceEcnAppDecide = 3
+} NL_INTERFACE_ECN_CAPABILITY, *PNL_INTERFACE_ECN_CAPABILITY;
+
+typedef enum _NL_INTERNET_CONNECTIVITY_STATUS {
+ NlNoInternetConnectivity,
+ NlNoInternetDnsResolutionSucceeded,
+ NlInternetConnectivityDetected,
+ NlInternetConnectivityUnknown = -1
+} NL_INTERNET_CONNECTIVITY_STATUS, *PNL_INTERNET_CONNECTIVITY_STATUS;
+
+typedef union _IP_ADDRESS_STORAGE {
+ IN_ADDR Ipv4;
+ IN6_ADDR Ipv6;
+ UCHAR Buffer[sizeof(IN6_ADDR)];
+} IP_ADDRESS_STORAGE, *PIP_ADDRESS_STORAGE;
+
+typedef struct _NL_INTERFACE_RW {
+ BOOLEAN AdvertisingEnabled;
+ BOOLEAN ForwardingEnabled;
+ BOOLEAN MulticastForwardingEnabled;
+ BOOLEAN WeakHostSend;
+ BOOLEAN WeakHostReceive;
+ BOOLEAN UseNeighborUnreachabilityDetection;
+ BOOLEAN UseAutomaticMetric;
+ BOOLEAN UseZeroBroadcastAddress;
+ BOOLEAN UseBroadcastForRouterDiscovery;
+ BOOLEAN DhcpRouterDiscoveryEnabled;
+ BOOLEAN ManagedAddressConfigurationSupported;
+ BOOLEAN OtherStatefulConfigurationSupported;
+ BOOLEAN AdvertiseDefaultRoute;
+ NL_NETWORK_CATEGORY NetworkCategory;
+ NL_ROUTER_DISCOVERY_BEHAVIOR RouterDiscoveryBehavior;
+ NL_TYPE_OF_INTERFACE TypeOfInterface;
+ ULONG Metric;
+ ULONG BaseReachableTime; // Base for random ReachableTime (in ms).
+ ULONG RetransmitTime; // Neighbor Solicitation timeout (in ms).
+ ULONG PathMtuDiscoveryTimeout; // Path MTU discovery timeout (in ms).
+ ULONG DadTransmits; // DupAddrDetectTransmits in RFC 2462.
+ NL_LINK_LOCAL_ADDRESS_BEHAVIOR LinkLocalAddressBehavior;
+ ULONG LinkLocalAddressTimeout; // In ms.
+ ULONG ZoneIndices[ScopeLevelCount]; // Zone part of a SCOPE_ID.
+ ULONG NlMtu;
+ ULONG SitePrefixLength;
+ ULONG MulticastForwardingHopLimit;
+ ULONG CurrentHopLimit;
+ IP_ADDRESS_STORAGE LinkLocalAddress;
+ BOOLEAN DisableDefaultRoutes;
+ ULONG AdvertisedRouterLifetime;
+ BOOLEAN SendUnsolicitedNeighborAdvertisementOnDad;
+ BOOLEAN LimitedLinkConnectivity;
+ BOOLEAN ForceARPNDPattern;
+ BOOLEAN EnableDirectMACPattern;
+ BOOLEAN EnableWol;
+ BOOLEAN ForceTunneling;
+ NL_DOMAIN_NETWORK_LOCATION DomainNetworkLocation;
+ ULONGLONG RandomizedEpoch;
+ NL_INTERFACE_ECN_CAPABILITY EcnCapability;
+ NL_DOMAIN_TYPE DomainType;
+ GUID NetworkSignature;
+ NL_INTERNET_CONNECTIVITY_STATUS InternetConnectivityDetected;
+ BOOLEAN ProxyDetected;
+ ULONG DadRetransmitTime;
+ BOOLEAN PrefixSharing;
+ BOOLEAN DisableUnconstrainedRouteLookup;
+ ULONG NetworkContext;
+ BOOLEAN ResetAutoconfigurationOnOperStatusDown;
+ BOOLEAN ClampMssEnabled;
+
+} NL_INTERFACE_RW, *PNL_INTERFACE_RW;
+
+__inline
+VOID
+NlInitializeInterfaceRw(
+ IN OUT PNL_INTERFACE_RW Rw
+ )
+{
+ //
+ // Initialize all fields to values that indicate "no change".
+ //
+ memset(Rw, 0xff, sizeof(*Rw));
+ Rw->BaseReachableTime = 0;
+ Rw->RetransmitTime = 0;
+ Rw->PathMtuDiscoveryTimeout = 0;
+ Rw->NlMtu = 0;
+ Rw->DadRetransmitTime = 0;
+}
+
+typedef enum {
+ NlBestRouteObject,
+ NlCompartmentForwardingObject,
+ NlCompartmentObject,
+ NlControlProtocolObject,
+ NlEchoRequestObject,
+ NlEchoSequenceRequestObject,
+ NlGlobalObject,
+ NlInterfaceObject,
+ NlLocalAnycastAddressObject,
+ NlLocalMulticastAddressObject,
+ NlLocalUnicastAddressObject,
+ NlNeighborObject,
+ NlPathObject,
+ NlPotentialRouterObject,
+ NlPrefixPolicyObject,
+ NlProxyNeighborObject,
+ NlRouteObject,
+ NlSitePrefixObject,
+ NlSubInterfaceObject,
+ NlWakeUpPatternObject,
+ NlResolveNeighborObject,
+ NlSortAddressesObject,
+ NlMfeObject,
+ NlMfeNotifyObject,
+ NlInterfaceHopObject,
+ NlInterfaceUnprivilegedObject,
+ NlTunnelPhysicalInterfaceObject,
+ NlLocalityObject,
+ NlLocalityDataObject,
+ NlLocalityPrivateObject,
+ NlLocalBottleneckObject,
+ NlTimerObject,
+ NlDisconnectInterface,
+ NlMaximumObject
+} NL_OBJECT_TYPE, *PNL_OBJECT_TYPE;
+
NSISTATUS
NsiGetParameter(
__in NSI_STORE Store,
@@ -67,6 +232,18 @@ NsiGetParameter(
__in ULONG ParameterOffset
);
+NSISTATUS
+NsiSetAllParameters(
+ __in NSI_STORE Store,
+ __in NSI_SET_ACTION Action,
+ __in PNPI_MODULEID ModuleId,
+ __in ULONG ObjectIndex,
+ __in_bcount_opt(KeyStructLength) PVOID KeyStruct,
+ __in ULONG KeyStructLength,
+ __in_bcount_opt(RwParameterStructLength) PVOID RwParameterStruct,
+ __in ULONG RwParameterStructLength
+ );
+
extern CONST NPI_MODULEID NPI_MS_NDIS_MODULEID;
typedef enum _NDIS_NSI_OBJECT_INDEX
diff --git a/examples/drivers/windows/otLwf/precomp.h b/examples/drivers/windows/otLwf/precomp.h
index b2501cc37..be0dec0ff 100644
--- a/examples/drivers/windows/otLwf/precomp.h
+++ b/examples/drivers/windows/otLwf/precomp.h
@@ -61,6 +61,8 @@ RtlCopyBufferToMdl(
#include
#include
+#include
+#include
#include
#include
#include
diff --git a/examples/platforms/posix/platform.c b/examples/platforms/posix/platform.c
index e83ee60bc..eb181eea5 100644
--- a/examples/platforms/posix/platform.c
+++ b/examples/platforms/posix/platform.c
@@ -42,6 +42,7 @@
#include
#include
+#include
#include
#include
diff --git a/include/Makefile.am b/include/Makefile.am
index 1095e1b48..32d0e531e 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -60,10 +60,14 @@ PRETTY_SUBDIRS = \
include_HEADERS = \
openthread.h \
- openthread-diag.h \
- openthread-crypto.h \
- openthread-types.h \
openthread-coap.h \
+ openthread-crypto.h \
+ openthread-diag.h \
+ openthread-ip6.h \
+ openthread-message.h \
+ openthread-tasklet.h \
+ openthread-types.h \
+ openthread-udp.h \
$(NULL)
install-headers: install-includeHEADERS
diff --git a/include/commissioning/commissioner.h b/include/commissioning/commissioner.h
index a919ad3c9..42f809819 100644
--- a/include/commissioning/commissioner.h
+++ b/include/commissioning/commissioner.h
@@ -35,6 +35,8 @@
#ifndef OPENTHREAD_COMMISSIONER_H_
#define OPENTHREAD_COMMISSIONER_H_
+#include
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -54,7 +56,7 @@ extern "C" {
* @retval kThreadError_None Successfully started the Commissioner role.
*
*/
-ThreadError otCommissionerStart(otInstance *aInstance);
+OTAPI ThreadError OTCALL otCommissionerStart(otInstance *aInstance);
/**
* This function disables the Thread Commissioner role.
@@ -64,7 +66,7 @@ ThreadError otCommissionerStart(otInstance *aInstance);
* @retval kThreadError_None Successfully started the Commissioner role.
*
*/
-ThreadError otCommissionerStop(otInstance *aInstance);
+OTAPI ThreadError OTCALL otCommissionerStop(otInstance *aInstance);
/**
* This function adds a Joiner entry.
@@ -78,7 +80,8 @@ ThreadError otCommissionerStop(otInstance *aInstance);
* @retval kThreadError_InvalidArgs @p aExtAddress or @p aPSKd is invalid.
*
*/
-ThreadError otCommissionerAddJoiner(otInstance *aInstance, const otExtAddress *aExtAddress, const char *aPSKd);
+OTAPI ThreadError OTCALL otCommissionerAddJoiner(otInstance *aInstance, const otExtAddress *aExtAddress,
+ const char *aPSKd);
/**
* This function removes a Joiner entry.
@@ -91,7 +94,7 @@ ThreadError otCommissionerAddJoiner(otInstance *aInstance, const otExtAddress *a
* @retval kThreadError_InvalidArgs @p aExtAddress is invalid.
*
*/
-ThreadError otCommissionerRemoveJoiner(otInstance *aIntsance, const otExtAddress *aExtAddress);
+OTAPI ThreadError OTCALL otCommissionerRemoveJoiner(otInstance *aIntsance, const otExtAddress *aExtAddress);
/**
* This function sets the Provisioning URL.
@@ -102,7 +105,7 @@ ThreadError otCommissionerRemoveJoiner(otInstance *aIntsance, const otExtAddress
* @retval kThreadError_InvalidArgs @p aProvisioningUrl is invalid.
*
*/
-ThreadError otCommissionerSetProvisioningUrl(otInstance *aInstance, const char *aProvisioningUrl);
+OTAPI ThreadError OTCALL otCommissionerSetProvisioningUrl(otInstance *aInstance, const char *aProvisioningUrl);
/**
* This function sends an Announce Begin message.
@@ -117,8 +120,9 @@ ThreadError otCommissionerSetProvisioningUrl(otInstance *aInstance, const char *
* @retval kThreadError_NoBufs Insufficient buffers to generate an Announce Begin message.
*
*/
-ThreadError otCommissionerAnnounceBegin(otInstance *aInstance, uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod,
- const otIp6Address *aAddress);
+OTAPI ThreadError OTCALL otCommissionerAnnounceBegin(otInstance *aInstance, uint32_t aChannelMask, uint8_t aCount,
+ uint16_t aPeriod,
+ const otIp6Address *aAddress);
/**
* This function pointer is called when the Commissioner receives an Energy Report.
@@ -129,8 +133,8 @@ ThreadError otCommissionerAnnounceBegin(otInstance *aInstance, uint32_t aChannel
* @param[in] aContext A pointer to application-specific context.
*
*/
-typedef void (*otCommissionerEnergyReportCallback)(uint32_t aChannelMask, const uint8_t *aEnergyList,
- uint8_t aEnergyListLength, void *aContext);
+typedef void (OTCALL *otCommissionerEnergyReportCallback)(uint32_t aChannelMask, const uint8_t *aEnergyList,
+ uint8_t aEnergyListLength, void *aContext);
/**
* This function sends an Energy Scan Query message.
@@ -148,9 +152,9 @@ typedef void (*otCommissionerEnergyReportCallback)(uint32_t aChannelMask, const
* @retval kThreadError_NoBufs Insufficient buffers to generate an Energy Scan Query message.
*
*/
-ThreadError otCommissionerEnergyScan(otInstance *aInstance, uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod,
- uint16_t aScanDuration, const otIp6Address *aAddress,
- otCommissionerEnergyReportCallback aCallback, void *aContext);
+OTAPI ThreadError OTCALL otCommissionerEnergyScan(otInstance *aInstance, uint32_t aChannelMask, uint8_t aCount,
+ uint16_t aPeriod, uint16_t aScanDuration, const otIp6Address *aAddress,
+ otCommissionerEnergyReportCallback aCallback, void *aContext);
/**
* This function pointer is called when the Commissioner receives a PAN ID Conflict message.
@@ -160,7 +164,7 @@ ThreadError otCommissionerEnergyScan(otInstance *aInstance, uint32_t aChannelMas
* @param[in] aContext A pointer to application-specific context.
*
*/
-typedef void (*otCommissionerPanIdConflictCallback)(uint16_t aPanId, uint32_t aChannelMask, void *aContext);
+typedef void (OTCALL *otCommissionerPanIdConflictCallback)(uint16_t aPanId, uint32_t aChannelMask, void *aContext);
/**
* This function sends a PAN ID Query message.
@@ -176,9 +180,9 @@ typedef void (*otCommissionerPanIdConflictCallback)(uint16_t aPanId, uint32_t aC
* @retval kThreadError_NoBufs Insufficient buffers to generate a PAN ID Query message.
*
*/
-ThreadError otCommissionerPanIdQuery(otInstance *aInstance, uint16_t aPanId, uint32_t aChannelMask,
- const otIp6Address *aAddress,
- otCommissionerPanIdConflictCallback aCallback, void *aContext);
+OTAPI ThreadError OTCALL otCommissionerPanIdQuery(otInstance *aInstance, uint16_t aPanId, uint32_t aChannelMask,
+ const otIp6Address *aAddress,
+ otCommissionerPanIdConflictCallback aCallback, void *aContext);
/**
* This function sends MGMT_COMMISSIONER_GET.
@@ -191,7 +195,7 @@ ThreadError otCommissionerPanIdQuery(otInstance *aInstance, uint16_t aPanId, uin
* @retval kThreadError_NoBufs Insufficient buffer space to send.
*
*/
-ThreadError otSendMgmtCommissionerGet(otInstance *, const uint8_t *aTlvs, uint8_t aLength);
+OTAPI ThreadError OTCALL otSendMgmtCommissionerGet(otInstance *, const uint8_t *aTlvs, uint8_t aLength);
/**
* This function sends MGMT_COMMISSIONER_SET.
@@ -205,8 +209,8 @@ ThreadError otSendMgmtCommissionerGet(otInstance *, const uint8_t *aTlvs, uint8_
* @retval kThreadError_NoBufs Insufficient buffer space to send.
*
*/
-ThreadError otSendMgmtCommissionerSet(otInstance *, const otCommissioningDataset *aDataset,
- const uint8_t *aTlvs, uint8_t aLength);
+OTAPI ThreadError OTCALL otSendMgmtCommissionerSet(otInstance *, const otCommissioningDataset *aDataset,
+ const uint8_t *aTlvs, uint8_t aLength);
/**
* @}
diff --git a/include/commissioning/joiner.h b/include/commissioning/joiner.h
index db46bab8e..011797978 100644
--- a/include/commissioning/joiner.h
+++ b/include/commissioning/joiner.h
@@ -35,6 +35,8 @@
#ifndef OPENTHREAD_JOINER_H_
#define OPENTHREAD_JOINER_H_
+#include
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -57,7 +59,7 @@ extern "C" {
* @retval kThreadError_InvalidArgs @p aPSKd or @p aProvisioningUrl is invalid.
*
*/
-ThreadError otJoinerStart(otInstance *aInstance, const char *aPSKd, const char *aProvisioningUrl);
+OTAPI ThreadError OTCALL otJoinerStart(otInstance *aInstance, const char *aPSKd, const char *aProvisioningUrl);
/**
* This function disables the Thread Joiner role.
@@ -65,7 +67,7 @@ ThreadError otJoinerStart(otInstance *aInstance, const char *aPSKd, const char *
* @param[in] aInstance A pointer to an OpenThread instance.
*
*/
-ThreadError otJoinerStop(otInstance *aInstance);
+OTAPI ThreadError OTCALL otJoinerStop(otInstance *aInstance);
/**
* @}
diff --git a/include/openthread-ip6.h b/include/openthread-ip6.h
new file mode 100644
index 000000000..63904d77a
--- /dev/null
+++ b/include/openthread-ip6.h
@@ -0,0 +1,245 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file
+ * @brief
+ * This file defines the top-level ip6 functions for the OpenThread library.
+ */
+
+#ifndef OPENTHREAD_IP6_H_
+#define OPENTHREAD_IP6_H_
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup api API
+ * @brief
+ * This module includes the application programming interface to the OpenThread stack.
+ *
+ * @{
+ *
+ * @defgroup execution Execution
+ * @defgroup commands Commands
+ * @defgroup config Configuration
+ * @defgroup diags Diagnostics
+ * @defgroup messages Message Buffers
+ * @defgroup ip6 IPv6
+ * @defgroup udp UDP
+ * @defgroup coap CoAP
+ *
+ * @}
+ *
+ */
+
+/**
+ * @addtogroup diags Diagnostics
+ *
+ * @brief
+ * This module includes functions that expose internal state.
+ *
+ * @{
+ *
+ */
+
+/**
+ * This function pointer is called when an IEEE 802.15.4 frame is received.
+ *
+ * @note This callback is called after FCS processing and @p aFrame may not contain the actual FCS that was received.
+ *
+ * @note This callback is called before IEEE 802.15.4 security processing and mSecurityValid in @p aFrame will
+ * always be false.
+ *
+ * @param[in] aFrame A pointer to the received IEEE 802.15.4 frame.
+ * @param[in] aContext A pointer to application-specific context.
+ *
+ */
+typedef void (*otLinkPcapCallback)(const RadioPacket *aFrame, void *aContext);
+
+/**
+ * This function registers a callback to provide received raw IEEE 802.15.4 frames.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aPcapCallback A pointer to a function that is called when receiving an IEEE 802.15.4 link frame or
+ * NULL to disable the callback.
+ * @param[in] aCallbackContext A pointer to application-specific context.
+ *
+ */
+void otSetLinkPcapCallback(otInstance *aInstance, otLinkPcapCallback aPcapCallback, void *aCallbackContext);
+
+/**
+ * This function indicates whether or not promiscuous mode is enabled at the link layer.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
+ * @retval true Promiscuous mode is enabled.
+ * @retval false Promiscuous mode is not enabled.
+ *
+ */
+bool otIsLinkPromiscuous(otInstance *aInstance);
+
+/**
+ * This function enables or disables the link layer promiscuous mode.
+ *
+ * @note Promiscuous mode may only be enabled when the Thread interface is disabled.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aPromiscuous true to enable promiscuous mode, or false otherwise.
+ *
+ * @retval kThreadError_None Successfully enabled promiscuous mode.
+ * @retval kThreadError_InvalidState Could not enable promiscuous mode because
+ * the Thread interface is enabled.
+ *
+ */
+ThreadError otSetLinkPromiscuous(otInstance *aInstance, bool aPromiscuous);
+
+/**
+ * @}
+ *
+ */
+
+/**
+ * @addtogroup ip6 IPv6
+ *
+ * @brief
+ * This module includes functions that control IPv6 communication.
+ *
+ * @{
+ *
+ */
+
+/**
+ * Allocate a new message buffer for sending an IPv6 message.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aLinkSecurityEnabled TRUE if the message should be secured at Layer 2
+ *
+ * @returns A pointer to the message buffer or NULL if no message buffers are available.
+ *
+ * @sa otFreeMessage
+ */
+otMessage otNewIp6Message(otInstance *aInstance, bool aLinkSecurityEnabled);
+
+/**
+ * This function pointer is called when an IPv6 datagram is received.
+ *
+ * @param[in] aMessage A pointer to the message buffer containing the received IPv6 datagram.
+ * @param[in] aContext A pointer to application-specific context.
+ *
+ */
+typedef void (*otReceiveIp6DatagramCallback)(otMessage aMessage, void *aContext);
+
+/**
+ * This function registers a callback to provide received IPv6 datagrams.
+ *
+ * By default, this callback does not pass Thread control traffic. See otSetReceiveIp6DatagramFilterEnabled() to
+ * change the Thread control traffic filter setting.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aCallback A pointer to a function that is called when an IPv6 datagram is received or
+ * NULL to disable the callback.
+ * @param[in] aCallbackContext A pointer to application-specific context.
+ *
+ * @sa otIsReceiveIp6DatagramFilterEnabled
+ * @sa otSetReceiveIp6DatagramFilterEnabled
+ *
+ */
+void otSetReceiveIp6DatagramCallback(otInstance *aInstance, otReceiveIp6DatagramCallback aCallback,
+ void *aCallbackContext);
+
+/**
+ * This function indicates whether or not Thread control traffic is filtered out when delivering IPv6 datagrams
+ * via the callback specified in otSetReceiveIp6DatagramCallback().
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
+ * @returns TRUE if Thread control traffic is filtered out, FALSE otherwise.
+ *
+ * @sa otSetReceiveIp6DatagramCallback
+ * @sa otSetReceiveIp6DatagramFilterEnabled
+ *
+ */
+bool otIsReceiveIp6DatagramFilterEnabled(otInstance *aInstance);
+
+/**
+ * This function sets whether or not Thread control traffic is filtered out when delivering IPv6 datagrams
+ * via the callback specified in otSetReceiveIp6DatagramCallback().
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aEnabled TRUE if Thread control traffic is filtered out, FALSE otherwise.
+ *
+ * @sa otSetReceiveIp6DatagramCallback
+ * @sa otIsReceiveIp6DatagramFilterEnabled
+ *
+ */
+void otSetReceiveIp6DatagramFilterEnabled(otInstance *aInstance, bool aEnabled);
+
+/**
+ * This function sends an IPv6 datagram via the Thread interface.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aMessage A pointer to the message buffer containing the IPv6 datagram.
+ *
+ */
+ThreadError otSendIp6Datagram(otInstance *aInstance, otMessage aMessage);
+
+/**
+ * This function indicates whether or not ICMPv6 Echo processing is enabled.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
+ * @retval TRUE ICMPv6 Echo processing is enabled.
+ * @retval FALSE ICMPv6 Echo processing is disabled.
+ *
+ */
+bool otIsIcmpEchoEnabled(otInstance *aInstance);
+
+/**
+ * This function sets whether or not ICMPv6 Echo processing is enabled.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aEnabled TRUE to enable ICMPv6 Echo processing, FALSE otherwise.
+ *
+ */
+void otSetIcmpEchoEnabled(otInstance *aInstance, bool aEnabled);
+
+/**
+ * @}
+ *
+ */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_IP6_H_
diff --git a/include/openthread-message.h b/include/openthread-message.h
new file mode 100644
index 000000000..382c40241
--- /dev/null
+++ b/include/openthread-message.h
@@ -0,0 +1,241 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file
+ * @brief
+ * This file defines the top-level ip6 functions for the OpenThread library.
+ */
+
+#ifndef OPENTHREAD_MESSAGE_H_
+#define OPENTHREAD_MESSAGE_H_
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup api API
+ * @brief
+ * This module includes the application programming interface to the OpenThread stack.
+ *
+ * @{
+ *
+ * @defgroup execution Execution
+ * @defgroup commands Commands
+ * @defgroup config Configuration
+ * @defgroup diags Diagnostics
+ * @defgroup messages Message Buffers
+ * @defgroup ip6 IPv6
+ * @defgroup udp UDP
+ * @defgroup coap CoAP
+ *
+ * @}
+ *
+ */
+
+/**
+ * @addtogroup messages Message Buffers
+ *
+ * @brief
+ * This module includes functions that manipulate OpenThread message buffers
+ *
+ * @{
+ *
+ */
+
+/**
+ * Free an allocated message buffer.
+ *
+ * @param[in] aMessage A pointer to a message buffer.
+ *
+ * @retval kThreadErrorNone Successfully freed the message buffer.
+ *
+ * @sa otNewUdpMessage
+ * @sa otAppendMessage
+ * @sa otGetMessageLength
+ * @sa otSetMessageLength
+ * @sa otGetMessageOffset
+ * @sa otSetMessageOffset
+ * @sa otReadMessage
+ * @sa otWriteMessage
+ */
+ThreadError otFreeMessage(otMessage aMessage);
+
+/**
+ * Get the message length in bytes.
+ *
+ * @param[in] aMessage A pointer to a message buffer.
+ *
+ * @returns The message length in bytes.
+ *
+ * @sa otNewUdpMessage
+ * @sa otFreeMessage
+ * @sa otAppendMessage
+ * @sa otSetMessageLength
+ * @sa otGetMessageOffset
+ * @sa otSetMessageOffset
+ * @sa otReadMessage
+ * @sa otWriteMessage
+ * @sa otSetMessageLength
+ */
+uint16_t otGetMessageLength(otMessage aMessage);
+
+/**
+ * Set the message length in bytes.
+ *
+ * @param[in] aMessage A pointer to a message buffer.
+ * @param[in] aLength A length in bytes.
+ *
+ * @retval kThreadErrorNone Successfully set the message length.
+ * @retval kThreadErrorNoBufs No available buffers to grow the message.
+ *
+ * @sa otNewUdpMessage
+ * @sa otFreeMessage
+ * @sa otAppendMessage
+ * @sa otGetMessageLength
+ * @sa otGetMessageOffset
+ * @sa otSetMessageOffset
+ * @sa otReadMessage
+ * @sa otWriteMessage
+ */
+ThreadError otSetMessageLength(otMessage aMessage, uint16_t aLength);
+
+/**
+ * Get the message offset in bytes.
+ *
+ * @param[in] aMessage A pointer to a message buffer.
+ *
+ * @returns The message offset value.
+ *
+ * @sa otNewUdpMessage
+ * @sa otFreeMessage
+ * @sa otAppendMessage
+ * @sa otGetMessageLength
+ * @sa otSetMessageLength
+ * @sa otSetMessageOffset
+ * @sa otReadMessage
+ * @sa otWriteMessage
+ */
+uint16_t otGetMessageOffset(otMessage aMessage);
+
+/**
+ * Set the message offset in bytes.
+ *
+ * @param[in] aMessage A pointer to a message buffer.
+ * @param[in] aOffset An offset in bytes.
+ *
+ * @retval kThreadErrorNone Successfully set the message offset.
+ * @retval kThreadErrorInvalidArg The offset is beyond the message length.
+ *
+ * @sa otNewUdpMessage
+ * @sa otFreeMessage
+ * @sa otAppendMessage
+ * @sa otGetMessageLength
+ * @sa otSetMessageLength
+ * @sa otGetMessageOffset
+ * @sa otReadMessage
+ * @sa otWriteMessage
+ */
+ThreadError otSetMessageOffset(otMessage aMessage, uint16_t aOffset);
+
+/**
+ * Append bytes to a message.
+ *
+ * @param[in] aMessage A pointer to a message buffer.
+ * @param[in] aBuf A pointer to the data to append.
+ * @param[in] aLength Number of bytes to append.
+ *
+ * @retval kThreadErrorNone Successfully appended to the message
+ * @retval kThreadErrorNoBufs No available buffers to grow the message.
+ *
+ * @sa otNewUdpMessage
+ * @sa otFreeMessage
+ * @sa otGetMessageLength
+ * @sa otSetMessageLength
+ * @sa otGetMessageOffset
+ * @sa otSetMessageOffset
+ * @sa otReadMessage
+ * @sa otWriteMessage
+ */
+ThreadError otAppendMessage(otMessage aMessage, const void *aBuf, uint16_t aLength);
+
+/**
+ * Read bytes from a message.
+ *
+ * @param[in] aMessage A pointer to a message buffer.
+ * @param[in] aOffset An offset in bytes.
+ * @param[in] aBuf A pointer to a buffer that message bytes are read to.
+ * @param[in] aLength Number of bytes to read.
+ *
+ * @returns The number of bytes read.
+ *
+ * @sa otNewUdpMessage
+ * @sa otFreeMessage
+ * @sa otAppendMessage
+ * @sa otGetMessageLength
+ * @sa otSetMessageLength
+ * @sa otGetMessageOffset
+ * @sa otSetMessageOffset
+ * @sa otWriteMessage
+ */
+int otReadMessage(otMessage aMessage, uint16_t aOffset, void *aBuf, uint16_t aLength);
+
+/**
+ * Write bytes to a message.
+ *
+ * @param[in] aMessage A pointer to a message buffer.
+ * @param[in] aOffset An offset in bytes.
+ * @param[in] aBuf A pointer to a buffer that message bytes are written from.
+ * @param[in] aLength Number of bytes to write.
+ *
+ * @returns The number of bytes written.
+ *
+ * @sa otNewUdpMessage
+ * @sa otFreeMessage
+ * @sa otAppendMessage
+ * @sa otGetMessageLength
+ * @sa otSetMessageLength
+ * @sa otGetMessageOffset
+ * @sa otSetMessageOffset
+ * @sa otReadMessage
+ */
+int otWriteMessage(otMessage aMessage, uint16_t aOffset, const void *aBuf, uint16_t aLength);
+
+/**
+ * @}
+ *
+ */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_MESSAGE_H_
diff --git a/include/openthread-tasklet.h b/include/openthread-tasklet.h
new file mode 100644
index 000000000..eed8ee167
--- /dev/null
+++ b/include/openthread-tasklet.h
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file
+ * @brief
+ * This file includes the platform abstraction for the tasklet service.
+ */
+
+#ifndef OPENTHREAD_TASKLET_H_
+#define OPENTHREAD_TASKLET_H_
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup execution Execution
+ *
+ * @brief
+ * This module includes functions that control the Thread stack's execution.
+ *
+ * @{
+ *
+ */
+
+/**
+ * Run all queued OpenThread tasklets at the time this is called.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ */
+void otProcessQueuedTasklets(otInstance *aInstance);
+
+/**
+ * Indicates whether or not OpenThread has tasklets pending.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
+ * @retval TRUE If there are tasklets pending.
+ * @retval FALSE If there are no tasklets pending.
+ */
+bool otAreTaskletsPending(otInstance *aInstance);
+
+/**
+ * OpenThread calls this function when the tasklet queue transitions from empty to non-empty.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
+ */
+extern void otSignalTaskletPending(otInstance *aInstance);
+
+/**
+ * @}
+ *
+ */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_TASKLET_H_
diff --git a/include/openthread-types.h b/include/openthread-types.h
index 609e42b5d..b810f8386 100644
--- a/include/openthread-types.h
+++ b/include/openthread-types.h
@@ -37,6 +37,9 @@
#include
#include
+#ifdef OTDLL
+#include
+#endif
#include
@@ -61,14 +64,32 @@ extern "C" {
#define myoffsetof(s,m) (((size_t)&(((s*)BASE)->m))-BASE)
#define CONTAINING_RECORD(address, type, field) \
((type *)((uint8_t*)(address) - myoffsetof(type, field)))
-#endif
-#endif
+#endif /* CONTAINING_RECORD */
+#endif /* _WIN32 */
/**
* This type represents the OpenThread instance structure.
*/
typedef struct otInstance otInstance;
+#ifdef OTDLL
+
+/**
+ * This type represents the handle to the OpenThread API.
+ */
+typedef struct otApiInstance otApiInstance;
+
+/**
+ * This type represents a list of device GUIDs.
+ */
+typedef struct otDeviceList
+{
+ uint16_t aDevicesLength;
+ GUID aDevices[1];
+} otDeviceList;
+
+#endif
+
/**
* This enumeration represents error codes used throughout OpenThread.
*/
@@ -489,6 +510,7 @@ typedef enum otMeshcopTlvType
/**
* This structure represents an MLE Link Mode configuration.
*/
+OT_TOOL_ALIGN(4)
typedef struct otLinkModeConfig
{
/**
@@ -709,6 +731,7 @@ typedef struct otMacBlacklistEntry
*/
typedef enum
{
+ kDeviceRoleOffline, ///< The Thread device is offline and unavailable.
kDeviceRoleDisabled, ///< The Thread stack is disabled.
kDeviceRoleDetached, ///< Not currently participating in a Thread network/partition.
kDeviceRoleChild, ///< The Thread Child role.
@@ -764,6 +787,7 @@ typedef struct
* This structure holds diagnostic information for a Thread Router
*
*/
+OT_TOOL_ALIGN(4)
typedef struct
{
otExtAddress mExtAddress; ///< IEEE 802.15.4 Extended Address
diff --git a/include/openthread-udp.h b/include/openthread-udp.h
new file mode 100644
index 000000000..7281a49d5
--- /dev/null
+++ b/include/openthread-udp.h
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file
+ * @brief
+ * This file defines the top-level ip6 functions for the OpenThread library.
+ */
+
+#ifndef OPENTHREAD_UDP_H_
+#define OPENTHREAD_UDP_H_
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup api API
+ * @brief
+ * This module includes the application programming interface to the OpenThread stack.
+ *
+ * @{
+ *
+ * @defgroup execution Execution
+ * @defgroup commands Commands
+ * @defgroup config Configuration
+ * @defgroup diags Diagnostics
+ * @defgroup messages Message Buffers
+ * @defgroup ip6 IPv6
+ * @defgroup udp UDP
+ * @defgroup coap CoAP
+ *
+ * @}
+ *
+ */
+
+/**
+ * @addtogroup udp UDP
+ *
+ * @brief
+ * This module includes functions that control UDP communication.
+ *
+ * @{
+ *
+ */
+
+/**
+ * Allocate a new message buffer for sending a UDP message.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aLinkSecurityEnabled TRUE if the message should be secured at Layer 2.
+ *
+ * @returns A pointer to the message buffer or NULL if no message buffers are available.
+ *
+ * @sa otFreeMessage
+ */
+otMessage otNewUdpMessage(otInstance *aInstance, bool aLinkSecurityEnabled);
+
+/**
+ * Open a UDP/IPv6 socket.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aSocket A pointer to a UDP socket structure.
+ * @param[in] aCallback A pointer to the application callback function.
+ * @param[in] aContext A pointer to application-specific context.
+ *
+ * @retval kThreadErrorNone Successfully opened the socket.
+ * @retval kThreadErrorInvalidArgs Given socket structure was already opened.
+ *
+ * @sa otNewUdpMessage
+ * @sa otCloseUdpSocket
+ * @sa otBindUdpSocket
+ * @sa otSendUdp
+ */
+ThreadError otOpenUdpSocket(otInstance *aInstance, otUdpSocket *aSocket, otUdpReceive aCallback, void *aContext);
+
+/**
+ * Close a UDP/IPv6 socket.
+ *
+ * @param[in] aSocket A pointer to a UDP socket structure.
+ *
+ * @retval kThreadErrorNone Successfully closed the socket.
+ *
+ * @sa otNewUdpMessage
+ * @sa otOpenUdpSocket
+ * @sa otBindUdpSocket
+ * @sa otSendUdp
+ */
+ThreadError otCloseUdpSocket(otUdpSocket *aSocket);
+
+/**
+ * Bind a UDP/IPv6 socket.
+ *
+ * @param[in] aSocket A pointer to a UDP socket structure.
+ * @param[in] aSockName A pointer to an IPv6 socket address structure.
+ *
+ * @retval kThreadErrorNone Bind operation was successful.
+ *
+ * @sa otNewUdpMessage
+ * @sa otOpenUdpSocket
+ * @sa otCloseUdpSocket
+ * @sa otSendUdp
+ */
+ThreadError otBindUdpSocket(otUdpSocket *aSocket, otSockAddr *aSockName);
+
+/**
+ * Send a UDP/IPv6 message.
+ *
+ * @param[in] aSocket A pointer to a UDP socket structure.
+ * @param[in] aMessage A pointer to a message buffer.
+ * @param[in] aMessageInfo A pointer to a message info structure.
+ *
+ * @sa otNewUdpMessage
+ * @sa otOpenUdpSocket
+ * @sa otCloseUdpSocket
+ * @sa otBindUdpSocket
+ * @sa otSendUdp
+ */
+ThreadError otSendUdp(otUdpSocket *aSocket, otMessage aMessage, const otMessageInfo *aMessageInfo);
+
+/**
+ * @}
+ *
+ */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_UDP_H_
diff --git a/include/openthread.h b/include/openthread.h
index c5345b402..35d25388d 100644
--- a/include/openthread.h
+++ b/include/openthread.h
@@ -35,11 +35,7 @@
#ifndef OPENTHREAD_H_
#define OPENTHREAD_H_
-#include
-#include
-
#include
-#include
#ifdef __cplusplus
extern "C" {
@@ -104,46 +100,6 @@ extern "C" {
*
*/
-/**
- * @addtogroup execution Execution
- *
- * @brief
- * This module includes functions that control the Thread stack's execution.
- *
- * @{
- *
- */
-
-/**
- * Run all queued OpenThread tasklets at the time this is called.
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- */
-void otProcessQueuedTasklets(otInstance *aInstance);
-
-/**
- * Indicates whether or not OpenThread has tasklets pending.
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- *
- * @retval TRUE If there are tasklets pending.
- * @retval FALSE If there are no tasklets pending.
- */
-bool otAreTaskletsPending(otInstance *aInstance);
-
-/**
- * OpenThread calls this function when the tasklet queue transitions from empty to non-empty.
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- *
- */
-extern void otSignalTaskletPending(otInstance *aInstance);
-
-/**
- * @}
- *
- */
-
/**
* @addtogroup commands Commands
*
@@ -160,11 +116,116 @@ extern void otSignalTaskletPending(otInstance *aInstance);
* @returns A pointer to the OpenThread version.
*
*/
-const char *otGetVersionString(void);
+OTAPI const char *OTCALL otGetVersionString(void);
+
+#ifdef OTDLL
+
+/**
+ * This function initializes a new instance of the OpenThread library.
+ *
+ * @retval otApiInstance* The new OpenThread context structure.
+ *
+ * @sa otApiFinalize
+ *
+ */
+OTAPI otApiInstance *OTCALL otApiInit();
+
+/**
+ * This function uninitializes the OpenThread library.
+ *
+ * Call this function when OpenThread is no longer in use.
+ *
+ * @param[in] aApiInstance The OpenThread api instance.
+ *
+ */
+OTAPI void OTCALL otApiFinalize(otApiInstance *aApiInstance);
+
+/**
+ * This function frees any memory returned/allocated by the library.
+ *
+ * @param[in] aMem The memory to free.
+ *
+ */
+OTAPI void OTCALL otFreeMemory(const void *aMem);
+
+/**
+ * This function pointer is called to notify addition and removal of OpenThread devices.
+ *
+ * @param[in] aAdded A flag indicating if the device was added or removed.
+ * @param[in] aDeviceGuid A GUID indicating which device state changed.
+ * @param[in] aContext A pointer to application-specific context.
+ *
+ */
+typedef void (OTCALL *otDeviceAvailabilityChangedCallback)(bool aAdded, const GUID *aDeviceGuid, void *aContext);
+
+/**
+ * This function registers a callback to indicate OpenThread devices come and go.
+ *
+ * @param[in] aApiInstance The OpenThread api instance.
+ * @param[in] aCallback A pointer to a function that is called with the state changes.
+ * @param[in] aContextContext A pointer to application-specific context.
+ *
+ */
+OTAPI void OTCALL otSetDeviceAvailabilityChangedCallback(otApiInstance *aApiInstance,
+ otDeviceAvailabilityChangedCallback aCallback, void *aCallbackContext);
+
+/**
+ * This function querys the list of OpenThread device contexts on the system.
+ *
+ * @param[in] aApiInstance The OpenThread api instance.
+ *
+ * @sa otFreeMemory
+ */
+OTAPI otDeviceList *OTCALL otEnumerateDevices(otApiInstance *aApiInstance);
+
+/**
+ * This function initializes an OpenThread context for a device.
+ *
+ * @param[in] aApiInstance The OpenThread api instance.
+ * @param[in] aDeviceGuid The device guid to create an OpenThread context for.
+ *
+ * @retval otInstance* The new OpenThread device instance structure for the device.
+ *
+ * @sa otFreeMemory
+ *
+ */
+OTAPI otInstance *OTCALL otInstanceInit(otApiInstance *aApiInstance, const GUID *aDeviceGuid);
+
+/**
+ * This queries the Windows device/interface GUID for the otContext.
+ *
+ * @param[in] aContext The OpenThread context structure.
+ *
+ * @retval GUID The device GUID.
+ *
+ */
+OTAPI GUID OTCALL otGetDeviceGuid(otInstance *aInstance);
+
+/**
+ * This queries the Windows device/interface IfIndex for the otContext.
+ *
+ * @param[in] aContext The OpenThread context structure.
+ *
+ * @retval uint32_t The device IfIndex.
+ *
+ */
+OTAPI uint32_t OTCALL otGetDeviceIfIndex(otInstance *aInstance);
+
+/**
+ * This queries the Windows Compartment ID for the otContext.
+ *
+ * @param[in] aContext The OpenThread context structure.
+ *
+ * @retval uint32_t The compartment ID.
+ *
+ */
+OTAPI uint32_t OTCALL otGetCompartmentId(otInstance *aInstance);
+
+#else
#ifdef OPENTHREAD_MULTIPLE_INSTANCE
/**
- * This function initializes a new instance of the OpenThread library.
+ * This function initializes the OpenThread library.
*
* This function initializes OpenThread and prepares it for subsequent OpenThread API calls. This function must be
* called before any other calls to OpenThread. By default, OpenThread is initialized in the 'enabled' state.
@@ -175,6 +236,8 @@ const char *otGetVersionString(void);
*
* @retval otInstance* The new OpenThread instance structure.
*
+ * @sa otContextFinalize
+ *
*/
otInstance *otInstanceInit(void *aInstanceBuffer, size_t *aInstanceBufferSize);
#else
@@ -200,6 +263,8 @@ otInstance *otInstanceInit(void);
*/
void otInstanceFinalize(otInstance *aInstance);
+#endif
+
/**
* This function brings up the IPv6 interface.
*
@@ -211,7 +276,7 @@ void otInstanceFinalize(otInstance *aInstance);
* or the interface was already enabled.
*
*/
-ThreadError otInterfaceUp(otInstance *aInstance);
+OTAPI ThreadError OTCALL otInterfaceUp(otInstance *aInstance);
/**
* This function brings down the IPv6 interface.
@@ -224,7 +289,7 @@ ThreadError otInterfaceUp(otInstance *aInstance);
* or the interface was already down.
*
*/
-ThreadError otInterfaceDown(otInstance *aInstance);
+OTAPI ThreadError OTCALL otInterfaceDown(otInstance *aInstance);
/**
* This function indicates whether or not the IPv6 interface is up.
@@ -235,7 +300,7 @@ ThreadError otInterfaceDown(otInstance *aInstance);
* @retval FALSE The IPv6 interface is down.
*
*/
-bool otIsInterfaceUp(otInstance *aInstance);
+OTAPI bool OTCALL otIsInterfaceUp(otInstance *aInstance);
/**
* This function starts Thread protocol operation.
@@ -248,7 +313,7 @@ bool otIsInterfaceUp(otInstance *aInstance);
* @retval kThreadError_InvalidState The network interface was not not up.
*
*/
-ThreadError otThreadStart(otInstance *aInstance);
+OTAPI ThreadError OTCALL otThreadStart(otInstance *aInstance);
/**
* This function stops Thread protocol operation.
@@ -258,7 +323,7 @@ ThreadError otThreadStart(otInstance *aInstance);
* @retval kThreadError_None Successfully stopped Thread protocol operation.
*
*/
-ThreadError otThreadStop(otInstance *aInstance);
+OTAPI ThreadError OTCALL otThreadStop(otInstance *aInstance);
/**
* This function indicates whether a node is the only router on the network.
@@ -269,7 +334,7 @@ ThreadError otThreadStop(otInstance *aInstance);
* @retval FALSE It is a child or is not a single router in the network.
*
*/
-bool otIsSingleton(otInstance *aInstance);
+OTAPI bool OTCALL otIsSingleton(otInstance *aInstance);
/**
* This function pointer is called during an IEEE 802.15.4 Active Scan when an IEEE 802.15.4 Beacon is received or
@@ -279,7 +344,7 @@ bool otIsSingleton(otInstance *aInstance);
* @param[in] aContext A pointer to application-specific context.
*
*/
-typedef void (*otHandleActiveScanResult)(otActiveScanResult *aResult, void *aContext);
+typedef void (OTCALL *otHandleActiveScanResult)(otActiveScanResult *aResult, void *aContext);
/**
* This function starts an IEEE 802.15.4 Active Scan
@@ -294,8 +359,8 @@ typedef void (*otHandleActiveScanResult)(otActiveScanResult *aResult, void *aCon
* @retval kThreadError_Busy Already performing an Active Scan.
*
*/
-ThreadError otActiveScan(otInstance *aInstance, uint32_t aScanChannels, uint16_t aScanDuration,
- otHandleActiveScanResult aCallback, void *aCallbackContext);
+OTAPI ThreadError OTCALL otActiveScan(otInstance *aInstance, uint32_t aScanChannels, uint16_t aScanDuration,
+ otHandleActiveScanResult aCallback, void *aCallbackContext);
/**
* This function indicates whether or not an IEEE 802.15.4 Active Scan is currently in progress.
@@ -304,7 +369,7 @@ ThreadError otActiveScan(otInstance *aInstance, uint32_t aScanChannels, uint16_t
*
* @returns true if an IEEE 802.15.4 Active Scan is in progress, false otherwise.
*/
-bool otIsActiveScanInProgress(otInstance *aInstance);
+OTAPI bool OTCALL otIsActiveScanInProgress(otInstance *aInstance);
/**
* This function pointer is called during an IEEE 802.15.4 Energy Scan when the result for a channel is ready or the
@@ -314,7 +379,7 @@ bool otIsActiveScanInProgress(otInstance *aInstance);
* @param[in] aContext A pointer to application-specific context.
*
*/
-typedef void (*otHandleEnergyScanResult)(otEnergyScanResult *aResult, void *aContext);
+typedef void (OTCALL *otHandleEnergyScanResult)(otEnergyScanResult *aResult, void *aContext);
/**
* This function starts an IEEE 802.15.4 Energy Scan
@@ -329,8 +394,8 @@ typedef void (*otHandleEnergyScanResult)(otEnergyScanResult *aResult, void *aCon
* @retval kThreadError_Busy Could not start the energy scan.
*
*/
-ThreadError otEnergyScan(otInstance *aInstance, uint32_t aScanChannels, uint16_t aScanDuration,
- otHandleEnergyScanResult aCallback, void *aCallbackContext);
+OTAPI ThreadError OTCALL otEnergyScan(otInstance *aInstance, uint32_t aScanChannels, uint16_t aScanDuration,
+ otHandleEnergyScanResult aCallback, void *aCallbackContext);
/**
* This function indicates whether or not an IEEE 802.15.4 Energy Scan is currently in progress.
@@ -340,7 +405,7 @@ ThreadError otEnergyScan(otInstance *aInstance, uint32_t aScanChannels, uint16_t
* @returns true if an IEEE 802.15.4 Energy Scan is in progress, false otherwise.
*
*/
-bool otIsEnergyScanInProgress(otInstance *aInstance);
+OTAPI bool OTCALL otIsEnergyScanInProgress(otInstance *aInstance);
/**
* This function starts a Thread Discovery scan.
@@ -356,8 +421,9 @@ bool otIsEnergyScanInProgress(otInstance *aInstance);
* @retval kThreadError_Busy Already performing an Thread Discovery.
*
*/
-ThreadError otDiscover(otInstance *aInstance, uint32_t aScanChannels, uint16_t aScanDuration, uint16_t aPanid,
- otHandleActiveScanResult aCallback, void *aCallbackContext);
+OTAPI ThreadError OTCALL otDiscover(otInstance *aInstance, uint32_t aScanChannels, uint16_t aScanDuration,
+ uint16_t aPanid,
+ otHandleActiveScanResult aCallback, void *aCallbackContext);
/**
* This function determines if an MLE Thread Discovery is currently in progress.
@@ -365,7 +431,7 @@ ThreadError otDiscover(otInstance *aInstance, uint32_t aScanChannels, uint16_t a
* @param[in] aInstance A pointer to an OpenThread instance.
*
*/
-bool otIsDiscoverInProgress(otInstance *aInstance);
+OTAPI bool OTCALL otIsDiscoverInProgress(otInstance *aInstance);
/**
* @}
@@ -401,7 +467,7 @@ bool otIsDiscoverInProgress(otInstance *aInstance);
*
* @sa otSetChannel
*/
-uint8_t otGetChannel(otInstance *aInstance);
+OTAPI uint8_t OTCALL otGetChannel(otInstance *aInstance);
/**
* Set the IEEE 802.15.4 channel
@@ -414,7 +480,7 @@ uint8_t otGetChannel(otInstance *aInstance);
*
* @sa otGetChannel
*/
-ThreadError otSetChannel(otInstance *aInstance, uint8_t aChannel);
+OTAPI ThreadError OTCALL otSetChannel(otInstance *aInstance, uint8_t aChannel);
/**
* Get the maximum number of children currently allowed.
@@ -425,7 +491,7 @@ ThreadError otSetChannel(otInstance *aInstance, uint8_t aChannel);
*
* @sa otSetMaxAllowedChildren
*/
-uint8_t otGetMaxAllowedChildren(otInstance *aInstance);
+OTAPI uint8_t OTCALL otGetMaxAllowedChildren(otInstance *aInstance);
/**
* Set the maximum number of children currently allowed.
@@ -442,7 +508,7 @@ uint8_t otGetMaxAllowedChildren(otInstance *aInstance);
*
* @sa otGetMaxAllowedChildren, otThreadStop
*/
-ThreadError otSetMaxAllowedChildren(otInstance *aInstance, uint8_t aMaxChildren);
+OTAPI ThreadError OTCALL otSetMaxAllowedChildren(otInstance *aInstance, uint8_t aMaxChildren);
/**
* Get the Thread Child Timeout used when operating in the Child role.
@@ -453,7 +519,7 @@ ThreadError otSetMaxAllowedChildren(otInstance *aInstance, uint8_t aMaxChildren)
*
* @sa otSetChildTimeout
*/
-uint32_t otGetChildTimeout(otInstance *aInstance);
+OTAPI uint32_t OTCALL otGetChildTimeout(otInstance *aInstance);
/**
* Set the Thread Child Timeout used when operating in the Child role.
@@ -462,7 +528,7 @@ uint32_t otGetChildTimeout(otInstance *aInstance);
*
* @sa otSetChildTimeout
*/
-void otSetChildTimeout(otInstance *aInstance, uint32_t aTimeout);
+OTAPI void OTCALL otSetChildTimeout(otInstance *aInstance, uint32_t aTimeout);
/**
* Get the IEEE 802.15.4 Extended Address.
@@ -471,7 +537,7 @@ void otSetChildTimeout(otInstance *aInstance, uint32_t aTimeout);
*
* @returns A pointer to the IEEE 802.15.4 Extended Address.
*/
-const uint8_t *otGetExtendedAddress(otInstance *aInstance);
+OTAPI const uint8_t *OTCALL otGetExtendedAddress(otInstance *aInstance);
/**
* This function sets the IEEE 802.15.4 Extended Address.
@@ -483,7 +549,7 @@ const uint8_t *otGetExtendedAddress(otInstance *aInstance);
* @retval kThreadError_InvalidArgs @p aExtendedAddress was NULL.
*
*/
-ThreadError otSetExtendedAddress(otInstance *aInstance, const otExtAddress *aExtendedAddress);
+OTAPI ThreadError OTCALL otSetExtendedAddress(otInstance *aInstance, const otExtAddress *aExtendedAddress);
/**
* Get the IEEE 802.15.4 Extended PAN ID.
@@ -494,7 +560,7 @@ ThreadError otSetExtendedAddress(otInstance *aInstance, const otExtAddress *aExt
*
* @sa otSetExtendedPanId
*/
-const uint8_t *otGetExtendedPanId(otInstance *aInstance);
+OTAPI const uint8_t *OTCALL otGetExtendedPanId(otInstance *aInstance);
/**
* Set the IEEE 802.15.4 Extended PAN ID.
@@ -504,7 +570,7 @@ const uint8_t *otGetExtendedPanId(otInstance *aInstance);
*
* @sa otGetExtendedPanId
*/
-void otSetExtendedPanId(otInstance *aInstance, const uint8_t *aExtendedPanId);
+OTAPI void OTCALL otSetExtendedPanId(otInstance *aInstance, const uint8_t *aExtendedPanId);
/**
* Get the factory-assigned IEEE EUI-64.
@@ -513,7 +579,7 @@ void otSetExtendedPanId(otInstance *aInstance, const uint8_t *aExtendedPanId);
* @param[out] aEui64 A pointer to where the factory-assigned IEEE EUI-64 is placed.
*
*/
-void otGetFactoryAssignedIeeeEui64(otInstance *aInstance, otExtAddress *aEui64);
+OTAPI void OTCALL otGetFactoryAssignedIeeeEui64(otInstance *aInstance, otExtAddress *aEui64);
/**
* Get the Hash Mac Address.
@@ -525,7 +591,7 @@ void otGetFactoryAssignedIeeeEui64(otInstance *aInstance, otExtAddress *aEui64);
* @param[out] aHashMacAddress A pointer to where the Hash Mac Address is placed.
*
*/
-void otGetHashMacAddress(otInstance *aInstance, otExtAddress *aHashMacAddress);
+OTAPI void OTCALL otGetHashMacAddress(otInstance *aInstance, otExtAddress *aHashMacAddress);
/**
* This function returns a pointer to the Leader's RLOC.
@@ -538,7 +604,7 @@ void otGetHashMacAddress(otInstance *aInstance, otExtAddress *aHashMacAddress);
* @retval kThreadError_Detached Not currently attached to a Thread Partition.
*
*/
-ThreadError otGetLeaderRloc(otInstance *aInstance, otIp6Address *aLeaderRloc);
+OTAPI ThreadError OTCALL otGetLeaderRloc(otInstance *aInstance, otIp6Address *aLeaderRloc);
/**
* Get the MLE Link Mode configuration.
@@ -549,7 +615,7 @@ ThreadError otGetLeaderRloc(otInstance *aInstance, otIp6Address *aLeaderRloc);
*
* @sa otSetLinkMode
*/
-otLinkModeConfig otGetLinkMode(otInstance *aInstance);
+OTAPI otLinkModeConfig OTCALL otGetLinkMode(otInstance *aInstance);
/**
* Set the MLE Link Mode configuration.
@@ -561,7 +627,7 @@ otLinkModeConfig otGetLinkMode(otInstance *aInstance);
*
* @sa otGetLinkMode
*/
-ThreadError otSetLinkMode(otInstance *aInstance, otLinkModeConfig aConfig);
+OTAPI ThreadError OTCALL otSetLinkMode(otInstance *aInstance, otLinkModeConfig aConfig);
/**
* Get the thrMasterKey.
@@ -574,7 +640,7 @@ ThreadError otSetLinkMode(otInstance *aInstance, otLinkModeConfig aConfig);
*
* @sa otSetMasterKey
*/
-const uint8_t *otGetMasterKey(otInstance *aInstance, uint8_t *aKeyLength);
+OTAPI const uint8_t *OTCALL otGetMasterKey(otInstance *aInstance, uint8_t *aKeyLength);
/**
* Set the thrMasterKey.
@@ -588,7 +654,7 @@ const uint8_t *otGetMasterKey(otInstance *aInstance, uint8_t *aKeyLength);
*
* @sa otGetMasterKey
*/
-ThreadError otSetMasterKey(otInstance *aInstance, const uint8_t *aKey, uint8_t aKeyLength);
+OTAPI ThreadError OTCALL otSetMasterKey(otInstance *aInstance, const uint8_t *aKey, uint8_t aKeyLength);
/**
* This function returns the maximum transmit power setting in dBm.
@@ -598,7 +664,7 @@ ThreadError otSetMasterKey(otInstance *aInstance, const uint8_t *aKey, uint8_t a
* @returns The maximum transmit power setting.
*
*/
-int8_t otGetMaxTransmitPower(otInstance *aInstance);
+OTAPI int8_t OTCALL otGetMaxTransmitPower(otInstance *aInstance);
/**
* This function sets the maximum transmit power in dBm.
@@ -607,7 +673,7 @@ int8_t otGetMaxTransmitPower(otInstance *aInstance);
* @param[in] aPower The maximum transmit power in dBm.
*
*/
-void otSetMaxTransmitPower(otInstance *aInstance, int8_t aPower);
+OTAPI void OTCALL otSetMaxTransmitPower(otInstance *aInstance, int8_t aPower);
/**
* This function returns a pointer to the Mesh Local EID.
@@ -617,7 +683,7 @@ void otSetMaxTransmitPower(otInstance *aInstance, int8_t aPower);
* @returns A pointer to the Mesh Local EID.
*
*/
-const otIp6Address *otGetMeshLocalEid(otInstance *aInstance);
+OTAPI const otIp6Address *OTCALL otGetMeshLocalEid(otInstance *aInstance);
/**
* This function returns a pointer to the Mesh Local Prefix.
@@ -627,7 +693,7 @@ const otIp6Address *otGetMeshLocalEid(otInstance *aInstance);
* @returns A pointer to the Mesh Local Prefix.
*
*/
-const uint8_t *otGetMeshLocalPrefix(otInstance *aInstance);
+OTAPI const uint8_t *OTCALL otGetMeshLocalPrefix(otInstance *aInstance);
/**
* This function sets the Mesh Local Prefix.
@@ -638,7 +704,7 @@ const uint8_t *otGetMeshLocalPrefix(otInstance *aInstance);
* @retval kThreadError_None Successfully set the Mesh Local Prefix.
*
*/
-ThreadError otSetMeshLocalPrefix(otInstance *aInstance, const uint8_t *aMeshLocalPrefix);
+OTAPI ThreadError OTCALL otSetMeshLocalPrefix(otInstance *aInstance, const uint8_t *aMeshLocalPrefix);
/**
* This method provides a full or stable copy of the Leader's Thread Network Data.
@@ -649,7 +715,8 @@ ThreadError otSetMeshLocalPrefix(otInstance *aInstance, const uint8_t *aMeshLoca
* @param[inout] aDataLength On entry, size of the data buffer pointed to by @p aData.
* On exit, number of copied bytes.
*/
-ThreadError otGetNetworkDataLeader(otInstance *aInstance, bool aStable, uint8_t *aData, uint8_t *aDataLength);
+OTAPI ThreadError OTCALL otGetNetworkDataLeader(otInstance *aInstance, bool aStable, uint8_t *aData,
+ uint8_t *aDataLength);
/**
* This method provides a full or stable copy of the local Thread Network Data.
@@ -660,7 +727,8 @@ ThreadError otGetNetworkDataLeader(otInstance *aInstance, bool aStable, uint8_t
* @param[inout] aDataLength On entry, size of the data buffer pointed to by @p aData.
* On exit, number of copied bytes.
*/
-ThreadError otGetNetworkDataLocal(otInstance *aInstance, bool aStable, uint8_t *aData, uint8_t *aDataLength);
+OTAPI ThreadError OTCALL otGetNetworkDataLocal(otInstance *aInstance, bool aStable, uint8_t *aData,
+ uint8_t *aDataLength);
/**
* Get the Thread Network Name.
@@ -671,7 +739,7 @@ ThreadError otGetNetworkDataLocal(otInstance *aInstance, bool aStable, uint8_t *
*
* @sa otSetNetworkName
*/
-const char *otGetNetworkName(otInstance *aInstance);
+OTAPI const char *OTCALL otGetNetworkName(otInstance *aInstance);
/**
* Set the Thread Network Name.
@@ -683,7 +751,7 @@ const char *otGetNetworkName(otInstance *aInstance);
*
* @sa otGetNetworkName
*/
-ThreadError otSetNetworkName(otInstance *aInstance, const char *aNetworkName);
+OTAPI ThreadError OTCALL otSetNetworkName(otInstance *aInstance, const char *aNetworkName);
/**
* This function gets the next On Mesh Prefix in the Network Data.
@@ -698,8 +766,8 @@ ThreadError otSetNetworkName(otInstance *aInstance, const char *aNetworkName);
* @retval kThreadError_NotFound No subsequent On Mesh prefix exists in the Thread Network Data.
*
*/
-ThreadError otGetNextOnMeshPrefix(otInstance *aInstance, bool aLocal, otNetworkDataIterator *aIterator,
- otBorderRouterConfig *aConfig);
+OTAPI ThreadError OTCALL otGetNextOnMeshPrefix(otInstance *aInstance, bool aLocal, otNetworkDataIterator *aIterator,
+ otBorderRouterConfig *aConfig);
/**
* Get the IEEE 802.15.4 PAN ID.
@@ -710,7 +778,7 @@ ThreadError otGetNextOnMeshPrefix(otInstance *aInstance, bool aLocal, otNetworkD
*
* @sa otSetPanId
*/
-otPanId otGetPanId(otInstance *aInstance);
+OTAPI otPanId OTCALL otGetPanId(otInstance *aInstance);
/**
* Set the IEEE 802.15.4 PAN ID.
@@ -723,7 +791,7 @@ otPanId otGetPanId(otInstance *aInstance);
*
* @sa otGetPanId
*/
-ThreadError otSetPanId(otInstance *aInstance, otPanId aPanId);
+OTAPI ThreadError OTCALL otSetPanId(otInstance *aInstance, otPanId aPanId);
/**
* This function indicates whether or not the Router Role is enabled.
@@ -734,7 +802,7 @@ ThreadError otSetPanId(otInstance *aInstance, otPanId aPanId);
* @retval FALSE If the Router Role is not enabled.
*
*/
-bool otIsRouterRoleEnabled(otInstance *aInstance);
+OTAPI bool OTCALL otIsRouterRoleEnabled(otInstance *aInstance);
/**
* This function sets whether or not the Router Role is enabled.
@@ -743,7 +811,7 @@ bool otIsRouterRoleEnabled(otInstance *aInstance);
* @param[in] aEnabled TRUE if the Router Role is enabled, FALSE otherwise.
*
*/
-void otSetRouterRoleEnabled(otInstance *aInstance, bool aEnabled);
+OTAPI void OTCALL otSetRouterRoleEnabled(otInstance *aInstance, bool aEnabled);
/**
* Get the IEEE 802.15.4 Short Address.
@@ -752,7 +820,7 @@ void otSetRouterRoleEnabled(otInstance *aInstance, bool aEnabled);
*
* @returns A pointer to the IEEE 802.15.4 Short Address.
*/
-otShortAddress otGetShortAddress(otInstance *aInstance);
+OTAPI otShortAddress OTCALL otGetShortAddress(otInstance *aInstance);
/**
* Get the list of IPv6 addresses assigned to the Thread interface.
@@ -761,7 +829,7 @@ otShortAddress otGetShortAddress(otInstance *aInstance);
*
* @returns A pointer to the first Network Interface Address.
*/
-const otNetifAddress *otGetUnicastAddresses(otInstance *aInstance);
+OTAPI const otNetifAddress *OTCALL otGetUnicastAddresses(otInstance *aInstance);
/**
* Add a Network Interface Address to the Thread interface.
@@ -776,7 +844,7 @@ const otNetifAddress *otGetUnicastAddresses(otInstance *aInstance);
* @retval kThreadError_InvalidArgs The IP Address indicated by @p aAddress is an internal address.
* @retval kThreadError_NoBufs The Network Interface is already storing the maximum allowed external addresses.
*/
-ThreadError otAddUnicastAddress(otInstance *aInstance, const otNetifAddress *aAddress);
+OTAPI ThreadError OTCALL otAddUnicastAddress(otInstance *aInstance, const otNetifAddress *aAddress);
/**
* Remove a Network Interface Address from the Thread interface.
@@ -788,7 +856,7 @@ ThreadError otAddUnicastAddress(otInstance *aInstance, const otNetifAddress *aAd
* @retval kThreadError_InvalidArgs The IP Address indicated by @p aAddress is an internal address.
* @retval kThreadError_NotFound The IP Address indicated by @p aAddress was not found.
*/
-ThreadError otRemoveUnicastAddress(otInstance *aInstance, const otIp6Address *aAddress);
+OTAPI ThreadError OTCALL otRemoveUnicastAddress(otInstance *aInstance, const otIp6Address *aAddress);
/**
* Get the list of IPv6 multicast addresses subscribed to the Thread interface.
@@ -926,7 +994,7 @@ ThreadError otCreateSemanticallyOpaqueIid(otInstance *aInstance, otNetifAddress
* @param[in] aContext A pointer to application-specific context.
*
*/
-typedef void (*otStateChangedCallback)(uint32_t aFlags, void *aContext);
+typedef void (OTCALL *otStateChangedCallback)(uint32_t aFlags, void *aContext);
/**
* This function registers a callback to indicate when certain configuration or state changes within OpenThread.
@@ -939,7 +1007,8 @@ typedef void (*otStateChangedCallback)(uint32_t aFlags, void *aContext);
* @retval kThreadError_NoBufs Could not add the callback due to resource constraints.
*
*/
-ThreadError otSetStateChangedCallback(otInstance *aInstance, otStateChangedCallback aCallback, void *aContext);
+OTAPI ThreadError OTCALL otSetStateChangedCallback(otInstance *aInstance, otStateChangedCallback aCallback,
+ void *aContext);
/**
* This function removes a callback to indicate when certain configuration or state changes within OpenThread.
@@ -949,7 +1018,8 @@ ThreadError otSetStateChangedCallback(otInstance *aInstance, otStateChangedCallb
* @param[in] aContext A pointer to application-specific context.
*
*/
-void otRemoveStateChangeCallback(otInstance *aInstance, otStateChangedCallback aCallback, void *aCallbackContext);
+OTAPI void OTCALL otRemoveStateChangeCallback(otInstance *aInstance, otStateChangedCallback aCallback,
+ void *aCallbackContext);
/**
* This function gets the Active Operational Dataset.
@@ -961,7 +1031,7 @@ void otRemoveStateChangeCallback(otInstance *aInstance, otStateChangedCallback a
* @retval kThreadError_InvalidArgs @p aDataset was NULL.
*
*/
-ThreadError otGetActiveDataset(otInstance *aInstance, otOperationalDataset *aDataset);
+OTAPI ThreadError OTCALL otGetActiveDataset(otInstance *aInstance, otOperationalDataset *aDataset);
/**
* This function sets the Active Operational Dataset.
@@ -974,7 +1044,7 @@ ThreadError otGetActiveDataset(otInstance *aInstance, otOperationalDataset *aDat
* @retval kThreadError_InvalidArgs @p aDataset was NULL.
*
*/
-ThreadError otSetActiveDataset(otInstance *aInstance, const otOperationalDataset *aDataset);
+OTAPI ThreadError OTCALL otSetActiveDataset(otInstance *aInstance, const otOperationalDataset *aDataset);
/**
* This function gets the Pending Operational Dataset.
@@ -986,7 +1056,7 @@ ThreadError otSetActiveDataset(otInstance *aInstance, const otOperationalDataset
* @retval kThreadError_InvalidArgs @p aDataset was NULL.
*
*/
-ThreadError otGetPendingDataset(otInstance *aInstance, otOperationalDataset *aDataset);
+OTAPI ThreadError OTCALL otGetPendingDataset(otInstance *aInstance, otOperationalDataset *aDataset);
/**
* This function sets the Pending Operational Dataset.
@@ -999,7 +1069,7 @@ ThreadError otGetPendingDataset(otInstance *aInstance, otOperationalDataset *aDa
* @retval kThreadError_InvalidArgs @p aDataset was NULL.
*
*/
-ThreadError otSetPendingDataset(otInstance *aInstance, const otOperationalDataset *aDataset);
+OTAPI ThreadError OTCALL otSetPendingDataset(otInstance *aInstance, const otOperationalDataset *aDataset);
/**
* This function sends MGMT_ACTIVE_GET.
@@ -1013,8 +1083,8 @@ ThreadError otSetPendingDataset(otInstance *aInstance, const otOperationalDatase
* @retval kThreadError_NoBufs Insufficient buffer space to send.
*
*/
-ThreadError otSendActiveGet(otInstance *aInstance, const uint8_t *aTlvTypes, uint8_t aLength,
- const otIp6Address *aAddress);
+OTAPI ThreadError OTCALL otSendActiveGet(otInstance *aInstance, const uint8_t *aTlvTypes, uint8_t aLength,
+ const otIp6Address *aAddress);
/**
* This function sends MGMT_ACTIVE_SET.
@@ -1028,8 +1098,8 @@ ThreadError otSendActiveGet(otInstance *aInstance, const uint8_t *aTlvTypes, uin
* @retval kThreadError_NoBufs Insufficient buffer space to send.
*
*/
-ThreadError otSendActiveSet(otInstance *aInstance, const otOperationalDataset *aDataset, const uint8_t *aTlvs,
- uint8_t aLength);
+OTAPI ThreadError OTCALL otSendActiveSet(otInstance *aInstance, const otOperationalDataset *aDataset,
+ const uint8_t *aTlvs, uint8_t aLength);
/**
* This function sends MGMT_PENDING_GET.
@@ -1043,8 +1113,8 @@ ThreadError otSendActiveSet(otInstance *aInstance, const otOperationalDataset *a
* @retval kThreadError_NoBufs Insufficient buffer space to send.
*
*/
-ThreadError otSendPendingGet(otInstance *aInstance, const uint8_t *aTlvTypes, uint8_t aLength,
- const otIp6Address *aAddress);
+OTAPI ThreadError OTCALL otSendPendingGet(otInstance *aInstance, const uint8_t *aTlvTypes, uint8_t aLength,
+ const otIp6Address *aAddress);
/**
* This function sends MGMT_PENDING_SET.
@@ -1058,8 +1128,8 @@ ThreadError otSendPendingGet(otInstance *aInstance, const uint8_t *aTlvTypes, ui
* @retval kThreadError_NoBufs Insufficient buffer space to send.
*
*/
-ThreadError otSendPendingSet(otInstance *aInstance, const otOperationalDataset *aDataset, const uint8_t *aTlvs,
- uint8_t aLength);
+OTAPI ThreadError OTCALL otSendPendingSet(otInstance *aInstance, const otOperationalDataset *aDataset,
+ const uint8_t *aTlvs, uint8_t aLength);
/**
* Get the data poll period of sleepy end device.
@@ -1070,7 +1140,7 @@ ThreadError otSendPendingSet(otInstance *aInstance, const otOperationalDataset *
*
* @sa otSetPollPeriod
*/
-uint32_t otGetPollPeriod(otInstance *aInstance);
+OTAPI uint32_t OTCALL otGetPollPeriod(otInstance *aInstance);
/**
* Set the data poll period for sleepy end device.
@@ -1080,7 +1150,7 @@ uint32_t otGetPollPeriod(otInstance *aInstance);
*
* @sa otGetPollPeriod
*/
-void otSetPollPeriod(otInstance *aInstance, uint32_t aPollPeriod);
+OTAPI void OTCALL otSetPollPeriod(otInstance *aInstance, uint32_t aPollPeriod);
/**
* Set the preferred Router Id.
@@ -1122,7 +1192,7 @@ ThreadError otSetPreferredRouterId(otInstance *aInstance, uint8_t aRouterId);
*
* @sa otSetLeaderWeight
*/
-uint8_t otGetLocalLeaderWeight(otInstance *aInstance);
+OTAPI uint8_t OTCALL otGetLocalLeaderWeight(otInstance *aInstance);
/**
* Set the Thread Leader Weight used when operating in the Leader role.
@@ -1132,7 +1202,7 @@ uint8_t otGetLocalLeaderWeight(otInstance *aInstance);
*
* @sa otGetLeaderWeight
*/
-void otSetLocalLeaderWeight(otInstance *aInstance, uint8_t aWeight);
+OTAPI void OTCALL otSetLocalLeaderWeight(otInstance *aInstance, uint8_t aWeight);
/**
* Get the Thread Leader Partition Id used when operating in the Leader role.
@@ -1142,7 +1212,7 @@ void otSetLocalLeaderWeight(otInstance *aInstance, uint8_t aWeight);
* @returns The Thread Leader Partition Id value.
*
*/
-uint32_t otGetLocalLeaderPartitionId(otInstance *aInstance);
+OTAPI uint32_t OTCALL otGetLocalLeaderPartitionId(otInstance *aInstance);
/**
* Set the Thread Leader Partition Id used when operating in the Leader role.
@@ -1151,7 +1221,7 @@ uint32_t otGetLocalLeaderPartitionId(otInstance *aInstance);
* @param[in] aPartitionId The Thread Leader Partition Id value.
*
*/
-void otSetLocalLeaderPartitionId(otInstance *aInstance, uint32_t aPartitionId);
+OTAPI void OTCALL otSetLocalLeaderPartitionId(otInstance *aInstance, uint32_t aPartitionId);
/**
* Get the Joiner UDP Port.
@@ -1162,7 +1232,7 @@ void otSetLocalLeaderPartitionId(otInstance *aInstance, uint32_t aPartitionId);
*
* @sa otSetJoinerUdpPort
*/
-uint16_t otGetJoinerUdpPort(otInstance *aInstance);
+OTAPI uint16_t OTCALL otGetJoinerUdpPort(otInstance *aInstance);
/**
* Set the Joiner UDP Port
@@ -1174,7 +1244,7 @@ uint16_t otGetJoinerUdpPort(otInstance *aInstance);
*
* @sa otGetJoinerUdpPort
*/
-ThreadError otSetJoinerUdpPort(otInstance *aInstance, uint16_t aJoinerUdpPort);
+OTAPI ThreadError OTCALL otSetJoinerUdpPort(otInstance *aInstance, uint16_t aJoinerUdpPort);
/**
* @}
@@ -1203,7 +1273,7 @@ ThreadError otSetJoinerUdpPort(otInstance *aInstance, uint16_t aJoinerUdpPort);
* @sa otRemoveBorderRouter
* @sa otSendServerData
*/
-ThreadError otAddBorderRouter(otInstance *aInstance, const otBorderRouterConfig *aConfig);
+OTAPI ThreadError OTCALL otAddBorderRouter(otInstance *aInstance, const otBorderRouterConfig *aConfig);
/**
* Remove a border router configuration from the local network data.
@@ -1216,7 +1286,7 @@ ThreadError otAddBorderRouter(otInstance *aInstance, const otBorderRouterConfig
* @sa otAddBorderRouter
* @sa otSendServerData
*/
-ThreadError otRemoveBorderRouter(otInstance *aInstance, const otIp6Prefix *aPrefix);
+OTAPI ThreadError OTCALL otRemoveBorderRouter(otInstance *aInstance, const otIp6Prefix *aPrefix);
/**
* Add an external route configuration to the local network data.
@@ -1231,7 +1301,7 @@ ThreadError otRemoveBorderRouter(otInstance *aInstance, const otIp6Prefix *aPref
* @sa otRemoveExternalRoute
* @sa otSendServerData
*/
-ThreadError otAddExternalRoute(otInstance *aInstance, const otExternalRouteConfig *aConfig);
+OTAPI ThreadError OTCALL otAddExternalRoute(otInstance *aInstance, const otExternalRouteConfig *aConfig);
/**
* Remove an external route configuration from the local network data.
@@ -1244,7 +1314,7 @@ ThreadError otAddExternalRoute(otInstance *aInstance, const otExternalRouteConfi
* @sa otAddExternalRoute
* @sa otSendServerData
*/
-ThreadError otRemoveExternalRoute(otInstance *aInstance, const otIp6Prefix *aPrefix);
+OTAPI ThreadError OTCALL otRemoveExternalRoute(otInstance *aInstance, const otIp6Prefix *aPrefix);
/**
* Immediately register the local network data with the Leader.
@@ -1258,7 +1328,7 @@ ThreadError otRemoveExternalRoute(otInstance *aInstance, const otIp6Prefix *aPre
* @sa otAddExternalRoute
* @sa otRemoveExternalRoute
*/
-ThreadError otSendServerData(otInstance *aInstance);
+OTAPI ThreadError OTCALL otSendServerData(otInstance *aInstance);
/**
* This function adds a port to the allowed unsecured port list.
@@ -1321,7 +1391,7 @@ const uint16_t *otGetUnsecurePorts(otInstance *aInstance, uint8_t *aNumEntries);
*
* @sa otSetContextIdReuseDelay
*/
-uint32_t otGetContextIdReuseDelay(otInstance *aInstance);
+OTAPI uint32_t OTCALL otGetContextIdReuseDelay(otInstance *aInstance);
/**
* Set the CONTEXT_ID_REUSE_DELAY parameter used in the Leader role.
@@ -1331,7 +1401,7 @@ uint32_t otGetContextIdReuseDelay(otInstance *aInstance);
*
* @sa otGetContextIdReuseDelay
*/
-void otSetContextIdReuseDelay(otInstance *aInstance, uint32_t aDelay);
+OTAPI void OTCALL otSetContextIdReuseDelay(otInstance *aInstance, uint32_t aDelay);
/**
* Get the thrKeySequenceCounter.
@@ -1342,7 +1412,7 @@ void otSetContextIdReuseDelay(otInstance *aInstance, uint32_t aDelay);
*
* @sa otSetKeySequenceCounter
*/
-uint32_t otGetKeySequenceCounter(otInstance *aInstance);
+OTAPI uint32_t OTCALL otGetKeySequenceCounter(otInstance *aInstance);
/**
* Set the thrKeySequenceCounter.
@@ -1352,7 +1422,7 @@ uint32_t otGetKeySequenceCounter(otInstance *aInstance);
*
* @sa otGetKeySequenceCounter
*/
-void otSetKeySequenceCounter(otInstance *aInstance, uint32_t aKeySequenceCounter);
+OTAPI void OTCALL otSetKeySequenceCounter(otInstance *aInstance, uint32_t aKeySequenceCounter);
/**
* Get the thrKeySwitchGuardTime
@@ -1363,7 +1433,7 @@ void otSetKeySequenceCounter(otInstance *aInstance, uint32_t aKeySequenceCounter
*
* @sa otSetKeySwitchGuardTime
*/
-uint32_t otGetKeySwitchGuardTime(otInstance *aInstance);
+OTAPI uint32_t OTCALL otGetKeySwitchGuardTime(otInstance *aInstance);
/**
* Set the thrKeySwitchGuardTime
@@ -1373,7 +1443,7 @@ uint32_t otGetKeySwitchGuardTime(otInstance *aInstance);
*
* @sa otGetKeySwitchGuardTime
*/
-void otSetKeySwitchGuardTime(otInstance *aInstance, uint32_t aKeySwitchGuardTime);
+OTAPI void OTCALL otSetKeySwitchGuardTime(otInstance *aInstance, uint32_t aKeySwitchGuardTime);
/**
@@ -1385,7 +1455,7 @@ void otSetKeySwitchGuardTime(otInstance *aInstance, uint32_t aKeySwitchGuardTime
*
* @sa otSetNetworkIdTimeout
*/
-uint8_t otGetNetworkIdTimeout(otInstance *aInstance);
+OTAPI uint8_t OTCALL otGetNetworkIdTimeout(otInstance *aInstance);
/**
* Set the NETWORK_ID_TIMEOUT parameter used in the Leader role.
@@ -1395,7 +1465,7 @@ uint8_t otGetNetworkIdTimeout(otInstance *aInstance);
*
* @sa otGetNetworkIdTimeout
*/
-void otSetNetworkIdTimeout(otInstance *aInstance, uint8_t aTimeout);
+OTAPI void OTCALL otSetNetworkIdTimeout(otInstance *aInstance, uint8_t aTimeout);
/**
* Get the ROUTER_UPGRADE_THRESHOLD parameter used in the REED role.
@@ -1406,7 +1476,7 @@ void otSetNetworkIdTimeout(otInstance *aInstance, uint8_t aTimeout);
*
* @sa otSetRouterUpgradeThreshold
*/
-uint8_t otGetRouterUpgradeThreshold(otInstance *aInstance);
+OTAPI uint8_t OTCALL otGetRouterUpgradeThreshold(otInstance *aInstance);
/**
* Set the ROUTER_UPGRADE_THRESHOLD parameter used in the Leader role.
@@ -1416,7 +1486,7 @@ uint8_t otGetRouterUpgradeThreshold(otInstance *aInstance);
*
* @sa otGetRouterUpgradeThreshold
*/
-void otSetRouterUpgradeThreshold(otInstance *aInstance, uint8_t aThreshold);
+OTAPI void OTCALL otSetRouterUpgradeThreshold(otInstance *aInstance, uint8_t aThreshold);
/**
* Release a Router ID that has been allocated by the device in the Leader role.
@@ -1426,7 +1496,7 @@ void otSetRouterUpgradeThreshold(otInstance *aInstance, uint8_t aThreshold);
*
* @retval kThreadErrorNone Successfully released the Router ID specified by aRouterId.
*/
-ThreadError otReleaseRouterId(otInstance *aInstance, uint8_t aRouterId);
+OTAPI ThreadError OTCALL otReleaseRouterId(otInstance *aInstance, uint8_t aRouterId);
/**
* Add an IEEE 802.15.4 Extended Address to the MAC whitelist.
@@ -1444,7 +1514,7 @@ ThreadError otReleaseRouterId(otInstance *aInstance, uint8_t aRouterId);
* @sa otDisableMacWhitelist
* @sa otEnableMacWhitelist
*/
-ThreadError otAddMacWhitelist(otInstance *aInstance, const uint8_t *aExtAddr);
+OTAPI ThreadError OTCALL otAddMacWhitelist(otInstance *aInstance, const uint8_t *aExtAddr);
/**
* Add an IEEE 802.15.4 Extended Address to the MAC whitelist and fix the RSSI value.
@@ -1463,7 +1533,7 @@ ThreadError otAddMacWhitelist(otInstance *aInstance, const uint8_t *aExtAddr);
* @sa otDisableMacWhitelist
* @sa otEnableMacWhitelist
*/
-ThreadError otAddMacWhitelistRssi(otInstance *aInstance, const uint8_t *aExtAddr, int8_t aRssi);
+OTAPI ThreadError OTCALL otAddMacWhitelistRssi(otInstance *aInstance, const uint8_t *aExtAddr, int8_t aRssi);
/**
* Remove an IEEE 802.15.4 Extended Address from the MAC whitelist.
@@ -1478,7 +1548,7 @@ ThreadError otAddMacWhitelistRssi(otInstance *aInstance, const uint8_t *aExtAddr
* @sa otDisableMacWhitelist
* @sa otEnableMacWhitelist
*/
-void otRemoveMacWhitelist(otInstance *aInstance, const uint8_t *aExtAddr);
+OTAPI void OTCALL otRemoveMacWhitelist(otInstance *aInstance, const uint8_t *aExtAddr);
/**
* This function gets a MAC whitelist entry.
@@ -1491,7 +1561,7 @@ void otRemoveMacWhitelist(otInstance *aInstance, const uint8_t *aExtAddr);
* @retval kThreadError_InvalidArgs @p aIndex is out of bounds or @p aEntry is NULL.
*
*/
-ThreadError otGetMacWhitelistEntry(otInstance *aInstance, uint8_t aIndex, otMacWhitelistEntry *aEntry);
+OTAPI ThreadError OTCALL otGetMacWhitelistEntry(otInstance *aInstance, uint8_t aIndex, otMacWhitelistEntry *aEntry);
/**
* Remove all entries from the MAC whitelist.
@@ -1505,7 +1575,7 @@ ThreadError otGetMacWhitelistEntry(otInstance *aInstance, uint8_t aIndex, otMacW
* @sa otDisableMacWhitelist
* @sa otEnableMacWhitelist
*/
-void otClearMacWhitelist(otInstance *aInstance);
+OTAPI void OTCALL otClearMacWhitelist(otInstance *aInstance);
/**
* Disable MAC whitelist filtering.
@@ -1519,7 +1589,7 @@ void otClearMacWhitelist(otInstance *aInstance);
* @sa otGetMacWhitelistEntry
* @sa otEnableMacWhitelist
*/
-void otDisableMacWhitelist(otInstance *aInstance);
+OTAPI void OTCALL otDisableMacWhitelist(otInstance *aInstance);
/**
* Enable MAC whitelist filtering.
@@ -1533,7 +1603,7 @@ void otDisableMacWhitelist(otInstance *aInstance);
* @sa otGetMacWhitelistEntry
* @sa otDisableMacWhitelist
*/
-void otEnableMacWhitelist(otInstance *aInstance);
+OTAPI void OTCALL otEnableMacWhitelist(otInstance *aInstance);
/**
* This function indicates whether or not the MAC whitelist is enabled.
@@ -1551,7 +1621,7 @@ void otEnableMacWhitelist(otInstance *aInstance);
* @sa otEnableMacWhitelist
*
*/
-bool otIsMacWhitelistEnabled(otInstance *aInstance);
+OTAPI bool OTCALL otIsMacWhitelistEnabled(otInstance *aInstance);
/**
* Detach from the Thread network.
@@ -1561,7 +1631,7 @@ bool otIsMacWhitelistEnabled(otInstance *aInstance);
* @retval kThreadErrorNone Successfully detached from the Thread network.
* @retval kThreadErrorInvalidState Thread is disabled.
*/
-ThreadError otBecomeDetached(otInstance *aInstance);
+OTAPI ThreadError OTCALL otBecomeDetached(otInstance *aInstance);
/**
* Attempt to reattach as a child.
@@ -1572,7 +1642,7 @@ ThreadError otBecomeDetached(otInstance *aInstance);
* @retval kThreadErrorNone Successfully begin attempt to become a child.
* @retval kThreadErrorInvalidState Thread is disabled.
*/
-ThreadError otBecomeChild(otInstance *aInstance, otMleAttachFilter aFilter);
+OTAPI ThreadError OTCALL otBecomeChild(otInstance *aInstance, otMleAttachFilter aFilter);
/**
* Attempt to become a router.
@@ -1582,7 +1652,7 @@ ThreadError otBecomeChild(otInstance *aInstance, otMleAttachFilter aFilter);
* @retval kThreadErrorNone Successfully begin attempt to become a router.
* @retval kThreadErrorInvalidState Thread is disabled.
*/
-ThreadError otBecomeRouter(otInstance *aInstance);
+OTAPI ThreadError OTCALL otBecomeRouter(otInstance *aInstance);
/**
* Become a leader and start a new partition.
@@ -1592,7 +1662,7 @@ ThreadError otBecomeRouter(otInstance *aInstance);
* @retval kThreadErrorNone Successfully became a leader and started a new partition.
* @retval kThreadErrorInvalidState Thread is disabled.
*/
-ThreadError otBecomeLeader(otInstance *aInstance);
+OTAPI ThreadError OTCALL otBecomeLeader(otInstance *aInstance);
/**
* Add an IEEE 802.15.4 Extended Address to the MAC blacklist.
@@ -1609,7 +1679,7 @@ ThreadError otBecomeLeader(otInstance *aInstance);
* @sa otDisableMacBlacklist
* @sa otEnableMacBlacklist
*/
-ThreadError otAddMacBlacklist(otInstance *aInstance, const uint8_t *aExtAddr);
+OTAPI ThreadError OTCALL otAddMacBlacklist(otInstance *aInstance, const uint8_t *aExtAddr);
/**
* Remove an IEEE 802.15.4 Extended Address from the MAC blacklist.
@@ -1623,7 +1693,7 @@ ThreadError otAddMacBlacklist(otInstance *aInstance, const uint8_t *aExtAddr);
* @sa otDisableMacBlacklist
* @sa otEnableMacBlacklist
*/
-void otRemoveMacBlacklist(otInstance *aInstance, const uint8_t *aExtAddr);
+OTAPI void OTCALL otRemoveMacBlacklist(otInstance *aInstance, const uint8_t *aExtAddr);
/**
* This function gets a MAC Blacklist entry.
@@ -1636,7 +1706,7 @@ void otRemoveMacBlacklist(otInstance *aInstance, const uint8_t *aExtAddr);
* @retval kThreadError_InvalidArgs @p aIndex is out of bounds or @p aEntry is NULL.
*
*/
-ThreadError otGetMacBlacklistEntry(otInstance *aInstance, uint8_t aIndex, otMacBlacklistEntry *aEntry);
+OTAPI ThreadError OTCALL otGetMacBlacklistEntry(otInstance *aInstance, uint8_t aIndex, otMacBlacklistEntry *aEntry);
/**
* Remove all entries from the MAC Blacklist.
@@ -1649,7 +1719,7 @@ ThreadError otGetMacBlacklistEntry(otInstance *aInstance, uint8_t aIndex, otMacB
* @sa otDisableMacBlacklist
* @sa otEnableMacBlacklist
*/
-void otClearMacBlacklist(otInstance *aInstance);
+OTAPI void OTCALL otClearMacBlacklist(otInstance *aInstance);
/**
* Disable MAC blacklist filtering.
@@ -1663,7 +1733,7 @@ void otClearMacBlacklist(otInstance *aInstance);
* @sa otGetMacBlacklistEntry
* @sa otEnableMacBlacklist
*/
-void otDisableMacBlacklist(otInstance *aInstance);
+OTAPI void OTCALL otDisableMacBlacklist(otInstance *aInstance);
/**
* Enable MAC Blacklist filtering.
@@ -1676,7 +1746,7 @@ void otDisableMacBlacklist(otInstance *aInstance);
* @sa otGetMacBlacklistEntry
* @sa otDisableMacBlacklist
*/
-void otEnableMacBlacklist(otInstance *aInstance);
+OTAPI void OTCALL otEnableMacBlacklist(otInstance *aInstance);
/**
* This function indicates whether or not the MAC Blacklist is enabled.
@@ -1693,7 +1763,7 @@ void otEnableMacBlacklist(otInstance *aInstance);
* @sa otEnableMacBlacklist
*
*/
-bool otIsMacBlacklistEnabled(otInstance *aInstance);
+OTAPI bool OTCALL otIsMacBlacklistEnabled(otInstance *aInstance);
/**
* Get the assigned link quality which is on the link to a given extended address.
@@ -1707,7 +1777,7 @@ bool otIsMacBlacklistEnabled(otInstance *aInstance);
*
* @sa otSetAssignLinkQuality
*/
-ThreadError otGetAssignLinkQuality(otInstance *aInstance, const uint8_t *aExtAddr, uint8_t *aLinkQuality);
+OTAPI ThreadError OTCALL otGetAssignLinkQuality(otInstance *aInstance, const uint8_t *aExtAddr, uint8_t *aLinkQuality);
/**
* Set the link quality which is on the link to a given extended address.
@@ -1718,14 +1788,14 @@ ThreadError otGetAssignLinkQuality(otInstance *aInstance, const uint8_t *aExtAdd
*
* @sa otGetAssignLinkQuality
*/
-void otSetAssignLinkQuality(otInstance *aInstance, const uint8_t *aExtAddr, uint8_t aLinkQuality);
+OTAPI void OTCALL otSetAssignLinkQuality(otInstance *aInstance, const uint8_t *aExtAddr, uint8_t aLinkQuality);
/**
* This method triggers platform reset.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*/
-void otPlatformReset(otInstance *aInstance);
+OTAPI void OTCALL otPlatformReset(otInstance *aInstance);
/**
* This method deletes all the settings stored on non-volatile memory, and then triggers platform reset.
@@ -1743,7 +1813,7 @@ void otFactoryReset(otInstance *aInstance);
*
* @sa otSetRouterDowngradeThreshold
*/
-uint8_t otGetRouterDowngradeThreshold(otInstance *aInstance);
+OTAPI uint8_t OTCALL otGetRouterDowngradeThreshold(otInstance *aInstance);
/**
* Set the ROUTER_DOWNGRADE_THRESHOLD parameter used in the Leader role.
@@ -1753,25 +1823,28 @@ uint8_t otGetRouterDowngradeThreshold(otInstance *aInstance);
*
* @sa otGetRouterDowngradeThreshold
*/
-void otSetRouterDowngradeThreshold(otInstance *aInstance, uint8_t aThreshold);
+OTAPI void OTCALL otSetRouterDowngradeThreshold(otInstance *aInstance, uint8_t aThreshold);
/**
* Get the ROUTER_SELECTION_JITTER parameter used in the REED/Router role.
*
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
* @returns The ROUTER_SELECTION_JITTER value.
*
* @sa otSetRouterSelectionJitter
*/
-uint8_t otGetRouterSelectionJitter(otInstance *aInstance);
+OTAPI uint8_t OTCALL otGetRouterSelectionJitter(otInstance *aInstance);
/**
* Set the ROUTER_SELECTION_JITTER parameter used in the REED/Router role.
*
+ * @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aRouterJitter The ROUTER_SELECTION_JITTER value.
*
* @sa otGetRouterSelectionJitter
*/
-void otSetRouterSelectionJitter(otInstance *aInstance, uint8_t aRouterJitter);
+OTAPI void OTCALL otSetRouterSelectionJitter(otInstance *aInstance, uint8_t aRouterJitter);
/**
* @}
@@ -1801,7 +1874,7 @@ void otSetRouterSelectionJitter(otInstance *aInstance, uint8_t aRouterJitter);
* @param[out] aChildInfo A pointer to where the child information is placed.
*
*/
-ThreadError otGetChildInfoById(otInstance *aInstance, uint16_t aChildId, otChildInfo *aChildInfo);
+OTAPI ThreadError OTCALL otGetChildInfoById(otInstance *aInstance, uint16_t aChildId, otChildInfo *aChildInfo);
/**
* The function retains diagnostic information for an attached Child by the internal table index.
@@ -1811,7 +1884,7 @@ ThreadError otGetChildInfoById(otInstance *aInstance, uint16_t aChildId, otChild
* @param[out] aChildInfo A pointer to where the child information is placed.
*
*/
-ThreadError otGetChildInfoByIndex(otInstance *aInstance, uint8_t aChildIndex, otChildInfo *aChildInfo);
+OTAPI ThreadError OTCALL otGetChildInfoByIndex(otInstance *aInstance, uint8_t aChildIndex, otChildInfo *aChildInfo);
/**
* This function gets the next neighbor information. It is used to go through the entries of
@@ -1840,7 +1913,7 @@ ThreadError otGetNextNeighborInfo(otInstance *aInstance, otNeighborInfoIterator
* @retval ::kDeviceRoleRouter The device is currently operating as a Thread Router.
* @retval ::kDeviceRoleLeader The device is currently operating as a Thread Leader.
*/
-otDeviceRole otGetDeviceRole(otInstance *aInstance);
+OTAPI otDeviceRole OTCALL otGetDeviceRole(otInstance *aInstance);
/**
* This function gets an EID cache entry.
@@ -1853,7 +1926,7 @@ otDeviceRole otGetDeviceRole(otInstance *aInstance);
* @retval kThreadError_InvalidArgs @p aIndex was out of bounds or @p aEntry was NULL.
*
*/
-ThreadError otGetEidCacheEntry(otInstance *aInstance, uint8_t aIndex, otEidCacheEntry *aEntry);
+OTAPI ThreadError OTCALL otGetEidCacheEntry(otInstance *aInstance, uint8_t aIndex, otEidCacheEntry *aEntry);
/**
* This function get the Thread Leader Data.
@@ -1866,7 +1939,7 @@ ThreadError otGetEidCacheEntry(otInstance *aInstance, uint8_t aIndex, otEidCache
* @retval kThreadError_InvalidArgs @p aLeaderData is NULL.
*
*/
-ThreadError otGetLeaderData(otInstance *aInstance, otLeaderData *aLeaderData);
+OTAPI ThreadError OTCALL otGetLeaderData(otInstance *aInstance, otLeaderData *aLeaderData);
/**
* Get the Leader's Router ID.
@@ -1875,7 +1948,7 @@ ThreadError otGetLeaderData(otInstance *aInstance, otLeaderData *aLeaderData);
*
* @returns The Leader's Router ID.
*/
-uint8_t otGetLeaderRouterId(otInstance *aInstance);
+OTAPI uint8_t OTCALL otGetLeaderRouterId(otInstance *aInstance);
/**
* Get the Leader's Weight.
@@ -1884,7 +1957,7 @@ uint8_t otGetLeaderRouterId(otInstance *aInstance);
*
* @returns The Leader's Weight.
*/
-uint8_t otGetLeaderWeight(otInstance *aInstance);
+OTAPI uint8_t OTCALL otGetLeaderWeight(otInstance *aInstance);
/**
* Get the Network Data Version.
@@ -1893,7 +1966,7 @@ uint8_t otGetLeaderWeight(otInstance *aInstance);
*
* @returns The Network Data Version.
*/
-uint8_t otGetNetworkDataVersion(otInstance *aInstance);
+OTAPI uint8_t OTCALL otGetNetworkDataVersion(otInstance *aInstance);
/**
* Get the Partition ID.
@@ -1902,7 +1975,7 @@ uint8_t otGetNetworkDataVersion(otInstance *aInstance);
*
* @returns The Partition ID.
*/
-uint32_t otGetPartitionId(otInstance *aInstance);
+OTAPI uint32_t OTCALL otGetPartitionId(otInstance *aInstance);
/**
* Get the RLOC16.
@@ -1911,7 +1984,7 @@ uint32_t otGetPartitionId(otInstance *aInstance);
*
* @returns The RLOC16.
*/
-uint16_t otGetRloc16(otInstance *aInstance);
+OTAPI uint16_t OTCALL otGetRloc16(otInstance *aInstance);
/**
* Get the current Router ID Sequence.
@@ -1920,7 +1993,7 @@ uint16_t otGetRloc16(otInstance *aInstance);
*
* @returns The Router ID Sequence.
*/
-uint8_t otGetRouterIdSequence(otInstance *aInstance);
+OTAPI uint8_t OTCALL otGetRouterIdSequence(otInstance *aInstance);
/**
* The function retains diagnostic information for a given Thread Router.
@@ -1930,7 +2003,7 @@ uint8_t otGetRouterIdSequence(otInstance *aInstance);
* @param[out] aRouterInfo A pointer to where the router information is placed.
*
*/
-ThreadError otGetRouterInfo(otInstance *aInstance, uint16_t aRouterId, otRouterInfo *aRouterInfo);
+OTAPI ThreadError OTCALL otGetRouterInfo(otInstance *aInstance, uint16_t aRouterId, otRouterInfo *aRouterInfo);
/**
* The function retains diagnostic information for a Thread Router as parent.
@@ -1939,7 +2012,7 @@ ThreadError otGetRouterInfo(otInstance *aInstance, uint16_t aRouterId, otRouterI
* @param[out] aParentInfo A pointer to where the parent router information is placed.
*
*/
-ThreadError otGetParentInfo(otInstance *aInstance, otRouterInfo *aParentInfo);
+OTAPI ThreadError OTCALL otGetParentInfo(otInstance *aInstance, otRouterInfo *aParentInfo);
/**
* Get the Stable Network Data Version.
@@ -1948,58 +2021,28 @@ ThreadError otGetParentInfo(otInstance *aInstance, otRouterInfo *aParentInfo);
*
* @returns The Stable Network Data Version.
*/
-uint8_t otGetStableNetworkDataVersion(otInstance *aInstance);
+OTAPI uint8_t OTCALL otGetStableNetworkDataVersion(otInstance *aInstance);
/**
- * This function pointer is called when an IEEE 802.15.4 frame is received.
- *
- * @note This callback is called after FCS processing and @p aFrame may not contain the actual FCS that was received.
- *
- * @note This callback is called before IEEE 802.15.4 security processing and mSecurityValid in @p aFrame will
- * always be false.
- *
- * @param[in] aFrame A pointer to the received IEEE 802.15.4 frame.
- * @param[in] aContext A pointer to application-specific context.
+ * Send a Network Diagnostic Get request
*
+ * @param[in] aDestination A pointer to destination address.
+ * @param[in] aTlvTypes An array of Network Diagnostic TLV types.
+ * @param[in] aCount Number of types in aTlvTypes
*/
-typedef void (*otLinkPcapCallback)(const RadioPacket *aFrame, void *aContext);
+OTAPI ThreadError OTCALL otSendDiagnosticGet(otInstance *aInstance, const otIp6Address *aDestination,
+ const uint8_t aTlvTypes[], uint8_t aCount);
/**
- * This function registers a callback to provide received raw IEEE 802.15.4 frames.
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- * @param[in] aPcapCallback A pointer to a function that is called when receiving an IEEE 802.15.4 link frame or
- * NULL to disable the callback.
- * @param[in] aCallbackContext A pointer to application-specific context.
+ * Send a Network Diagnostic Reset request
*
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aDestination A pointer to destination address.
+ * @param[in] aTlvTypes An array of Network Diagnostic TLV types. Currently only Type 9 is allowed.
+ * @param[in] aCount Number of types in aTlvTypes
*/
-void otSetLinkPcapCallback(otInstance *aInstance, otLinkPcapCallback aPcapCallback, void *aCallbackContext);
-
-/**
- * This function indicates whether or not promiscuous mode is enabled at the link layer.
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- *
- * @retval true Promiscuous mode is enabled.
- * @retval false Promiscuous mode is not enabled.
- *
- */
-bool otIsLinkPromiscuous(otInstance *aInstance);
-
-/**
- * This function enables or disables the link layer promiscuous mode.
- *
- * @note Promiscuous mode may only be enabled when the Thread interface is disabled.
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- * @param[in] aPromiscuous true to enable promiscuous mode, or false otherwise.
- *
- * @retval kThreadError_None Successfully enabled promiscuous mode.
- * @retval kThreadError_InvalidState Could not enable promiscuous mode because
- * the Thread interface is enabled.
- *
- */
-ThreadError otSetLinkPromiscuous(otInstance *aInstance, bool aPromiscuous);
+OTAPI ThreadError OTCALL otSendDiagnosticReset(otInstance *aInstance, const otIp6Address *aDestination,
+ const uint8_t aTlvTypes[], uint8_t aCount);
/**
* Get the MAC layer counters.
@@ -2008,7 +2051,7 @@ ThreadError otSetLinkPromiscuous(otInstance *aInstance, bool aPromiscuous);
*
* @returns A pointer to the MAC layer counters.
*/
-const otMacCounters *otGetMacCounters(otInstance *aInstance);
+OTAPI const otMacCounters *OTCALL otGetMacCounters(otInstance *aInstance);
/**
* @}
@@ -2024,7 +2067,7 @@ const otMacCounters *otGetMacCounters(otInstance *aInstance);
* @retval TRUE The two IPv6 addresses are the same.
* @retval FALSE The two IPv6 addresses are not the same.
*/
-bool otIsIp6AddressEqual(const otIp6Address *a, const otIp6Address *b);
+OTAPI bool OTCALL otIsIp6AddressEqual(const otIp6Address *a, const otIp6Address *b);
/**
* Convert a human-readable IPv6 address string into a binary representation.
@@ -2035,285 +2078,7 @@ bool otIsIp6AddressEqual(const otIp6Address *a, const otIp6Address *b);
* @retval kThreadErrorNone Successfully parsed the string.
* @retval kThreadErrorInvalidArg Failed to parse the string.
*/
-ThreadError otIp6AddressFromString(const char *aString, otIp6Address *aAddress);
-
-/**
- * @addtogroup messages Message Buffers
- *
- * @brief
- * This module includes functions that manipulate OpenThread message buffers
- *
- * @{
- *
- */
-
-/**
- * Free an allocated message buffer.
- *
- * @param[in] aMessage A pointer to a message buffer.
- *
- * @retval kThreadErrorNone Successfully freed the message buffer.
- *
- * @sa otNewUdpMessage
- * @sa otAppendMessage
- * @sa otGetMessageLength
- * @sa otSetMessageLength
- * @sa otGetMessageOffset
- * @sa otSetMessageOffset
- * @sa otReadMessage
- * @sa otWriteMessage
- */
-ThreadError otFreeMessage(otMessage aMessage);
-
-/**
- * Get the message length in bytes.
- *
- * @param[in] aMessage A pointer to a message buffer.
- *
- * @returns The message length in bytes.
- *
- * @sa otNewUdpMessage
- * @sa otFreeMessage
- * @sa otAppendMessage
- * @sa otSetMessageLength
- * @sa otGetMessageOffset
- * @sa otSetMessageOffset
- * @sa otReadMessage
- * @sa otWriteMessage
- * @sa otSetMessageLength
- */
-uint16_t otGetMessageLength(otMessage aMessage);
-
-/**
- * Set the message length in bytes.
- *
- * @param[in] aMessage A pointer to a message buffer.
- * @param[in] aLength A length in bytes.
- *
- * @retval kThreadErrorNone Successfully set the message length.
- * @retval kThreadErrorNoBufs No available buffers to grow the message.
- *
- * @sa otNewUdpMessage
- * @sa otFreeMessage
- * @sa otAppendMessage
- * @sa otGetMessageLength
- * @sa otGetMessageOffset
- * @sa otSetMessageOffset
- * @sa otReadMessage
- * @sa otWriteMessage
- */
-ThreadError otSetMessageLength(otMessage aMessage, uint16_t aLength);
-
-/**
- * Get the message offset in bytes.
- *
- * @param[in] aMessage A pointer to a message buffer.
- *
- * @returns The message offset value.
- *
- * @sa otNewUdpMessage
- * @sa otFreeMessage
- * @sa otAppendMessage
- * @sa otGetMessageLength
- * @sa otSetMessageLength
- * @sa otSetMessageOffset
- * @sa otReadMessage
- * @sa otWriteMessage
- */
-uint16_t otGetMessageOffset(otMessage aMessage);
-
-/**
- * Set the message offset in bytes.
- *
- * @param[in] aMessage A pointer to a message buffer.
- * @param[in] aOffset An offset in bytes.
- *
- * @retval kThreadErrorNone Successfully set the message offset.
- * @retval kThreadErrorInvalidArg The offset is beyond the message length.
- *
- * @sa otNewUdpMessage
- * @sa otFreeMessage
- * @sa otAppendMessage
- * @sa otGetMessageLength
- * @sa otSetMessageLength
- * @sa otGetMessageOffset
- * @sa otReadMessage
- * @sa otWriteMessage
- */
-ThreadError otSetMessageOffset(otMessage aMessage, uint16_t aOffset);
-
-/**
- * Append bytes to a message.
- *
- * @param[in] aMessage A pointer to a message buffer.
- * @param[in] aBuf A pointer to the data to append.
- * @param[in] aLength Number of bytes to append.
- *
- * @retval kThreadErrorNone Successfully appended to the message
- * @retval kThreadErrorNoBufs No available buffers to grow the message.
- *
- * @sa otNewUdpMessage
- * @sa otFreeMessage
- * @sa otGetMessageLength
- * @sa otSetMessageLength
- * @sa otGetMessageOffset
- * @sa otSetMessageOffset
- * @sa otReadMessage
- * @sa otWriteMessage
- */
-ThreadError otAppendMessage(otMessage aMessage, const void *aBuf, uint16_t aLength);
-
-/**
- * Read bytes from a message.
- *
- * @param[in] aMessage A pointer to a message buffer.
- * @param[in] aOffset An offset in bytes.
- * @param[in] aBuf A pointer to a buffer that message bytes are read to.
- * @param[in] aLength Number of bytes to read.
- *
- * @returns The number of bytes read.
- *
- * @sa otNewUdpMessage
- * @sa otFreeMessage
- * @sa otAppendMessage
- * @sa otGetMessageLength
- * @sa otSetMessageLength
- * @sa otGetMessageOffset
- * @sa otSetMessageOffset
- * @sa otWriteMessage
- */
-int otReadMessage(otMessage aMessage, uint16_t aOffset, void *aBuf, uint16_t aLength);
-
-/**
- * Write bytes to a message.
- *
- * @param[in] aMessage A pointer to a message buffer.
- * @param[in] aOffset An offset in bytes.
- * @param[in] aBuf A pointer to a buffer that message bytes are written from.
- * @param[in] aLength Number of bytes to write.
- *
- * @returns The number of bytes written.
- *
- * @sa otNewUdpMessage
- * @sa otFreeMessage
- * @sa otAppendMessage
- * @sa otGetMessageLength
- * @sa otSetMessageLength
- * @sa otGetMessageOffset
- * @sa otSetMessageOffset
- * @sa otReadMessage
- */
-int otWriteMessage(otMessage aMessage, uint16_t aOffset, const void *aBuf, uint16_t aLength);
-
-/**
- * @}
- *
- */
-
-/**
- * @addtogroup ip6 IPv6
- *
- * @brief
- * This module includes functions that control IPv6 communication.
- *
- * @{
- *
- */
-
-/**
- * Allocate a new message buffer for sending an IPv6 message.
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- * @param[in] aLinkSecurityEnabled TRUE if the message should be secured at Layer 2
- *
- * @returns A pointer to the message buffer or NULL if no message buffers are available.
- *
- * @sa otFreeMessage
- */
-otMessage otNewIp6Message(otInstance *aInstance, bool aLinkSecurityEnabled);
-
-/**
- * This function pointer is called when an IPv6 datagram is received.
- *
- * @param[in] aMessage A pointer to the message buffer containing the received IPv6 datagram.
- * @param[in] aContext A pointer to application-specific context.
- *
- */
-typedef void (*otReceiveIp6DatagramCallback)(otMessage aMessage, void *aContext);
-
-/**
- * This function registers a callback to provide received IPv6 datagrams.
- *
- * By default, this callback does not pass Thread control traffic. See otSetReceiveIp6DatagramFilterEnabled() to
- * change the Thread control traffic filter setting.
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- * @param[in] aCallback A pointer to a function that is called when an IPv6 datagram is received or
- * NULL to disable the callback.
- * @param[in] aCallbackContext A pointer to application-specific context.
- *
- * @sa otIsReceiveIp6DatagramFilterEnabled
- * @sa otSetReceiveIp6DatagramFilterEnabled
- *
- */
-void otSetReceiveIp6DatagramCallback(otInstance *aInstance, otReceiveIp6DatagramCallback aCallback,
- void *aCallbackContext);
-
-/**
- * This function indicates whether or not Thread control traffic is filtered out when delivering IPv6 datagrams
- * via the callback specified in otSetReceiveIp6DatagramCallback().
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- *
- * @returns TRUE if Thread control traffic is filtered out, FALSE otherwise.
- *
- * @sa otSetReceiveIp6DatagramCallback
- * @sa otSetReceiveIp6DatagramFilterEnabled
- *
- */
-bool otIsReceiveIp6DatagramFilterEnabled(otInstance *aInstance);
-
-/**
- * This function sets whether or not Thread control traffic is filtered out when delivering IPv6 datagrams
- * via the callback specified in otSetReceiveIp6DatagramCallback().
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- * @param[in] aEnabled TRUE if Thread control traffic is filtered out, FALSE otherwise.
- *
- * @sa otSetReceiveIp6DatagramCallback
- * @sa otIsReceiveIp6DatagramFilterEnabled
- *
- */
-void otSetReceiveIp6DatagramFilterEnabled(otInstance *aInstance, bool aEnabled);
-
-/**
- * This function sends an IPv6 datagram via the Thread interface.
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- * @param[in] aMessage A pointer to the message buffer containing the IPv6 datagram.
- *
- */
-ThreadError otSendIp6Datagram(otInstance *aInstance, otMessage aMessage);
-
-/**
- * This function indicates whether or not ICMPv6 Echo processing is enabled.
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- *
- * @retval TRUE ICMPv6 Echo processing is enabled.
- * @retval FALSE ICMPv6 Echo processing is disabled.
- *
- */
-bool otIsIcmpEchoEnabled(otInstance *aInstance);
-
-/**
- * This function sets whether or not ICMPv6 Echo processing is enabled.
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- * @param[in] aEnabled TRUE to enable ICMPv6 Echo processing, FALSE otherwise.
- *
- */
-void otSetIcmpEchoEnabled(otInstance *aInstance, bool aEnabled);
+OTAPI ThreadError OTCALL otIp6AddressFromString(const char *aString, otIp6Address *aAddress);
/**
* This function returns the prefix match length (bits) for two IPv6 addresses.
@@ -2324,122 +2089,7 @@ void otSetIcmpEchoEnabled(otInstance *aInstance, bool aEnabled);
* @returns The prefix match length in bits.
*
*/
-uint8_t otIp6PrefixMatch(const otIp6Address *aFirst, const otIp6Address *aSecond);
-
-/**
- * @}
- *
- */
-
-/**
- * @addtogroup udp UDP
- *
- * @brief
- * This module includes functions that control UDP communication.
- *
- * @{
- *
- */
-
-/**
- * Allocate a new message buffer for sending a UDP message.
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- * @param[in] aLinkSecurityEnabled TRUE if the message should be secured at Layer 2.
- *
- * @returns A pointer to the message buffer or NULL if no message buffers are available.
- *
- * @sa otFreeMessage
- */
-otMessage otNewUdpMessage(otInstance *aInstance, bool aLinkSecurityEnabled);
-
-/**
- * Open a UDP/IPv6 socket.
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- * @param[in] aSocket A pointer to a UDP socket structure.
- * @param[in] aCallback A pointer to the application callback function.
- * @param[in] aContext A pointer to application-specific context.
- *
- * @retval kThreadErrorNone Successfully opened the socket.
- * @retval kThreadErrorInvalidArgs Given socket structure was already opened.
- *
- * @sa otNewUdpMessage
- * @sa otCloseUdpSocket
- * @sa otBindUdpSocket
- * @sa otSendUdp
- */
-ThreadError otOpenUdpSocket(otInstance *aInstance, otUdpSocket *aSocket, otUdpReceive aCallback, void *aContext);
-
-/**
- * Close a UDP/IPv6 socket.
- *
- * @param[in] aSocket A pointer to a UDP socket structure.
- *
- * @retval kThreadErrorNone Successfully closed the socket.
- *
- * @sa otNewUdpMessage
- * @sa otOpenUdpSocket
- * @sa otBindUdpSocket
- * @sa otSendUdp
- */
-ThreadError otCloseUdpSocket(otUdpSocket *aSocket);
-
-/**
- * Bind a UDP/IPv6 socket.
- *
- * @param[in] aSocket A pointer to a UDP socket structure.
- * @param[in] aSockName A pointer to an IPv6 socket address structure.
- *
- * @retval kThreadErrorNone Bind operation was successful.
- *
- * @sa otNewUdpMessage
- * @sa otOpenUdpSocket
- * @sa otCloseUdpSocket
- * @sa otSendUdp
- */
-ThreadError otBindUdpSocket(otUdpSocket *aSocket, otSockAddr *aSockName);
-
-/**
- * Send a UDP/IPv6 message.
- *
- * @param[in] aSocket A pointer to a UDP socket structure.
- * @param[in] aMessage A pointer to a message buffer.
- * @param[in] aMessageInfo A pointer to a message info structure.
- *
- * @sa otNewUdpMessage
- * @sa otOpenUdpSocket
- * @sa otCloseUdpSocket
- * @sa otBindUdpSocket
- * @sa otSendUdp
- */
-ThreadError otSendUdp(otUdpSocket *aSocket, otMessage aMessage, const otMessageInfo *aMessageInfo);
-
-/**
- * Send a Network Diagnostic Get request
- *
- * @param[in] aDestination A pointer to destination address.
- * @param[in] aTlvTypes An array of Network Diagnostic TLV types.
- * @param[in] aCount Number of types in aTlvTypes
- */
-ThreadError otSendDiagnosticGet(otInstance *aInstance, const otIp6Address *aDestination, const uint8_t aTlvTypes[],
- uint8_t aCount);
-
-/**
- * Send a Network Diagnostic Reset request
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- * @param[in] aDestination A pointer to destination address.
- * @param[in] aTlvTypes An array of Network Diagnostic TLV types. Currently only Type 9 is allowed.
- * @param[in] aCount Number of types in aTlvTypes
- */
-ThreadError otSendDiagnosticReset(otInstance *aInstance, const otIp6Address *aDestination, const uint8_t aTlvTypes[],
- uint8_t aCount);
-
-/**
- * @}
- *
- */
+OTAPI uint8_t OTCALL otIp6PrefixMatch(const otIp6Address *aFirst, const otIp6Address *aSecond);
#ifdef __cplusplus
} // extern "C"
diff --git a/include/platform/toolchain.h b/include/platform/toolchain.h
index 9b9d39d8d..bf684687d 100644
--- a/include/platform/toolchain.h
+++ b/include/platform/toolchain.h
@@ -96,6 +96,8 @@ extern "C" {
#define OT_TOOL_PACKED_FIELD __attribute__((packed))
#define OT_TOOL_PACKED_END __attribute__((packed))
+#define OT_TOOL_ALIGN(X)
+
#elif defined(__ICCARM__) || defined(__ICC8051__)
// http://supp.iar.com/FilesPublic/UPDINFO/004916/arm/doc/EWARM_DevelopmentGuide.ENU.pdf
@@ -106,12 +108,16 @@ extern "C" {
#define OT_TOOL_PACKED_FIELD
#define OT_TOOL_PACKED_END
+#define OT_TOOL_ALIGN(X)
+
#elif defined(_MSC_VER)
#define OT_TOOL_PACKED_BEGIN __pragma(pack(push,1))
#define OT_TOOL_PACKED_FIELD
#define OT_TOOL_PACKED_END __pragma(pack(pop))
+#define OT_TOOL_ALIGN(X) __declspec(align(4))
+
#elif defined(__SDCC)
// Structures are packed by default in sdcc, as it primarily targets 8-bit MCUs.
@@ -120,6 +126,8 @@ extern "C" {
#define OT_TOOL_PACKED_FIELD
#define OT_TOOL_PACKED_END
+#define OT_TOOL_ALIGN(X)
+
#else
#error "Error: No valid Toolchain specified"
@@ -130,6 +138,8 @@ extern "C" {
#define OT_TOOL_PACKED_FIELD
#define OT_TOOL_PACKED_END
+#define OT_TOOL_ALIGN(X)
+
#endif
// =========== TOOLCHAIN SELECTION : END ===========
@@ -137,10 +147,8 @@ extern "C" {
#ifdef _MSC_VER
#ifdef _WIN64
-#define OT_CALL
#define OT_CDECL
#else
-#define OT_CALL __stdcall
#define OT_CDECL __cdecl
#endif
@@ -151,6 +159,16 @@ extern "C" {
#endif
+#ifdef OTDLL
+#ifndef OTAPI
+#define OTAPI __declspec(dllimport)
+#endif
+#define OTCALL WINAPI
+#else
+#define OTAPI
+#define OTCALL
+#endif
+
/**
* @}
*
diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp
index f3dce9c1a..fd0185161 100644
--- a/src/cli/cli.cpp
+++ b/src/cli/cli.cpp
@@ -2033,6 +2033,10 @@ void Interpreter::ProcessState(int argc, char *argv[])
{
switch (otGetDeviceRole(mInstance))
{
+ case kDeviceRoleOffline:
+ sServer->OutputFormat("offline\r\n");
+ break;
+
case kDeviceRoleDisabled:
sServer->OutputFormat("disabled\r\n");
break;
diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp
index ad4657d06..364633e81 100644
--- a/src/cli/cli.hpp
+++ b/src/cli/cli.hpp
@@ -42,6 +42,8 @@
#include
+#include
+#include
#include
#include
#include
diff --git a/src/core/common/tasklet.hpp b/src/core/common/tasklet.hpp
index e6c83c29c..497bdb489 100644
--- a/src/core/common/tasklet.hpp
+++ b/src/core/common/tasklet.hpp
@@ -35,6 +35,7 @@
#define TASKLET_HPP_
#include
+#include
namespace Thread {
diff --git a/src/core/net/ip6.hpp b/src/core/net/ip6.hpp
index 6a96c3299..d973ecb6e 100644
--- a/src/core/net/ip6.hpp
+++ b/src/core/net/ip6.hpp
@@ -36,7 +36,8 @@
#include
-#include
+#include
+#include
#include
#include
#include
diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp
index 862f5bb0c..26e3a436d 100644
--- a/src/ncp/ncp_base.cpp
+++ b/src/ncp/ncp_base.cpp
@@ -1728,6 +1728,7 @@ ThreadError NcpBase::GetPropertyHandler_NET_ROLE(uint8_t header, spinel_prop_key
switch (otGetDeviceRole(mInstance))
{
+ case kDeviceRoleOffline:
case kDeviceRoleDisabled:
case kDeviceRoleDetached:
role = SPINEL_NET_ROLE_DETACHED;