mirror of
https://github.com/espressif/openthread.git
synced 2026-08-02 00:57:47 +00:00
Windows otLwf Tunnel Mode (#984)
* Integrate 'Tunnel Mode' otLwf code and a few other minor changes in the Windows code/projects.
This commit is contained in:
@@ -57,6 +57,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenThread", "OpenThread.vc
|
||||
{ED0EA262-C222-42C7-98D3-E70C72978ED2} = {ED0EA262-C222-42C7-98D3-E70C72978ED2}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spinel_k", "spinel_k.vcxproj", "{A55766B5-58B6-4519-835E-5A4B7C164B5A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM = Debug|ARM
|
||||
@@ -291,6 +293,24 @@ Global
|
||||
{F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Release|x86.ActiveCfg = Release|Win32
|
||||
{F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Release|x86.Build.0 = Release|Win32
|
||||
{F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Release|x86.Deploy.0 = Release|Win32
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Debug|x64.Build.0 = Debug|x64
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Debug|x86.Build.0 = Debug|Win32
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Debug|x86.Deploy.0 = Debug|Win32
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Release|ARM.Build.0 = Release|ARM
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Release|x64.ActiveCfg = Release|x64
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Release|x64.Build.0 = Release|x64
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Release|x64.Deploy.0 = Release|x64
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Release|x86.ActiveCfg = Release|Win32
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Release|x86.Build.0 = Release|Win32
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Release|x86.Deploy.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -313,5 +333,6 @@ Global
|
||||
{B7C6F344-7287-4930-AF38-223622BD8CBB} = {61E8A4A0-8138-49DB-97B4-3BEC87C8E133}
|
||||
{D5577E51-FA31-4802-8669-1DB32805935E} = {35F6AB71-5BD2-4D53-8A51-D75CCD4CCC3D}
|
||||
{F8C22844-9B93-4978-80DF-8AF2B37A7ABB} = {76EA541E-CAB1-4DB5-A39F-E3DB2A78CDDD}
|
||||
{A55766B5-58B6-4519-835E-5A4B7C164B5A} = {95BD0669-04C8-4EEB-B3CC-0535B03F4468}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
..\..\include;
|
||||
..\..\examples\drivers\windows\include;
|
||||
..\..\examples\drivers\windows\otLwf;
|
||||
..\..\src;
|
||||
..\..\src\core;
|
||||
..\..\src\missing\stdint;
|
||||
..\..\src\missing\stdbool;
|
||||
@@ -78,6 +79,9 @@
|
||||
cng.lib;
|
||||
</AdditionalDependencies>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command Condition="'$(Platform)'=='ARM'">inf2cat /driver:$(TargetDir) /os:8_ARM</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\address.c" />
|
||||
@@ -87,6 +91,8 @@
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\eventprocessing.c" />
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\iocontrol.c" />
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\settings.c" />
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\thread.c" />
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\tunnel.c" />
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\oid.c" />
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\precomp.c">
|
||||
<AdditionalIncludeDirectories>..;.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
@@ -103,6 +109,8 @@
|
||||
<ClInclude Include="..\..\examples\drivers\windows\otLwf\nsihelper.h" />
|
||||
<ClInclude Include="..\..\examples\drivers\windows\otLwf\oid.h" />
|
||||
<ClInclude Include="..\..\examples\drivers\windows\otLwf\radio.h" />
|
||||
<ClInclude Include="..\..\examples\drivers\windows\otLwf\thread.h" />
|
||||
<ClInclude Include="..\..\examples\drivers\windows\otLwf\tunnel.h" />
|
||||
<ClInclude Include="..\..\examples\drivers\windows\otLwf\precomp.h" />
|
||||
<ClInclude Include="..\..\examples\drivers\windows\otLwf\filter.h" />
|
||||
<ResourceCompile Include="..\..\examples\drivers\windows\otLwf\filter.rc" />
|
||||
@@ -118,6 +126,9 @@
|
||||
<ProjectReference Include="mbedtls_k.vcxproj">
|
||||
<Project>{69be8e8c-cf1e-46d6-932b-db435f47059b}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="spinel_k.vcxproj">
|
||||
<Project>{a55766b5-58b6-4519-835e-5a4b7c164b5a}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
|
||||
@@ -48,6 +48,12 @@
|
||||
<ClInclude Include="..\..\examples\drivers\windows\otLwf\radio.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\examples\drivers\windows\otLwf\thread.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\examples\drivers\windows\otLwf\tunnel.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\filter.c">
|
||||
@@ -83,6 +89,12 @@
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\address.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\tunnel.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\thread.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\settings.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="openthread.configuration.props" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{A55766B5-58B6-4519-835E-5A4B7C164B5A}</ProjectGuid>
|
||||
<TemplateGuid>{8c0e3d8b-df43-455b-815a-4a0e72973bc6}</TemplateGuid>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
|
||||
<RootNamespace>Thread</RootNamespace>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="PropertySheets">
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup>
|
||||
<OutDir>..\..\build\bin\$(Platform)\$(Configuration)\lib\</OutDir>
|
||||
<IntDir>..\..\build\obj\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>
|
||||
%(PreprocessorDefinitions);
|
||||
HAVE_STRNLEN=1;
|
||||
SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR=1;
|
||||
</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>
|
||||
%(AdditionalIncludeDirectories);
|
||||
..\..\include;
|
||||
..\..\src\missing\stdint;
|
||||
..\..\src\missing\stdbool;
|
||||
</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>4100;4706;4748;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppScanConfigurationData>..\..\include\platform\logging-windows.h</WppScanConfigurationData>
|
||||
<WppAdditionalOptions>-km %(WppAdditionalOptions)</WppAdditionalOptions>
|
||||
<WppModuleName>otCore</WppModuleName>
|
||||
<WppSearchString>WPP_INIT_TRACING</WppSearchString>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\ncp\spinel.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\ncp\spinel.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{C034F7F4-3CBD-4B9A-A033-0D76A195B581}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{7A95885E-AD23-439A-B283-9BDE0E39D84E}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{1E1DF93E-9746-4688-A1F0-7B59378CF28F}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\ncp\spinel.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\ncp\spinel.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -36,6 +36,11 @@
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<Grid>
|
||||
<Grid.Background>
|
||||
<ImageBrush ImageSource="ms-appx:///Assets/Wide310x150Logo.png" Opacity="0.25" Stretch="Uniform"/>
|
||||
</Grid.Background>
|
||||
</Grid>
|
||||
<!-- Interface List -->
|
||||
<TextBlock
|
||||
Text="Thread UX"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">
|
||||
<Identity Name="7926e3f9-835e-421c-94c1-2812f3569f4a" Publisher="CN=nibanks" Version="1.0.10.0" />
|
||||
<Identity Name="7926e3f9-835e-421c-94c1-2812f3569f4a" Publisher="CN=nibanks" Version="1.0.12.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="7926e3f9-835e-421c-94c1-2812f3569f4a" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>OpenThread</DisplayName>
|
||||
|
||||
@@ -256,10 +256,12 @@ typedef enum _OTLWF_NOTIF_TYPE
|
||||
// GUID - InterfaceGuid
|
||||
// otShortAddress - aShortAddress
|
||||
|
||||
/* NOT USED
|
||||
#define IOCTL_OTLWF_OT_UNICAST_ADDRESSES \
|
||||
OTLWF_CTL_CODE(120, METHOD_BUFFERED, FILE_READ_DATA)
|
||||
// GUID - InterfaceGuid
|
||||
// otNetifAddress[] - aAddresses
|
||||
*/
|
||||
|
||||
#define IOCTL_OTLWF_OT_ACTIVE_DATASET \
|
||||
OTLWF_CTL_CODE(121, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
|
||||
@@ -616,6 +618,7 @@ typedef struct otCommissionConfig
|
||||
// GUID - InterfaceGuid
|
||||
// uint8_t - aLength
|
||||
// uint8_t[aLength] - aTlvTypes
|
||||
// otIp6Address - aAddress (optional)
|
||||
|
||||
#define IOCTL_OTLWF_OT_SEND_ACTIVE_SET \
|
||||
OTLWF_CTL_CODE(186, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
@@ -629,6 +632,7 @@ typedef struct otCommissionConfig
|
||||
// GUID - InterfaceGuid
|
||||
// uint8_t - aLength
|
||||
// uint8_t[aLength] - aTlvTypes
|
||||
// otIp6Address - aAddress (optional)
|
||||
|
||||
#define IOCTL_OTLWF_OT_SEND_PENDING_SET \
|
||||
OTLWF_CTL_CODE(188, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
@@ -654,9 +658,13 @@ typedef struct otCommissionConfig
|
||||
OTLWF_CTL_CODE(191, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
|
||||
// GUID - InterfaceGuid
|
||||
// uint32_t - aKeySwitchGuardTime
|
||||
|
||||
#define IOCTL_OTLWF_OT_FACTORY_RESET \
|
||||
OTLWF_CTL_CODE(192, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
// GUID - InterfaceGuid
|
||||
|
||||
// OpenThread function IOCTL codes
|
||||
#define MIN_OTLWF_IOCTL_FUNC_CODE 100
|
||||
#define MAX_OTLWF_IOCTL_FUNC_CODE 191
|
||||
#define MAX_OTLWF_IOCTL_FUNC_CODE 192
|
||||
|
||||
#endif //__OTLWFIOCTL_H__
|
||||
|
||||
@@ -35,7 +35,7 @@ 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;
|
||||
const DWORD c_MaxOverlappedWaitTimeMS = 5 * 1000;
|
||||
|
||||
// Version string returned by the API
|
||||
const char c_Version[] = "Windows"; // TODO - What should we really put here?
|
||||
@@ -2144,6 +2144,7 @@ otSendActiveGet(
|
||||
if (aTlvTypes == nullptr && aLength != 0) return kThreadError_InvalidArgs;
|
||||
|
||||
DWORD BufferSize = sizeof(GUID) + sizeof(uint8_t) + aLength;
|
||||
if (aAddress) BufferSize += sizeof(otIp6Address);
|
||||
PBYTE Buffer = (PBYTE)malloc(BufferSize);
|
||||
if (Buffer == nullptr) return kThreadError_NoBufs;
|
||||
|
||||
@@ -2151,9 +2152,8 @@ otSendActiveGet(
|
||||
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);
|
||||
if (aAddress)
|
||||
memcpy_s(Buffer + sizeof(GUID) + sizeof(uint8_t) + aLength, BufferSize - sizeof(GUID) - sizeof(uint8_t) - aLength, aAddress, sizeof(otIp6Address));
|
||||
|
||||
ThreadError result =
|
||||
DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_SEND_ACTIVE_GET, Buffer, BufferSize, nullptr, 0));
|
||||
@@ -2206,6 +2206,7 @@ otSendPendingGet(
|
||||
if (aTlvTypes == nullptr && aLength != 0) return kThreadError_InvalidArgs;
|
||||
|
||||
DWORD BufferSize = sizeof(GUID) + sizeof(uint8_t) + aLength;
|
||||
if (aAddress) BufferSize += sizeof(otIp6Address);
|
||||
PBYTE Buffer = (PBYTE)malloc(BufferSize);
|
||||
if (Buffer == nullptr) return kThreadError_NoBufs;
|
||||
|
||||
@@ -2213,9 +2214,8 @@ otSendPendingGet(
|
||||
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);
|
||||
if (aAddress)
|
||||
memcpy_s(Buffer + sizeof(GUID) + sizeof(uint8_t) + aLength, BufferSize - sizeof(GUID) - sizeof(uint8_t) - aLength, aAddress, sizeof(otIp6Address));
|
||||
|
||||
ThreadError result =
|
||||
DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_SEND_PENDING_GET, Buffer, BufferSize, nullptr, 0));
|
||||
@@ -2844,8 +2844,7 @@ otFactoryReset(
|
||||
_In_ otInstance *aInstance
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(aInstance);
|
||||
// TODO ...
|
||||
if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_FACTORY_RESET);
|
||||
}
|
||||
|
||||
OTAPI
|
||||
@@ -3042,6 +3041,18 @@ otGetMacCounters(
|
||||
return aCounters;
|
||||
}
|
||||
|
||||
OTAPI
|
||||
void
|
||||
OTCALL
|
||||
otGetMessageBufferInfo(
|
||||
_In_ otInstance *,
|
||||
_Out_ otBufferInfo *aBufferInfo
|
||||
)
|
||||
{
|
||||
// Not supported on Windows
|
||||
ZeroMemory(aBufferInfo, sizeof(otBufferInfo));
|
||||
}
|
||||
|
||||
OTAPI
|
||||
bool
|
||||
OTCALL
|
||||
|
||||
@@ -373,7 +373,7 @@ otLwfEventProcessingAddressChanged(
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfAddressesUpdated(
|
||||
otLwfRadioAddressesUpdated(
|
||||
_In_ PMS_FILTER pFilter
|
||||
)
|
||||
{
|
||||
@@ -382,6 +382,8 @@ otLwfAddressesUpdated(
|
||||
ULONG FoundInOpenThread = 0; // Bit field
|
||||
ULONG OriginalCacheLength = pFilter->otCachedAddrCount;
|
||||
|
||||
NT_ASSERT(pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO);
|
||||
|
||||
const otNetifAddress* addr = otGetUnicastAddresses(pFilter->otCtx);
|
||||
|
||||
// Process the addresses
|
||||
@@ -411,3 +413,76 @@ otLwfAddressesUpdated(
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfTunAddressesUpdated(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_reads_bytes_(value_data_len) const uint8_t* value_data_ptr,
|
||||
_In_ spinel_size_t value_data_len,
|
||||
_Out_ uint32_t *aNotifFlags
|
||||
)
|
||||
{
|
||||
ULONG FoundInOpenThread = 0; // Bit field
|
||||
ULONG OriginalCacheLength = pFilter->otCachedAddrCount;
|
||||
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
NT_ASSERT (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_THREAD);
|
||||
|
||||
*aNotifFlags = 0;
|
||||
|
||||
while (value_data_len > 0)
|
||||
{
|
||||
const uint8_t *entry_ptr = NULL;
|
||||
spinel_size_t entry_len = 0;
|
||||
|
||||
spinel_ssize_t len = spinel_datatype_unpack(value_data_ptr, value_data_len, "D.", &entry_ptr, &entry_len);
|
||||
if (len < 1) break;
|
||||
|
||||
{
|
||||
PIN6_ADDR pAddr = NULL;
|
||||
otNetifAddress addr = { { 0 }, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, NULL };
|
||||
|
||||
spinel_datatype_unpack(
|
||||
entry_ptr,
|
||||
entry_len,
|
||||
"6CLL",
|
||||
&pAddr,
|
||||
&addr.mPrefixLength,
|
||||
&addr.mValidLifetime,
|
||||
&addr.mPreferredLifetime);
|
||||
|
||||
if (pAddr)
|
||||
{
|
||||
int index = otLwfFindCachedAddrIndex(pFilter, pAddr);
|
||||
if (index == -1)
|
||||
{
|
||||
memcpy_s(&addr.mAddress, sizeof(addr.mAddress), pAddr, sizeof(IN6_ADDR));
|
||||
otLwfOnAddressAdded(pFilter, &addr, TRUE);
|
||||
*aNotifFlags |= OT_IP6_ADDRESS_ADDED;
|
||||
}
|
||||
else
|
||||
{
|
||||
NT_ASSERT(index < 8 * sizeof(FoundInOpenThread));
|
||||
FoundInOpenThread |= 1 << index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
value_data_len -= len;
|
||||
value_data_ptr += len;
|
||||
}
|
||||
|
||||
// Look for missing addresses and mark them as removed
|
||||
for (int i = OriginalCacheLength - 1; i >= 0; i--)
|
||||
{
|
||||
if ((FoundInOpenThread & (1 << i)) == 0)
|
||||
{
|
||||
otLwfOnAddressRemoved(pFilter, (ULONG)i, TRUE);
|
||||
*aNotifFlags |= OT_IP6_ADDRESS_REMOVED;
|
||||
}
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
@@ -148,14 +148,34 @@ Arguments:
|
||||
--*/
|
||||
{
|
||||
PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
|
||||
|
||||
UNREFERENCED_PARAMETER(SendCompleteFlags);
|
||||
|
||||
LogFuncEntryMsg(DRIVER_DATA_PATH, "Filter: %p, NBL: %p", FilterModuleContext, NetBufferLists);
|
||||
LogFuncEntryMsg(DRIVER_DATA_PATH, "Filter: %p, NBL: %p %!STATUS!", FilterModuleContext, NetBufferLists, NetBufferLists->Status);
|
||||
|
||||
NT_ASSERT(NetBufferLists == pFilter->SendNetBufferList);
|
||||
NT_ASSERT(kStateTransmit == pFilter->otPhyState);
|
||||
KeSetEvent(&pFilter->SendNetBufferListComplete, 0, FALSE);
|
||||
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
|
||||
{
|
||||
NT_ASSERT(NetBufferLists == pFilter->SendNetBufferList);
|
||||
NT_ASSERT(kStateTransmit == pFilter->otPhyState);
|
||||
KeSetEvent(&pFilter->SendNetBufferListComplete, 0, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
NT_ASSERT(NET_BUFFER_LIST_NEXT_NBL(NetBufferLists) == NULL);
|
||||
PNET_BUFFER NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferLists);
|
||||
|
||||
// Cancel command if we failed to send the NBL
|
||||
if (!NT_SUCCESS(NetBufferLists->Status))
|
||||
{
|
||||
spinel_tid_t tid = (spinel_tid_t)(ULONG_PTR)NetBuffer->ProtocolReserved[1];
|
||||
if (tid != 0)
|
||||
{
|
||||
otLwfCancelCommandHandler(pFilter, NDIS_TEST_SEND_COMPLETE_AT_DISPATCH_LEVEL(SendCompleteFlags), tid);
|
||||
}
|
||||
}
|
||||
|
||||
NetBuffer->DataLength = (ULONG)(ULONG_PTR)NetBuffer->ProtocolReserved[0];
|
||||
NdisAdvanceNetBufferDataStart(NetBuffer, NetBuffer->DataLength, TRUE, NULL);
|
||||
NdisFreeNetBufferList(NetBufferLists);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DATA_PATH);
|
||||
}
|
||||
@@ -214,14 +234,39 @@ Arguments:
|
||||
}
|
||||
else
|
||||
{
|
||||
// Indicate a new NBL to process on our worker thread
|
||||
otLwfEventProcessingIndicateNewNetBufferLists(
|
||||
pFilter,
|
||||
DispatchLevel,
|
||||
FALSE,
|
||||
PortNumber,
|
||||
NetBufferLists
|
||||
);
|
||||
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
|
||||
{
|
||||
// Indicate a new NBL to process on our worker thread
|
||||
otLwfEventProcessingIndicateNewNetBufferLists(
|
||||
pFilter,
|
||||
DispatchLevel,
|
||||
FALSE,
|
||||
PortNumber,
|
||||
NetBufferLists
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
PNET_BUFFER_LIST CurrNbl = NetBufferLists;
|
||||
while (CurrNbl)
|
||||
{
|
||||
PNET_BUFFER CurrNb = NET_BUFFER_LIST_FIRST_NB(CurrNbl);
|
||||
while (CurrNb)
|
||||
{
|
||||
otLwfSendTunnelPacket(pFilter, DispatchLevel, CurrNb, TRUE);
|
||||
CurrNb = NET_BUFFER_NEXT_NB(CurrNb);
|
||||
}
|
||||
|
||||
NET_BUFFER_LIST_STATUS(CurrNbl) = NDIS_STATUS_SUCCESS;
|
||||
CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
|
||||
}
|
||||
|
||||
NdisFSendNetBufferListsComplete(
|
||||
pFilter->FilterHandle,
|
||||
NetBufferLists,
|
||||
DispatchLevel ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0
|
||||
);
|
||||
}
|
||||
|
||||
// Release the data path ref now
|
||||
ExReleaseRundownProtection(&pFilter->DataPathRundown);
|
||||
@@ -273,15 +318,19 @@ Arguments:
|
||||
{
|
||||
LogVerbose(DRIVER_DATA_PATH, "NBL failed on return: %!STATUS!", CurrNbl->Status);
|
||||
}
|
||||
|
||||
//if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO ||
|
||||
// pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_THREAD)
|
||||
{
|
||||
PNET_BUFFER_LIST NblToFree = CurrNbl;
|
||||
PNET_BUFFER NbToFree = NET_BUFFER_LIST_FIRST_NB(NblToFree);
|
||||
|
||||
PNET_BUFFER_LIST NblToFree = CurrNbl;
|
||||
PNET_BUFFER NbToFree = NET_BUFFER_LIST_FIRST_NB(NblToFree);
|
||||
CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
|
||||
NET_BUFFER_LIST_NEXT_NBL(NblToFree) = NULL;
|
||||
|
||||
CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
|
||||
NET_BUFFER_LIST_NEXT_NBL(NblToFree) = NULL;
|
||||
|
||||
NdisAdvanceNetBufferDataStart(NbToFree, NET_BUFFER_DATA_LENGTH(NbToFree), TRUE, NULL);
|
||||
NdisFreeNetBufferList(NblToFree);
|
||||
NdisAdvanceNetBufferDataStart(NbToFree, NET_BUFFER_DATA_LENGTH(NbToFree), TRUE, NULL);
|
||||
NdisFreeNetBufferList(NblToFree);
|
||||
}
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DATA_PATH);
|
||||
@@ -343,8 +392,46 @@ N.B.: It is important to check the ReceiveFlags in NDIS_TEST_RECEIVE_CANNOT_PEND
|
||||
CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
|
||||
}
|
||||
}
|
||||
else if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_THREAD)
|
||||
{
|
||||
PNET_BUFFER_LIST CurrNbl = NetBufferLists;
|
||||
while (CurrNbl)
|
||||
{
|
||||
PNET_BUFFER CurrNb = NET_BUFFER_LIST_FIRST_NB(CurrNbl);
|
||||
while (CurrNb)
|
||||
{
|
||||
PUCHAR Buffer = (PUCHAR)NdisGetDataBuffer(CurrNb, CurrNb->DataLength, NULL, 1, 0);
|
||||
if (Buffer == NULL)
|
||||
{
|
||||
Buffer = (PUCHAR)FILTER_ALLOC_MEM(pFilter->FilterHandle, CurrNb->DataLength);
|
||||
if (Buffer != NULL)
|
||||
{
|
||||
PUCHAR _Buffer = (PUCHAR)NdisGetDataBuffer(CurrNb, CurrNb->DataLength, Buffer, 1, 0);
|
||||
NT_ASSERT(_Buffer == Buffer);
|
||||
UNREFERENCED_PARAMETER(_Buffer);
|
||||
otLwfReceiveTunnelPacket(pFilter, DispatchLevel, Buffer, CurrNb->DataLength);
|
||||
FILTER_FREE_MEM(Buffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
otLwfReceiveTunnelPacket(pFilter, DispatchLevel, Buffer, CurrNb->DataLength);
|
||||
}
|
||||
CurrNb = NET_BUFFER_NEXT_NB(CurrNb);
|
||||
}
|
||||
|
||||
NET_BUFFER_LIST_STATUS(CurrNbl) = NDIS_STATUS_SUCCESS;
|
||||
CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
|
||||
}
|
||||
|
||||
NdisFReturnNetBufferLists(
|
||||
pFilter->FilterHandle,
|
||||
NetBufferLists,
|
||||
DispatchLevel ? NDIS_RETURN_FLAGS_DISPATCH_LEVEL : 0
|
||||
);
|
||||
}
|
||||
// Try to grab a ref on the data path first, to make sure we are allowed
|
||||
else if(pFilter->otPhyState == kStateDisabled || !ExAcquireRundownProtection(&pFilter->DataPathRundown))
|
||||
else if (pFilter->otPhyState == kStateDisabled || !ExAcquireRundownProtection(&pFilter->DataPathRundown))
|
||||
{
|
||||
LogVerbose(DRIVER_DATA_PATH, "Failing ReceiveNetBufferLists because data path isn't active.");
|
||||
|
||||
@@ -415,26 +502,19 @@ Arguments:
|
||||
PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
|
||||
|
||||
LogFuncEntryMsg(DRIVER_DATA_PATH, "Filter: %p, CancelId: %p", FilterModuleContext, CancelId);
|
||||
|
||||
otLwfEventProcessingIndicateNetBufferListsCancelled(pFilter, CancelId);
|
||||
|
||||
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
|
||||
{
|
||||
otLwfEventProcessingIndicateNetBufferListsCancelled(pFilter, CancelId);
|
||||
}
|
||||
else
|
||||
{
|
||||
NT_ASSERT(FALSE); // TODO
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DATA_PATH);
|
||||
}
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct UDPHeader
|
||||
{
|
||||
USHORT SourcePort;
|
||||
USHORT DestinationPort;
|
||||
USHORT TotalLength;
|
||||
USHORT Checksum;
|
||||
|
||||
} UDPHeader;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
// Callback received from OpenThread when it has an IPv6 packet ready for
|
||||
// delivery to TCPIP.
|
||||
void
|
||||
|
||||
@@ -532,7 +532,7 @@ otLwfIndicateNotification(
|
||||
{
|
||||
LogWarning(DRIVER_IOCTL, "Dropping old notification!");
|
||||
otLwfReleaseNotification(DeviceClient->PendingNotifications[DeviceClient->NotificationOffset]);
|
||||
DeviceClient->NotificationOffset++;
|
||||
DeviceClient->NotificationOffset = (DeviceClient->NotificationOffset + 1) % OTLWF_MAX_PENDING_NOTIFICATIONS_PER_CLIENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -142,6 +142,8 @@ otLwfEventProcessingStop(
|
||||
_In_ PMS_FILTER pFilter
|
||||
)
|
||||
{
|
||||
PLIST_ENTRY Link = NULL;
|
||||
|
||||
LogFuncEntryMsg(DRIVER_DEFAULT, "Filter: %p", pFilter);
|
||||
|
||||
// By this point, we have disabled the Data Path, so no more
|
||||
@@ -172,57 +174,66 @@ otLwfEventProcessingStop(
|
||||
}
|
||||
|
||||
// Clean up any left over events
|
||||
PLIST_ENTRY Link = pFilter->AddressChangesHead.Flink;
|
||||
while (Link != &pFilter->AddressChangesHead)
|
||||
if (pFilter->AddressChangesHead.Flink)
|
||||
{
|
||||
POTLWF_ADDR_EVENT Event = CONTAINING_RECORD(Link, OTLWF_ADDR_EVENT, Link);
|
||||
Link = Link->Flink;
|
||||
Link = pFilter->AddressChangesHead.Flink;
|
||||
while (Link != &pFilter->AddressChangesHead)
|
||||
{
|
||||
POTLWF_ADDR_EVENT Event = CONTAINING_RECORD(Link, OTLWF_ADDR_EVENT, Link);
|
||||
Link = Link->Flink;
|
||||
|
||||
// Delete the event
|
||||
NdisFreeMemory(Event, 0, 0);
|
||||
// Delete the event
|
||||
NdisFreeMemory(Event, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up any left over events
|
||||
Link = pFilter->NBLsHead.Flink;
|
||||
while (Link != &pFilter->NBLsHead)
|
||||
if (pFilter->NBLsHead.Flink)
|
||||
{
|
||||
POTLWF_NBL_EVENT Event = CONTAINING_RECORD(Link, OTLWF_NBL_EVENT, Link);
|
||||
Link = Link->Flink;
|
||||
Link = pFilter->NBLsHead.Flink;
|
||||
while (Link != &pFilter->NBLsHead)
|
||||
{
|
||||
POTLWF_NBL_EVENT Event = CONTAINING_RECORD(Link, OTLWF_NBL_EVENT, Link);
|
||||
Link = Link->Flink;
|
||||
|
||||
otLwfCompleteNBLs(pFilter, FALSE, Event->Received, Event->NetBufferLists, STATUS_CANCELLED);
|
||||
otLwfCompleteNBLs(pFilter, FALSE, Event->Received, Event->NetBufferLists, STATUS_CANCELLED);
|
||||
|
||||
// Delete the event
|
||||
NdisFreeMemory(Event, 0, 0);
|
||||
// Delete the event
|
||||
NdisFreeMemory(Event, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Reinitialize the list head
|
||||
InitializeListHead(&pFilter->AddressChangesHead);
|
||||
InitializeListHead(&pFilter->NBLsHead);
|
||||
|
||||
FILTER_ACQUIRE_LOCK(&pFilter->EventsLock, FALSE);
|
||||
|
||||
// Clean up any left over IRPs
|
||||
Link = pFilter->EventIrpListHead.Flink;
|
||||
while (Link != &pFilter->EventIrpListHead)
|
||||
if (pFilter->EventIrpListHead.Flink)
|
||||
{
|
||||
PIRP Irp = CONTAINING_RECORD(Link, IRP, Tail.Overlay.ListEntry);
|
||||
Link = Link->Flink;
|
||||
|
||||
// Before we are allowed to complete the pending IRP, we must remove the cancel routine
|
||||
KIRQL irql;
|
||||
IoAcquireCancelSpinLock(&irql);
|
||||
IoSetCancelRoutine(Irp, NULL);
|
||||
IoReleaseCancelSpinLock(irql);
|
||||
FILTER_ACQUIRE_LOCK(&pFilter->EventsLock, FALSE);
|
||||
|
||||
Irp->IoStatus.Status = STATUS_CANCELLED;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
// Clean up any left over IRPs
|
||||
Link = pFilter->EventIrpListHead.Flink;
|
||||
while (Link != &pFilter->EventIrpListHead)
|
||||
{
|
||||
PIRP Irp = CONTAINING_RECORD(Link, IRP, Tail.Overlay.ListEntry);
|
||||
Link = Link->Flink;
|
||||
|
||||
// Before we are allowed to complete the pending IRP, we must remove the cancel routine
|
||||
KIRQL irql;
|
||||
IoAcquireCancelSpinLock(&irql);
|
||||
IoSetCancelRoutine(Irp, NULL);
|
||||
IoReleaseCancelSpinLock(irql);
|
||||
|
||||
Irp->IoStatus.Status = STATUS_CANCELLED;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
// Reinitialize the list head
|
||||
InitializeListHead(&pFilter->EventIrpListHead);
|
||||
|
||||
FILTER_RELEASE_LOCK(&pFilter->EventsLock, FALSE);
|
||||
}
|
||||
|
||||
// Reinitialize the list head
|
||||
InitializeListHead(&pFilter->EventIrpListHead);
|
||||
|
||||
FILTER_RELEASE_LOCK(&pFilter->EventsLock, FALSE);
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
@@ -307,23 +318,31 @@ otLwfEventProcessingIndicateAddressChange(
|
||||
_In_ PIN6_ADDR pAddr
|
||||
)
|
||||
{
|
||||
POTLWF_ADDR_EVENT Event = FILTER_ALLOC_MEM(pFilter->FilterHandle, sizeof(OTLWF_ADDR_EVENT));
|
||||
if (Event == NULL)
|
||||
if (pFilter->InternalStateInitialized == FALSE)
|
||||
{
|
||||
LogWarning(DRIVER_DATA_PATH, "Failed to alloc new OTLWF_ADDR_EVENT");
|
||||
return;
|
||||
}
|
||||
|
||||
Event->NotificationType = NotificationType;
|
||||
Event->Address = *pAddr;
|
||||
|
||||
// Add the event to the queue
|
||||
NdisAcquireSpinLock(&pFilter->EventsLock);
|
||||
InsertTailList(&pFilter->AddressChangesHead, &Event->Link);
|
||||
NdisReleaseSpinLock(&pFilter->EventsLock);
|
||||
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
|
||||
{
|
||||
POTLWF_ADDR_EVENT Event = FILTER_ALLOC_MEM(pFilter->FilterHandle, sizeof(OTLWF_ADDR_EVENT));
|
||||
if (Event == NULL)
|
||||
{
|
||||
LogWarning(DRIVER_DATA_PATH, "Failed to alloc new OTLWF_ADDR_EVENT");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the event to indicate we have a new address to process
|
||||
KeSetEvent(&pFilter->EventWorkerThreadProcessAddressChanges, 0, FALSE);
|
||||
Event->NotificationType = NotificationType;
|
||||
Event->Address = *pAddr;
|
||||
|
||||
// Add the event to the queue
|
||||
NdisAcquireSpinLock(&pFilter->EventsLock);
|
||||
InsertTailList(&pFilter->AddressChangesHead, &Event->Link);
|
||||
NdisReleaseSpinLock(&pFilter->EventsLock);
|
||||
|
||||
// Set the event to indicate we have a new address to process
|
||||
KeSetEvent(&pFilter->EventWorkerThreadProcessAddressChanges, 0, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
// Called to indicate that we have a NetBufferLists to process
|
||||
@@ -689,7 +708,7 @@ otLwfEventWorkerThread(
|
||||
return;
|
||||
}
|
||||
|
||||
#if DBG
|
||||
#if DEBUG_ALLOC
|
||||
// Initialize the list head for allocations
|
||||
InitializeListHead(&pFilter->otOutStandingAllocations);
|
||||
|
||||
@@ -1017,7 +1036,7 @@ exit:
|
||||
otInstanceFinalize(pFilter->otCtx);
|
||||
pFilter->otCtx = NULL;
|
||||
|
||||
#if DBG
|
||||
#if DEBUG_ALLOC
|
||||
{
|
||||
NT_ASSERT(pFilter->otOutstandingAllocationCount == 0);
|
||||
NT_ASSERT(pFilter->otOutstandingMemoryAllocated == 0);
|
||||
|
||||
@@ -93,7 +93,6 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
|
||||
NTSTATUS NtStatus;
|
||||
NDIS_FILTER_ATTRIBUTES FilterAttributes;
|
||||
ULONG Size;
|
||||
PNET_BUFFER SendNetBuffer;
|
||||
ULONG bytesProcessed = 0;
|
||||
COMPARTMENT_ID OriginalCompartmentID;
|
||||
|
||||
@@ -119,8 +118,7 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
|
||||
break;
|
||||
}
|
||||
|
||||
Size = sizeof(MS_FILTER) +
|
||||
AttachParameters->BaseMiniportInstanceName->Length;
|
||||
Size = sizeof(MS_FILTER) + AttachParameters->BaseMiniportInstanceName->Length;
|
||||
|
||||
pFilter = (PMS_FILTER)FILTER_ALLOC_MEM(NdisFilterHandle, Size);
|
||||
if (pFilter == NULL)
|
||||
@@ -135,8 +133,7 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
|
||||
// Format of "\DEVICE\{5BA90C49-0D7E-455B-8D3B-614F6714A212}"
|
||||
AttachParameters->BaseMiniportName->Buffer += 8;
|
||||
AttachParameters->BaseMiniportName->Length -= 8 * sizeof(WCHAR);
|
||||
NtStatus = RtlGUIDFromString(AttachParameters->BaseMiniportName,
|
||||
&pFilter->InterfaceGuid);
|
||||
NtStatus = RtlGUIDFromString(AttachParameters->BaseMiniportName, &pFilter->InterfaceGuid);
|
||||
AttachParameters->BaseMiniportName->Buffer -= 8;
|
||||
AttachParameters->BaseMiniportName->Length += 8 * sizeof(WCHAR);
|
||||
if (!NT_SUCCESS(NtStatus))
|
||||
@@ -164,15 +161,27 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
|
||||
FilterAttributes.Flags = 0;
|
||||
|
||||
NDIS_DECLARE_FILTER_MODULE_CONTEXT(MS_FILTER);
|
||||
Status = NdisFSetAttributes(NdisFilterHandle,
|
||||
pFilter,
|
||||
&FilterAttributes);
|
||||
Status = NdisFSetAttributes(NdisFilterHandle, pFilter, &FilterAttributes);
|
||||
if (Status != NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
LogWarning(DRIVER_DEFAULT, "Failed to set attributes, %!NDIS_STATUS!", Status);
|
||||
LogError(DRIVER_DEFAULT, "Failed to set attributes, %!NDIS_STATUS!", Status);
|
||||
break;
|
||||
}
|
||||
|
||||
// Filter initially in Paused state
|
||||
pFilter->State = FilterPaused;
|
||||
NdisInitializeEvent(&pFilter->FilterPauseComplete);
|
||||
|
||||
// Initialize initial ref count on IoControl to 1, which we release on shutdown
|
||||
RtlInitializeReferenceCount(&pFilter->IoControlReferences);
|
||||
NdisInitializeEvent(&pFilter->IoControlShutdownComplete);
|
||||
|
||||
// Initialize PendingOidRequest lock
|
||||
NdisAllocateSpinLock(&pFilter->PendingOidRequestLock);
|
||||
|
||||
// Initialize datapath to disabled with no active references
|
||||
pFilter->DataPathRundown.Count = EX_RUNDOWN_ACTIVE;
|
||||
|
||||
// Create the NDIS pool for creating the SendNetBufferList
|
||||
NET_BUFFER_LIST_POOL_PARAMETERS PoolParams =
|
||||
{
|
||||
@@ -191,111 +200,30 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
|
||||
break;
|
||||
}
|
||||
|
||||
// Create the SendNetBufferList
|
||||
pFilter->SendNetBufferList =
|
||||
NdisAllocateNetBufferAndNetBufferList(
|
||||
pFilter->NetBufferListPool, // PoolHandle
|
||||
0, // ContextSize
|
||||
0, // ContextBackFill
|
||||
NULL, // MdlChain
|
||||
0, // DataOffset
|
||||
0 // DataLength
|
||||
// Query the compartment ID for this interface to use for the IP stack
|
||||
pFilter->InterfaceCompartmentID = GetInterfaceCompartmentID(&pFilter->InterfaceLuid);
|
||||
LogVerbose(DRIVER_DEFAULT, "Interface %!GUID! is in Compartment %u", &pFilter->InterfaceGuid, (ULONG)pFilter->InterfaceCompartmentID);
|
||||
|
||||
// Make sure we are in the right compartment
|
||||
(VOID)otLwfSetCompartment(pFilter, &OriginalCompartmentID);
|
||||
|
||||
// Register for address changed notifications
|
||||
NtStatus =
|
||||
NotifyUnicastIpAddressChange(
|
||||
AF_INET6,
|
||||
otLwfAddressChangeCallback,
|
||||
pFilter,
|
||||
FALSE,
|
||||
&pFilter->AddressChangeHandle
|
||||
);
|
||||
if (pFilter->SendNetBufferList == NULL)
|
||||
|
||||
// Revert the compartment, now that we have the table
|
||||
otLwfRevertCompartment(OriginalCompartmentID);
|
||||
|
||||
if (!NT_SUCCESS(NtStatus))
|
||||
{
|
||||
NdisFreeNetBufferListPool(pFilter->NetBufferListPool);
|
||||
Status = NDIS_STATUS_RESOURCES;
|
||||
LogWarning(DRIVER_DEFAULT, "Failed to create Send NetBufferList");
|
||||
break;
|
||||
}
|
||||
|
||||
// Initialize NetBuffer fields
|
||||
SendNetBuffer = NET_BUFFER_LIST_FIRST_NB(pFilter->SendNetBufferList);
|
||||
NET_BUFFER_CURRENT_MDL(SendNetBuffer) = NULL;
|
||||
NET_BUFFER_CURRENT_MDL_OFFSET(SendNetBuffer) = 0;
|
||||
NET_BUFFER_DATA_LENGTH(SendNetBuffer) = 0;
|
||||
NET_BUFFER_DATA_OFFSET(SendNetBuffer) = 0;
|
||||
NET_BUFFER_FIRST_MDL(SendNetBuffer) = NULL;
|
||||
|
||||
// Allocate the NetBuffer for SendNetBufferList
|
||||
Status = NdisRetreatNetBufferDataStart(SendNetBuffer, kMaxPHYPacketSize, 0, NULL);
|
||||
if (Status != NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
NdisFreeNetBufferList(pFilter->SendNetBufferList);
|
||||
NdisFreeNetBufferListPool(pFilter->NetBufferListPool);
|
||||
LogError(DRIVER_DEFAULT, "Failed to allocate NB for Send NetBufferList, %!NDIS_STATUS!", Status);
|
||||
break;
|
||||
}
|
||||
|
||||
// Filter initially in Paused state
|
||||
pFilter->State = FilterPaused;
|
||||
NdisInitializeEvent(&pFilter->FilterPauseComplete);
|
||||
|
||||
// Initialize initial ref count on IoControl to 1, which we release on shutdown
|
||||
RtlInitializeReferenceCount(&pFilter->IoControlReferences);
|
||||
NdisInitializeEvent(&pFilter->IoControlShutdownComplete);
|
||||
|
||||
// Initialize PendingOidRequest lock
|
||||
NdisAllocateSpinLock(&pFilter->PendingOidRequestLock);
|
||||
|
||||
// Initialize datapath to disabled with no active references
|
||||
pFilter->DataPathRundown.Count = EX_RUNDOWN_ACTIVE;
|
||||
KeInitializeEvent(
|
||||
&pFilter->SendNetBufferListComplete,
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
FALSE // event initially non-signalled
|
||||
);
|
||||
|
||||
// Initialize the event processing
|
||||
pFilter->EventWorkerThread = NULL;
|
||||
NdisAllocateSpinLock(&pFilter->EventsLock);
|
||||
InitializeListHead(&pFilter->AddressChangesHead);
|
||||
InitializeListHead(&pFilter->NBLsHead);
|
||||
InitializeListHead(&pFilter->EventIrpListHead);
|
||||
KeInitializeEvent(
|
||||
&pFilter->EventWorkerThreadStopEvent,
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
FALSE // event initially non-signalled
|
||||
);
|
||||
KeInitializeEvent(
|
||||
&pFilter->EventWorkerThreadWaitTimeUpdated,
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
FALSE // event initially non-signalled
|
||||
);
|
||||
KeInitializeEvent(
|
||||
&pFilter->EventWorkerThreadProcessTasklets,
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
FALSE // event initially non-signalled
|
||||
);
|
||||
KeInitializeEvent(
|
||||
&pFilter->EventWorkerThreadProcessAddressChanges,
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
FALSE // event initially non-signalled
|
||||
);
|
||||
KeInitializeEvent(
|
||||
&pFilter->EventWorkerThreadProcessNBLs,
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
FALSE // event initially non-signalled
|
||||
);
|
||||
KeInitializeEvent(
|
||||
&pFilter->EventWorkerThreadProcessIrp,
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
FALSE // event initially non-signalled
|
||||
);
|
||||
KeInitializeEvent(
|
||||
&pFilter->EventWorkerThreadEnergyScanComplete,
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
FALSE // event initially non-signalled
|
||||
);
|
||||
pFilter->EventHighPrecisionTimer =
|
||||
ExAllocateTimer(
|
||||
otLwfEventProcessingTimer,
|
||||
pFilter,
|
||||
EX_TIMER_HIGH_RESOLUTION
|
||||
);
|
||||
if (pFilter->EventHighPrecisionTimer == NULL)
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Failed to allocate timer!");
|
||||
LogError(DRIVER_DEFAULT, "NotifyUnicastIpAddressChange failed, %!STATUS!", NtStatus);
|
||||
Status = NDIS_STATUS_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -330,37 +258,11 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
|
||||
}
|
||||
|
||||
// Make sure we are in RADIO mode
|
||||
if (pFilter->MiniportCapabilities.MiniportMode != OT_MP_MODE_RADIO)
|
||||
if (pFilter->MiniportCapabilities.MiniportMode != OT_MP_MODE_RADIO &&
|
||||
pFilter->MiniportCapabilities.MiniportMode != OT_MP_MODE_THREAD)
|
||||
{
|
||||
Status = NDIS_STATUS_NOT_SUPPORTED;
|
||||
LogError(DRIVER_DEFAULT, "Miniport indicated it isn't running in RADIO mode!");
|
||||
break;
|
||||
}
|
||||
|
||||
// Query the compartment ID for this interface to use for the IP stack
|
||||
pFilter->InterfaceCompartmentID = GetInterfaceCompartmentID(&pFilter->InterfaceLuid);
|
||||
LogVerbose(DRIVER_DEFAULT, "Interface %!GUID! is in Compartment %u", &pFilter->InterfaceGuid, (ULONG)pFilter->InterfaceCompartmentID);
|
||||
|
||||
// Make sure we are in the right compartment
|
||||
(VOID)otLwfSetCompartment(pFilter, &OriginalCompartmentID);
|
||||
|
||||
// Register for address changed notifications
|
||||
NtStatus =
|
||||
NotifyUnicastIpAddressChange(
|
||||
AF_INET6,
|
||||
otLwfAddressChangeCallback,
|
||||
pFilter,
|
||||
FALSE,
|
||||
&pFilter->AddressChangeHandle
|
||||
);
|
||||
|
||||
// Revert the compartment, now that we have the table
|
||||
otLwfRevertCompartment(OriginalCompartmentID);
|
||||
|
||||
if (!NT_SUCCESS(NtStatus))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "NotifyUnicastIpAddressChange failed, %!STATUS!", NtStatus);
|
||||
Status = NDIS_STATUS_FAILURE;
|
||||
LogError(DRIVER_DEFAULT, "Miniport indicated it isn't running in RADIO or THREAD mode!");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -369,16 +271,6 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
|
||||
InsertTailList(&FilterModuleList, &pFilter->FilterModuleLink);
|
||||
NdisReleaseSpinLock(&FilterListLock);
|
||||
|
||||
// Initialize the event processing thread
|
||||
if (!NT_SUCCESS(otLwfEventProcessingStart(pFilter)))
|
||||
{
|
||||
NdisAcquireSpinLock(&FilterListLock);
|
||||
RemoveEntryList(&pFilter->FilterModuleLink);
|
||||
NdisReleaseSpinLock(&FilterListLock);
|
||||
Status = NDIS_STATUS_RESOURCES;
|
||||
break;
|
||||
}
|
||||
|
||||
LogVerbose(DRIVER_DEFAULT, "Created Filter: %p", pFilter);
|
||||
|
||||
} while (FALSE);
|
||||
@@ -392,11 +284,13 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
|
||||
CancelMibChangeNotify2(pFilter->AddressChangeHandle);
|
||||
pFilter->AddressChangeHandle = NULL;
|
||||
}
|
||||
|
||||
// Stop event processing thread
|
||||
otLwfEventProcessingStop(pFilter);
|
||||
|
||||
if (pFilter->EventHighPrecisionTimer) ExDeleteTimer(pFilter->EventHighPrecisionTimer, TRUE, FALSE, NULL);
|
||||
// Free NBL Pool
|
||||
if (pFilter->NetBufferListPool)
|
||||
{
|
||||
NdisFreeNetBufferPool(pFilter->NetBufferListPool);
|
||||
}
|
||||
|
||||
NdisFreeMemory(pFilter, 0, 0);
|
||||
}
|
||||
}
|
||||
@@ -456,21 +350,29 @@ NOTE: Called at PASSIVE_LEVEL and the filter is in paused state
|
||||
CancelMibChangeNotify2(pFilter->AddressChangeHandle);
|
||||
pFilter->AddressChangeHandle = NULL;
|
||||
|
||||
// Stop event processing thread
|
||||
otLwfEventProcessingStop(pFilter);
|
||||
if (pFilter->InternalStateInitialized)
|
||||
{
|
||||
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
|
||||
{
|
||||
otLwfUninitializeThreadMode(pFilter);
|
||||
}
|
||||
else if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_THREAD)
|
||||
{
|
||||
otLwfUninitializeTunnelMode(pFilter);
|
||||
}
|
||||
else
|
||||
{
|
||||
NT_ASSERT(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove this Filter from the global list
|
||||
NdisAcquireSpinLock(&FilterListLock);
|
||||
RemoveEntryList(&pFilter->FilterModuleLink);
|
||||
NdisReleaseSpinLock(&FilterListLock);
|
||||
|
||||
// Free NBL & Pools
|
||||
NdisAdvanceNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB(pFilter->SendNetBufferList), kMaxPHYPacketSize, TRUE, NULL);
|
||||
NdisFreeNetBufferList(pFilter->SendNetBufferList);
|
||||
// Free NBL Pool
|
||||
NdisFreeNetBufferPool(pFilter->NetBufferListPool);
|
||||
|
||||
// Free timer
|
||||
ExDeleteTimer(pFilter->EventHighPrecisionTimer, TRUE, FALSE, NULL);
|
||||
|
||||
// Free the memory allocated
|
||||
NdisFreeMemory(pFilter, 0, 0);
|
||||
@@ -557,6 +459,37 @@ Return Value:
|
||||
//
|
||||
NdisGeneralAttributes->LookaheadSize = 128;
|
||||
}
|
||||
|
||||
|
||||
// Initialize the processing logic
|
||||
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
|
||||
{
|
||||
NtStatus = otLwfInitializeThreadMode(pFilter);
|
||||
if (!NT_SUCCESS(NtStatus))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "otLwfInitializeThreadMode failed, %!STATUS!", NtStatus);
|
||||
NdisStatus = NDIS_STATUS_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
pFilter->InternalStateInitialized = TRUE;
|
||||
}
|
||||
else if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_THREAD)
|
||||
{
|
||||
NtStatus = otLwfInitializeTunnelMode(pFilter);
|
||||
if (!NT_SUCCESS(NtStatus))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "otLwfInitializeTunnelMode failed, %!STATUS!", NtStatus);
|
||||
NdisStatus = NDIS_STATUS_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
pFilter->InternalStateInitialized = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
NT_ASSERT(FALSE);
|
||||
NdisStatus = NDIS_STATUS_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
key.Luid = pFilter->InterfaceLuid;
|
||||
NlInitializeInterfaceRw(&interfaceRw);
|
||||
@@ -600,6 +533,19 @@ exit:
|
||||
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
pFilter->State = FilterPaused;
|
||||
|
||||
if (pFilter->InternalStateInitialized)
|
||||
{
|
||||
pFilter->InternalStateInitialized = FALSE;
|
||||
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
|
||||
{
|
||||
otLwfUninitializeThreadMode(pFilter);
|
||||
}
|
||||
else
|
||||
{
|
||||
otLwfUninitializeTunnelMode(pFilter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogFuncExitNDIS(DRIVER_DEFAULT, NdisStatus);
|
||||
@@ -654,13 +600,6 @@ N.B.: When the filter is in Pausing state, it can still process OID requests,
|
||||
//
|
||||
NT_ASSERT(pFilter->State == FilterRunning);
|
||||
pFilter->State = FilterPausing;
|
||||
|
||||
//
|
||||
// Make sure we are disconnected from the network
|
||||
//
|
||||
// TODO ...
|
||||
//otBecomeDetached(pFilter->otCtx); // TODO - This should block or we wait for it to complete
|
||||
//otDisable(pFilter->otCtx);
|
||||
|
||||
otLwfNotifyDeviceAvailabilityChange(pFilter, FALSE);
|
||||
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! removal.", &pFilter->InterfaceGuid);
|
||||
@@ -724,6 +663,7 @@ NOTE: called at <= DISPATCH_LEVEL
|
||||
LogInfo(DRIVER_DEFAULT, "Filter: %p, completed energy scan: Rssi:%d, Status:%!NDIS_STATUS!", FilterModuleContext, ScanResult->MaxRssi, ScanResult->Status);
|
||||
|
||||
// Marshal to OpenThread worker to indicate back
|
||||
NT_ASSERT(pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO);
|
||||
otLwfEventProcessingIndicateEnergyScanResult(pFilter, ScanResult->MaxRssi);
|
||||
}
|
||||
|
||||
@@ -872,6 +812,13 @@ otLwfSetCompartment(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_Out_ COMPARTMENT_ID* pOriginalCompartment
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Sets the current thread's compartment ID to match the filter instance.
|
||||
|
||||
--*/
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
@@ -899,6 +846,13 @@ VOID
|
||||
otLwfRevertCompartment(
|
||||
_In_ COMPARTMENT_ID OriginalCompartment
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Resets the current thread's compartment ID.
|
||||
|
||||
--*/
|
||||
{
|
||||
// Revert the compartment if it is set
|
||||
if (OriginalCompartment != 0)
|
||||
@@ -906,337 +860,3 @@ otLwfRevertCompartment(
|
||||
(VOID)NdisSetCurrentThreadCompartmentId(OriginalCompartment);
|
||||
}
|
||||
}
|
||||
|
||||
#if DBG
|
||||
PMS_FILTER
|
||||
otLwfFindFromCurrentThread()
|
||||
{
|
||||
PMS_FILTER pOutput = NULL;
|
||||
HANDLE CurThreadId = PsGetCurrentThreadId();
|
||||
|
||||
NdisAcquireSpinLock(&FilterListLock);
|
||||
|
||||
for (PLIST_ENTRY Link = FilterModuleList.Flink; Link != &FilterModuleList; Link = Link->Flink)
|
||||
{
|
||||
PMS_FILTER pFilter = CONTAINING_RECORD(Link, MS_FILTER, FilterModuleLink);
|
||||
|
||||
if (pFilter->otThreadId == CurThreadId)
|
||||
{
|
||||
pOutput = pFilter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NdisReleaseSpinLock(&FilterListLock);
|
||||
|
||||
NT_ASSERT(pOutput);
|
||||
return pOutput;
|
||||
}
|
||||
#endif
|
||||
|
||||
void *otPlatCAlloc(size_t aNum, size_t aSize)
|
||||
{
|
||||
size_t totalSize = aNum * aSize;
|
||||
#if DBG
|
||||
totalSize += sizeof(OT_ALLOC);
|
||||
#endif
|
||||
PVOID mem = ExAllocatePoolWithTag(NonPagedPoolNx, totalSize, 'OTDM');
|
||||
if (mem)
|
||||
{
|
||||
RtlZeroMemory(mem, totalSize);
|
||||
#if DBG
|
||||
PMS_FILTER pFilter = otLwfFindFromCurrentThread();
|
||||
//LogVerbose(DRIVER_DEFAULT, "otPlatAlloc(%u) = ID:%u %p", (ULONG)totalSize, pFilter->otAllocationID, mem);
|
||||
|
||||
OT_ALLOC* AllocHeader = (OT_ALLOC*)mem;
|
||||
AllocHeader->Length = (LONG)totalSize;
|
||||
AllocHeader->ID = pFilter->otAllocationID++;
|
||||
InsertTailList(&pFilter->otOutStandingAllocations, &AllocHeader->Link);
|
||||
|
||||
InterlockedIncrement(&pFilter->otOutstandingAllocationCount);
|
||||
InterlockedAdd(&pFilter->otOutstandingMemoryAllocated, AllocHeader->Length);
|
||||
|
||||
mem = (PUCHAR)(mem) + sizeof(OT_ALLOC);
|
||||
#endif
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
void otPlatFree(void *aPtr)
|
||||
{
|
||||
if (aPtr == NULL) return;
|
||||
#if DBG
|
||||
aPtr = (PUCHAR)(aPtr) - sizeof(OT_ALLOC);
|
||||
//LogVerbose(DRIVER_DEFAULT, "otPlatFree(%p)", aPtr);
|
||||
OT_ALLOC* AllocHeader = (OT_ALLOC*)aPtr;
|
||||
|
||||
PMS_FILTER pFilter = otLwfFindFromCurrentThread();
|
||||
InterlockedDecrement(&pFilter->otOutstandingAllocationCount);
|
||||
InterlockedAdd(&pFilter->otOutstandingMemoryAllocated, -AllocHeader->Length);
|
||||
RemoveEntryList(&AllocHeader->Link);
|
||||
#endif
|
||||
ExFreePoolWithTag(aPtr, 'OTDM');
|
||||
}
|
||||
|
||||
uint32_t otPlatRandomGet()
|
||||
{
|
||||
LARGE_INTEGER Counter = KeQueryPerformanceCounter(NULL);
|
||||
return (uint32_t)RtlRandomEx(&Counter.LowPart);
|
||||
}
|
||||
|
||||
ThreadError otPlatRandomSecureGet(uint16_t aInputLength, uint8_t *aOutput, uint16_t *aOutputLength)
|
||||
{
|
||||
// Just use the system-preferred random number generator algorithm
|
||||
NTSTATUS status =
|
||||
BCryptGenRandom(
|
||||
NULL,
|
||||
aOutput,
|
||||
(ULONG)aInputLength,
|
||||
BCRYPT_USE_SYSTEM_PREFERRED_RNG
|
||||
);
|
||||
NT_ASSERT(NT_SUCCESS(status));
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "BCryptGenRandom failed, %!STATUS!", status);
|
||||
return kThreadError_Failed;
|
||||
}
|
||||
|
||||
*aOutputLength = aInputLength;
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
void otSignalTaskletPending(_In_ otInstance *otCtx)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "otSignalTaskletPending");
|
||||
PMS_FILTER pFilter = otCtxToFilter(otCtx);
|
||||
otLwfEventProcessingIndicateNewTasklet(pFilter);
|
||||
}
|
||||
|
||||
// Process a role state change
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
VOID
|
||||
otLwfProcessRoleStateChange(
|
||||
_In_ PMS_FILTER pFilter
|
||||
)
|
||||
{
|
||||
otDeviceRole prevRole = pFilter->otCachedRole;
|
||||
pFilter->otCachedRole = otGetDeviceRole(pFilter->otCtx);
|
||||
if (prevRole == pFilter->otCachedRole) return;
|
||||
|
||||
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! new role: %!otDeviceRole!", &pFilter->InterfaceGuid, pFilter->otCachedRole);
|
||||
|
||||
// Make sure we are in the correct media connect state
|
||||
otLwfIndicateLinkState(
|
||||
pFilter,
|
||||
IsAttached(pFilter->otCachedRole) ?
|
||||
MediaConnectStateConnected :
|
||||
MediaConnectStateDisconnected);
|
||||
}
|
||||
|
||||
void otLwfStateChangedCallback(uint32_t aFlags, _In_ void *aContext)
|
||||
{
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
PMS_FILTER pFilter = (PMS_FILTER)aContext;
|
||||
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
|
||||
|
||||
//
|
||||
// Process the notification internally
|
||||
//
|
||||
|
||||
if ((aFlags & OT_IP6_ADDRESS_ADDED) != 0)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_IP6_ADDRESS_ADDED", pFilter);
|
||||
otLwfAddressesUpdated(pFilter);
|
||||
}
|
||||
|
||||
if ((aFlags & OT_IP6_ADDRESS_REMOVED) != 0)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_IP6_ADDRESS_REMOVED", pFilter);
|
||||
otLwfAddressesUpdated(pFilter);
|
||||
}
|
||||
|
||||
if ((aFlags & OT_NET_ROLE) != 0)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_NET_ROLE", pFilter);
|
||||
otLwfProcessRoleStateChange(pFilter);
|
||||
}
|
||||
|
||||
if ((aFlags & OT_NET_PARTITION_ID) != 0)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_NET_PARTITION_ID", pFilter);
|
||||
}
|
||||
|
||||
if ((aFlags & OT_NET_KEY_SEQUENCE_COUNTER) != 0)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_NET_KEY_SEQUENCE_COUNTER", pFilter);
|
||||
}
|
||||
|
||||
if ((aFlags & OT_THREAD_CHILD_ADDED) != 0)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_THREAD_CHILD_ADDED", pFilter);
|
||||
}
|
||||
|
||||
if ((aFlags & OT_THREAD_CHILD_REMOVED) != 0)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_THREAD_CHILD_REMOVED", pFilter);
|
||||
}
|
||||
|
||||
if ((aFlags & OT_THREAD_NETDATA_UPDATED) != 0)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_THREAD_NETDATA_UPDATED", pFilter);
|
||||
otSlaacUpdate(pFilter->otCtx, pFilter->otAutoAddresses, ARRAYSIZE(pFilter->otAutoAddresses), otCreateRandomIid, NULL);
|
||||
}
|
||||
|
||||
if ((aFlags & OT_IP6_ML_ADDR_CHANGED) != 0)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_IP6_ML_ADDR_CHANGED", pFilter);
|
||||
}
|
||||
|
||||
//
|
||||
// Queue the notification for clients
|
||||
//
|
||||
|
||||
if (NotifEntry)
|
||||
{
|
||||
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
|
||||
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
|
||||
NotifEntry->Notif.NotifType = OTLWF_NOTIF_STATE_CHANGE;
|
||||
NotifEntry->Notif.StateChangePayload.Flags = aFlags;
|
||||
|
||||
otLwfIndicateNotification(NotifEntry);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
void otLwfActiveScanCallback(_In_ otActiveScanResult *aResult, _In_ void *aContext)
|
||||
{
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
PMS_FILTER pFilter = (PMS_FILTER)aContext;
|
||||
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
|
||||
if (NotifEntry)
|
||||
{
|
||||
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
|
||||
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
|
||||
NotifEntry->Notif.NotifType = OTLWF_NOTIF_ACTIVE_SCAN;
|
||||
|
||||
if (aResult)
|
||||
{
|
||||
NotifEntry->Notif.ActiveScanPayload.Valid = TRUE;
|
||||
NotifEntry->Notif.ActiveScanPayload.Results = *aResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
NotifEntry->Notif.ActiveScanPayload.Valid = FALSE;
|
||||
}
|
||||
|
||||
otLwfIndicateNotification(NotifEntry);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
void otLwfEnergyScanCallback(_In_ otEnergyScanResult *aResult, _In_ void *aContext)
|
||||
{
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
PMS_FILTER pFilter = (PMS_FILTER)aContext;
|
||||
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
|
||||
if (NotifEntry)
|
||||
{
|
||||
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
|
||||
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
|
||||
NotifEntry->Notif.NotifType = OTLWF_NOTIF_ENERGY_SCAN;
|
||||
|
||||
if (aResult)
|
||||
{
|
||||
NotifEntry->Notif.EnergyScanPayload.Valid = TRUE;
|
||||
NotifEntry->Notif.EnergyScanPayload.Results = *aResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
NotifEntry->Notif.EnergyScanPayload.Valid = FALSE;
|
||||
}
|
||||
|
||||
otLwfIndicateNotification(NotifEntry);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
void otLwfDiscoverCallback(_In_ otActiveScanResult *aResult, _In_ void *aContext)
|
||||
{
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
PMS_FILTER pFilter = (PMS_FILTER)aContext;
|
||||
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
|
||||
if (NotifEntry)
|
||||
{
|
||||
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
|
||||
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
|
||||
NotifEntry->Notif.NotifType = OTLWF_NOTIF_DISCOVER;
|
||||
|
||||
if (aResult)
|
||||
{
|
||||
NotifEntry->Notif.DiscoverPayload.Valid = TRUE;
|
||||
NotifEntry->Notif.DiscoverPayload.Results = *aResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
NotifEntry->Notif.DiscoverPayload.Valid = FALSE;
|
||||
}
|
||||
|
||||
otLwfIndicateNotification(NotifEntry);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
void otLwfCommissionerEnergyReportCallback(uint32_t aChannelMask, const uint8_t *aEnergyList, uint8_t aEnergyListLength, void *aContext)
|
||||
{
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
PMS_FILTER pFilter = (PMS_FILTER)aContext;
|
||||
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
|
||||
if (NotifEntry)
|
||||
{
|
||||
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
|
||||
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
|
||||
NotifEntry->Notif.NotifType = OTLWF_NOTIF_COMMISSIONER_ENERGY_REPORT;
|
||||
|
||||
// Limit the number of reports if necessary
|
||||
if (aEnergyListLength > MAX_ENERGY_REPORT_LENGTH) aEnergyListLength = MAX_ENERGY_REPORT_LENGTH;
|
||||
|
||||
NotifEntry->Notif.CommissionerEnergyReportPayload.ChannelMask = aChannelMask;
|
||||
NotifEntry->Notif.CommissionerEnergyReportPayload.EnergyListLength = aEnergyListLength;
|
||||
memcpy(NotifEntry->Notif.CommissionerEnergyReportPayload.EnergyList, aEnergyList, aEnergyListLength);
|
||||
|
||||
otLwfIndicateNotification(NotifEntry);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
void otLwfCommissionerPanIdConflictCallback(uint16_t aPanId, uint32_t aChannelMask, _In_ void *aContext)
|
||||
{
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
PMS_FILTER pFilter = (PMS_FILTER)aContext;
|
||||
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
|
||||
if (NotifEntry)
|
||||
{
|
||||
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
|
||||
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
|
||||
NotifEntry->Notif.NotifType = OTLWF_NOTIF_COMMISSIONER_PANID_QUERY;
|
||||
|
||||
NotifEntry->Notif.CommissionerPanIdQueryPayload.PanId = aPanId;
|
||||
NotifEntry->Notif.CommissionerPanIdQueryPayload.ChannelMask = aChannelMask;
|
||||
|
||||
otLwfIndicateNotification(NotifEntry);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
@@ -124,102 +124,113 @@ typedef struct _MS_FILTER
|
||||
NDIS_EVENT IoControlShutdownComplete;
|
||||
|
||||
//
|
||||
// Event processing
|
||||
//
|
||||
PVOID EventWorkerThread;
|
||||
KEVENT EventWorkerThreadStopEvent;
|
||||
KEVENT EventWorkerThreadProcessAddressChanges;
|
||||
KEVENT EventWorkerThreadProcessNBLs;
|
||||
NDIS_SPIN_LOCK EventsLock;
|
||||
LIST_ENTRY AddressChangesHead;
|
||||
LIST_ENTRY NBLsHead;
|
||||
ULONG CountPendingRecvNBLs;
|
||||
LARGE_INTEGER NextAlarmTickCount;
|
||||
KEVENT EventWorkerThreadWaitTimeUpdated;
|
||||
KEVENT EventWorkerThreadProcessTasklets;
|
||||
PEX_TIMER EventHighPrecisionTimer;
|
||||
UCHAR EventTimerState;
|
||||
LIST_ENTRY EventIrpListHead;
|
||||
KEVENT EventWorkerThreadProcessIrp;
|
||||
KEVENT EventWorkerThreadEnergyScanComplete;
|
||||
|
||||
//
|
||||
// Data Path Synchronization
|
||||
// Data Path
|
||||
//
|
||||
EX_RUNDOWN_REF DataPathRundown;
|
||||
NDIS_HANDLE NetBufferListPool;
|
||||
BOOLEAN SendPending;
|
||||
PNET_BUFFER_LIST SendNetBufferList;
|
||||
KEVENT SendNetBufferListComplete;
|
||||
|
||||
//
|
||||
// OpenThread state management
|
||||
//
|
||||
otDeviceRole otCachedRole;
|
||||
BOOLEAN InternalStateInitialized;
|
||||
|
||||
//
|
||||
// OpenThread addresses
|
||||
//
|
||||
IN6_ADDR otCachedAddr[OT_MAX_ADDRESSES];
|
||||
ULONG otCachedAddrCount;
|
||||
IN6_ADDR otLinkLocalAddr;
|
||||
otNetifAddress otAutoAddresses[OT_MAX_AUTO_ADDRESSES];
|
||||
IN6_ADDR otCachedAddr[OT_MAX_ADDRESSES];
|
||||
ULONG otCachedAddrCount;
|
||||
IN6_ADDR otLinkLocalAddr;
|
||||
otNetifAddress otAutoAddresses[OT_MAX_AUTO_ADDRESSES];
|
||||
|
||||
union
|
||||
{
|
||||
struct // Thread Mode Variables
|
||||
{
|
||||
//
|
||||
// OpenThread Event processing
|
||||
//
|
||||
PVOID EventWorkerThread;
|
||||
KEVENT EventWorkerThreadStopEvent;
|
||||
KEVENT EventWorkerThreadProcessAddressChanges;
|
||||
KEVENT EventWorkerThreadProcessNBLs;
|
||||
NDIS_SPIN_LOCK EventsLock;
|
||||
LIST_ENTRY AddressChangesHead;
|
||||
LIST_ENTRY NBLsHead;
|
||||
ULONG CountPendingRecvNBLs;
|
||||
LARGE_INTEGER NextAlarmTickCount;
|
||||
KEVENT EventWorkerThreadWaitTimeUpdated;
|
||||
KEVENT EventWorkerThreadProcessTasklets;
|
||||
PEX_TIMER EventHighPrecisionTimer;
|
||||
UCHAR EventTimerState;
|
||||
LIST_ENTRY EventIrpListHead;
|
||||
KEVENT EventWorkerThreadProcessIrp;
|
||||
KEVENT EventWorkerThreadEnergyScanComplete;
|
||||
|
||||
//
|
||||
// OpenThread state management
|
||||
//
|
||||
otDeviceRole otCachedRole;
|
||||
|
||||
//
|
||||
// OpenThread data path state
|
||||
//
|
||||
BOOLEAN SendPending;
|
||||
PNET_BUFFER_LIST SendNetBufferList;
|
||||
KEVENT SendNetBufferListComplete;
|
||||
|
||||
//
|
||||
// OpenThread radio variables
|
||||
//
|
||||
otRadioCaps otRadioCapabilities;
|
||||
PhyState otPhyState;
|
||||
uint8_t otCurrentListenChannel;
|
||||
uint8_t otReceiveMessage[kMaxPHYPacketSize];
|
||||
uint8_t otTransmitMessage[kMaxPHYPacketSize];
|
||||
RadioPacket otReceiveFrame;
|
||||
RadioPacket otTransmitFrame;
|
||||
CHAR otLastEnergyScanMaxRssi;
|
||||
//
|
||||
// OpenThread radio variables
|
||||
//
|
||||
otRadioCaps otRadioCapabilities;
|
||||
PhyState otPhyState;
|
||||
uint8_t otCurrentListenChannel;
|
||||
uint8_t otReceiveMessage[kMaxPHYPacketSize];
|
||||
uint8_t otTransmitMessage[kMaxPHYPacketSize];
|
||||
RadioPacket otReceiveFrame;
|
||||
RadioPacket otTransmitFrame;
|
||||
CHAR otLastEnergyScanMaxRssi;
|
||||
|
||||
BOOLEAN otPromiscuous;
|
||||
uint16_t otPanID;
|
||||
uint64_t otFactoryAddress;
|
||||
uint64_t otExtendedAddress;
|
||||
uint16_t otShortAddress;
|
||||
BOOLEAN otPromiscuous;
|
||||
uint16_t otPanID;
|
||||
uint64_t otFactoryAddress;
|
||||
uint64_t otExtendedAddress;
|
||||
uint16_t otShortAddress;
|
||||
|
||||
BOOLEAN otPendingMacOffloadEnabled;
|
||||
uint8_t otPendingShortAddressCount;
|
||||
uint16_t otPendingShortAddresses[MAX_PENDING_MAC_SIZE];
|
||||
uint8_t otPendingExtendedAddressCount;
|
||||
uint64_t otPendingExtendedAddresses[MAX_PENDING_MAC_SIZE];
|
||||
BOOLEAN otPendingMacOffloadEnabled;
|
||||
uint8_t otPendingShortAddressCount;
|
||||
uint16_t otPendingShortAddresses[MAX_PENDING_MAC_SIZE];
|
||||
uint8_t otPendingExtendedAddressCount;
|
||||
uint64_t otPendingExtendedAddresses[MAX_PENDING_MAC_SIZE];
|
||||
|
||||
#if DBG
|
||||
// Used for tracking memory allocations
|
||||
HANDLE otThreadId;
|
||||
volatile LONG otOutstandingAllocationCount;
|
||||
volatile LONG otOutstandingMemoryAllocated;
|
||||
LIST_ENTRY otOutStandingAllocations;
|
||||
ULONG otAllocationID;
|
||||
#if DEBUG_ALLOC
|
||||
// Used for tracking memory allocations
|
||||
HANDLE otThreadId;
|
||||
volatile LONG otOutstandingAllocationCount;
|
||||
volatile LONG otOutstandingMemoryAllocated;
|
||||
LIST_ENTRY otOutStandingAllocations;
|
||||
ULONG otAllocationID;
|
||||
#endif
|
||||
|
||||
//
|
||||
// OpenThread context buffer
|
||||
//
|
||||
otInstance* otCtx;
|
||||
PUCHAR otInstanceBuffer;
|
||||
//
|
||||
// OpenThread context buffer
|
||||
//
|
||||
otInstance* otCtx;
|
||||
PUCHAR otInstanceBuffer;
|
||||
};
|
||||
struct // Tunnel Mode Variables
|
||||
{
|
||||
NDIS_SPIN_LOCK tunCommandLock;
|
||||
LIST_ENTRY tunCommandHandlers;
|
||||
USHORT tunTIDsInUse;
|
||||
spinel_tid_t tunNextTID;
|
||||
|
||||
PVOID TunWorkerThread;
|
||||
KEVENT TunWorkerThreadStopEvent;
|
||||
KEVENT TunWorkerThreadAddressChangedEvent;
|
||||
};
|
||||
};
|
||||
|
||||
} MS_FILTER, * PMS_FILTER;
|
||||
|
||||
// Helper function that converts an otInstance pointer to a MS_FILTER pointer
|
||||
__inline PMS_FILTER otCtxToFilter(_In_ otInstance* otCtx)
|
||||
{
|
||||
return *(PMS_FILTER*)((PUCHAR)otCtx - sizeof(PMS_FILTER));
|
||||
}
|
||||
|
||||
// Helper function to indicate if a role means it is attached or not
|
||||
_inline BOOLEAN IsAttached(_In_ otDeviceRole role)
|
||||
{
|
||||
return role > kDeviceRoleDetached;
|
||||
}
|
||||
|
||||
//
|
||||
// function prototypes
|
||||
// NDIS Filter Functions
|
||||
//
|
||||
|
||||
FILTER_ATTACH FilterAttach;
|
||||
@@ -235,6 +246,10 @@ FILTER_SEND_NET_BUFFER_LISTS_COMPLETE FilterSendNetBufferListsComplete;
|
||||
FILTER_RECEIVE_NET_BUFFER_LISTS FilterReceiveNetBufferLists;
|
||||
FILTER_CANCEL_SEND_NET_BUFFER_LISTS FilterCancelSendNetBufferLists;
|
||||
|
||||
//
|
||||
// Link State Functions
|
||||
//
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
VOID
|
||||
otLwfIndicateLinkState(
|
||||
@@ -259,76 +274,6 @@ otLwfRevertCompartment(
|
||||
_In_ COMPARTMENT_ID OriginalCompartment
|
||||
);
|
||||
|
||||
//
|
||||
// Event Processing Functions
|
||||
//
|
||||
|
||||
EXT_CALLBACK otLwfEventProcessingTimer;
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
otLwfEventProcessingStart(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingStop(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingIndicateNewWaitTime(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ ULONG waitTime
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingIndicateNewTasklet(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingIndicateAddressChange(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ MIB_NOTIFICATION_TYPE NotificationType,
|
||||
_In_ PIN6_ADDR pAddr
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingIndicateNewNetBufferLists(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_ BOOLEAN Received,
|
||||
_In_ NDIS_PORT_NUMBER PortNumber,
|
||||
_In_ PNET_BUFFER_LIST NetBufferLists
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingIndicateNetBufferListsCancelled(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ PVOID CancelId
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingIndicateIrp(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ PIRP Irp
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingIndicateEnergyScanResult(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ CHAR MaxRssi
|
||||
);
|
||||
|
||||
//
|
||||
// Data Path functions
|
||||
//
|
||||
@@ -345,18 +290,6 @@ otLwfDisableDataPath(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
//
|
||||
// OpenThread callbacks
|
||||
//
|
||||
|
||||
void otLwfStateChangedCallback(uint32_t aFlags, _In_ void *aContext);
|
||||
void otLwfReceiveIp6DatagramCallback(_In_ otMessage aMessage, _In_ void *aContext);
|
||||
void otLwfActiveScanCallback(_In_ otActiveScanResult *aResult, _In_ void *aContext);
|
||||
void otLwfEnergyScanCallback(_In_ otEnergyScanResult *aResult, _In_ void *aContext);
|
||||
void otLwfDiscoverCallback(_In_ otActiveScanResult *aResult, _In_ void *aContext);
|
||||
void otLwfCommissionerEnergyReportCallback(uint32_t aChannelMask, const uint8_t *aEnergyList, uint8_t aEnergyListLength, void *aContext);
|
||||
void otLwfCommissionerPanIdConflictCallback(uint16_t aPanId, uint32_t aChannelMask, _In_ void *aContext);
|
||||
|
||||
//
|
||||
// Address Functions
|
||||
//
|
||||
@@ -386,16 +319,41 @@ otLwfInitializeAddresses(
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfAddressesUpdated(
|
||||
otLwfRadioAddressesUpdated(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfTunAddressesUpdated(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_reads_bytes_(value_data_len) const uint8_t* value_data_ptr,
|
||||
_In_ spinel_size_t value_data_len,
|
||||
_Out_ uint32_t *aNotifFlags
|
||||
);
|
||||
|
||||
int
|
||||
otLwfFindCachedAddrIndex(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ PIN6_ADDR addr
|
||||
);
|
||||
|
||||
//
|
||||
// Tunnel Logic Functions
|
||||
//
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NDIS_STATUS
|
||||
otLwfInitializeTunnelMode(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
void
|
||||
otLwfUninitializeTunnelMode(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
//
|
||||
// Logging Helper
|
||||
//
|
||||
@@ -412,7 +370,7 @@ otLogBuffer(
|
||||
// Debug Helpers
|
||||
//
|
||||
|
||||
#if DBG
|
||||
#if DEBUG_ALLOC
|
||||
|
||||
typedef struct _OT_ALLOC
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -32,6 +32,7 @@
|
||||
//
|
||||
// Function prototype for general Io Control functions
|
||||
//
|
||||
|
||||
typedef
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
@@ -69,9 +70,16 @@ otLwfCompleteOpenThreadIrp(
|
||||
_In_ PIRP Irp
|
||||
);
|
||||
|
||||
// Helper for converting IoCtl to string
|
||||
const char*
|
||||
IoCtlString(
|
||||
ULONG IoControlCode
|
||||
);
|
||||
|
||||
//
|
||||
// Function prototype for OpenThread Io Control functions
|
||||
//
|
||||
|
||||
typedef
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
@@ -85,96 +93,136 @@ OTLWF_OT_IOCTL_FUNC(
|
||||
_Inout_ PULONG OutBufferLength
|
||||
);
|
||||
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otInterface;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otThread;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otActiveScan;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otDiscover;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otChannel;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otChildTimeout;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otExtendedAddress;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otExtendedPanId;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otLeaderRloc;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otLinkMode;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMasterKey;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMeshLocalEid;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMeshLocalPrefix;
|
||||
//OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otNetworkDataLeader
|
||||
//OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otNetworkDataLocal
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otNetworkName;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otPanId;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRouterRollEnabled;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otShortAddress;
|
||||
//OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otUnicastAddresses
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otActiveDataset;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otPendingDataset;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otLocalLeaderWeight;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otAddBorderRouter;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRemoveBorderRouter;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otAddExternalRoute;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRemoveExternalRoute;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSendServerData;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otContextIdReuseDelay;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otKeySequenceCounter;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otNetworkIdTimeout;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRouterUpgradeThreshold;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otReleaseRouterId;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMacWhitelistEnabled;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otAddMacWhitelist;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRemoveMacWhitelist;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMacWhitelistEntry;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otClearMacWhitelist;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otDeviceRole;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otChildInfoById;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otChildInfoByIndex;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otEidCacheEntry;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otLeaderData;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otLeaderRouterId;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otLeaderWeight;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otNetworkDataVersion;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otPartitionId;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRloc16;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRouterIdSequence;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRouterInfo;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otStableNetworkDataVersion;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMacBlacklistEnabled;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otAddMacBlacklist;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRemoveMacBlacklist;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMacBlacklistEntry;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otClearMacBlacklist;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMaxTransmitPower;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otNextOnMeshPrefix;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otPollPeriod;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otLocalLeaderPartitionId;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otAssignLinkQuality;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otPlatformReset;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otParentInfo;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSingleton;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMacCounters;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMaxChildren;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otCommissionerStart;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otCommissionerStop;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otJoinerStart;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otJoinerStop;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otFactoryAssignedIeeeEui64;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otHashMacAddress;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRouterDowngradeThreshold;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otCommissionerPanIdQuery;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otCommissionerEnergyScan;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRouterSelectionJitter;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otJoinerUdpPort;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSendDiagnosticGet;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSendDiagnosticReset;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otCommissionerAddJoiner;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otCommissionerRemoveJoiner;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otCommissionerProvisioningUrl;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otCommissionerAnnounceBegin;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otEnergyScan;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSendActiveGet;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSendActiveSet;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSendPendingGet;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSendPendingSet;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSendMgmtCommissionerGet;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSendMgmtCommissionerSet;
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otKeySwitchGuardtime;
|
||||
typedef
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
OTLWF_TUN_IOCTL_FUNC(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ PIRP Irp,
|
||||
_In_reads_bytes_(InBufferLength)
|
||||
PUCHAR InBuffer,
|
||||
_In_ ULONG InBufferLength,
|
||||
_In_ ULONG OutBufferLength
|
||||
);
|
||||
|
||||
typedef
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
NTSTATUS
|
||||
(SPINEL_IRP_CMD_HANDLER)(
|
||||
_In_ spinel_prop_key_t Key,
|
||||
_In_reads_bytes_(DataLength) const uint8_t* Data,
|
||||
_In_ spinel_size_t DataLength,
|
||||
_Out_writes_bytes_(*OutBufferLength)
|
||||
PVOID OutBuffer,
|
||||
_Inout_ PULONG OutBufferLength
|
||||
);
|
||||
|
||||
#define DECL_IOCTL_FUNC(X) \
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_##X
|
||||
|
||||
#define DECL_IOCTL_FUNC_WITH_TUN(X) \
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_##X; \
|
||||
OTLWF_TUN_IOCTL_FUNC otLwfTunIoCtl_##X
|
||||
|
||||
#define DECL_IOCTL_FUNC_WITH_TUN2(X) \
|
||||
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_##X; \
|
||||
OTLWF_TUN_IOCTL_FUNC otLwfTunIoCtl_##X; \
|
||||
SPINEL_IRP_CMD_HANDLER otLwfTunIoCtl_##X##_Handler
|
||||
|
||||
#define REF_IOCTL_FUNC(X) otLwfIoCtl_##X , NULL
|
||||
|
||||
#define REF_IOCTL_FUNC_WITH_TUN(X) otLwfIoCtl_##X , otLwfTunIoCtl_##X
|
||||
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otInterface);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otThread);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otActiveScan);
|
||||
DECL_IOCTL_FUNC(otDiscover);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otChannel);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otChildTimeout);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otExtendedAddress);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otExtendedPanId);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otLeaderRloc);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otLinkMode);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otMasterKey);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otMeshLocalEid);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otMeshLocalPrefix);
|
||||
//DECL_IOCTL_FUNC(otNetworkDataLeader);
|
||||
//DECL_IOCTL_FUNC(otNetworkDataLocal);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otNetworkName);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otPanId);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otRouterRollEnabled);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otShortAddress);
|
||||
DECL_IOCTL_FUNC(otActiveDataset);
|
||||
DECL_IOCTL_FUNC(otPendingDataset);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otLocalLeaderWeight);
|
||||
DECL_IOCTL_FUNC_WITH_TUN(otAddBorderRouter);
|
||||
DECL_IOCTL_FUNC_WITH_TUN(otRemoveBorderRouter);
|
||||
DECL_IOCTL_FUNC_WITH_TUN(otAddExternalRoute);
|
||||
DECL_IOCTL_FUNC_WITH_TUN(otRemoveExternalRoute);
|
||||
DECL_IOCTL_FUNC(otSendServerData);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otContextIdReuseDelay);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otKeySequenceCounter);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otNetworkIdTimeout);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otRouterUpgradeThreshold);
|
||||
DECL_IOCTL_FUNC_WITH_TUN(otReleaseRouterId);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otMacWhitelistEnabled);
|
||||
DECL_IOCTL_FUNC_WITH_TUN(otAddMacWhitelist);
|
||||
DECL_IOCTL_FUNC_WITH_TUN(otRemoveMacWhitelist);
|
||||
DECL_IOCTL_FUNC(otMacWhitelistEntry);
|
||||
DECL_IOCTL_FUNC_WITH_TUN(otClearMacWhitelist);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otDeviceRole);
|
||||
DECL_IOCTL_FUNC(otChildInfoById);
|
||||
DECL_IOCTL_FUNC(otChildInfoByIndex);
|
||||
DECL_IOCTL_FUNC(otEidCacheEntry);
|
||||
DECL_IOCTL_FUNC(otLeaderData);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otLeaderRouterId);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otLeaderWeight);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otNetworkDataVersion);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otPartitionId);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otRloc16);
|
||||
DECL_IOCTL_FUNC(otRouterIdSequence);
|
||||
DECL_IOCTL_FUNC(otRouterInfo);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otStableNetworkDataVersion);
|
||||
DECL_IOCTL_FUNC(otMacBlacklistEnabled);
|
||||
DECL_IOCTL_FUNC(otAddMacBlacklist);
|
||||
DECL_IOCTL_FUNC(otRemoveMacBlacklist);
|
||||
DECL_IOCTL_FUNC(otMacBlacklistEntry);
|
||||
DECL_IOCTL_FUNC(otClearMacBlacklist);
|
||||
DECL_IOCTL_FUNC(otMaxTransmitPower);
|
||||
DECL_IOCTL_FUNC(otNextOnMeshPrefix);
|
||||
DECL_IOCTL_FUNC(otPollPeriod);
|
||||
DECL_IOCTL_FUNC(otLocalLeaderPartitionId);
|
||||
DECL_IOCTL_FUNC(otAssignLinkQuality);
|
||||
DECL_IOCTL_FUNC_WITH_TUN(otPlatformReset);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otParentInfo);
|
||||
DECL_IOCTL_FUNC(otSingleton);
|
||||
DECL_IOCTL_FUNC(otMacCounters);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otMaxChildren);
|
||||
DECL_IOCTL_FUNC(otCommissionerStart);
|
||||
DECL_IOCTL_FUNC(otCommissionerStop);
|
||||
DECL_IOCTL_FUNC(otJoinerStart);
|
||||
DECL_IOCTL_FUNC(otJoinerStop);
|
||||
DECL_IOCTL_FUNC(otFactoryAssignedIeeeEui64);
|
||||
DECL_IOCTL_FUNC(otHashMacAddress);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otRouterDowngradeThreshold);
|
||||
DECL_IOCTL_FUNC(otCommissionerPanIdQuery);
|
||||
DECL_IOCTL_FUNC(otCommissionerEnergyScan);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otRouterSelectionJitter);
|
||||
DECL_IOCTL_FUNC(otJoinerUdpPort);
|
||||
DECL_IOCTL_FUNC(otSendDiagnosticGet);
|
||||
DECL_IOCTL_FUNC(otSendDiagnosticReset);
|
||||
DECL_IOCTL_FUNC(otCommissionerAddJoiner);
|
||||
DECL_IOCTL_FUNC(otCommissionerRemoveJoiner);
|
||||
DECL_IOCTL_FUNC(otCommissionerProvisioningUrl);
|
||||
DECL_IOCTL_FUNC(otCommissionerAnnounceBegin);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otEnergyScan);
|
||||
DECL_IOCTL_FUNC(otSendActiveGet);
|
||||
DECL_IOCTL_FUNC(otSendActiveSet);
|
||||
DECL_IOCTL_FUNC(otSendPendingGet);
|
||||
DECL_IOCTL_FUNC(otSendPendingSet);
|
||||
DECL_IOCTL_FUNC(otSendMgmtCommissionerGet);
|
||||
DECL_IOCTL_FUNC(otSendMgmtCommissionerSet);
|
||||
DECL_IOCTL_FUNC_WITH_TUN2(otKeySwitchGuardtime);
|
||||
DECL_IOCTL_FUNC(otFactoryReset);
|
||||
|
||||
#endif // _IOCONTROL_H
|
||||
|
||||
@@ -72,6 +72,7 @@ RtlCopyBufferToMdl(
|
||||
#include <platform/misc.h>
|
||||
#include <platform/alarm.h>
|
||||
#include <platform/settings.h>
|
||||
#include <ncp/spinel.h>
|
||||
|
||||
#include <otLwfIoctl.h>
|
||||
#include <otOID.h>
|
||||
@@ -89,7 +90,22 @@ RtlCopyBufferToMdl(
|
||||
|
||||
typedef struct _MS_FILTER MS_FILTER, *PMS_FILTER;
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct UDPHeader
|
||||
{
|
||||
USHORT SourcePort;
|
||||
USHORT DestinationPort;
|
||||
USHORT TotalLength;
|
||||
USHORT Checksum;
|
||||
|
||||
} UDPHeader;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
//#define DEBUG_TIMING
|
||||
//#define DEBUG_ALLOC
|
||||
//#define LOG_BUFFERS
|
||||
//#define FORCE_SYNCHRONOUS_RECEIVE
|
||||
|
||||
@@ -99,3 +115,5 @@ typedef struct _MS_FILTER MS_FILTER, *PMS_FILTER;
|
||||
#include "oid.h"
|
||||
#include "radio.h"
|
||||
#include "filter.h"
|
||||
#include "thread.h"
|
||||
#include "tunnel.h"
|
||||
|
||||
@@ -0,0 +1,533 @@
|
||||
/*
|
||||
* 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 implements the Thread mode (Radio Miniport) functions required for the OpenThread library.
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
#include "thread.tmh"
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NDIS_STATUS
|
||||
otLwfInitializeThreadMode(
|
||||
_In_ PMS_FILTER pFilter
|
||||
)
|
||||
{
|
||||
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
||||
PNET_BUFFER SendNetBuffer;
|
||||
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
do
|
||||
{
|
||||
// Create the SendNetBufferList
|
||||
pFilter->SendNetBufferList =
|
||||
NdisAllocateNetBufferAndNetBufferList(
|
||||
pFilter->NetBufferListPool, // PoolHandle
|
||||
0, // ContextSize
|
||||
0, // ContextBackFill
|
||||
NULL, // MdlChain
|
||||
0, // DataOffset
|
||||
0 // DataLength
|
||||
);
|
||||
if (pFilter->SendNetBufferList == NULL)
|
||||
{
|
||||
Status = NDIS_STATUS_RESOURCES;
|
||||
LogWarning(DRIVER_DEFAULT, "Failed to create Send NetBufferList");
|
||||
break;
|
||||
}
|
||||
|
||||
// Initialize NetBuffer fields
|
||||
SendNetBuffer = NET_BUFFER_LIST_FIRST_NB(pFilter->SendNetBufferList);
|
||||
NET_BUFFER_CURRENT_MDL(SendNetBuffer) = NULL;
|
||||
NET_BUFFER_CURRENT_MDL_OFFSET(SendNetBuffer) = 0;
|
||||
NET_BUFFER_DATA_LENGTH(SendNetBuffer) = 0;
|
||||
NET_BUFFER_DATA_OFFSET(SendNetBuffer) = 0;
|
||||
NET_BUFFER_FIRST_MDL(SendNetBuffer) = NULL;
|
||||
|
||||
// Allocate the NetBuffer for SendNetBufferList
|
||||
Status = NdisRetreatNetBufferDataStart(SendNetBuffer, kMaxPHYPacketSize, 0, NULL);
|
||||
if (Status != NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Failed to allocate NB for Send NetBufferList, %!NDIS_STATUS!", Status);
|
||||
break;
|
||||
}
|
||||
|
||||
KeInitializeEvent(
|
||||
&pFilter->SendNetBufferListComplete,
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
FALSE // event initially non-signalled
|
||||
);
|
||||
|
||||
// Initialize the event processing
|
||||
pFilter->EventWorkerThread = NULL;
|
||||
NdisAllocateSpinLock(&pFilter->EventsLock);
|
||||
InitializeListHead(&pFilter->AddressChangesHead);
|
||||
InitializeListHead(&pFilter->NBLsHead);
|
||||
InitializeListHead(&pFilter->EventIrpListHead);
|
||||
KeInitializeEvent(
|
||||
&pFilter->EventWorkerThreadStopEvent,
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
FALSE // event initially non-signalled
|
||||
);
|
||||
KeInitializeEvent(
|
||||
&pFilter->EventWorkerThreadWaitTimeUpdated,
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
FALSE // event initially non-signalled
|
||||
);
|
||||
KeInitializeEvent(
|
||||
&pFilter->EventWorkerThreadProcessTasklets,
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
FALSE // event initially non-signalled
|
||||
);
|
||||
KeInitializeEvent(
|
||||
&pFilter->EventWorkerThreadProcessAddressChanges,
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
FALSE // event initially non-signalled
|
||||
);
|
||||
KeInitializeEvent(
|
||||
&pFilter->EventWorkerThreadProcessNBLs,
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
FALSE // event initially non-signalled
|
||||
);
|
||||
KeInitializeEvent(
|
||||
&pFilter->EventWorkerThreadProcessIrp,
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
FALSE // event initially non-signalled
|
||||
);
|
||||
KeInitializeEvent(
|
||||
&pFilter->EventWorkerThreadEnergyScanComplete,
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
FALSE // event initially non-signalled
|
||||
);
|
||||
pFilter->EventHighPrecisionTimer =
|
||||
ExAllocateTimer(
|
||||
otLwfEventProcessingTimer,
|
||||
pFilter,
|
||||
EX_TIMER_HIGH_RESOLUTION
|
||||
);
|
||||
if (pFilter->EventHighPrecisionTimer == NULL)
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Failed to allocate timer!");
|
||||
break;
|
||||
}
|
||||
|
||||
// Initialize the event processing thread
|
||||
if (!NT_SUCCESS(otLwfEventProcessingStart(pFilter)))
|
||||
{
|
||||
Status = NDIS_STATUS_RESOURCES;
|
||||
break;
|
||||
}
|
||||
|
||||
} while (FALSE);
|
||||
|
||||
if (Status != NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
// Stop event processing thread
|
||||
otLwfEventProcessingStop(pFilter);
|
||||
|
||||
// Stop and free the timer
|
||||
if (pFilter->EventHighPrecisionTimer)
|
||||
{
|
||||
ExDeleteTimer(pFilter->EventHighPrecisionTimer, TRUE, FALSE, NULL);
|
||||
}
|
||||
|
||||
// Free NBL
|
||||
if (pFilter->SendNetBufferList)
|
||||
{
|
||||
NdisAdvanceNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB(pFilter->SendNetBufferList), kMaxPHYPacketSize, TRUE, NULL);
|
||||
NdisFreeNetBufferList(pFilter->SendNetBufferList);
|
||||
}
|
||||
}
|
||||
|
||||
LogFuncExitNDIS(DRIVER_DEFAULT, Status);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
void
|
||||
otLwfUninitializeThreadMode(
|
||||
_In_ PMS_FILTER pFilter
|
||||
)
|
||||
{
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
// Stop event processing thread
|
||||
otLwfEventProcessingStop(pFilter);
|
||||
|
||||
// Free timer
|
||||
ExDeleteTimer(pFilter->EventHighPrecisionTimer, TRUE, FALSE, NULL);
|
||||
|
||||
// Free NBL & Pools
|
||||
NdisAdvanceNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB(pFilter->SendNetBufferList), kMaxPHYPacketSize, TRUE, NULL);
|
||||
NdisFreeNetBufferList(pFilter->SendNetBufferList);
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
#if DEBUG_ALLOC
|
||||
PMS_FILTER
|
||||
otLwfFindFromCurrentThread()
|
||||
{
|
||||
PMS_FILTER pOutput = NULL;
|
||||
HANDLE CurThreadId = PsGetCurrentThreadId();
|
||||
|
||||
NdisAcquireSpinLock(&FilterListLock);
|
||||
|
||||
for (PLIST_ENTRY Link = FilterModuleList.Flink; Link != &FilterModuleList; Link = Link->Flink)
|
||||
{
|
||||
PMS_FILTER pFilter = CONTAINING_RECORD(Link, MS_FILTER, FilterModuleLink);
|
||||
|
||||
if (pFilter->otThreadId == CurThreadId)
|
||||
{
|
||||
pOutput = pFilter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NdisReleaseSpinLock(&FilterListLock);
|
||||
|
||||
NT_ASSERT(pOutput);
|
||||
return pOutput;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// OpenThread Platform functions
|
||||
//
|
||||
|
||||
void *otPlatCAlloc(size_t aNum, size_t aSize)
|
||||
{
|
||||
size_t totalSize = aNum * aSize;
|
||||
#if DEBUG_ALLOC
|
||||
totalSize += sizeof(OT_ALLOC);
|
||||
#endif
|
||||
PVOID mem = ExAllocatePoolWithTag(NonPagedPoolNx, totalSize, 'OTDM');
|
||||
if (mem)
|
||||
{
|
||||
RtlZeroMemory(mem, totalSize);
|
||||
#if DEBUG_ALLOC
|
||||
PMS_FILTER pFilter = otLwfFindFromCurrentThread();
|
||||
//LogVerbose(DRIVER_DEFAULT, "otPlatAlloc(%u) = ID:%u %p", (ULONG)totalSize, pFilter->otAllocationID, mem);
|
||||
|
||||
OT_ALLOC* AllocHeader = (OT_ALLOC*)mem;
|
||||
AllocHeader->Length = (LONG)totalSize;
|
||||
AllocHeader->ID = pFilter->otAllocationID++;
|
||||
InsertTailList(&pFilter->otOutStandingAllocations, &AllocHeader->Link);
|
||||
|
||||
InterlockedIncrement(&pFilter->otOutstandingAllocationCount);
|
||||
InterlockedAdd(&pFilter->otOutstandingMemoryAllocated, AllocHeader->Length);
|
||||
|
||||
mem = (PUCHAR)(mem) + sizeof(OT_ALLOC);
|
||||
#endif
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
void otPlatFree(void *aPtr)
|
||||
{
|
||||
if (aPtr == NULL) return;
|
||||
#if DEBUG_ALLOC
|
||||
aPtr = (PUCHAR)(aPtr) - sizeof(OT_ALLOC);
|
||||
//LogVerbose(DRIVER_DEFAULT, "otPlatFree(%p)", aPtr);
|
||||
OT_ALLOC* AllocHeader = (OT_ALLOC*)aPtr;
|
||||
|
||||
PMS_FILTER pFilter = otLwfFindFromCurrentThread();
|
||||
InterlockedDecrement(&pFilter->otOutstandingAllocationCount);
|
||||
InterlockedAdd(&pFilter->otOutstandingMemoryAllocated, -AllocHeader->Length);
|
||||
RemoveEntryList(&AllocHeader->Link);
|
||||
#endif
|
||||
ExFreePoolWithTag(aPtr, 'OTDM');
|
||||
}
|
||||
|
||||
uint32_t otPlatRandomGet()
|
||||
{
|
||||
LARGE_INTEGER Counter = KeQueryPerformanceCounter(NULL);
|
||||
return (uint32_t)RtlRandomEx(&Counter.LowPart);
|
||||
}
|
||||
|
||||
ThreadError otPlatRandomSecureGet(uint16_t aInputLength, uint8_t *aOutput, uint16_t *aOutputLength)
|
||||
{
|
||||
// Just use the system-preferred random number generator algorithm
|
||||
NTSTATUS status =
|
||||
BCryptGenRandom(
|
||||
NULL,
|
||||
aOutput,
|
||||
(ULONG)aInputLength,
|
||||
BCRYPT_USE_SYSTEM_PREFERRED_RNG
|
||||
);
|
||||
NT_ASSERT(NT_SUCCESS(status));
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "BCryptGenRandom failed, %!STATUS!", status);
|
||||
return kThreadError_Failed;
|
||||
}
|
||||
|
||||
*aOutputLength = aInputLength;
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
void otSignalTaskletPending(_In_ otInstance *otCtx)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "otSignalTaskletPending");
|
||||
PMS_FILTER pFilter = otCtxToFilter(otCtx);
|
||||
otLwfEventProcessingIndicateNewTasklet(pFilter);
|
||||
}
|
||||
|
||||
// Process a role state change
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
VOID
|
||||
otLwfProcessRoleStateChange(
|
||||
_In_ PMS_FILTER pFilter
|
||||
)
|
||||
{
|
||||
otDeviceRole prevRole = pFilter->otCachedRole;
|
||||
pFilter->otCachedRole = otGetDeviceRole(pFilter->otCtx);
|
||||
if (prevRole == pFilter->otCachedRole) return;
|
||||
|
||||
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! new role: %!otDeviceRole!", &pFilter->InterfaceGuid, pFilter->otCachedRole);
|
||||
|
||||
// Make sure we are in the correct media connect state
|
||||
otLwfIndicateLinkState(
|
||||
pFilter,
|
||||
IsAttached(pFilter->otCachedRole) ?
|
||||
MediaConnectStateConnected :
|
||||
MediaConnectStateDisconnected);
|
||||
}
|
||||
|
||||
void otLwfStateChangedCallback(uint32_t aFlags, _In_ void *aContext)
|
||||
{
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
PMS_FILTER pFilter = (PMS_FILTER)aContext;
|
||||
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
|
||||
|
||||
//
|
||||
// Process the notification internally
|
||||
//
|
||||
|
||||
if ((aFlags & OT_IP6_ADDRESS_ADDED) != 0)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_IP6_ADDRESS_ADDED", pFilter);
|
||||
otLwfRadioAddressesUpdated(pFilter);
|
||||
}
|
||||
|
||||
if ((aFlags & OT_IP6_ADDRESS_REMOVED) != 0)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_IP6_ADDRESS_REMOVED", pFilter);
|
||||
otLwfRadioAddressesUpdated(pFilter);
|
||||
}
|
||||
|
||||
if ((aFlags & OT_NET_ROLE) != 0)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_NET_ROLE", pFilter);
|
||||
otLwfProcessRoleStateChange(pFilter);
|
||||
}
|
||||
|
||||
if ((aFlags & OT_NET_PARTITION_ID) != 0)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_NET_PARTITION_ID", pFilter);
|
||||
}
|
||||
|
||||
if ((aFlags & OT_NET_KEY_SEQUENCE_COUNTER) != 0)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_NET_KEY_SEQUENCE_COUNTER", pFilter);
|
||||
}
|
||||
|
||||
if ((aFlags & OT_THREAD_CHILD_ADDED) != 0)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_THREAD_CHILD_ADDED", pFilter);
|
||||
}
|
||||
|
||||
if ((aFlags & OT_THREAD_CHILD_REMOVED) != 0)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_THREAD_CHILD_REMOVED", pFilter);
|
||||
}
|
||||
|
||||
if ((aFlags & OT_THREAD_NETDATA_UPDATED) != 0)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_THREAD_NETDATA_UPDATED", pFilter);
|
||||
otSlaacUpdate(pFilter->otCtx, pFilter->otAutoAddresses, ARRAYSIZE(pFilter->otAutoAddresses), otCreateRandomIid, NULL);
|
||||
}
|
||||
|
||||
if ((aFlags & OT_IP6_ML_ADDR_CHANGED) != 0)
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_IP6_ML_ADDR_CHANGED", pFilter);
|
||||
}
|
||||
|
||||
//
|
||||
// Queue the notification for clients
|
||||
//
|
||||
|
||||
if (NotifEntry)
|
||||
{
|
||||
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
|
||||
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
|
||||
NotifEntry->Notif.NotifType = OTLWF_NOTIF_STATE_CHANGE;
|
||||
NotifEntry->Notif.StateChangePayload.Flags = aFlags;
|
||||
|
||||
otLwfIndicateNotification(NotifEntry);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
void otLwfActiveScanCallback(_In_ otActiveScanResult *aResult, _In_ void *aContext)
|
||||
{
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
PMS_FILTER pFilter = (PMS_FILTER)aContext;
|
||||
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
|
||||
if (NotifEntry)
|
||||
{
|
||||
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
|
||||
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
|
||||
NotifEntry->Notif.NotifType = OTLWF_NOTIF_ACTIVE_SCAN;
|
||||
|
||||
if (aResult)
|
||||
{
|
||||
NotifEntry->Notif.ActiveScanPayload.Valid = TRUE;
|
||||
NotifEntry->Notif.ActiveScanPayload.Results = *aResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
NotifEntry->Notif.ActiveScanPayload.Valid = FALSE;
|
||||
}
|
||||
|
||||
otLwfIndicateNotification(NotifEntry);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
void otLwfEnergyScanCallback(_In_ otEnergyScanResult *aResult, _In_ void *aContext)
|
||||
{
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
PMS_FILTER pFilter = (PMS_FILTER)aContext;
|
||||
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
|
||||
if (NotifEntry)
|
||||
{
|
||||
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
|
||||
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
|
||||
NotifEntry->Notif.NotifType = OTLWF_NOTIF_ENERGY_SCAN;
|
||||
|
||||
if (aResult)
|
||||
{
|
||||
NotifEntry->Notif.EnergyScanPayload.Valid = TRUE;
|
||||
NotifEntry->Notif.EnergyScanPayload.Results = *aResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
NotifEntry->Notif.EnergyScanPayload.Valid = FALSE;
|
||||
}
|
||||
|
||||
otLwfIndicateNotification(NotifEntry);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
void otLwfDiscoverCallback(_In_ otActiveScanResult *aResult, _In_ void *aContext)
|
||||
{
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
PMS_FILTER pFilter = (PMS_FILTER)aContext;
|
||||
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
|
||||
if (NotifEntry)
|
||||
{
|
||||
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
|
||||
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
|
||||
NotifEntry->Notif.NotifType = OTLWF_NOTIF_DISCOVER;
|
||||
|
||||
if (aResult)
|
||||
{
|
||||
NotifEntry->Notif.DiscoverPayload.Valid = TRUE;
|
||||
NotifEntry->Notif.DiscoverPayload.Results = *aResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
NotifEntry->Notif.DiscoverPayload.Valid = FALSE;
|
||||
}
|
||||
|
||||
otLwfIndicateNotification(NotifEntry);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
void otLwfCommissionerEnergyReportCallback(uint32_t aChannelMask, const uint8_t *aEnergyList, uint8_t aEnergyListLength, void *aContext)
|
||||
{
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
PMS_FILTER pFilter = (PMS_FILTER)aContext;
|
||||
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
|
||||
if (NotifEntry)
|
||||
{
|
||||
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
|
||||
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
|
||||
NotifEntry->Notif.NotifType = OTLWF_NOTIF_COMMISSIONER_ENERGY_REPORT;
|
||||
|
||||
// Limit the number of reports if necessary
|
||||
if (aEnergyListLength > MAX_ENERGY_REPORT_LENGTH) aEnergyListLength = MAX_ENERGY_REPORT_LENGTH;
|
||||
|
||||
NotifEntry->Notif.CommissionerEnergyReportPayload.ChannelMask = aChannelMask;
|
||||
NotifEntry->Notif.CommissionerEnergyReportPayload.EnergyListLength = aEnergyListLength;
|
||||
memcpy(NotifEntry->Notif.CommissionerEnergyReportPayload.EnergyList, aEnergyList, aEnergyListLength);
|
||||
|
||||
otLwfIndicateNotification(NotifEntry);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
void otLwfCommissionerPanIdConflictCallback(uint16_t aPanId, uint32_t aChannelMask, _In_ void *aContext)
|
||||
{
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
PMS_FILTER pFilter = (PMS_FILTER)aContext;
|
||||
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
|
||||
if (NotifEntry)
|
||||
{
|
||||
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
|
||||
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
|
||||
NotifEntry->Notif.NotifType = OTLWF_NOTIF_COMMISSIONER_PANID_QUERY;
|
||||
|
||||
NotifEntry->Notif.CommissionerPanIdQueryPayload.PanId = aPanId;
|
||||
NotifEntry->Notif.CommissionerPanIdQueryPayload.ChannelMask = aChannelMask;
|
||||
|
||||
otLwfIndicateNotification(NotifEntry);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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 functions for the otLwf Filter Thread mode.
|
||||
*/
|
||||
|
||||
#ifndef _THREAD_H_
|
||||
#define _THREAD_H_
|
||||
|
||||
// Helper function that converts an otInstance pointer to a MS_FILTER pointer
|
||||
__inline PMS_FILTER otCtxToFilter(_In_ otInstance* otCtx)
|
||||
{
|
||||
return *(PMS_FILTER*)((PUCHAR)otCtx - sizeof(PMS_FILTER));
|
||||
}
|
||||
|
||||
// Helper function to indicate if a role means it is attached or not
|
||||
_inline BOOLEAN IsAttached(_In_ otDeviceRole role)
|
||||
{
|
||||
return role > kDeviceRoleDetached;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialization functions
|
||||
//
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NDIS_STATUS
|
||||
otLwfInitializeThreadMode(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
void
|
||||
otLwfUninitializeThreadMode(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
//
|
||||
// Event Processing Functions
|
||||
//
|
||||
|
||||
EXT_CALLBACK otLwfEventProcessingTimer;
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
otLwfEventProcessingStart(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingStop(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingIndicateNewWaitTime(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ ULONG waitTime
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingIndicateNewTasklet(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingIndicateAddressChange(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ MIB_NOTIFICATION_TYPE NotificationType,
|
||||
_In_ PIN6_ADDR pAddr
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingIndicateNewNetBufferLists(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_ BOOLEAN Received,
|
||||
_In_ NDIS_PORT_NUMBER PortNumber,
|
||||
_In_ PNET_BUFFER_LIST NetBufferLists
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingIndicateNetBufferListsCancelled(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ PVOID CancelId
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingIndicateIrp(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ PIRP Irp
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingIndicateEnergyScanResult(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ CHAR MaxRssi
|
||||
);
|
||||
|
||||
//
|
||||
// OpenThread callbacks
|
||||
//
|
||||
|
||||
void otLwfStateChangedCallback(uint32_t aFlags, _In_ void *aContext);
|
||||
void otLwfReceiveIp6DatagramCallback(_In_ otMessage aMessage, _In_ void *aContext);
|
||||
void otLwfActiveScanCallback(_In_ otActiveScanResult *aResult, _In_ void *aContext);
|
||||
void otLwfEnergyScanCallback(_In_ otEnergyScanResult *aResult, _In_ void *aContext);
|
||||
void otLwfDiscoverCallback(_In_ otActiveScanResult *aResult, _In_ void *aContext);
|
||||
void otLwfCommissionerEnergyReportCallback(uint32_t aChannelMask, const uint8_t *aEnergyList, uint8_t aEnergyListLength, void *aContext);
|
||||
void otLwfCommissionerPanIdConflictCallback(uint16_t aPanId, uint32_t aChannelMask, _In_ void *aContext);
|
||||
|
||||
#endif //_THREAD_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* 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 functions for the otLwf Filter Tunnel mode.
|
||||
*/
|
||||
|
||||
#ifndef _TUNNEL_H_
|
||||
#define _TUNNEL_H_
|
||||
|
||||
typedef
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
VOID
|
||||
(SPINEL_CMD_HANDLER)(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ PVOID Context,
|
||||
_In_ UINT Command,
|
||||
_In_ spinel_prop_key_t Key,
|
||||
_In_reads_bytes_(DataLength) const uint8_t* Data,
|
||||
_In_ spinel_size_t DataLength
|
||||
);
|
||||
|
||||
typedef struct _SPINEL_CMD_HANDLER_ENTRY
|
||||
{
|
||||
LIST_ENTRY Link;
|
||||
SPINEL_CMD_HANDLER *Handler;
|
||||
PVOID Context;
|
||||
spinel_tid_t TransactionId;
|
||||
} SPINEL_CMD_HANDLER_ENTRY;
|
||||
|
||||
//
|
||||
// Initialization Functions
|
||||
//
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NDIS_STATUS
|
||||
otLwfInitializeTunnelMode(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
void
|
||||
otLwfUninitializeTunnelMode(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
//
|
||||
// Spinel Packet Functions
|
||||
//
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
BOOLEAN
|
||||
otLwfCancelCommandHandler(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_ spinel_tid_t tid
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
otLwfSendTunnelCommandWithHandlerV(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_opt_ SPINEL_CMD_HANDLER *Handler,
|
||||
_In_opt_ PVOID HandlerContext,
|
||||
_Out_opt_ spinel_tid_t *pTid,
|
||||
_In_ UINT Command,
|
||||
_In_ spinel_prop_key_t Key,
|
||||
_In_ ULONG MaxDataLength,
|
||||
_In_opt_ const char *pack_format,
|
||||
_In_opt_ va_list args
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
otLwfSendTunnelCommandWithHandler(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_opt_ SPINEL_CMD_HANDLER *Handler,
|
||||
_In_opt_ PVOID HandlerContext,
|
||||
_Out_opt_ spinel_tid_t *pTid,
|
||||
_In_ UINT Command,
|
||||
_In_ spinel_prop_key_t Key,
|
||||
_In_ ULONG MaxDataLength,
|
||||
_In_opt_ const char *pack_format,
|
||||
...
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
NTSTATUS
|
||||
otLwfSendTunnelPacket(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_ PNET_BUFFER IpNetBuffer,
|
||||
_In_ BOOLEAN Secured
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
void
|
||||
otLwfReceiveTunnelPacket(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_reads_bytes_(BufferLength) const PUCHAR Buffer,
|
||||
_In_ ULONG BufferLength
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
void
|
||||
otLwfProcessSpinelIPv6Packet(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_ BOOLEAN Secure,
|
||||
_In_reads_bytes_(BufferLength) const uint8_t* Buffer,
|
||||
_In_ UINT BufferLength
|
||||
);
|
||||
|
||||
//
|
||||
// Irp Commands
|
||||
//
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ PIRP Irp,
|
||||
_In_opt_ SPINEL_IRP_CMD_HANDLER *Handler,
|
||||
_In_ UINT Command,
|
||||
_In_ spinel_prop_key_t Key,
|
||||
_In_ ULONG MaxDataLength,
|
||||
_In_opt_ const char *pack_format,
|
||||
...
|
||||
);
|
||||
|
||||
//
|
||||
// Spinel Helper Functions
|
||||
//
|
||||
|
||||
ThreadError
|
||||
SpinelStatusToThreadError(
|
||||
spinel_status_t error
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
try_spinel_datatype_unpack(
|
||||
const uint8_t *data_in,
|
||||
spinel_size_t data_len,
|
||||
const char *pack_format,
|
||||
...
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
otLwfGetTunProp(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_Out_opt_ PVOID *DataBuffer,
|
||||
_In_ spinel_prop_key_t Key,
|
||||
_In_ const char *pack_format,
|
||||
...
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
otLwfSetTunProp(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ spinel_prop_key_t Key,
|
||||
_In_ const char *pack_format,
|
||||
...
|
||||
);
|
||||
|
||||
#endif //_TUNNEL_H_
|
||||
+9
-2
@@ -70,6 +70,12 @@
|
||||
#define EINVAL 1
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL_MODE
|
||||
#define va_copy(destination, source) ((destination) = (source))
|
||||
#undef errno
|
||||
#define assert_printf(fmt, ...)
|
||||
#endif
|
||||
|
||||
#if defined(errno) && SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR
|
||||
#error "SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR is set but errno is already defined."
|
||||
#endif
|
||||
@@ -443,7 +449,7 @@ spinel_datatype_vunpack_(const uint8_t *data_ptr, spinel_size_t data_len, const
|
||||
*block_len_ptr = block_len;
|
||||
}
|
||||
|
||||
block_len += pui_len;
|
||||
block_len += (uint16_t)pui_len;
|
||||
ret += block_len;
|
||||
data_ptr += block_len;
|
||||
data_len -= block_len;
|
||||
@@ -480,7 +486,7 @@ spinel_datatype_vunpack_(const uint8_t *data_ptr, spinel_size_t data_len, const
|
||||
|
||||
if (pui_len)
|
||||
{
|
||||
block_len += pui_len;
|
||||
block_len += (uint16_t)pui_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -525,6 +531,7 @@ spinel_datatype_unpack(const uint8_t *data_ptr, spinel_size_t data_len, const ch
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
spinel_ssize_t
|
||||
spinel_datatype_vunpack(const uint8_t *data_ptr, spinel_size_t data_len, const char *pack_format, va_list args)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user