mirror of
https://github.com/espressif/openthread.git
synced 2026-08-07 03:07:47 +00:00
Windows Host Side Updates (#1217)
* Add otLinkRaw API * Separate Mac and otLinkRaw* * Make pretty * otLinkRawSetEnabled doen't change radio enable state. Assumed to always be enabled right now. * NCP usage of otLinkRaw * Make otLinkRaw compile time removal (on by default). Disable otLinkRaw on Windows kernel mode. Check for mLinkRawEnabled state in otLinkRaw APIs and return errors. * Make raw usage compile time removable. * Additional cleanup * Fix Linux build breaks * Merge otlwf changes for new Spinel command interface * CC2538 Add Support for ACK timeouts * Revert "CC2538 Add Support for ACK timeouts" This reverts commit 7dcc4caebc3dc50dc56401cf7e009f315b4c196c. * Updates for the energy scan interface
This commit is contained in:
@@ -86,6 +86,7 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\address.c" />
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\alarm.c" />
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\command.c" />
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\datapath.c" />
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\driver.c" />
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\eventprocessing.c" />
|
||||
@@ -103,6 +104,7 @@
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\filter.c" />
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\device.c" />
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\radio.c" />
|
||||
<ClInclude Include="..\..\examples\drivers\windows\otLwf\command.h" />
|
||||
<ClInclude Include="..\..\examples\drivers\windows\otLwf\device.h" />
|
||||
<ClInclude Include="..\..\examples\drivers\windows\otLwf\driver.h" />
|
||||
<ClInclude Include="..\..\examples\drivers\windows\otLwf\iocontrol.h" />
|
||||
|
||||
@@ -98,6 +98,9 @@
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\settings.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\examples\drivers\windows\otLwf\command.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\..\examples\drivers\windows\otLwf\filter.rc">
|
||||
|
||||
@@ -3205,6 +3205,157 @@ otIp6PrefixMatch(
|
||||
return rval;
|
||||
}
|
||||
|
||||
OTAPI
|
||||
const char *
|
||||
OTCALL
|
||||
otThreadErrorToString(
|
||||
ThreadError aError
|
||||
)
|
||||
{
|
||||
const char *retval;
|
||||
|
||||
switch (aError)
|
||||
{
|
||||
case kThreadError_None:
|
||||
retval = "None";
|
||||
break;
|
||||
|
||||
case kThreadError_Failed:
|
||||
retval = "Failed";
|
||||
break;
|
||||
|
||||
case kThreadError_Drop:
|
||||
retval = "Drop";
|
||||
break;
|
||||
|
||||
case kThreadError_NoBufs:
|
||||
retval = "NoBufs";
|
||||
break;
|
||||
|
||||
case kThreadError_NoRoute:
|
||||
retval = "NoRoute";
|
||||
break;
|
||||
|
||||
case kThreadError_Busy:
|
||||
retval = "Busy";
|
||||
break;
|
||||
|
||||
case kThreadError_Parse:
|
||||
retval = "Parse";
|
||||
break;
|
||||
|
||||
case kThreadError_InvalidArgs:
|
||||
retval = "InvalidArgs";
|
||||
break;
|
||||
|
||||
case kThreadError_Security:
|
||||
retval = "Security";
|
||||
break;
|
||||
|
||||
case kThreadError_AddressQuery:
|
||||
retval = "AddressQuery";
|
||||
break;
|
||||
|
||||
case kThreadError_NoAddress:
|
||||
retval = "NoAddress";
|
||||
break;
|
||||
|
||||
case kThreadError_NotReceiving:
|
||||
retval = "NotReceiving";
|
||||
break;
|
||||
|
||||
case kThreadError_Abort:
|
||||
retval = "Abort";
|
||||
break;
|
||||
|
||||
case kThreadError_NotImplemented:
|
||||
retval = "NotImplemented";
|
||||
break;
|
||||
|
||||
case kThreadError_InvalidState:
|
||||
retval = "InvalidState";
|
||||
break;
|
||||
|
||||
case kThreadError_NoTasklets:
|
||||
retval = "NoTasklets";
|
||||
break;
|
||||
|
||||
case kThreadError_NoAck:
|
||||
retval = "NoAck";
|
||||
break;
|
||||
|
||||
case kThreadError_ChannelAccessFailure:
|
||||
retval = "ChannelAccessFailure";
|
||||
break;
|
||||
|
||||
case kThreadError_Detached:
|
||||
retval = "Detached";
|
||||
break;
|
||||
|
||||
case kThreadError_FcsErr:
|
||||
retval = "FcsErr";
|
||||
break;
|
||||
|
||||
case kThreadError_NoFrameReceived:
|
||||
retval = "NoFrameReceived";
|
||||
break;
|
||||
|
||||
case kThreadError_UnknownNeighbor:
|
||||
retval = "UnknownNeighbor";
|
||||
break;
|
||||
|
||||
case kThreadError_InvalidSourceAddress:
|
||||
retval = "InvalidSourceAddress";
|
||||
break;
|
||||
|
||||
case kThreadError_WhitelistFiltered:
|
||||
retval = "WhitelistFiltered";
|
||||
break;
|
||||
|
||||
case kThreadError_DestinationAddressFiltered:
|
||||
retval = "DestinationAddressFiltered";
|
||||
break;
|
||||
|
||||
case kThreadError_NotFound:
|
||||
retval = "NotFound";
|
||||
break;
|
||||
|
||||
case kThreadError_Already:
|
||||
retval = "Already";
|
||||
break;
|
||||
|
||||
case kThreadError_BlacklistFiltered:
|
||||
retval = "BlacklistFiltered";
|
||||
break;
|
||||
|
||||
case kThreadError_Ipv6AddressCreationFailure:
|
||||
retval = "Ipv6AddressCreationFailure";
|
||||
break;
|
||||
|
||||
case kThreadError_NotCapable:
|
||||
retval = "NotCapable";
|
||||
break;
|
||||
|
||||
case kThreadError_ResponseTimeout:
|
||||
retval = "ResponseTimeout";
|
||||
break;
|
||||
|
||||
case kThreadError_Duplicated:
|
||||
retval = "Duplicated";
|
||||
break;
|
||||
|
||||
case kThreadError_Error:
|
||||
retval = "GenericError";
|
||||
break;
|
||||
|
||||
default:
|
||||
retval = "UnknownErrorType";
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
OTAPI
|
||||
ThreadError
|
||||
OTCALL
|
||||
@@ -3267,7 +3418,7 @@ OTAPI
|
||||
ThreadError
|
||||
OTCALL
|
||||
otCommissionerStart(
|
||||
_In_ otInstance *aInstance
|
||||
_In_ otInstance *aInstance
|
||||
)
|
||||
{
|
||||
if (aInstance == nullptr) return kThreadError_InvalidArgs;
|
||||
@@ -3278,7 +3429,7 @@ OTAPI
|
||||
ThreadError
|
||||
OTCALL
|
||||
otCommissionerAddJoiner(
|
||||
_In_ otInstance *aInstance,
|
||||
_In_ otInstance *aInstance,
|
||||
const otExtAddress *aExtAddress,
|
||||
const char *aPSKd
|
||||
)
|
||||
@@ -3308,7 +3459,7 @@ OTAPI
|
||||
ThreadError
|
||||
OTCALL
|
||||
otCommissionerRemoveJoiner(
|
||||
_In_ otInstance *aInstance,
|
||||
_In_ otInstance *aInstance,
|
||||
const otExtAddress *aExtAddress
|
||||
)
|
||||
{
|
||||
@@ -3329,7 +3480,7 @@ OTAPI
|
||||
ThreadError
|
||||
OTCALL
|
||||
otCommissionerSetProvisioningUrl(
|
||||
_In_ otInstance *aInstance,
|
||||
_In_ otInstance *aInstance,
|
||||
const char *aProvisioningUrl
|
||||
)
|
||||
{
|
||||
@@ -3371,7 +3522,7 @@ OTAPI
|
||||
ThreadError
|
||||
OTCALL
|
||||
otCommissionerStop(
|
||||
_In_ otInstance *aInstance
|
||||
_In_ otInstance *aInstance
|
||||
)
|
||||
{
|
||||
if (aInstance == nullptr) return kThreadError_InvalidArgs;
|
||||
@@ -3382,7 +3533,7 @@ OTAPI
|
||||
ThreadError
|
||||
OTCALL
|
||||
otCommissionerEnergyScan(
|
||||
_In_ otInstance *aInstance,
|
||||
_In_ otInstance *aInstance,
|
||||
uint32_t aChannelMask,
|
||||
uint8_t aCount,
|
||||
uint16_t aPeriod,
|
||||
@@ -3407,12 +3558,12 @@ OTAPI
|
||||
ThreadError
|
||||
OTCALL
|
||||
otCommissionerPanIdQuery(
|
||||
_In_ otInstance *aInstance,
|
||||
_In_ otInstance *aInstance,
|
||||
uint16_t aPanId,
|
||||
uint32_t aChannelMask,
|
||||
const otIp6Address *aAddress,
|
||||
_In_ otCommissionerPanIdConflictCallback aCallback,
|
||||
_In_ void *aContext
|
||||
_In_ otCommissionerPanIdConflictCallback aCallback,
|
||||
_In_ void *aContext
|
||||
)
|
||||
{
|
||||
if (aInstance == nullptr) return kThreadError_InvalidArgs;
|
||||
@@ -3430,7 +3581,7 @@ OTAPI
|
||||
ThreadError
|
||||
OTCALL
|
||||
otSendMgmtCommissionerGet(
|
||||
_In_ otInstance *aInstance,
|
||||
_In_ otInstance *aInstance,
|
||||
const uint8_t *aTlvs,
|
||||
uint8_t aLength
|
||||
)
|
||||
@@ -3458,7 +3609,7 @@ OTAPI
|
||||
ThreadError
|
||||
OTCALL
|
||||
otSendMgmtCommissionerSet(
|
||||
_In_ otInstance *aInstance,
|
||||
_In_ otInstance *aInstance,
|
||||
const otCommissioningDataset *aDataset,
|
||||
const uint8_t *aTlvs,
|
||||
uint8_t aLength
|
||||
@@ -3484,11 +3635,23 @@ otSendMgmtCommissionerSet(
|
||||
return result;
|
||||
}
|
||||
|
||||
OTAPI
|
||||
uint16_t
|
||||
OTCALL
|
||||
otCommissionerGetSessionId(
|
||||
_In_ otInstance *aInstance
|
||||
)
|
||||
{
|
||||
if (aInstance == nullptr) return 0;
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
OTAPI
|
||||
ThreadError
|
||||
OTCALL
|
||||
otJoinerStart(
|
||||
_In_ otInstance *aInstance,
|
||||
_In_ otInstance *aInstance,
|
||||
const char *aPSKd,
|
||||
const char *aProvisioningUrl,
|
||||
const char *aVendorName,
|
||||
@@ -3534,7 +3697,7 @@ OTAPI
|
||||
ThreadError
|
||||
OTCALL
|
||||
otJoinerStop(
|
||||
_In_ otInstance *aInstance
|
||||
_In_ otInstance *aInstance
|
||||
)
|
||||
{
|
||||
if (aInstance == nullptr) return kThreadError_InvalidArgs;
|
||||
|
||||
@@ -256,12 +256,19 @@ otLwfAddressChangeCallback(
|
||||
// Since we don't pass in the initial flag, we shouldn't get this type
|
||||
NT_ASSERT(NotificationType != MibInitialNotification);
|
||||
|
||||
// Queue up the event for processing
|
||||
otLwfEventProcessingIndicateAddressChange(
|
||||
pFilter,
|
||||
NotificationType,
|
||||
&Row->Address.Ipv6.sin6_addr
|
||||
);
|
||||
// Make sure we can reference the interface
|
||||
if (ExAcquireRundownProtection(&pFilter->ExternalRefs))
|
||||
{
|
||||
// Queue up the event for processing
|
||||
otLwfEventProcessingIndicateAddressChange(
|
||||
pFilter,
|
||||
NotificationType,
|
||||
&Row->Address.Ipv6.sin6_addr
|
||||
);
|
||||
|
||||
// Release reference on the interface
|
||||
ExReleaseRundownProtection(&pFilter->ExternalRefs);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
@@ -382,7 +389,7 @@ otLwfRadioAddressesUpdated(
|
||||
ULONG FoundInOpenThread = 0; // Bit field
|
||||
ULONG OriginalCacheLength = pFilter->otCachedAddrCount;
|
||||
|
||||
NT_ASSERT(pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO);
|
||||
NT_ASSERT(pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_RADIO_MODE);
|
||||
|
||||
const otNetifAddress* addr = otGetUnicastAddresses(pFilter->otCtx);
|
||||
|
||||
@@ -428,7 +435,7 @@ otLwfTunAddressesUpdated(
|
||||
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
NT_ASSERT (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_THREAD);
|
||||
NT_ASSERT (pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_THREAD_MODE);
|
||||
|
||||
*aNotifFlags = 0;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* 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 sending/receiving Spinel commands to the miniport.
|
||||
*/
|
||||
|
||||
#ifndef _COMMAND_H_
|
||||
#define _COMMAND_H_
|
||||
|
||||
//
|
||||
// Initialization
|
||||
//
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NDIS_STATUS
|
||||
otLwfCmdInitialize(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
void
|
||||
otLwfCmdUninitialize(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
//
|
||||
// Receive Spinel Encoded Command
|
||||
//
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
void
|
||||
otLwfCmdRecveive(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_reads_bytes_(BufferLength) const PUCHAR Buffer,
|
||||
_In_ ULONG BufferLength
|
||||
);
|
||||
|
||||
//
|
||||
// Send Async Spinel Encoded Command
|
||||
//
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
otLwfCmdSendAsyncV(
|
||||
_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
|
||||
otLwfCmdSendAsync(
|
||||
_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)
|
||||
BOOLEAN
|
||||
otLwfCmdCancel(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_ spinel_tid_t tid
|
||||
);
|
||||
|
||||
//
|
||||
// Send Packet/Frame
|
||||
//
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
NTSTATUS
|
||||
otLwfCmdSendIp6PacketAsync(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_ PNET_BUFFER IpNetBuffer,
|
||||
_In_ BOOLEAN Secured
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfCmdSendMacFrameAsync(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ RadioPacket* Packet
|
||||
);
|
||||
|
||||
//
|
||||
// Send Synchronous Spinel Encoded Command
|
||||
//
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
otLwfCmdGetProp(
|
||||
_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
|
||||
otLwfCmdSetProp(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ spinel_prop_key_t Key,
|
||||
_In_ const char *pack_format,
|
||||
...
|
||||
);
|
||||
|
||||
//
|
||||
// General Spinel Helpers
|
||||
//
|
||||
|
||||
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,
|
||||
...
|
||||
);
|
||||
|
||||
#endif //_COMMAND_H_
|
||||
@@ -74,52 +74,6 @@ otLogBuffer(
|
||||
|
||||
#endif
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfEnableDataPath(
|
||||
_In_ PMS_FILTER pFilter
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Enables the datapath to allow NLBs to go through to OpenThread.
|
||||
|
||||
--*/
|
||||
{
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! enabling data path.", &pFilter->InterfaceGuid);
|
||||
|
||||
// Re-enabling data path
|
||||
ExReInitializeRundownProtection(&pFilter->DataPathRundown);
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfDisableDataPath(
|
||||
_In_ PMS_FILTER pFilter
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Disables the datapath and waits for any outstanding calls
|
||||
into OpenThread to complete.
|
||||
|
||||
--*/
|
||||
{
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! disabling data path.", &pFilter->InterfaceGuid);
|
||||
|
||||
ExWaitForRundownProtectionRelease(&pFilter->DataPathRundown);
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
VOID
|
||||
FilterSendNetBufferListsComplete(
|
||||
@@ -151,32 +105,35 @@ Arguments:
|
||||
|
||||
LogFuncEntryMsg(DRIVER_DATA_PATH, "Filter: %p, NBL: %p %!STATUS!", FilterModuleContext, NetBufferLists, NetBufferLists->Status);
|
||||
|
||||
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
|
||||
PNET_BUFFER_LIST NBL = NetBufferLists;
|
||||
while (NBL)
|
||||
{
|
||||
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);
|
||||
PNET_BUFFER_LIST NextNBL = NBL->Next;
|
||||
PNET_BUFFER NetBuffer = NET_BUFFER_LIST_FIRST_NB(NBL);
|
||||
|
||||
// Cancel command if we failed to send the NBL
|
||||
if (!NT_SUCCESS(NetBufferLists->Status))
|
||||
if (!NT_SUCCESS(NBL->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);
|
||||
#if DBG
|
||||
NT_ASSERT(pFilter->cmdInitTryCount < 9 || NBL->Status != NDIS_STATUS_PAUSED);
|
||||
#endif
|
||||
otLwfCmdCancel(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);
|
||||
NdisFreeNetBufferList(NBL);
|
||||
|
||||
// Release the command rundown protection
|
||||
ExReleaseRundownProtection(&pFilter->cmdRundown);
|
||||
|
||||
NBL = NextNBL;
|
||||
}
|
||||
|
||||
|
||||
LogFuncExit(DRIVER_DATA_PATH);
|
||||
}
|
||||
|
||||
@@ -211,11 +168,13 @@ Arguments:
|
||||
{
|
||||
PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
|
||||
BOOLEAN DispatchLevel = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags);
|
||||
|
||||
|
||||
UNREFERENCED_PARAMETER(PortNumber);
|
||||
|
||||
LogFuncEntryMsg(DRIVER_DATA_PATH, "Filter: %p, NBL: %p", FilterModuleContext, NetBufferLists);
|
||||
|
||||
|
||||
// Try to grab a ref on the data path first, to make sure we are allowed
|
||||
if (!ExAcquireRundownProtection(&pFilter->DataPathRundown))
|
||||
if (!ExAcquireRundownProtection(&pFilter->ExternalRefs))
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Failing SendNetBufferLists because data path isn't active.");
|
||||
|
||||
@@ -234,14 +193,12 @@ Arguments:
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
|
||||
if (pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_RADIO_MODE)
|
||||
{
|
||||
// Indicate a new NBL to process on our worker thread
|
||||
otLwfEventProcessingIndicateNewNetBufferLists(
|
||||
pFilter,
|
||||
DispatchLevel,
|
||||
FALSE,
|
||||
PortNumber,
|
||||
NetBufferLists
|
||||
);
|
||||
}
|
||||
@@ -253,7 +210,7 @@ Arguments:
|
||||
PNET_BUFFER CurrNb = NET_BUFFER_LIST_FIRST_NB(CurrNbl);
|
||||
while (CurrNb)
|
||||
{
|
||||
otLwfSendTunnelPacket(pFilter, DispatchLevel, CurrNb, TRUE);
|
||||
otLwfCmdSendIp6PacketAsync(pFilter, DispatchLevel, CurrNb, TRUE);
|
||||
CurrNb = NET_BUFFER_NEXT_NB(CurrNb);
|
||||
}
|
||||
|
||||
@@ -269,12 +226,48 @@ Arguments:
|
||||
}
|
||||
|
||||
// Release the data path ref now
|
||||
ExReleaseRundownProtection(&pFilter->DataPathRundown);
|
||||
ExReleaseRundownProtection(&pFilter->ExternalRefs);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DATA_PATH);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
VOID
|
||||
FilterCancelSendNetBufferLists(
|
||||
NDIS_HANDLE FilterModuleContext,
|
||||
PVOID CancelId
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This function cancels any NET_BUFFER_LISTs pended in the filter and then
|
||||
calls the NdisFCancelSendNetBufferLists to propagate the cancel operation.
|
||||
|
||||
If your driver does not queue any send NBLs, you may omit this routine.
|
||||
NDIS will propagate the cancelation on your behalf more efficiently.
|
||||
|
||||
Arguments:
|
||||
|
||||
FilterModuleContext - our filter context area.
|
||||
CancelId - an identifier for all NBLs that should be dequeued
|
||||
|
||||
*/
|
||||
{
|
||||
PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
|
||||
|
||||
LogFuncEntryMsg(DRIVER_DATA_PATH, "Filter: %p, CancelId: %p", FilterModuleContext, CancelId);
|
||||
|
||||
// Only cancel if we are 'Thread on Host', otherwise we do everything inline
|
||||
if (pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_RADIO_MODE)
|
||||
{
|
||||
otLwfEventProcessingIndicateNetBufferListsCancelled(pFilter, CancelId);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DATA_PATH);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
VOID
|
||||
FilterReturnNetBufferLists(
|
||||
@@ -318,19 +311,15 @@ 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);
|
||||
|
||||
CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
|
||||
NET_BUFFER_LIST_NEXT_NBL(NblToFree) = NULL;
|
||||
PNET_BUFFER_LIST NblToFree = CurrNbl;
|
||||
PNET_BUFFER NbToFree = NET_BUFFER_LIST_FIRST_NB(NblToFree);
|
||||
|
||||
NdisAdvanceNetBufferDataStart(NbToFree, NET_BUFFER_DATA_LENGTH(NbToFree), TRUE, NULL);
|
||||
NdisFreeNetBufferList(NblToFree);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DATA_PATH);
|
||||
@@ -375,143 +364,55 @@ N.B.: It is important to check the ReceiveFlags in NDIS_TEST_RECEIVE_CANNOT_PEND
|
||||
|
||||
PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
|
||||
BOOLEAN DispatchLevel = NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags);
|
||||
|
||||
|
||||
UNREFERENCED_PARAMETER(PortNumber);
|
||||
UNREFERENCED_PARAMETER(NumberOfNetBufferLists);
|
||||
|
||||
LogFuncEntryMsg(DRIVER_DATA_PATH, "Filter: %p, NBL: %p", FilterModuleContext, NetBufferLists);
|
||||
|
||||
ASSERT(NumberOfNetBufferLists >= 1);
|
||||
UNREFERENCED_PARAMETER(NumberOfNetBufferLists);
|
||||
|
||||
// We don't support non-pending NBLs
|
||||
NT_ASSERT(NDIS_TEST_RECEIVE_CAN_PEND(ReceiveFlags));
|
||||
if (NDIS_TEST_RECEIVE_CANNOT_PEND(ReceiveFlags))
|
||||
// Iterate through each NBL/NB and grab the data as a contiguous buffer to
|
||||
// indicate to the Spinel command layer.
|
||||
PNET_BUFFER_LIST CurrNbl = NetBufferLists;
|
||||
while (CurrNbl)
|
||||
{
|
||||
PNET_BUFFER_LIST CurrNbl = NetBufferLists;
|
||||
while (CurrNbl)
|
||||
PNET_BUFFER CurrNb = NET_BUFFER_LIST_FIRST_NB(CurrNbl);
|
||||
while (CurrNb)
|
||||
{
|
||||
NET_BUFFER_LIST_STATUS(CurrNbl) = NDIS_STATUS_NOT_SUPPORTED;
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
if (_Buffer)
|
||||
{
|
||||
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);
|
||||
otLwfCmdRecveive(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);
|
||||
else
|
||||
{
|
||||
otLwfCmdRecveive(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);
|
||||
}
|
||||
|
||||
if (NDIS_TEST_RECEIVE_CAN_PEND(ReceiveFlags))
|
||||
{
|
||||
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))
|
||||
{
|
||||
LogVerbose(DRIVER_DATA_PATH, "Failing ReceiveNetBufferLists because data path isn't active.");
|
||||
|
||||
// Ignore any NBLs we get if we aren't active (can't get a ref)
|
||||
PNET_BUFFER_LIST CurrNbl = NetBufferLists;
|
||||
while (CurrNbl)
|
||||
{
|
||||
NET_BUFFER_LIST_STATUS(CurrNbl) = NDIS_STATUS_PAUSED;
|
||||
CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
|
||||
}
|
||||
NdisFReturnNetBufferLists(
|
||||
pFilter->FilterHandle,
|
||||
NetBufferLists,
|
||||
DispatchLevel ? NDIS_RETURN_FLAGS_DISPATCH_LEVEL : 0
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if DBG
|
||||
PNET_BUFFER_LIST CurrNbl = NetBufferLists;
|
||||
while (CurrNbl)
|
||||
{
|
||||
POT_NBL_CONTEXT NblContext = GetNBLContext(CurrNbl);
|
||||
NT_ASSERT(NblContext->Channel >= 11 && NblContext->Channel <= 26);
|
||||
CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
|
||||
}
|
||||
|
||||
#endif
|
||||
// Indicate a new NBL to process on our worker thread
|
||||
otLwfEventProcessingIndicateNewNetBufferLists(
|
||||
pFilter,
|
||||
DispatchLevel,
|
||||
TRUE,
|
||||
PortNumber,
|
||||
NetBufferLists
|
||||
);
|
||||
|
||||
// Release the data path ref now
|
||||
ExReleaseRundownProtection(&pFilter->DataPathRundown);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DATA_PATH);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
VOID
|
||||
FilterCancelSendNetBufferLists(
|
||||
NDIS_HANDLE FilterModuleContext,
|
||||
PVOID CancelId
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This function cancels any NET_BUFFER_LISTs pended in the filter and then
|
||||
calls the NdisFCancelSendNetBufferLists to propagate the cancel operation.
|
||||
|
||||
If your driver does not queue any send NBLs, you may omit this routine.
|
||||
NDIS will propagate the cancelation on your behalf more efficiently.
|
||||
|
||||
Arguments:
|
||||
|
||||
FilterModuleContext - our filter context area.
|
||||
CancelId - an identifier for all NBLs that should be dequeued
|
||||
|
||||
*/
|
||||
{
|
||||
PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
|
||||
|
||||
LogFuncEntryMsg(DRIVER_DATA_PATH, "Filter: %p, CancelId: %p", FilterModuleContext, CancelId);
|
||||
|
||||
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
|
||||
{
|
||||
otLwfEventProcessingIndicateNetBufferListsCancelled(pFilter, CancelId);
|
||||
}
|
||||
else
|
||||
{
|
||||
NT_ASSERT(FALSE); // TODO
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DATA_PATH);
|
||||
}
|
||||
|
||||
@@ -539,7 +440,7 @@ otLwfReceiveIp6DatagramCallback(
|
||||
// Create the NetBufferList
|
||||
NetBufferList =
|
||||
NdisAllocateNetBufferAndNetBufferList(
|
||||
pFilter->NetBufferListPool, // PoolHandle
|
||||
pFilter->cmdNblPool, // PoolHandle
|
||||
0, // ContextSize
|
||||
0, // ContextBackFill
|
||||
NULL, // MdlChain
|
||||
@@ -556,7 +457,7 @@ otLwfReceiveIp6DatagramCallback(
|
||||
NdisSetNblFlag(NetBufferList, NDIS_NBL_FLAGS_IS_IPV6);
|
||||
NET_BUFFER_LIST_INFO(NetBufferList, NetBufferListFrameType) =
|
||||
UlongToPtr(RtlUshortByteSwap(ETHERNET_TYPE_IPV6));
|
||||
|
||||
|
||||
// Initialize NetBuffer fields
|
||||
NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
|
||||
NET_BUFFER_CURRENT_MDL(NetBuffer) = NULL;
|
||||
@@ -607,7 +508,7 @@ otLwfReceiveIp6DatagramCallback(
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p dropping internal address message.", pFilter);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
// Filter internal Thread messages
|
||||
if (v6Header->NextHeader == IPPROTO_UDP &&
|
||||
messageLength >= sizeof(IPV6_HEADER) + sizeof(UDPHeader) &&
|
||||
@@ -624,7 +525,7 @@ otLwfReceiveIp6DatagramCallback(
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, IP6_RECV: %p : %!IPV6ADDR! => %!IPV6ADDR! (%u bytes)",
|
||||
pFilter, NetBufferList, &v6Header->SourceAddress, &v6Header->DestinationAddress,
|
||||
messageLength);
|
||||
@@ -664,3 +565,108 @@ error:
|
||||
|
||||
otFreeMessage(aMessage);
|
||||
}
|
||||
|
||||
// Called in response to receiving a Spinel Ip6 packet command
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
void
|
||||
otLwfTunReceiveIp6Packet(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_ BOOLEAN Secure,
|
||||
_In_reads_bytes_(BufferLength) const uint8_t* Buffer,
|
||||
_In_ UINT BufferLength
|
||||
)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
PNET_BUFFER_LIST NetBufferList = NULL;
|
||||
PNET_BUFFER NetBuffer = NULL;
|
||||
PUCHAR DataBuffer = NULL;
|
||||
IPV6_HEADER* v6Header;
|
||||
|
||||
UNREFERENCED_PARAMETER(Secure); // TODO - What should we do with unsecured packets?
|
||||
|
||||
NetBufferList =
|
||||
NdisAllocateNetBufferAndNetBufferList(
|
||||
pFilter->cmdNblPool, // PoolHandle
|
||||
0, // ContextSize
|
||||
0, // ContextBackFill
|
||||
NULL, // MdlChain
|
||||
0, // DataOffset
|
||||
0 // DataLength
|
||||
);
|
||||
if (NetBufferList == NULL)
|
||||
{
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
LogWarning(DRIVER_DEFAULT, "Failed to create command NetBufferList");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Set the flag to indicate its a IPv6 packet
|
||||
NdisSetNblFlag(NetBufferList, NDIS_NBL_FLAGS_IS_IPV6);
|
||||
NET_BUFFER_LIST_INFO(NetBufferList, NetBufferListFrameType) =
|
||||
UlongToPtr(RtlUshortByteSwap(ETHERNET_TYPE_IPV6));
|
||||
|
||||
// Initialize NetBuffer fields
|
||||
NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
|
||||
NET_BUFFER_CURRENT_MDL(NetBuffer) = NULL;
|
||||
NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer) = 0;
|
||||
NET_BUFFER_DATA_LENGTH(NetBuffer) = 0;
|
||||
NET_BUFFER_DATA_OFFSET(NetBuffer) = 0;
|
||||
NET_BUFFER_FIRST_MDL(NetBuffer) = NULL;
|
||||
|
||||
// Allocate the NetBuffer for NetBufferList
|
||||
if (NdisRetreatNetBufferDataStart(NetBuffer, BufferLength, 0, NULL) != NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
NetBuffer = NULL;
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
LogError(DRIVER_DEFAULT, "Failed to allocate NB for command NetBufferList, %u bytes", BufferLength);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Get the pointer to the data buffer for the header data
|
||||
DataBuffer = (PUCHAR)NdisGetDataBuffer(NetBuffer, BufferLength, NULL, 1, 0);
|
||||
NT_ASSERT(DataBuffer);
|
||||
|
||||
// Copy the data over
|
||||
RtlCopyMemory(DataBuffer, Buffer, BufferLength);
|
||||
|
||||
v6Header = (IPV6_HEADER*)DataBuffer;
|
||||
|
||||
// Filter messages to addresses we expose
|
||||
if (!IN6_IS_ADDR_MULTICAST(&v6Header->DestinationAddress) &&
|
||||
otLwfFindCachedAddrIndex(pFilter, &v6Header->DestinationAddress) == -1)
|
||||
{
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p dropping internal address message.", pFilter);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, IP6_RECV: %p : %!IPV6ADDR! => %!IPV6ADDR! (%u bytes)",
|
||||
pFilter, NetBufferList, &v6Header->SourceAddress, &v6Header->DestinationAddress,
|
||||
BufferLength);
|
||||
|
||||
#ifdef LOG_BUFFERS
|
||||
otLogBuffer(DataBuffer, BufferLength);
|
||||
#endif
|
||||
|
||||
// Send the NBL down
|
||||
NdisFIndicateReceiveNetBufferLists(
|
||||
pFilter->FilterHandle,
|
||||
NetBufferList,
|
||||
NDIS_DEFAULT_PORT_NUMBER,
|
||||
1,
|
||||
DispatchLevel ? NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL : 0);
|
||||
|
||||
// Clear local variable because we don't own the NBL any more
|
||||
NetBufferList = NULL;
|
||||
|
||||
exit:
|
||||
|
||||
if (NetBufferList)
|
||||
{
|
||||
if (NetBuffer)
|
||||
{
|
||||
NdisAdvanceNetBufferDataStart(NetBuffer, NetBuffer->DataLength, TRUE, NULL);
|
||||
}
|
||||
NdisFreeNetBufferList(NetBufferList);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ otLwfRegisterDevice(
|
||||
NdisInitUnicodeString(&DeviceLinkUnicodeString, LINKNAME_STRING);
|
||||
|
||||
Status = IoCreateDeviceSecure(FilterDriverObject, // DriverObject
|
||||
sizeof(OTLWF_DEVICE_EXTENSION), // DeviceExtension
|
||||
sizeof(OTLWF_DEVICE_EXTENSION), // DeviceExtension
|
||||
&DeviceName, // DeviceName
|
||||
FILE_DEVICE_NETWORK, // DeviceType
|
||||
FILE_DEVICE_SECURE_OPEN, // DeviceCharacteristics
|
||||
@@ -352,7 +352,7 @@ otLwfDeviceIoControl(
|
||||
ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
||||
ULONG IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
|
||||
|
||||
ULONG FuncCode = (IoControlCode >> 2) & 0xFFF;
|
||||
ULONG FuncCode = (IoControlCode >> 2) & 0xFFF;
|
||||
|
||||
LogFuncEntryMsg(DRIVER_IOCTL, "%p", IrpSp->FileObject);
|
||||
|
||||
@@ -442,9 +442,10 @@ otLwfFindAndRefInterface(
|
||||
if (pFilter->State == FilterRunning &&
|
||||
memcmp(InterfaceGuid, &pFilter->InterfaceGuid, sizeof(GUID)) == 0)
|
||||
{
|
||||
// Increment ref count on interface
|
||||
RtlIncrementReferenceCount(&pFilter->IoControlReferences);
|
||||
pOutput = pFilter;
|
||||
if (ExAcquireRundownProtection(&pFilter->ExternalRefs))
|
||||
{
|
||||
pOutput = pFilter;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -454,19 +455,6 @@ otLwfFindAndRefInterface(
|
||||
return pOutput;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
VOID
|
||||
otLwfReleaseInterface(
|
||||
_In_ PMS_FILTER pFilter
|
||||
)
|
||||
{
|
||||
// Decrement ref count, and set shutdown event if it goes to 0
|
||||
if (RtlDecrementReferenceCount(&pFilter->IoControlReferences))
|
||||
{
|
||||
NdisSetEvent(&pFilter->IoControlShutdownComplete);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Notification Functions
|
||||
//
|
||||
|
||||
@@ -132,14 +132,6 @@ otLwfFindAndRefInterface(
|
||||
_In_ PGUID InterfaceGuid
|
||||
);
|
||||
|
||||
// Releases a successfully referenced Thread interface from a previous
|
||||
// call to otLwfFindAndRefInterface.
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfReleaseInterface(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
//
|
||||
// Notification Type and Functions
|
||||
//
|
||||
|
||||
@@ -75,68 +75,67 @@ Return Value:
|
||||
|
||||
--*/
|
||||
{
|
||||
NDIS_STATUS Status;
|
||||
NDIS_FILTER_DRIVER_CHARACTERISTICS FChars;
|
||||
NDIS_STRING ServiceName = RTL_CONSTANT_STRING(FILTER_SERVICE_NAME);
|
||||
NDIS_STRING UniqueName = RTL_CONSTANT_STRING(FILTER_UNIQUE_NAME);
|
||||
NDIS_STRING FriendlyName = RTL_CONSTANT_STRING(FILTER_FRIENDLY_NAME);
|
||||
BOOLEAN bFalse = FALSE;
|
||||
NDIS_STATUS Status;
|
||||
|
||||
//
|
||||
// Initialize WPP logging
|
||||
//
|
||||
WPP_INIT_TRACING(DriverObject, RegistryPath);
|
||||
|
||||
//
|
||||
// Save global DriverObject
|
||||
//
|
||||
FilterDriverObject = DriverObject;
|
||||
|
||||
// Cache perf freq
|
||||
// Set the driver unload handler
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
|
||||
// Cache performance counter frequency
|
||||
(VOID)KeQueryPerformanceCounter(&FilterPerformanceFrequency);
|
||||
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
LogFuncEntryMsg(DRIVER_DEFAULT, "Registry: %S", RegistryPath->Buffer);
|
||||
|
||||
do
|
||||
{
|
||||
NdisZeroMemory(&FChars, sizeof(NDIS_FILTER_DRIVER_CHARACTERISTICS));
|
||||
FChars.Header.Type = NDIS_OBJECT_TYPE_FILTER_DRIVER_CHARACTERISTICS;
|
||||
FChars.Header.Size = sizeof(NDIS_FILTER_DRIVER_CHARACTERISTICS);
|
||||
NDIS_FILTER_DRIVER_CHARACTERISTICS FChars =
|
||||
{
|
||||
{
|
||||
NDIS_OBJECT_TYPE_FILTER_DRIVER_CHARACTERISTICS,
|
||||
#if NDIS_SUPPORT_NDIS61
|
||||
FChars.Header.Revision = NDIS_FILTER_CHARACTERISTICS_REVISION_2;
|
||||
NDIS_FILTER_CHARACTERISTICS_REVISION_2,
|
||||
#else
|
||||
FChars.Header.Revision = NDIS_FILTER_CHARACTERISTICS_REVISION_1;
|
||||
NDIS_FILTER_CHARACTERISTICS_REVISION_1,
|
||||
#endif
|
||||
sizeof(NDIS_FILTER_DRIVER_CHARACTERISTICS)
|
||||
},
|
||||
NDIS_FILTER_MAJOR_VERSION,
|
||||
NDIS_FILTER_MINOR_VERSION,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
RTL_CONSTANT_STRING(FILTER_FRIENDLY_NAME),
|
||||
RTL_CONSTANT_STRING(FILTER_UNIQUE_NAME),
|
||||
RTL_CONSTANT_STRING(FILTER_SERVICE_NAME),
|
||||
|
||||
FChars.MajorNdisVersion = NDIS_FILTER_MAJOR_VERSION;
|
||||
FChars.MinorNdisVersion = NDIS_FILTER_MINOR_VERSION;
|
||||
FChars.MajorDriverVersion = 1;
|
||||
FChars.MinorDriverVersion = 0;
|
||||
FChars.Flags = 0;
|
||||
|
||||
FChars.FriendlyName = FriendlyName;
|
||||
FChars.UniqueName = UniqueName;
|
||||
FChars.ServiceName = ServiceName;
|
||||
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
|
||||
FChars.AttachHandler = FilterAttach;
|
||||
FChars.DetachHandler = FilterDetach;
|
||||
FChars.RestartHandler = FilterRestart;
|
||||
FChars.PauseHandler = FilterPause;
|
||||
FChars.StatusHandler = FilterStatus;
|
||||
|
||||
FChars.OidRequestHandler = FilterOidRequest;
|
||||
FChars.OidRequestCompleteHandler = FilterOidRequestComplete;
|
||||
|
||||
FChars.DevicePnPEventNotifyHandler = FilterDevicePnPEventNotify;
|
||||
FChars.NetPnPEventHandler = FilterNetPnPEvent;
|
||||
|
||||
FChars.SendNetBufferListsHandler = FilterSendNetBufferLists;
|
||||
FChars.ReturnNetBufferListsHandler = FilterReturnNetBufferLists;
|
||||
FChars.SendNetBufferListsCompleteHandler = FilterSendNetBufferListsComplete;
|
||||
FChars.ReceiveNetBufferListsHandler = FilterReceiveNetBufferLists;
|
||||
FChars.CancelSendNetBufferListsHandler = FilterCancelSendNetBufferLists;
|
||||
NULL,
|
||||
NULL,
|
||||
FilterAttach,
|
||||
FilterDetach,
|
||||
FilterRestart,
|
||||
FilterPause,
|
||||
FilterSendNetBufferLists,
|
||||
FilterSendNetBufferListsComplete,
|
||||
FilterCancelSendNetBufferLists,
|
||||
FilterReceiveNetBufferLists,
|
||||
FilterReturnNetBufferLists,
|
||||
FilterOidRequest,
|
||||
FilterOidRequestComplete,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
FilterStatus,
|
||||
#if (NDIS_SUPPORT_NDIS61)
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
#endif
|
||||
};
|
||||
|
||||
//
|
||||
// Initialize global variables
|
||||
@@ -147,7 +146,6 @@ Return Value:
|
||||
//
|
||||
// Register the filter with NDIS
|
||||
//
|
||||
FilterDriverHandle = NULL;
|
||||
Status =
|
||||
NdisFRegisterFilterDriver(
|
||||
DriverObject,
|
||||
@@ -157,7 +155,6 @@ Return Value:
|
||||
);
|
||||
if (Status != NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
NdisFreeSpinLock(&FilterListLock);
|
||||
LogError(DRIVER_DEFAULT, "Register filter driver failed, %!NDIS_STATUS!", Status);
|
||||
break;
|
||||
}
|
||||
@@ -168,18 +165,21 @@ Return Value:
|
||||
Status = otLwfRegisterDevice();
|
||||
if (Status != NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
NdisFDeregisterFilterDriver(FilterDriverHandle);
|
||||
NdisFreeSpinLock(&FilterListLock);
|
||||
LogError(DRIVER_DEFAULT, "Register device for the filter driver failed, %!NDIS_STATUS!", Status);
|
||||
break;
|
||||
}
|
||||
|
||||
} while (bFalse);
|
||||
} while (FALSE);
|
||||
|
||||
LogFuncExitNDIS(DRIVER_DEFAULT, Status);
|
||||
|
||||
if (Status != NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
if (FilterDriverHandle)
|
||||
{
|
||||
NdisFDeregisterFilterDriver(FilterDriverHandle);
|
||||
FilterDriverHandle = NULL;
|
||||
}
|
||||
WPP_CLEANUP(DriverObject);
|
||||
}
|
||||
|
||||
@@ -223,6 +223,7 @@ Return Value:
|
||||
// Deregister the NDIS filter
|
||||
//
|
||||
NdisFDeregisterFilterDriver(FilterDriverHandle);
|
||||
FilterDriverHandle = NULL;
|
||||
|
||||
// Validate we have no outstanding filter instances
|
||||
NT_ASSERT(IsListEmpty(&FilterModuleList));
|
||||
|
||||
@@ -46,12 +46,19 @@ typedef struct _OTLWF_ADDR_EVENT
|
||||
typedef struct _OTLWF_NBL_EVENT
|
||||
{
|
||||
LIST_ENTRY Link;
|
||||
BOOLEAN Received;
|
||||
NDIS_PORT_NUMBER PortNumber;
|
||||
PNET_BUFFER_LIST NetBufferLists;
|
||||
|
||||
} OTLWF_NBL_EVENT, *POTLWF_NBL_EVENT;
|
||||
|
||||
typedef struct _OTLWF_MAC_FRAME_EVENT
|
||||
{
|
||||
LIST_ENTRY Link;
|
||||
uint8_t BufferLength;
|
||||
uint8_t Buffer[0];
|
||||
|
||||
} OTLWF_MAC_FRAME_EVENT, *POTLWF_MAC_FRAME_EVENT;
|
||||
|
||||
|
||||
KSTART_ROUTINE otLwfEventWorkerThread;
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
@@ -59,7 +66,6 @@ VOID
|
||||
otLwfCompleteNBLs(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_ BOOLEAN Received,
|
||||
_In_ PNET_BUFFER_LIST NetBufferLists,
|
||||
_In_ NTSTATUS Status
|
||||
);
|
||||
@@ -196,7 +202,21 @@ otLwfEventProcessingStop(
|
||||
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->NetBufferLists, STATUS_CANCELLED);
|
||||
|
||||
// Delete the event
|
||||
NdisFreeMemory(Event, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up any left over events
|
||||
if (pFilter->MacFramesHead.Flink)
|
||||
{
|
||||
Link = pFilter->MacFramesHead.Flink;
|
||||
while (Link != &pFilter->MacFramesHead)
|
||||
{
|
||||
POTLWF_MAC_FRAME_EVENT Event = CONTAINING_RECORD(Link, OTLWF_MAC_FRAME_EVENT, Link);
|
||||
Link = Link->Flink;
|
||||
|
||||
// Delete the event
|
||||
NdisFreeMemory(Event, 0, 0);
|
||||
@@ -206,6 +226,7 @@ otLwfEventProcessingStop(
|
||||
// Reinitialize the list head
|
||||
InitializeListHead(&pFilter->AddressChangesHead);
|
||||
InitializeListHead(&pFilter->NBLsHead);
|
||||
InitializeListHead(&pFilter->MacFramesHead);
|
||||
|
||||
if (pFilter->EventIrpListHead.Flink)
|
||||
{
|
||||
@@ -318,12 +339,7 @@ otLwfEventProcessingIndicateAddressChange(
|
||||
_In_ PIN6_ADDR pAddr
|
||||
)
|
||||
{
|
||||
if (pFilter->InternalStateInitialized == FALSE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
|
||||
if (pFilter->DeviceCapabilities == OTLWF_DEVICE_STATUS_RADIO_MODE)
|
||||
{
|
||||
POTLWF_ADDR_EVENT Event = FILTER_ALLOC_MEM(pFilter->FilterHandle, sizeof(OTLWF_ADDR_EVENT));
|
||||
if (Event == NULL)
|
||||
@@ -351,8 +367,6 @@ VOID
|
||||
otLwfEventProcessingIndicateNewNetBufferLists(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_ BOOLEAN Received,
|
||||
_In_ NDIS_PORT_NUMBER PortNumber,
|
||||
_In_ PNET_BUFFER_LIST NetBufferLists
|
||||
)
|
||||
{
|
||||
@@ -360,17 +374,14 @@ otLwfEventProcessingIndicateNewNetBufferLists(
|
||||
if (Event == NULL)
|
||||
{
|
||||
LogWarning(DRIVER_DATA_PATH, "Failed to alloc new OTLWF_NBL_EVENT");
|
||||
otLwfCompleteNBLs(pFilter, DispatchLevel, Received, NetBufferLists, STATUS_INSUFFICIENT_RESOURCES);
|
||||
otLwfCompleteNBLs(pFilter, DispatchLevel, NetBufferLists, STATUS_INSUFFICIENT_RESOURCES);
|
||||
return;
|
||||
}
|
||||
|
||||
Event->Received = Received;
|
||||
Event->PortNumber = PortNumber;
|
||||
Event->NetBufferLists = NetBufferLists;
|
||||
|
||||
// Add the event to the queue
|
||||
FILTER_ACQUIRE_LOCK(&pFilter->EventsLock, DispatchLevel);
|
||||
if (Received) pFilter->CountPendingRecvNBLs++;
|
||||
InsertTailList(&pFilter->NBLsHead, &Event->Link);
|
||||
FILTER_RELEASE_LOCK(&pFilter->EventsLock, DispatchLevel);
|
||||
|
||||
@@ -378,6 +389,35 @@ otLwfEventProcessingIndicateNewNetBufferLists(
|
||||
KeSetEvent(&pFilter->EventWorkerThreadProcessNBLs, 0, FALSE);
|
||||
}
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingIndicateNewMacFrameCommand(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_reads_bytes_(BufferLength)
|
||||
const uint8_t* Buffer,
|
||||
_In_ uint8_t BufferLength
|
||||
)
|
||||
{
|
||||
POTLWF_MAC_FRAME_EVENT Event = FILTER_ALLOC_MEM(pFilter->FilterHandle, FIELD_OFFSET(OTLWF_MAC_FRAME_EVENT, Buffer) + BufferLength);
|
||||
if (Event == NULL)
|
||||
{
|
||||
LogWarning(DRIVER_DATA_PATH, "Failed to alloc new OTLWF_MAC_FRAME_EVENT");
|
||||
return;
|
||||
}
|
||||
|
||||
Event->BufferLength = BufferLength;
|
||||
memcpy(Event->Buffer, Buffer, BufferLength);
|
||||
|
||||
// Add the event to the queue
|
||||
FILTER_ACQUIRE_LOCK(&pFilter->EventsLock, DispatchLevel);
|
||||
InsertTailList(&pFilter->MacFramesHead, &Event->Link);
|
||||
FILTER_RELEASE_LOCK(&pFilter->EventsLock, DispatchLevel);
|
||||
|
||||
// Set the event to indicate we have a new Mac Frame to process
|
||||
KeSetEvent(&pFilter->EventWorkerThreadProcessMacFrames, 0, FALSE);
|
||||
}
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingIndicateNetBufferListsCancelled(
|
||||
@@ -412,7 +452,7 @@ otLwfEventProcessingIndicateNetBufferListsCancelled(
|
||||
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->NetBufferLists, STATUS_CANCELLED);
|
||||
|
||||
// Delete the event
|
||||
NdisFreeMemory(Event, 0, 0);
|
||||
@@ -425,12 +465,11 @@ VOID
|
||||
otLwfCompleteNBLs(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_ BOOLEAN Received,
|
||||
_In_ PNET_BUFFER_LIST NetBufferLists,
|
||||
_In_ NTSTATUS Status
|
||||
)
|
||||
{
|
||||
LogVerbose(DRIVER_DATA_PATH, "otLwfCompleteNBLs, Filter:%p, NBL:%p, Recv:%u, Status:%!STATUS!", pFilter, NetBufferLists, Received, Status);
|
||||
LogVerbose(DRIVER_DATA_PATH, "otLwfCompleteNBLs, Filter:%p, NBL:%p, Status:%!STATUS!", pFilter, NetBufferLists, Status);
|
||||
|
||||
// Set the status for all the NBLs
|
||||
PNET_BUFFER_LIST CurrNbl = NetBufferLists;
|
||||
@@ -443,22 +482,11 @@ otLwfCompleteNBLs(
|
||||
NT_ASSERT(NetBufferLists);
|
||||
|
||||
// Indicate the completion
|
||||
if (Received)
|
||||
{
|
||||
NdisFReturnNetBufferLists(
|
||||
pFilter->FilterHandle,
|
||||
NetBufferLists,
|
||||
DispatchLevel ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
NdisFSendNetBufferListsComplete(
|
||||
pFilter->FilterHandle,
|
||||
NetBufferLists,
|
||||
DispatchLevel ? NDIS_RETURN_FLAGS_DISPATCH_LEVEL : 0
|
||||
);
|
||||
}
|
||||
NdisFSendNetBufferListsComplete(
|
||||
pFilter->FilterHandle,
|
||||
NetBufferLists,
|
||||
DispatchLevel ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0
|
||||
);
|
||||
}
|
||||
|
||||
_Function_class_(DRIVER_CANCEL)
|
||||
@@ -689,6 +717,7 @@ otLwfEventWorkerThread(
|
||||
{
|
||||
&pFilter->EventWorkerThreadStopEvent,
|
||||
&pFilter->EventWorkerThreadProcessNBLs,
|
||||
&pFilter->EventWorkerThreadProcessMacFrames,
|
||||
&pFilter->EventWorkerThreadWaitTimeUpdated,
|
||||
&pFilter->EventWorkerThreadProcessTasklets,
|
||||
&pFilter->SendNetBufferListComplete,
|
||||
@@ -823,7 +852,7 @@ otLwfEventWorkerThread(
|
||||
//
|
||||
|
||||
if (status == STATUS_TIMEOUT ||
|
||||
(pFilter->EventTimerState == OT_EVENT_TIMER_FIRED && status == STATUS_WAIT_0 + 2))
|
||||
(pFilter->EventTimerState == OT_EVENT_TIMER_FIRED && status == STATUS_WAIT_0 + 3))
|
||||
{
|
||||
// Reset the wait timeout
|
||||
pFilter->NextAlarmTickCount.QuadPart = 0;
|
||||
@@ -840,12 +869,11 @@ otLwfEventWorkerThread(
|
||||
POTLWF_NBL_EVENT Event = NULL;
|
||||
NdisAcquireSpinLock(&pFilter->EventsLock);
|
||||
|
||||
// Just get the first item ('send' or 'recv'), if available
|
||||
// Just get the first item, if available
|
||||
if (!IsListEmpty(&pFilter->NBLsHead))
|
||||
{
|
||||
PLIST_ENTRY Link = RemoveHeadList(&pFilter->NBLsHead);
|
||||
Event = CONTAINING_RECORD(Link, OTLWF_NBL_EVENT, Link);
|
||||
if (Event->Received) pFilter->CountPendingRecvNBLs--;
|
||||
}
|
||||
|
||||
NdisReleaseSpinLock(&pFilter->EventsLock);
|
||||
@@ -857,135 +885,162 @@ otLwfEventWorkerThread(
|
||||
NTSTATUS NblStatus = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
// Process the event
|
||||
if (Event->Received) // Received a MAC frame
|
||||
PNET_BUFFER_LIST CurrNbl = Event->NetBufferLists;
|
||||
while (CurrNbl != NULL)
|
||||
{
|
||||
PNET_BUFFER_LIST CurrNbl = Event->NetBufferLists;
|
||||
NT_ASSERT(CurrNbl);
|
||||
while (CurrNbl != NULL)
|
||||
PNET_BUFFER CurrNb = NET_BUFFER_LIST_FIRST_NB(CurrNbl);
|
||||
while (CurrNb != NULL)
|
||||
{
|
||||
LogVerbose(DRIVER_DATA_PATH, "Passing NBL:%p to OpenThread to recv.", CurrNbl);
|
||||
|
||||
PNET_BUFFER CurrNb = NET_BUFFER_LIST_FIRST_NB(CurrNbl);
|
||||
NT_ASSERT(CurrNb);
|
||||
while (CurrNb != NULL)
|
||||
NT_ASSERT(NET_BUFFER_DATA_LENGTH(CurrNb) <= MessageBufferSize);
|
||||
if (NET_BUFFER_DATA_LENGTH(CurrNb) <= MessageBufferSize)
|
||||
{
|
||||
NT_ASSERT(NET_BUFFER_DATA_LENGTH(CurrNb) <= sizeof(pFilter->otReceiveMessage));
|
||||
if (NET_BUFFER_DATA_LENGTH(CurrNb) <= sizeof(pFilter->otReceiveMessage))
|
||||
// Copy NB data into message
|
||||
if (NT_SUCCESS(CopyDataBuffer(CurrNb, NET_BUFFER_DATA_LENGTH(CurrNb), MessageBuffer)))
|
||||
{
|
||||
// Copy NB data into message
|
||||
if (NT_SUCCESS(CopyDataBuffer(CurrNb, NET_BUFFER_DATA_LENGTH(CurrNb), &pFilter->otReceiveMessage)))
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
// Create a new message
|
||||
otMessage message = otNewIp6Message(pFilter->otCtx, TRUE);
|
||||
if (message)
|
||||
{
|
||||
POT_NBL_CONTEXT NblContext = GetNBLContext(CurrNbl);
|
||||
pFilter->otReceiveFrame.mChannel = NblContext->Channel;
|
||||
pFilter->otReceiveFrame.mPower = NblContext->Power;
|
||||
pFilter->otReceiveFrame.mLqi = NblContext->Lqi;
|
||||
pFilter->otReceiveFrame.mLength = (uint8_t)NET_BUFFER_DATA_LENGTH(CurrNb);
|
||||
otLwfRadioReceiveFrame(pFilter, CurrNbl);
|
||||
NblStatus = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
CurrNb = NET_BUFFER_NEXT_NB(CurrNb);
|
||||
}
|
||||
|
||||
CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
|
||||
}
|
||||
}
|
||||
else // Sending an IPv6 packet
|
||||
{
|
||||
PNET_BUFFER_LIST CurrNbl = Event->NetBufferLists;
|
||||
while (CurrNbl != NULL)
|
||||
{
|
||||
PNET_BUFFER CurrNb = NET_BUFFER_LIST_FIRST_NB(CurrNbl);
|
||||
while (CurrNb != NULL)
|
||||
{
|
||||
NT_ASSERT(NET_BUFFER_DATA_LENGTH(CurrNb) <= MessageBufferSize);
|
||||
if (NET_BUFFER_DATA_LENGTH(CurrNb) <= MessageBufferSize)
|
||||
{
|
||||
// Copy NB data into message
|
||||
if (NT_SUCCESS(CopyDataBuffer(CurrNb, NET_BUFFER_DATA_LENGTH(CurrNb), MessageBuffer)))
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
// Create a new message
|
||||
otMessage message = otNewIp6Message(pFilter->otCtx, TRUE);
|
||||
if (message)
|
||||
// Write to the message
|
||||
error = otAppendMessage(message, MessageBuffer, (uint16_t)NET_BUFFER_DATA_LENGTH(CurrNb));
|
||||
if (error != kThreadError_None)
|
||||
{
|
||||
// Write to the message
|
||||
error = otAppendMessage(message, MessageBuffer, (uint16_t)NET_BUFFER_DATA_LENGTH(CurrNb));
|
||||
if (error != kThreadError_None)
|
||||
{
|
||||
LogError(DRIVER_DATA_PATH, "otAppendMessage failed with %!otError!", error);
|
||||
otFreeMessage(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
IPV6_HEADER* v6Header = (IPV6_HEADER*)MessageBuffer;
|
||||
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, IP6_SEND: %p : %!IPV6ADDR! => %!IPV6ADDR! (%u bytes)",
|
||||
pFilter, CurrNbl, &v6Header->SourceAddress, &v6Header->DestinationAddress,
|
||||
NET_BUFFER_DATA_LENGTH(CurrNb));
|
||||
|
||||
#ifdef LOG_BUFFERS
|
||||
otLogBuffer(MessageBuffer, NET_BUFFER_DATA_LENGTH(CurrNb));
|
||||
#endif
|
||||
|
||||
// Send message (it will free 'message')
|
||||
error = otSendIp6Datagram(pFilter->otCtx, message);
|
||||
if (error != kThreadError_None)
|
||||
{
|
||||
LogError(DRIVER_DATA_PATH, "otSendIp6Datagram failed with %!otError!", error);
|
||||
}
|
||||
else
|
||||
{
|
||||
NblStatus = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
LogError(DRIVER_DATA_PATH, "otAppendMessage failed with %!otError!", error);
|
||||
otFreeMessage(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError(DRIVER_DATA_PATH, "otNewIPv6Message failed!");
|
||||
IPV6_HEADER* v6Header = (IPV6_HEADER*)MessageBuffer;
|
||||
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, IP6_SEND: %p : %!IPV6ADDR! => %!IPV6ADDR! (%u bytes)",
|
||||
pFilter, CurrNbl, &v6Header->SourceAddress, &v6Header->DestinationAddress,
|
||||
NET_BUFFER_DATA_LENGTH(CurrNb));
|
||||
|
||||
#ifdef LOG_BUFFERS
|
||||
otLogBuffer(MessageBuffer, NET_BUFFER_DATA_LENGTH(CurrNb));
|
||||
#endif
|
||||
|
||||
// Send message (it will free 'message')
|
||||
error = otSendIp6Datagram(pFilter->otCtx, message);
|
||||
if (error != kThreadError_None)
|
||||
{
|
||||
LogError(DRIVER_DATA_PATH, "otSendIp6Datagram failed with %!otError!", error);
|
||||
}
|
||||
else
|
||||
{
|
||||
NblStatus = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError(DRIVER_DATA_PATH, "otNewIPv6Message failed!");
|
||||
}
|
||||
}
|
||||
|
||||
CurrNb = NET_BUFFER_NEXT_NB(CurrNb);
|
||||
}
|
||||
|
||||
CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
|
||||
CurrNb = NET_BUFFER_NEXT_NB(CurrNb);
|
||||
}
|
||||
|
||||
CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
|
||||
}
|
||||
|
||||
if (Event->NetBufferLists)
|
||||
{
|
||||
// Complete the NBLs
|
||||
otLwfCompleteNBLs(pFilter, FALSE, Event->Received, Event->NetBufferLists, NblStatus);
|
||||
otLwfCompleteNBLs(pFilter, FALSE, Event->NetBufferLists, NblStatus);
|
||||
}
|
||||
|
||||
// Free the event
|
||||
NdisFreeMemory(Event, 0, 0);
|
||||
}
|
||||
}
|
||||
else if (status == STATUS_WAIT_0 + 2) // EventWorkerThreadWaitTimeUpdated fired
|
||||
else if (status == STATUS_WAIT_0 + 2) // EventWorkerThreadProcessMacFrames fired
|
||||
{
|
||||
// Go through the queue until there are no more items
|
||||
for (;;)
|
||||
{
|
||||
POTLWF_MAC_FRAME_EVENT Event = NULL;
|
||||
NdisAcquireSpinLock(&pFilter->EventsLock);
|
||||
|
||||
// Just get the first item, if available
|
||||
if (!IsListEmpty(&pFilter->MacFramesHead))
|
||||
{
|
||||
PLIST_ENTRY Link = RemoveHeadList(&pFilter->MacFramesHead);
|
||||
Event = CONTAINING_RECORD(Link, OTLWF_MAC_FRAME_EVENT, Link);
|
||||
}
|
||||
|
||||
NdisReleaseSpinLock(&pFilter->EventsLock);
|
||||
|
||||
// Break out of the loop if we have emptied the queue
|
||||
if (Event == NULL) break;
|
||||
|
||||
// Read the initial length value and validate
|
||||
uint16_t packetLength = 0;
|
||||
if (try_spinel_datatype_unpack(
|
||||
Event->Buffer,
|
||||
Event->BufferLength,
|
||||
SPINEL_DATATYPE_UINT16_S,
|
||||
&packetLength) &&
|
||||
packetLength <= sizeof(pFilter->otReceiveMessage) &&
|
||||
Event->BufferLength > sizeof(uint16_t) + packetLength)
|
||||
{
|
||||
pFilter->otReceiveFrame.mLength = (uint8_t)packetLength;
|
||||
|
||||
uint8_t offset = 2;
|
||||
uint8_t length = Event->BufferLength - 2;
|
||||
|
||||
if (packetLength != 0)
|
||||
{
|
||||
memcpy(&pFilter->otReceiveMessage, Event->Buffer + offset, packetLength);
|
||||
offset += pFilter->otReceiveFrame.mLength;
|
||||
length -= pFilter->otReceiveFrame.mLength;
|
||||
}
|
||||
|
||||
ThreadError errorCode;
|
||||
int8_t noiseFloor = -128;
|
||||
uint16_t flags = 0;
|
||||
if (try_spinel_datatype_unpack(
|
||||
Event->Buffer + offset,
|
||||
length,
|
||||
"ccSiCC",
|
||||
&pFilter->otReceiveFrame.mPower,
|
||||
&noiseFloor,
|
||||
&flags,
|
||||
&errorCode,
|
||||
&pFilter->otReceiveFrame.mChannel,
|
||||
&pFilter->otReceiveFrame.mLqi))
|
||||
{
|
||||
otLwfRadioReceiveFrame(pFilter, errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
// Free the event
|
||||
NdisFreeMemory(Event, 0, 0);
|
||||
}
|
||||
}
|
||||
else if (status == STATUS_WAIT_0 + 3) // EventWorkerThreadWaitTimeUpdated fired
|
||||
{
|
||||
// Nothing to do, the next time we wait, we will be using the updated time
|
||||
}
|
||||
else if (status == STATUS_WAIT_0 + 3) // EventWorkerThreadProcessTasklets fired
|
||||
else if (status == STATUS_WAIT_0 + 4) // EventWorkerThreadProcessTasklets fired
|
||||
{
|
||||
// Process all tasklets that were indicated to us from OpenThread
|
||||
otProcessQueuedTasklets(pFilter->otCtx);
|
||||
}
|
||||
else if (status == STATUS_WAIT_0 + 4) // SendNetBufferListComplete fired
|
||||
else if (status == STATUS_WAIT_0 + 5) // SendNetBufferListComplete fired
|
||||
{
|
||||
// Handle the completion of the NBL send
|
||||
otLwfRadioTransmitFrameDone(pFilter);
|
||||
}
|
||||
else if (status == STATUS_WAIT_0 + 5) // EventWorkerThreadProcessIrp fired
|
||||
else if (status == STATUS_WAIT_0 + 6) // EventWorkerThreadProcessIrp fired
|
||||
{
|
||||
// Process any IRPs that were pended
|
||||
otLwfEventProcessingNextIrp(pFilter);
|
||||
}
|
||||
else if (status == STATUS_WAIT_0 + 6) // EventWorkerThreadProcessAddressChanges fired
|
||||
else if (status == STATUS_WAIT_0 + 7) // EventWorkerThreadProcessAddressChanges fired
|
||||
{
|
||||
// Go through the queue until there are no more items
|
||||
for (;;)
|
||||
@@ -1012,7 +1067,7 @@ otLwfEventWorkerThread(
|
||||
NdisFreeMemory(Event, 0, 0);
|
||||
}
|
||||
}
|
||||
else if (status == STATUS_WAIT_0 + 7) // EventWorkerThreadEnergyScanComplete fired
|
||||
else if (status == STATUS_WAIT_0 + 8) // EventWorkerThreadEnergyScanComplete fired
|
||||
{
|
||||
// Indicate energy scan complete
|
||||
otPlatRadioEnergyScanDone(pFilter->otCtx, pFilter->otLastEnergyScanMaxRssi);
|
||||
|
||||
@@ -93,8 +93,12 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
|
||||
NTSTATUS NtStatus;
|
||||
NDIS_FILTER_ATTRIBUTES FilterAttributes;
|
||||
ULONG Size;
|
||||
ULONG bytesProcessed = 0;
|
||||
COMPARTMENT_ID OriginalCompartmentID;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes = {0};
|
||||
|
||||
const ULONG RegKeyOffset = ARRAYSIZE(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\otlwf\\Parameters\\NdisAdapters\\") - 1;
|
||||
DECLARE_CONST_UNICODE_STRING(RegKeyPath, L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\otlwf\\Parameters\\NdisAdapters\\{00000000-0000-0000-0000-000000000000}");
|
||||
RtlCopyMemory(RegKeyPath.Buffer + RegKeyOffset, AttachParameters->BaseMiniportName->Buffer + 8, sizeof(L"{00000000-0000-0000-0000-000000000000}"));
|
||||
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
@@ -113,7 +117,6 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
|
||||
if (AttachParameters->MiniportMediaType != NdisMediumIP)
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Unsupported media type, 0x%x.", (ULONG)AttachParameters->MiniportMediaType);
|
||||
|
||||
Status = NDIS_STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
@@ -130,6 +133,24 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
|
||||
|
||||
NdisZeroMemory(pFilter, sizeof(MS_FILTER));
|
||||
|
||||
LogVerbose(DRIVER_DEFAULT, "Opening interface registry key %S", RegKeyPath.Buffer);
|
||||
|
||||
InitializeObjectAttributes(
|
||||
&ObjectAttributes,
|
||||
(PUNICODE_STRING)&RegKeyPath,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
// Open the registry key
|
||||
NtStatus = ZwOpenKey(&pFilter->InterfaceRegKey, KEY_ALL_ACCESS, &ObjectAttributes);
|
||||
if (!NT_SUCCESS(NtStatus))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "ZwOpenKey failed to open %S, %!STATUS!", RegKeyPath.Buffer, NtStatus);
|
||||
Status = NDIS_STATUS_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
// Format of "\DEVICE\{5BA90C49-0D7E-455B-8D3B-614F6714A212}"
|
||||
AttachParameters->BaseMiniportName->Buffer += 8;
|
||||
AttachParameters->BaseMiniportName->Length -= 8 * sizeof(WCHAR);
|
||||
@@ -142,12 +163,12 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
|
||||
Status = NDIS_STATUS_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
pFilter->MiniportFriendlyName.Length = pFilter->MiniportFriendlyName.MaximumLength = AttachParameters->BaseMiniportInstanceName->Length;
|
||||
pFilter->MiniportFriendlyName.Buffer = (PWSTR)((PUCHAR)pFilter + sizeof(MS_FILTER));
|
||||
NdisMoveMemory(pFilter->MiniportFriendlyName.Buffer,
|
||||
|
||||
pFilter->InterfaceFriendlyName.Length = pFilter->InterfaceFriendlyName.MaximumLength = AttachParameters->BaseMiniportInstanceName->Length;
|
||||
pFilter->InterfaceFriendlyName.Buffer = (PWSTR)((PUCHAR)pFilter + sizeof(MS_FILTER));
|
||||
NdisMoveMemory(pFilter->InterfaceFriendlyName.Buffer,
|
||||
AttachParameters->BaseMiniportInstanceName->Buffer,
|
||||
pFilter->MiniportFriendlyName.Length);
|
||||
pFilter->InterfaceFriendlyName.Length);
|
||||
|
||||
pFilter->InterfaceIndex = AttachParameters->BaseMiniportIfIndex;
|
||||
pFilter->InterfaceLuid = AttachParameters->BaseMiniportNetLuid;
|
||||
@@ -170,40 +191,18 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
|
||||
|
||||
// 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 =
|
||||
{
|
||||
{ NDIS_OBJECT_TYPE_DEFAULT, NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1, NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1 },
|
||||
NDIS_PROTOCOL_ID_DEFAULT,
|
||||
TRUE,
|
||||
0,
|
||||
'BNto', // otNB
|
||||
0
|
||||
};
|
||||
pFilter->NetBufferListPool = NdisAllocateNetBufferListPool(pFilter->FilterHandle, &PoolParams);
|
||||
if (pFilter->NetBufferListPool == NULL)
|
||||
{
|
||||
Status = NDIS_STATUS_RESOURCES;
|
||||
LogWarning(DRIVER_DEFAULT, "Failed to create NetBufferList pool");
|
||||
break;
|
||||
}
|
||||
// Initialize rundowns to disabled with no active references
|
||||
pFilter->ExternalRefs.Count = EX_RUNDOWN_ACTIVE;
|
||||
pFilter->cmdRundown.Count = EX_RUNDOWN_ACTIVE;
|
||||
|
||||
// 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);
|
||||
|
||||
@@ -227,45 +226,6 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
|
||||
break;
|
||||
}
|
||||
|
||||
// Little hack to pass the IfIndex to the VMP
|
||||
*((ULONG*)&pFilter->MiniportCapabilities) = AttachParameters->BaseMiniportIfIndex;
|
||||
|
||||
// Query the MP capabilities
|
||||
Status =
|
||||
otLwfSendInternalRequest(
|
||||
pFilter,
|
||||
NdisRequestQueryInformation,
|
||||
OID_OT_CAPABILITIES,
|
||||
&pFilter->MiniportCapabilities,
|
||||
sizeof(OT_CAPABILITIES),
|
||||
&bytesProcessed
|
||||
);
|
||||
if (Status != NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Query for OID_OT_CAPABILITIES failed, %!NDIS_STATUS!", Status);
|
||||
break;
|
||||
}
|
||||
|
||||
// Validate the return header
|
||||
if (bytesProcessed != SIZEOF_OT_CAPABILITIES_REVISION_1 ||
|
||||
pFilter->MiniportCapabilities.Header.Type != NDIS_OBJECT_TYPE_DEFAULT ||
|
||||
pFilter->MiniportCapabilities.Header.Revision != OT_CAPABILITIES_REVISION_1 ||
|
||||
pFilter->MiniportCapabilities.Header.Size != SIZEOF_OT_CAPABILITIES_REVISION_1)
|
||||
{
|
||||
Status = NDIS_STATUS_INVALID_DATA;
|
||||
LogError(DRIVER_DEFAULT, "Query for OID_OT_CAPABILITIES returned invalid data");
|
||||
break;
|
||||
}
|
||||
|
||||
// Make sure we are in RADIO mode
|
||||
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 or THREAD mode!");
|
||||
break;
|
||||
}
|
||||
|
||||
// Add Filter to global list of Thread Filters
|
||||
NdisAcquireSpinLock(&FilterListLock);
|
||||
InsertTailList(&FilterModuleList, &pFilter->FilterModuleLink);
|
||||
@@ -275,6 +235,7 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
|
||||
|
||||
} while (FALSE);
|
||||
|
||||
// Clean up on failure
|
||||
if (Status != NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
if (pFilter != NULL)
|
||||
@@ -285,12 +246,6 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
|
||||
pFilter->AddressChangeHandle = NULL;
|
||||
}
|
||||
|
||||
// Free NBL Pool
|
||||
if (pFilter->NetBufferListPool)
|
||||
{
|
||||
NdisFreeNetBufferPool(pFilter->NetBufferListPool);
|
||||
}
|
||||
|
||||
NdisFreeMemory(pFilter, 0, 0);
|
||||
}
|
||||
}
|
||||
@@ -330,49 +285,27 @@ NOTE: Called at PASSIVE_LEVEL and the filter is in paused state
|
||||
|
||||
// Filter must be in paused state and pretty much inactive
|
||||
NT_ASSERT(pFilter->State == FilterPaused);
|
||||
NT_ASSERT(pFilter->IoControlReferences > 0);
|
||||
NT_ASSERT(pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_UNINTIALIZED);
|
||||
|
||||
//
|
||||
// Detach must not fail, so do not put any code here that can possibly fail.
|
||||
//
|
||||
|
||||
// Release IoControl reference and wait for shutdown if there are active refernces
|
||||
NdisResetEvent(&pFilter->IoControlShutdownComplete);
|
||||
if (!RtlDecrementReferenceCount(&pFilter->IoControlReferences))
|
||||
{
|
||||
LogInfo(DRIVER_DEFAULT, "Waiting for Io Control shutdown...");
|
||||
NdisWaitEvent(&pFilter->IoControlShutdownComplete, 0);
|
||||
NT_ASSERT(pFilter->IoControlReferences == 0);
|
||||
LogInfo(DRIVER_DEFAULT, "Received Io Control shutdown event.");
|
||||
}
|
||||
|
||||
// Unregister from address change notifications
|
||||
CancelMibChangeNotify2(pFilter->AddressChangeHandle);
|
||||
pFilter->AddressChangeHandle = NULL;
|
||||
|
||||
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 Pool
|
||||
NdisFreeNetBufferPool(pFilter->NetBufferListPool);
|
||||
// Unregister from address change notifications
|
||||
CancelMibChangeNotify2(pFilter->AddressChangeHandle);
|
||||
pFilter->AddressChangeHandle = NULL;
|
||||
|
||||
// Close the registry key
|
||||
if (pFilter->InterfaceRegKey)
|
||||
{
|
||||
ZwClose(pFilter->InterfaceRegKey);
|
||||
pFilter->InterfaceRegKey = NULL;
|
||||
}
|
||||
|
||||
// Free the memory allocated
|
||||
NdisFreeMemory(pFilter, 0, 0);
|
||||
@@ -400,6 +333,74 @@ otLwfNotifyDeviceAvailabilityChange(
|
||||
}
|
||||
}
|
||||
|
||||
PAGED
|
||||
NTSTATUS
|
||||
GetRegDWORDValue(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ PCWSTR ValueName,
|
||||
_Out_ PULONG ValueData
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
ULONG resultLength;
|
||||
UCHAR keybuf[128] = {0};
|
||||
UNICODE_STRING UValueName;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
RtlInitUnicodeString(&UValueName, ValueName);
|
||||
|
||||
status = ZwQueryValueKey(
|
||||
pFilter->InterfaceRegKey,
|
||||
&UValueName,
|
||||
KeyValueFullInformation,
|
||||
keybuf,
|
||||
sizeof(keybuf),
|
||||
&resultLength);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
PKEY_VALUE_FULL_INFORMATION keyInfo = (PKEY_VALUE_FULL_INFORMATION)keybuf;
|
||||
|
||||
if (keyInfo->Type != REG_DWORD)
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER_MIX;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ValueData = *((ULONG UNALIGNED *)(keybuf + keyInfo->DataOffset));
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
PAGED
|
||||
NTSTATUS
|
||||
SetRegDWORDValue(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ PCWSTR ValueName,
|
||||
_In_ ULONG ValueData
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
UNICODE_STRING UValueName;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
RtlInitUnicodeString(&UValueName, ValueName);
|
||||
|
||||
status = ZwSetValueKey(
|
||||
pFilter->InterfaceRegKey,
|
||||
&UValueName,
|
||||
0,
|
||||
REG_DWORD,
|
||||
(PVOID)&ValueData,
|
||||
sizeof(ValueData));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
NDIS_STATUS
|
||||
FilterRestart(
|
||||
@@ -428,8 +429,12 @@ Return Value:
|
||||
NTSTATUS NtStatus = STATUS_SUCCESS;
|
||||
NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
|
||||
PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
|
||||
PVOID SpinelCapsDataBuffer = NULL;
|
||||
const uint8_t* SpinelCapsPtr = NULL;
|
||||
spinel_size_t SpinelCapsLen = 0;
|
||||
NL_INTERFACE_KEY key = {0};
|
||||
NL_INTERFACE_RW interfaceRw;
|
||||
ULONG ThreadOnHost = TRUE;
|
||||
|
||||
PNDIS_RESTART_GENERAL_ATTRIBUTES NdisGeneralAttributes;
|
||||
PNDIS_RESTART_ATTRIBUTES NdisRestartAttributes;
|
||||
@@ -459,52 +464,116 @@ Return Value:
|
||||
//
|
||||
NdisGeneralAttributes->LookaheadSize = 128;
|
||||
}
|
||||
|
||||
|
||||
// Initialize the processing logic
|
||||
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
|
||||
|
||||
// Initialize the Spinel command processing
|
||||
NdisStatus = otLwfCmdInitialize(pFilter);
|
||||
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "otLwfCmdInitialize failed, %!NDIS_STATUS!", NdisStatus);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Query the device capabilities
|
||||
NtStatus = otLwfCmdGetProp(pFilter, SpinelCapsDataBuffer, SPINEL_PROP_CAPS, SPINEL_DATATYPE_DATA_S, &SpinelCapsPtr, &SpinelCapsLen);
|
||||
if (!NT_SUCCESS(NtStatus))
|
||||
{
|
||||
NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
|
||||
LogError(DRIVER_DEFAULT, "Failed to query SPINEL_PROP_CAPS, %!STATUS!", NtStatus);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Iterate and process returned capabilities
|
||||
while (SpinelCapsLen > 0)
|
||||
{
|
||||
ULONG SpinelCap = 0;
|
||||
spinel_ssize_t len = spinel_datatype_unpack(SpinelCapsPtr, SpinelCapsLen, SPINEL_DATATYPE_UINT_PACKED_S, &SpinelCap);
|
||||
if (len < 1) break;
|
||||
SpinelCapsLen -= (spinel_size_t)len;
|
||||
|
||||
switch (SpinelCap)
|
||||
{
|
||||
case SPINEL_CAP_MAC_RAW:
|
||||
pFilter->DeviceCapabilities |= OTLWF_DEVICE_CAP_RADIO;
|
||||
pFilter->DeviceCapabilities |= OTLWF_DEVICE_CAP_RADIO_ACK_TIMEOUT;
|
||||
pFilter->DeviceCapabilities |= OTLWF_DEVICE_CAP_RADIO_ENERGY_SCAN;
|
||||
break;
|
||||
case SPINEL_CAP_NET_THREAD_1_0:
|
||||
pFilter->DeviceCapabilities |= OTLWF_DEVICE_CAP_THREAD_1_0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the state indicating where we should be running the Thread logic (Host or Device).
|
||||
if (!NT_SUCCESS(GetRegDWORDValue(pFilter, L"RunOnHost", &ThreadOnHost)))
|
||||
{
|
||||
// Default to running on the host if the key isn't present
|
||||
ThreadOnHost = TRUE;
|
||||
SetRegDWORDValue(pFilter, L"RunOnHost", ThreadOnHost);
|
||||
}
|
||||
|
||||
LogInfo(DRIVER_DEFAULT, "Filter: %p initializing ThreadOnHost=%d", FilterModuleContext, ThreadOnHost);
|
||||
|
||||
// Initialize the processing logic
|
||||
if (ThreadOnHost)
|
||||
{
|
||||
// Ensure the device has the capabilities to support raw radio commands
|
||||
if ((pFilter->DeviceCapabilities & OTLWF_DEVICE_CAP_RADIO) == 0)
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Failed to start because device doesn't support raw radio commands");
|
||||
NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
pFilter->DeviceStatus = OTLWF_DEVICE_STATUS_RADIO_MODE;
|
||||
NtStatus = otLwfInitializeThreadMode(pFilter);
|
||||
if (!NT_SUCCESS(NtStatus))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "otLwfInitializeThreadMode failed, %!STATUS!", NtStatus);
|
||||
NdisStatus = NDIS_STATUS_FAILURE;
|
||||
pFilter->DeviceStatus = OTLWF_DEVICE_STATUS_UNINTIALIZED;
|
||||
goto exit;
|
||||
}
|
||||
pFilter->InternalStateInitialized = TRUE;
|
||||
}
|
||||
else if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_THREAD)
|
||||
else
|
||||
{
|
||||
NtStatus = otLwfInitializeTunnelMode(pFilter);
|
||||
// Ensure the device has the capabilities to support Thread commands
|
||||
if ((pFilter->DeviceCapabilities & OTLWF_DEVICE_CAP_THREAD_1_0) == 0)
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Failed to start because device doesn't support thread commands");
|
||||
NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
pFilter->DeviceStatus = OTLWF_DEVICE_STATUS_THREAD_MODE;
|
||||
NtStatus = otLwfTunInitialize(pFilter);
|
||||
if (!NT_SUCCESS(NtStatus))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "otLwfInitializeTunnelMode failed, %!STATUS!", NtStatus);
|
||||
NdisStatus = NDIS_STATUS_FAILURE;
|
||||
pFilter->DeviceStatus = OTLWF_DEVICE_STATUS_UNINTIALIZED;
|
||||
goto exit;
|
||||
}
|
||||
pFilter->InternalStateInitialized = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
NT_ASSERT(FALSE);
|
||||
NdisStatus = NDIS_STATUS_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Disable DAD and Neighbor advertisements
|
||||
//
|
||||
key.Luid = pFilter->InterfaceLuid;
|
||||
NlInitializeInterfaceRw(&interfaceRw);
|
||||
interfaceRw.DadTransmits = 0;
|
||||
interfaceRw.SendUnsolicitedNeighborAdvertisementOnDad = FALSE;
|
||||
|
||||
NtStatus =
|
||||
NtStatus =
|
||||
NsiSetAllParameters(
|
||||
NsiActive,
|
||||
NsiSetDefault,
|
||||
&NPI_MS_IPV6_MODULEID,
|
||||
NlInterfaceObject,
|
||||
&key,
|
||||
sizeof(key),
|
||||
&interfaceRw,
|
||||
NsiActive,
|
||||
NsiSetDefault,
|
||||
&NPI_MS_IPV6_MODULEID,
|
||||
NlInterfaceObject,
|
||||
&key,
|
||||
sizeof(key),
|
||||
&interfaceRw,
|
||||
sizeof(interfaceRw));
|
||||
if (!NT_SUCCESS(NtStatus))
|
||||
{
|
||||
@@ -514,9 +583,9 @@ Return Value:
|
||||
}
|
||||
|
||||
//
|
||||
// Enable the data path
|
||||
// Enable the external references to the filter
|
||||
//
|
||||
otLwfEnableDataPath(pFilter);
|
||||
ExReInitializeRundownProtection(&pFilter->ExternalRefs);
|
||||
|
||||
//
|
||||
// If everything is OK, set the filter in running state.
|
||||
@@ -534,18 +603,25 @@ exit:
|
||||
{
|
||||
pFilter->State = FilterPaused;
|
||||
|
||||
if (pFilter->InternalStateInitialized)
|
||||
if (pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_RADIO_MODE)
|
||||
{
|
||||
pFilter->InternalStateInitialized = FALSE;
|
||||
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
|
||||
{
|
||||
otLwfUninitializeThreadMode(pFilter);
|
||||
}
|
||||
else
|
||||
{
|
||||
otLwfUninitializeTunnelMode(pFilter);
|
||||
}
|
||||
otLwfUninitializeThreadMode(pFilter);
|
||||
}
|
||||
else if (pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_THREAD_MODE)
|
||||
{
|
||||
otLwfTunUninitialize(pFilter);
|
||||
}
|
||||
|
||||
pFilter->DeviceStatus = OTLWF_DEVICE_STATUS_UNINTIALIZED;
|
||||
|
||||
// Clean up Spinel command processing
|
||||
otLwfCmdUninitialize(pFilter);
|
||||
}
|
||||
|
||||
// Free the buffer for the capabilities we queried
|
||||
if (SpinelCapsDataBuffer != NULL)
|
||||
{
|
||||
FILTER_FREE_MEM(SpinelCapsDataBuffer);
|
||||
}
|
||||
|
||||
LogFuncExitNDIS(DRIVER_DEFAULT, NdisStatus);
|
||||
@@ -592,24 +668,49 @@ N.B.: When the filter is in Pausing state, it can still process OID requests,
|
||||
|
||||
LogFuncEntryMsg(DRIVER_DEFAULT, "Filter: %p", FilterModuleContext);
|
||||
|
||||
// Reset the pause complete event
|
||||
NdisResetEvent(&pFilter->FilterPauseComplete);
|
||||
|
||||
//
|
||||
// Set the flag that the filter is going to pause
|
||||
//
|
||||
NT_ASSERT(pFilter->State == FilterRunning);
|
||||
NdisAcquireSpinLock(&FilterListLock);
|
||||
pFilter->State = FilterPausing;
|
||||
|
||||
NdisReleaseSpinLock(&FilterListLock);
|
||||
|
||||
//
|
||||
// Send final notification of interface removal
|
||||
//
|
||||
otLwfNotifyDeviceAvailabilityChange(pFilter, FALSE);
|
||||
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! removal.", &pFilter->InterfaceGuid);
|
||||
|
||||
//
|
||||
// Disable the data path
|
||||
// Disable external references and wait for existing calls to complete
|
||||
//
|
||||
otLwfDisableDataPath(pFilter);
|
||||
LogInfo(DRIVER_DEFAULT, "Disabling and waiting for external references to release");
|
||||
ExWaitForRundownProtectionRelease(&pFilter->ExternalRefs);
|
||||
LogInfo(DRIVER_DEFAULT, "External references released.");
|
||||
|
||||
//
|
||||
// Clean up based on the device mode
|
||||
//
|
||||
if (pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_RADIO_MODE)
|
||||
{
|
||||
otLwfUninitializeThreadMode(pFilter);
|
||||
}
|
||||
else if (pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_THREAD_MODE)
|
||||
{
|
||||
otLwfTunUninitialize(pFilter);
|
||||
}
|
||||
|
||||
pFilter->DeviceStatus = OTLWF_DEVICE_STATUS_UNINTIALIZED;
|
||||
|
||||
//
|
||||
// Clean up the Spinel command processing
|
||||
//
|
||||
otLwfCmdUninitialize(pFilter);
|
||||
|
||||
//
|
||||
// Set the state back to Paused now that we are done
|
||||
//
|
||||
pFilter->State = FilterPaused;
|
||||
|
||||
LogFuncExitNDIS(DRIVER_DEFAULT, Status);
|
||||
@@ -653,21 +754,6 @@ NOTE: called at <= DISPATCH_LEVEL
|
||||
// Cache the link state from the miniport
|
||||
memcpy(&pFilter->MiniportLinkState, LinkState, sizeof(NDIS_LINK_STATE));
|
||||
}
|
||||
else if (StatusIndication->StatusCode == NDIS_STATUS_OT_ENERGY_SCAN_RESULT)
|
||||
{
|
||||
NT_ASSERT(StatusIndication->StatusBufferSize == sizeof(OT_ENERGY_SCAN_RESULT));
|
||||
if (StatusIndication->StatusBufferSize != sizeof(OT_ENERGY_SCAN_RESULT)) goto exit;
|
||||
|
||||
POT_ENERGY_SCAN_RESULT ScanResult = (POT_ENERGY_SCAN_RESULT)StatusIndication->StatusBuffer;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
NdisFIndicateStatus(pFilter->FilterHandle, StatusIndication);
|
||||
|
||||
@@ -706,106 +792,6 @@ otLwfIndicateLinkState(
|
||||
NdisFIndicateStatus(pFilter->FilterHandle, &StatusIndication);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
VOID
|
||||
FilterDevicePnPEventNotify(
|
||||
NDIS_HANDLE FilterModuleContext,
|
||||
PNET_DEVICE_PNP_EVENT NetDevicePnPEvent
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Device PNP event handler
|
||||
|
||||
Arguments:
|
||||
|
||||
FilterModuleContext - our filter context
|
||||
NetDevicePnPEvent - a Device PnP event
|
||||
|
||||
NOTE: called at PASSIVE_LEVEL
|
||||
|
||||
--*/
|
||||
{
|
||||
PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
|
||||
NDIS_DEVICE_PNP_EVENT DevicePnPEvent = NetDevicePnPEvent->DevicePnPEvent;
|
||||
#if DBG
|
||||
BOOLEAN bFalse = FALSE;
|
||||
#endif
|
||||
|
||||
LogFuncEntryMsg(DRIVER_DEFAULT, "Filter: %p, DevicePnPEvent: %u", FilterModuleContext, NetDevicePnPEvent->DevicePnPEvent);
|
||||
|
||||
//
|
||||
// The filter may do processing on the event here, including intercepting
|
||||
// and dropping it entirely. However, the sample does nothing with Device
|
||||
// PNP events, except pass them down to the next lower* layer. It is more
|
||||
// efficient to omit the FilterDevicePnPEventNotify handler entirely if it
|
||||
// does nothing, but it is included in this sample for illustrative purposes.
|
||||
//
|
||||
// * Trivia: Device PNP events percolate DOWN the stack, instead of upwards
|
||||
// like status indications and Net PNP events. So the next layer is the
|
||||
// LOWER layer.
|
||||
//
|
||||
|
||||
switch (DevicePnPEvent)
|
||||
{
|
||||
case NdisDevicePnPEventQueryRemoved:
|
||||
case NdisDevicePnPEventRemoved:
|
||||
case NdisDevicePnPEventSurpriseRemoved:
|
||||
case NdisDevicePnPEventQueryStopped:
|
||||
case NdisDevicePnPEventStopped:
|
||||
case NdisDevicePnPEventPowerProfileChanged:
|
||||
case NdisDevicePnPEventFilterListChanged:
|
||||
break;
|
||||
|
||||
default:
|
||||
LogError(DRIVER_DEFAULT, "FilterDevicePnPEventNotify: Invalid event.\n");
|
||||
NT_ASSERT(bFalse);
|
||||
break;
|
||||
}
|
||||
|
||||
NdisFDevicePnPEventNotify(pFilter->FilterHandle, NetDevicePnPEvent);
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
NDIS_STATUS
|
||||
FilterNetPnPEvent(
|
||||
NDIS_HANDLE FilterModuleContext,
|
||||
PNET_PNP_EVENT_NOTIFICATION NetPnPEventNotification
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Net PNP event handler
|
||||
|
||||
Arguments:
|
||||
|
||||
FilterModuleContext - our filter context
|
||||
NetPnPEventNotification - a Net PnP event
|
||||
|
||||
NOTE: called at PASSIVE_LEVEL
|
||||
|
||||
--*/
|
||||
{
|
||||
PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
|
||||
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
||||
|
||||
//
|
||||
// The filter may do processing on the event here, including intercepting
|
||||
// and dropping it entirely. However, the sample does nothing with Net PNP
|
||||
// events, except pass them up to the next higher layer. It is more
|
||||
// efficient to omit the FilterNetPnPEvent handler entirely if it does
|
||||
// nothing, but it is included in this sample for illustrative purposes.
|
||||
//
|
||||
|
||||
Status = NdisFNetPnPEvent(pFilter->FilterHandle, NetPnPEventNotification);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
otLwfSetCompartment(
|
||||
|
||||
@@ -78,10 +78,45 @@ typedef enum _FILTER_STATE
|
||||
FilterRunning,
|
||||
} FILTER_STATE;
|
||||
|
||||
// Flags for the different device capabilities
|
||||
typedef enum OTLWF_DEVICE_CAPABILITY
|
||||
{
|
||||
// Device supports raw Radio commands
|
||||
OTLWF_DEVICE_CAP_RADIO = 1 << 0,
|
||||
|
||||
// Device supports Ack timeouts internally
|
||||
OTLWF_DEVICE_CAP_RADIO_ACK_TIMEOUT = 1 << 1,
|
||||
|
||||
// Device supports MAC retry logic and timers; as well as collision avoidance.
|
||||
OTLWF_DEVICE_CAP_RADIO_MAC_RETRY_AND_COLLISION_AVOIDANCE = 1 << 2,
|
||||
|
||||
// Device supports the energy scan command.
|
||||
OTLWF_DEVICE_CAP_RADIO_ENERGY_SCAN = 1 << 3,
|
||||
|
||||
// Device supports sleeping. If the device supports sleeping, it is assumed to
|
||||
// default to the sleep state on bring up.
|
||||
OTLWF_DEVICE_CAP_RADIO_SLEEP = 1 << 4,
|
||||
|
||||
// Device support Net & Thread commands.
|
||||
OTLWF_DEVICE_CAP_THREAD_1_0 = 1 << 16,
|
||||
|
||||
} OTLWF_DEVICE_CAPABILITY;
|
||||
|
||||
// Flags for the different device capabilities
|
||||
typedef enum OTLWF_DEVICE_STATUS
|
||||
{
|
||||
OTLWF_DEVICE_STATUS_UNINTIALIZED, // Not yet initialzied.
|
||||
OTLWF_DEVICE_STATUS_RADIO_MODE, // The device is just operating as a simple radio.
|
||||
OTLWF_DEVICE_STATUS_THREAD_MODE // The device is managing the Thread stack.
|
||||
|
||||
} OTLWF_DEVICE_STATUS;
|
||||
|
||||
#define OT_EVENT_TIMER_NOT_RUNNING 0
|
||||
#define OT_EVENT_TIMER_RUNNING 1
|
||||
#define OT_EVENT_TIMER_FIRED 2
|
||||
|
||||
#define MAX_PENDING_MAC_SIZE 32 // TODO
|
||||
|
||||
//
|
||||
// Define the filter struct
|
||||
//
|
||||
@@ -95,26 +130,24 @@ typedef struct _MS_FILTER
|
||||
|
||||
// Current state (Running or not) of the Filter instance
|
||||
FILTER_STATE State;
|
||||
NDIS_EVENT FilterPauseComplete;
|
||||
|
||||
// Handle for unicast IP address notifications
|
||||
HANDLE AddressChangeHandle;
|
||||
|
||||
|
||||
//
|
||||
// Interface / Adapter variables
|
||||
// Interface variables
|
||||
//
|
||||
GUID InterfaceGuid;
|
||||
NET_IFINDEX InterfaceIndex;
|
||||
NET_LUID InterfaceLuid;
|
||||
COMPARTMENT_ID InterfaceCompartmentID;
|
||||
NDIS_STRING MiniportFriendlyName;
|
||||
volatile LONG PendingDisconnectTasks;
|
||||
NDIS_STRING InterfaceFriendlyName;
|
||||
HANDLE InterfaceRegKey;
|
||||
|
||||
//
|
||||
// Miniport Capabilities
|
||||
// Miniport Link State
|
||||
//
|
||||
OT_CAPABILITIES MiniportCapabilities;
|
||||
NDIS_LINK_STATE MiniportLinkState;
|
||||
NDIS_LINK_STATE MiniportLinkState;
|
||||
|
||||
//
|
||||
// Pending OID Handling
|
||||
@@ -123,18 +156,29 @@ typedef struct _MS_FILTER
|
||||
PNDIS_OID_REQUEST PendingOidRequest;
|
||||
|
||||
//
|
||||
// Io Control Path Synchronization
|
||||
// External references management
|
||||
// Used for IOCTLs, SendNBLs, and Address Changed callbacks
|
||||
//
|
||||
RTL_REFERENCE_COUNT IoControlReferences;
|
||||
NDIS_EVENT IoControlShutdownComplete;
|
||||
EX_RUNDOWN_REF ExternalRefs;
|
||||
|
||||
//
|
||||
// Data Path
|
||||
// Spinel Command State
|
||||
//
|
||||
EX_RUNDOWN_REF DataPathRundown;
|
||||
NDIS_HANDLE NetBufferListPool;
|
||||
EX_RUNDOWN_REF cmdRundown;
|
||||
NDIS_SPIN_LOCK cmdLock;
|
||||
LIST_ENTRY cmdHandlers;
|
||||
USHORT cmdTIDsInUse;
|
||||
spinel_tid_t cmdNextTID;
|
||||
NDIS_HANDLE cmdNblPool;
|
||||
#if DBG
|
||||
ULONG cmdInitTryCount;
|
||||
#endif
|
||||
|
||||
BOOLEAN InternalStateInitialized;
|
||||
//
|
||||
// Device Capabilities / State
|
||||
//
|
||||
OTLWF_DEVICE_CAPABILITY DeviceCapabilities;
|
||||
OTLWF_DEVICE_STATUS DeviceStatus;
|
||||
|
||||
//
|
||||
// OpenThread addresses
|
||||
@@ -158,10 +202,11 @@ typedef struct _MS_FILTER
|
||||
KEVENT EventWorkerThreadStopEvent;
|
||||
KEVENT EventWorkerThreadProcessAddressChanges;
|
||||
KEVENT EventWorkerThreadProcessNBLs;
|
||||
KEVENT EventWorkerThreadProcessMacFrames;
|
||||
NDIS_SPIN_LOCK EventsLock;
|
||||
LIST_ENTRY AddressChangesHead;
|
||||
LIST_ENTRY NBLsHead;
|
||||
ULONG CountPendingRecvNBLs;
|
||||
LIST_ENTRY MacFramesHead;
|
||||
LARGE_INTEGER NextAlarmTickCount;
|
||||
KEVENT EventWorkerThreadWaitTimeUpdated;
|
||||
KEVENT EventWorkerThreadProcessTasklets;
|
||||
@@ -180,7 +225,6 @@ typedef struct _MS_FILTER
|
||||
// OpenThread data path state
|
||||
//
|
||||
BOOLEAN SendPending;
|
||||
PNET_BUFFER_LIST SendNetBufferList;
|
||||
KEVENT SendNetBufferListComplete;
|
||||
|
||||
//
|
||||
@@ -193,6 +237,8 @@ typedef struct _MS_FILTER
|
||||
uint8_t otTransmitMessage[kMaxPHYPacketSize];
|
||||
RadioPacket otReceiveFrame;
|
||||
RadioPacket otTransmitFrame;
|
||||
ThreadError otLastTransmitError;
|
||||
BOOLEAN otLastTransmitFramePending;
|
||||
CHAR otLastEnergyScanMaxRssi;
|
||||
|
||||
BOOLEAN otPromiscuous;
|
||||
@@ -224,11 +270,6 @@ typedef struct _MS_FILTER
|
||||
};
|
||||
struct // Tunnel Mode Variables
|
||||
{
|
||||
NDIS_SPIN_LOCK tunCommandLock;
|
||||
LIST_ENTRY tunCommandHandlers;
|
||||
USHORT tunTIDsInUse;
|
||||
spinel_tid_t tunNextTID;
|
||||
|
||||
PVOID TunWorkerThread;
|
||||
KEVENT TunWorkerThreadStopEvent;
|
||||
KEVENT TunWorkerThreadAddressChangedEvent;
|
||||
@@ -246,8 +287,6 @@ FILTER_DETACH FilterDetach;
|
||||
FILTER_RESTART FilterRestart;
|
||||
FILTER_PAUSE FilterPause;
|
||||
FILTER_STATUS FilterStatus;
|
||||
FILTER_DEVICE_PNP_EVENT_NOTIFY FilterDevicePnPEventNotify;
|
||||
FILTER_NET_PNP_EVENT FilterNetPnPEvent;
|
||||
FILTER_SEND_NET_BUFFER_LISTS FilterSendNetBufferLists;
|
||||
FILTER_RETURN_NET_BUFFER_LISTS FilterReturnNetBufferLists;
|
||||
FILTER_SEND_NET_BUFFER_LISTS_COMPLETE FilterSendNetBufferListsComplete;
|
||||
@@ -282,22 +321,6 @@ otLwfRevertCompartment(
|
||||
_In_ COMPARTMENT_ID OriginalCompartment
|
||||
);
|
||||
|
||||
//
|
||||
// Data Path functions
|
||||
//
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfEnableDataPath(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
otLwfDisableDataPath(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
//
|
||||
// Address Functions
|
||||
//
|
||||
|
||||
@@ -152,22 +152,6 @@ IoCtlString(
|
||||
return FuncCode < ARRAYSIZE(IoCtls) ? IoCtls[FuncCode].Name : "UNKNOWN IOCTL";
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
try_spinel_datatype_unpack(
|
||||
const uint8_t *data_in,
|
||||
spinel_size_t data_len,
|
||||
const char *pack_format,
|
||||
...
|
||||
)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, pack_format);
|
||||
spinel_ssize_t packed_len = spinel_datatype_vunpack(data_in, data_len, pack_format, args);
|
||||
va_end(args);
|
||||
|
||||
return !(packed_len < 0 || (spinel_size_t)packed_len > data_len);
|
||||
}
|
||||
|
||||
// Handles queries for the current list of Thread interfaces
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
@@ -275,7 +259,7 @@ otLwfIoCtlQueryInterface(
|
||||
pDevice->CompartmentID = pFilter->InterfaceCompartmentID;
|
||||
|
||||
// Release the ref on the interface
|
||||
otLwfReleaseInterface(pFilter);
|
||||
ExReleaseRundownProtection(&pFilter->ExternalRefs);
|
||||
|
||||
error:
|
||||
|
||||
@@ -318,7 +302,7 @@ otLwfIoCtlOpenThreadControl(
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
|
||||
if (pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_RADIO_MODE)
|
||||
{
|
||||
// Pend the Irp for processing on the OpenThread event processing thread
|
||||
otLwfEventProcessingIndicateIrp(pFilter, Irp);
|
||||
@@ -329,7 +313,7 @@ otLwfIoCtlOpenThreadControl(
|
||||
}
|
||||
|
||||
// Release our ref on the filter
|
||||
otLwfReleaseInterface(pFilter);
|
||||
ExReleaseRundownProtection(&pFilter->ExternalRefs);
|
||||
|
||||
error:
|
||||
|
||||
@@ -521,7 +505,7 @@ otLwfTunIoCtl_otInterface(
|
||||
}
|
||||
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -534,7 +518,7 @@ otLwfTunIoCtl_otInterface(
|
||||
else if (OutBufferLength >= sizeof(BOOLEAN))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otInterface_Handler,
|
||||
@@ -628,7 +612,7 @@ otLwfTunIoCtl_otThread(
|
||||
if (InBufferLength >= sizeof(BOOLEAN))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -641,7 +625,7 @@ otLwfTunIoCtl_otThread(
|
||||
else if (OutBufferLength >= sizeof(BOOLEAN))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otThread_Handler,
|
||||
@@ -740,11 +724,11 @@ otLwfTunIoCtl_otActiveScan(
|
||||
|
||||
// TODO - Send down scan channel & duration first
|
||||
UNREFERENCED_PARAMETER(aScanChannels);
|
||||
status = otLwfSetTunProp(pFilter, SPINEL_PROP_MAC_SCAN_MASK, SPINEL_DATATYPE_UINT16_S, aScanDuration);
|
||||
status = otLwfCmdSetProp(pFilter, SPINEL_PROP_MAC_SCAN_MASK, SPINEL_DATATYPE_UINT16_S, aScanDuration);
|
||||
if (!NT_SUCCESS(status)) goto error;
|
||||
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -757,7 +741,7 @@ otLwfTunIoCtl_otActiveScan(
|
||||
else if (OutBufferLength >= sizeof(BOOLEAN))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otActiveScan_Handler,
|
||||
@@ -860,11 +844,11 @@ otLwfTunIoCtl_otEnergyScan(
|
||||
|
||||
// TODO - Send down scan channel & duration first
|
||||
UNREFERENCED_PARAMETER(aScanChannels);
|
||||
status = otLwfSetTunProp(pFilter, SPINEL_PROP_MAC_SCAN_MASK, SPINEL_DATATYPE_UINT16_S, aScanDuration);
|
||||
status = otLwfCmdSetProp(pFilter, SPINEL_PROP_MAC_SCAN_MASK, SPINEL_DATATYPE_UINT16_S, aScanDuration);
|
||||
if (!NT_SUCCESS(status)) goto error;
|
||||
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -877,7 +861,7 @@ otLwfTunIoCtl_otEnergyScan(
|
||||
else if (OutBufferLength >= sizeof(BOOLEAN))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otEnergyScan_Handler,
|
||||
@@ -1009,7 +993,7 @@ otLwfTunIoCtl_otChannel(
|
||||
if (InBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -1022,7 +1006,7 @@ otLwfTunIoCtl_otChannel(
|
||||
else if (OutBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otChannel_Handler,
|
||||
@@ -1108,7 +1092,7 @@ otLwfTunIoCtl_otChildTimeout(
|
||||
if (InBufferLength >= sizeof(uint32_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -1121,7 +1105,7 @@ otLwfTunIoCtl_otChildTimeout(
|
||||
else if (OutBufferLength >= sizeof(uint32_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otChildTimeout_Handler,
|
||||
@@ -1206,7 +1190,7 @@ otLwfTunIoCtl_otExtendedAddress(
|
||||
if (InBufferLength >= sizeof(otExtAddress))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -1219,7 +1203,7 @@ otLwfTunIoCtl_otExtendedAddress(
|
||||
else if (OutBufferLength >= sizeof(otExtAddress))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otExtendedAddress_Handler,
|
||||
@@ -1307,7 +1291,7 @@ otLwfTunIoCtl_otExtendedPanId(
|
||||
if (InBufferLength >= sizeof(otExtendedPanId))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -1321,7 +1305,7 @@ otLwfTunIoCtl_otExtendedPanId(
|
||||
else if (OutBufferLength >= sizeof(otExtendedPanId))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otExtendedPanId_Handler,
|
||||
@@ -1469,7 +1453,7 @@ otLwfTunIoCtl_otLeaderRloc(
|
||||
if (InBufferLength >= sizeof(otIp6Address))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -1482,7 +1466,7 @@ otLwfTunIoCtl_otLeaderRloc(
|
||||
else if (OutBufferLength >= sizeof(otIp6Address))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otLeaderRloc_Handler,
|
||||
@@ -1586,7 +1570,7 @@ otLwfTunIoCtl_otLinkMode(
|
||||
if (aLinkMode->mNetworkData) numeric_mode |= kThreadMode_FullNetworkData;
|
||||
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -1599,7 +1583,7 @@ otLwfTunIoCtl_otLinkMode(
|
||||
else if (OutBufferLength >= sizeof(otLinkModeConfig))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otLinkMode_Handler,
|
||||
@@ -1698,7 +1682,7 @@ otLwfTunIoCtl_otMasterKey(
|
||||
spinel_size_t aKeyLength = *(uint8_t*)(InBuffer + sizeof(otMasterKey));
|
||||
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -1712,7 +1696,7 @@ otLwfTunIoCtl_otMasterKey(
|
||||
else if (OutBufferLength >= sizeof(otMasterKey) + sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otMasterKey_Handler,
|
||||
@@ -1802,7 +1786,7 @@ otLwfTunIoCtl_otMeshLocalEid(
|
||||
if (OutBufferLength >= sizeof(otIp6Address))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otMeshLocalEid_Handler,
|
||||
@@ -1892,7 +1876,7 @@ otLwfTunIoCtl_otMeshLocalPrefix(
|
||||
memcpy(&aAddress, InBuffer, sizeof(otMeshLocalPrefix));
|
||||
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -1905,7 +1889,7 @@ otLwfTunIoCtl_otMeshLocalPrefix(
|
||||
else if (OutBufferLength >= sizeof(otMeshLocalPrefix))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otMeshLocalPrefix_Handler,
|
||||
@@ -1995,7 +1979,7 @@ otLwfTunIoCtl_otNetworkName(
|
||||
if (InBufferLength >= sizeof(otNetworkName))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -2008,7 +1992,7 @@ otLwfTunIoCtl_otNetworkName(
|
||||
else if (OutBufferLength >= sizeof(otNetworkName))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otNetworkName_Handler,
|
||||
@@ -2095,7 +2079,7 @@ otLwfTunIoCtl_otPanId(
|
||||
if (InBufferLength >= sizeof(otPanId))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -2108,7 +2092,7 @@ otLwfTunIoCtl_otPanId(
|
||||
else if (OutBufferLength >= sizeof(otPanId))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otPanId_Handler,
|
||||
@@ -2194,7 +2178,7 @@ otLwfTunIoCtl_otRouterRollEnabled(
|
||||
if (InBufferLength >= sizeof(BOOLEAN))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -2207,7 +2191,7 @@ otLwfTunIoCtl_otRouterRollEnabled(
|
||||
else if (OutBufferLength >= sizeof(BOOLEAN))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otRouterRollEnabled_Handler,
|
||||
@@ -2293,7 +2277,7 @@ otLwfTunIoCtl_otShortAddress(
|
||||
if (OutBufferLength >= sizeof(otShortAddress))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otShortAddress_Handler,
|
||||
@@ -2445,7 +2429,7 @@ otLwfTunIoCtl_otLocalLeaderWeight(
|
||||
if (InBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -2458,7 +2442,7 @@ otLwfTunIoCtl_otLocalLeaderWeight(
|
||||
else if (OutBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otLocalLeaderWeight_Handler,
|
||||
@@ -2558,7 +2542,7 @@ otLwfTunIoCtl_otAddBorderRouter(
|
||||
if (aConfig->mOnMesh) flags |= kOnMeshFlag;
|
||||
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -2623,7 +2607,7 @@ otLwfTunIoCtl_otRemoveBorderRouter(
|
||||
memcpy_s(&prefix, sizeof(prefix), &aPrefix->mPrefix, aPrefix->mLength);
|
||||
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -2693,7 +2677,7 @@ otLwfTunIoCtl_otAddExternalRoute(
|
||||
if (aConfig->mOnMesh) flags |= kOnMeshFlag;
|
||||
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -2758,7 +2742,7 @@ otLwfTunIoCtl_otRemoveExternalRoute(
|
||||
memcpy_s(&prefix, sizeof(prefix), &aPrefix->mPrefix, aPrefix->mLength);
|
||||
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -2847,7 +2831,7 @@ otLwfTunIoCtl_otContextIdReuseDelay(
|
||||
if (InBufferLength >= sizeof(uint32_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -2860,7 +2844,7 @@ otLwfTunIoCtl_otContextIdReuseDelay(
|
||||
else if (OutBufferLength >= sizeof(uint32_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otContextIdReuseDelay_Handler,
|
||||
@@ -2946,7 +2930,7 @@ otLwfTunIoCtl_otKeySequenceCounter(
|
||||
if (InBufferLength >= sizeof(uint32_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -2959,7 +2943,7 @@ otLwfTunIoCtl_otKeySequenceCounter(
|
||||
else if (OutBufferLength >= sizeof(uint32_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otKeySequenceCounter_Handler,
|
||||
@@ -3045,7 +3029,7 @@ otLwfTunIoCtl_otNetworkIdTimeout(
|
||||
if (InBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -3058,7 +3042,7 @@ otLwfTunIoCtl_otNetworkIdTimeout(
|
||||
else if (OutBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otNetworkIdTimeout_Handler,
|
||||
@@ -3144,7 +3128,7 @@ otLwfTunIoCtl_otRouterUpgradeThreshold(
|
||||
if (InBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -3157,7 +3141,7 @@ otLwfTunIoCtl_otRouterUpgradeThreshold(
|
||||
else if (OutBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otRouterUpgradeThreshold_Handler,
|
||||
@@ -3243,7 +3227,7 @@ otLwfTunIoCtl_otRouterDowngradeThreshold(
|
||||
if (InBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -3256,7 +3240,7 @@ otLwfTunIoCtl_otRouterDowngradeThreshold(
|
||||
else if (OutBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otRouterDowngradeThreshold_Handler,
|
||||
@@ -3335,7 +3319,7 @@ otLwfTunIoCtl_otReleaseRouterId(
|
||||
if (InBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -3407,7 +3391,7 @@ otLwfTunIoCtl_otMacWhitelistEnabled(
|
||||
if (InBufferLength >= sizeof(BOOLEAN))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -3420,7 +3404,7 @@ otLwfTunIoCtl_otMacWhitelistEnabled(
|
||||
else if (OutBufferLength >= sizeof(BOOLEAN))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otMacWhitelistEnabled_Handler,
|
||||
@@ -3512,7 +3496,7 @@ otLwfTunIoCtl_otAddMacWhitelist(
|
||||
}
|
||||
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -3571,7 +3555,7 @@ otLwfTunIoCtl_otRemoveMacWhitelist(
|
||||
if (InBufferLength >= sizeof(otExtAddress))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -3660,7 +3644,7 @@ otLwfTunIoCtl_otClearMacWhitelist(
|
||||
UNREFERENCED_PARAMETER(OutBufferLength);
|
||||
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -3768,7 +3752,7 @@ otLwfTunIoCtl_otDeviceRole(
|
||||
}
|
||||
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -3781,7 +3765,7 @@ otLwfTunIoCtl_otDeviceRole(
|
||||
else if (OutBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otDeviceRole_Handler,
|
||||
@@ -4014,7 +3998,7 @@ otLwfTunIoCtl_otLeaderRouterId(
|
||||
if (OutBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otLeaderRouterId_Handler,
|
||||
@@ -4100,7 +4084,7 @@ otLwfTunIoCtl_otLeaderWeight(
|
||||
if (OutBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otLeaderWeight_Handler,
|
||||
@@ -4186,7 +4170,7 @@ otLwfTunIoCtl_otNetworkDataVersion(
|
||||
if (OutBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otNetworkDataVersion_Handler,
|
||||
@@ -4272,7 +4256,7 @@ otLwfTunIoCtl_otPartitionId(
|
||||
if (OutBufferLength >= sizeof(uint32_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otPartitionId_Handler,
|
||||
@@ -4358,7 +4342,7 @@ otLwfTunIoCtl_otRloc16(
|
||||
if (OutBufferLength >= sizeof(uint16_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otRloc16_Handler,
|
||||
@@ -4508,7 +4492,7 @@ otLwfTunIoCtl_otStableNetworkDataVersion(
|
||||
if (OutBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otStableNetworkDataVersion_Handler,
|
||||
@@ -4945,7 +4929,7 @@ otLwfTunIoCtl_otPlatformReset(
|
||||
UNREFERENCED_PARAMETER(OutBufferLength);
|
||||
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -5007,7 +4991,7 @@ otLwfTunIoCtl_otParentInfo(
|
||||
if (OutBufferLength >= sizeof(otRouterInfo))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otParentInfo_Handler,
|
||||
@@ -5157,7 +5141,7 @@ otLwfTunIoCtl_otMaxChildren(
|
||||
if (InBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -5170,7 +5154,7 @@ otLwfTunIoCtl_otMaxChildren(
|
||||
else if (OutBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otMaxChildren_Handler,
|
||||
@@ -5439,7 +5423,7 @@ otLwfTunIoCtl_otRouterSelectionJitter(
|
||||
if (InBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -5452,7 +5436,7 @@ otLwfTunIoCtl_otRouterSelectionJitter(
|
||||
else if (OutBufferLength >= sizeof(uint8_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otRouterSelectionJitter_Handler,
|
||||
@@ -6020,7 +6004,7 @@ otLwfTunIoCtl_otKeySwitchGuardtime(
|
||||
if (InBufferLength >= sizeof(uint32_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
NULL,
|
||||
@@ -6033,7 +6017,7 @@ otLwfTunIoCtl_otKeySwitchGuardtime(
|
||||
else if (OutBufferLength >= sizeof(uint32_t))
|
||||
{
|
||||
status =
|
||||
otLwfSendTunnelCommandForIrp(
|
||||
otLwfTunSendCommandForIrp(
|
||||
pFilter,
|
||||
pIrp,
|
||||
otLwfTunIoCtl_otKeySwitchGuardtime_Handler,
|
||||
|
||||
@@ -78,8 +78,6 @@ RtlCopyBufferToMdl(
|
||||
#include <ncp/spinel.h>
|
||||
|
||||
#include <otLwfIoctl.h>
|
||||
#include <otOID.h>
|
||||
#include <otNBLContext.h>
|
||||
|
||||
#ifdef _KERNEL_MODE
|
||||
#define CODE_SEG(segment) __declspec(code_seg(segment))
|
||||
@@ -109,7 +107,7 @@ typedef struct UDPHeader
|
||||
|
||||
//#define DEBUG_TIMING
|
||||
//#define DEBUG_ALLOC
|
||||
//#define LOG_BUFFERS
|
||||
#define LOG_BUFFERS
|
||||
//#define FORCE_SYNCHRONOUS_RECEIVE
|
||||
|
||||
#include "driver.h"
|
||||
@@ -118,5 +116,6 @@ typedef struct UDPHeader
|
||||
#include "oid.h"
|
||||
#include "radio.h"
|
||||
#include "filter.h"
|
||||
#include "command.h"
|
||||
#include "thread.h"
|
||||
#include "tunnel.h"
|
||||
|
||||
@@ -39,7 +39,6 @@ void
|
||||
LogMac(
|
||||
_In_ PCSTR szDir,
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ PNET_BUFFER_LIST NetBufferList,
|
||||
ULONG frameLength,
|
||||
_In_reads_bytes_(frameLength) PUCHAR frame
|
||||
);
|
||||
@@ -47,8 +46,8 @@ LogMac(
|
||||
const char MacSend[] = "MAC_SEND";
|
||||
const char MacRecv[] = "MAC_RECV";
|
||||
|
||||
#define LogMacSend(pFilter, NBL, frameLength, frame) LogMac(MacSend, pFilter, NBL, frameLength, frame)
|
||||
#define LogMacRecv(pFilter, NBL, frameLength, frame) LogMac(MacRecv, pFilter, NBL, frameLength, frame)
|
||||
#define LogMacSend(pFilter, frameLength, frame) LogMac(MacSend, pFilter, frameLength, frame)
|
||||
#define LogMacRecv(pFilter, frameLength, frame) LogMac(MacRecv, pFilter, frameLength, frame)
|
||||
|
||||
void
|
||||
otPlatReset(
|
||||
@@ -56,8 +55,27 @@ otPlatReset(
|
||||
)
|
||||
{
|
||||
NT_ASSERT(otCtx);
|
||||
// This function does nothing currently.
|
||||
UNREFERENCED_PARAMETER(otCtx);
|
||||
PMS_FILTER pFilter = otCtxToFilter(otCtx);
|
||||
NTSTATUS status;
|
||||
|
||||
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! resetting...", &pFilter->InterfaceGuid);
|
||||
|
||||
// Indicate to the miniport
|
||||
status =
|
||||
otLwfCmdSendAsync(
|
||||
pFilter,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
SPINEL_CMD_RESET,
|
||||
0,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Send SPINEL_CMD_RESET failed, %!STATUS!", status);
|
||||
}
|
||||
}
|
||||
|
||||
otPlatResetReason
|
||||
@@ -66,56 +84,38 @@ otPlatGetResetReason(
|
||||
)
|
||||
{
|
||||
NT_ASSERT(otCtx);
|
||||
UNREFERENCED_PARAMETER(otCtx);
|
||||
UNREFERENCED_PARAMETER(otCtx); // TODO - Cache from last status for RESET
|
||||
return kPlatResetReason_PowerOn;
|
||||
}
|
||||
|
||||
VOID
|
||||
otLwfRadioSendPacket(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ RadioPacket* Packet
|
||||
);
|
||||
|
||||
VOID
|
||||
otLwfRadioGetFactoryAddress(
|
||||
_In_ PMS_FILTER pFilter
|
||||
)
|
||||
{
|
||||
NDIS_STATUS status;
|
||||
ULONG bytesProcessed;
|
||||
OT_FACTORY_EXTENDED_ADDRESS OidBuffer = { {0} };
|
||||
NTSTATUS status;
|
||||
uint8_t *hwAddress = NULL;
|
||||
|
||||
RtlZeroMemory(&pFilter->otFactoryAddress, sizeof(pFilter->otFactoryAddress));
|
||||
|
||||
// Query the MP for the address
|
||||
status =
|
||||
otLwfSendInternalRequest(
|
||||
status =
|
||||
otLwfCmdGetProp(
|
||||
pFilter,
|
||||
NdisRequestQueryInformation,
|
||||
OID_OT_FACTORY_EXTENDED_ADDRESS,
|
||||
&OidBuffer,
|
||||
sizeof(OT_FACTORY_EXTENDED_ADDRESS),
|
||||
&bytesProcessed
|
||||
);
|
||||
if (status != NDIS_STATUS_SUCCESS)
|
||||
NULL,
|
||||
SPINEL_PROP_HWADDR,
|
||||
SPINEL_DATATYPE_EUI64_S,
|
||||
&hwAddress
|
||||
);
|
||||
if (!NT_SUCCESS(status) || hwAddress == NULL)
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Query for OID_FACTORY_EXTENDED_ADDRESS failed, %!NDIS_STATUS!", status);
|
||||
LogError(DRIVER_DEFAULT, "Get SPINEL_PROP_HWADDR failed, %!STATUS!", status);
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate the return header
|
||||
if (bytesProcessed != SIZEOF_OT_FACTORY_EXTENDED_ADDRESS_REVISION_1 ||
|
||||
OidBuffer.Header.Type != NDIS_OBJECT_TYPE_DEFAULT ||
|
||||
OidBuffer.Header.Revision != OT_FACTORY_EXTENDED_ADDRESS_REVISION_1 ||
|
||||
OidBuffer.Header.Size != SIZEOF_OT_FACTORY_EXTENDED_ADDRESS_REVISION_1)
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Query for OID_OT_FACTORY_EXTENDED_ADDRESS returned invalid data");
|
||||
return;
|
||||
}
|
||||
memcpy(&pFilter->otFactoryAddress, hwAddress, sizeof(pFilter->otFactoryAddress));
|
||||
|
||||
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! cached factory Extended Mac Address: %llX", &pFilter->InterfaceGuid, OidBuffer.ExtendedAddress);
|
||||
|
||||
pFilter->otFactoryAddress = OidBuffer.ExtendedAddress;
|
||||
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! cached factory Extended Mac Address: %llX", &pFilter->InterfaceGuid, pFilter->otFactoryAddress);
|
||||
}
|
||||
|
||||
VOID
|
||||
@@ -125,14 +125,17 @@ otLwfRadioInit(
|
||||
{
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
NT_ASSERT(pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO);
|
||||
NT_ASSERT(pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_RADIO_MODE);
|
||||
//NT_ASSERT((pFilter->DeviceCapabilities & OTLWF_DEVICE_CAP_RADIO_SLEEP) != 0);
|
||||
|
||||
// Initialize the OpenThread radio capability flags
|
||||
pFilter->otRadioCapabilities = kRadioCapsEnergyScan;
|
||||
if ((pFilter->MiniportCapabilities.RadioCapabilities & OT_RADIO_CAP_ACK_TIMEOUT) != 0)
|
||||
pFilter->otRadioCapabilities = 0;
|
||||
if ((pFilter->DeviceCapabilities & OTLWF_DEVICE_CAP_RADIO_ACK_TIMEOUT) != 0)
|
||||
pFilter->otRadioCapabilities |= kRadioCapsAckTimeout;
|
||||
if ((pFilter->MiniportCapabilities.RadioCapabilities & OT_RADIO_CAP_MAC_RETRY_AND_COLLISION_AVOIDANCE) != 0)
|
||||
if ((pFilter->DeviceCapabilities & OTLWF_DEVICE_CAP_RADIO_MAC_RETRY_AND_COLLISION_AVOIDANCE) != 0)
|
||||
pFilter->otRadioCapabilities |= kRadioCapsTransmitRetries;
|
||||
if ((pFilter->DeviceCapabilities & OTLWF_DEVICE_CAP_RADIO_ENERGY_SCAN) != 0)
|
||||
pFilter->otRadioCapabilities |= kRadioCapsEnergyScan;
|
||||
|
||||
pFilter->otPhyState = kStateDisabled;
|
||||
pFilter->otCurrentListenChannel = 0xFF;
|
||||
@@ -164,27 +167,23 @@ void otPlatRadioSetPanId(_In_ otInstance *otCtx, uint16_t panid)
|
||||
{
|
||||
NT_ASSERT(otCtx);
|
||||
PMS_FILTER pFilter = otCtxToFilter(otCtx);
|
||||
NDIS_STATUS status;
|
||||
ULONG bytesProcessed;
|
||||
OT_PAND_ID OidBuffer = { {NDIS_OBJECT_TYPE_DEFAULT, OT_PAND_ID_REVISION_1, SIZEOF_OT_PAND_ID_REVISION_1}, panid };
|
||||
NTSTATUS status;
|
||||
|
||||
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! set PanID: %X", &pFilter->InterfaceGuid, panid);
|
||||
|
||||
pFilter->otPanID = panid;
|
||||
|
||||
// Indicate to the miniport
|
||||
status =
|
||||
otLwfSendInternalRequest(
|
||||
status =
|
||||
otLwfCmdSetProp(
|
||||
pFilter,
|
||||
NdisRequestSetInformation,
|
||||
OID_OT_PAND_ID,
|
||||
&OidBuffer,
|
||||
sizeof(OidBuffer),
|
||||
&bytesProcessed
|
||||
);
|
||||
if (status != NDIS_STATUS_SUCCESS)
|
||||
SPINEL_PROP_MAC_15_4_PANID,
|
||||
SPINEL_DATATYPE_UINT16_S,
|
||||
panid
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Set for OID_OT_PAND_ID failed, %!NDIS_STATUS!", status);
|
||||
LogError(DRIVER_DEFAULT, "Set SPINEL_PROP_MAC_15_4_PANID failed, %!STATUS!", status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,28 +191,29 @@ void otPlatRadioSetExtendedAddress(_In_ otInstance *otCtx, uint8_t *address)
|
||||
{
|
||||
NT_ASSERT(otCtx);
|
||||
PMS_FILTER pFilter = otCtxToFilter(otCtx);
|
||||
NDIS_STATUS status;
|
||||
ULONG bytesProcessed;
|
||||
OT_EXTENDED_ADDRESS OidBuffer = { {NDIS_OBJECT_TYPE_DEFAULT, OT_EXTENDED_ADDRESS_REVISION_1, SIZEOF_OT_EXTENDED_ADDRESS_REVISION_1} };
|
||||
NTSTATUS status;
|
||||
spinel_eui64_t extAddr;
|
||||
|
||||
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! set Extended Mac Address: %llX", &pFilter->InterfaceGuid, *(ULONGLONG*)address);
|
||||
|
||||
pFilter->otExtendedAddress = *(ULONGLONG*)address;
|
||||
OidBuffer.ExtendedAddress = *(ULONGLONG*)address;
|
||||
|
||||
for (size_t i = 0; i < OT_EXT_ADDRESS_SIZE; i++)
|
||||
{
|
||||
extAddr.bytes[i] = address[7 - i];
|
||||
}
|
||||
|
||||
// Indicate to the miniport
|
||||
status =
|
||||
otLwfSendInternalRequest(
|
||||
status =
|
||||
otLwfCmdSetProp(
|
||||
pFilter,
|
||||
NdisRequestSetInformation,
|
||||
OID_OT_EXTENDED_ADDRESS,
|
||||
&OidBuffer,
|
||||
sizeof(OidBuffer),
|
||||
&bytesProcessed
|
||||
);
|
||||
if (status != NDIS_STATUS_SUCCESS)
|
||||
SPINEL_PROP_MAC_15_4_LADDR,
|
||||
SPINEL_DATATYPE_EUI64_S,
|
||||
&extAddr
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Set for OID_OT_EXTENDED_ADDRESS failed, %!NDIS_STATUS!", status);
|
||||
LogError(DRIVER_DEFAULT, "Set SPINEL_PROP_MAC_15_4_LADDR failed, %!STATUS!", status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,27 +221,23 @@ void otPlatRadioSetShortAddress(_In_ otInstance *otCtx, uint16_t address)
|
||||
{
|
||||
NT_ASSERT(otCtx);
|
||||
PMS_FILTER pFilter = otCtxToFilter(otCtx);
|
||||
NDIS_STATUS status;
|
||||
ULONG bytesProcessed;
|
||||
OT_SHORT_ADDRESS OidBuffer = { {NDIS_OBJECT_TYPE_DEFAULT, OT_SHORT_ADDRESS_REVISION_1, SIZEOF_OT_SHORT_ADDRESS_REVISION_1}, address };
|
||||
NTSTATUS status;
|
||||
|
||||
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! set Short Mac Address: %X", &pFilter->InterfaceGuid, address);
|
||||
|
||||
pFilter->otShortAddress = address;
|
||||
|
||||
// Indicate to the miniport
|
||||
status =
|
||||
otLwfSendInternalRequest(
|
||||
status =
|
||||
otLwfCmdSetProp(
|
||||
pFilter,
|
||||
NdisRequestSetInformation,
|
||||
OID_OT_SHORT_ADDRESS,
|
||||
&OidBuffer,
|
||||
sizeof(OidBuffer),
|
||||
&bytesProcessed
|
||||
);
|
||||
if (status != NDIS_STATUS_SUCCESS)
|
||||
SPINEL_PROP_MAC_15_4_SADDR,
|
||||
SPINEL_DATATYPE_UINT16_S,
|
||||
address
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Set for OID_OT_SHORT_ADDRESS failed, %!NDIS_STATUS!", status);
|
||||
LogError(DRIVER_DEFAULT, "Set SPINEL_PROP_MAC_15_4_SADDR failed, %!STATUS!", status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,25 +245,21 @@ void otPlatRadioSetPromiscuous(_In_ otInstance *otCtx, bool aEnable)
|
||||
{
|
||||
NT_ASSERT(otCtx);
|
||||
PMS_FILTER pFilter = otCtxToFilter(otCtx);
|
||||
NDIS_STATUS status;
|
||||
ULONG bytesProcessed;
|
||||
OT_PROMISCUOUS_MODE OidBuffer = { {NDIS_OBJECT_TYPE_DEFAULT, OT_PROMISCUOUS_MODE_REVISION_1, SIZEOF_OT_PROMISCUOUS_MODE_REVISION_1}, (BOOLEAN)aEnable };
|
||||
NTSTATUS status;
|
||||
|
||||
pFilter->otPromiscuous = (BOOLEAN)aEnable;
|
||||
|
||||
// Indicate to the miniport
|
||||
status =
|
||||
otLwfSendInternalRequest(
|
||||
status =
|
||||
otLwfCmdSetProp(
|
||||
pFilter,
|
||||
NdisRequestSetInformation,
|
||||
OID_OT_PROMISCUOUS_MODE,
|
||||
&OidBuffer,
|
||||
sizeof(OidBuffer),
|
||||
&bytesProcessed
|
||||
);
|
||||
if (status != NDIS_STATUS_SUCCESS)
|
||||
SPINEL_PROP_MAC_PROMISCUOUS_MODE,
|
||||
SPINEL_DATATYPE_UINT8_S,
|
||||
aEnable != 0 ? SPINEL_MAC_PROMISCUOUS_MODE_NETWORK : SPINEL_MAC_PROMISCUOUS_MODE_OFF
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Set for OID_OT_PROMISCUOUS_MODE failed, %!NDIS_STATUS!", status);
|
||||
LogError(DRIVER_DEFAULT, "Set SPINEL_PROP_MAC_PROMISCUOUS_MODE failed, %!STATUS!", status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,56 +267,90 @@ bool otPlatRadioIsEnabled(_In_ otInstance *otCtx)
|
||||
{
|
||||
NT_ASSERT(otCtx);
|
||||
PMS_FILTER pFilter = otCtxToFilter(otCtx);
|
||||
return pFilter->otPhyState != kStateSleep;
|
||||
return pFilter->otPhyState != kStateDisabled;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioEnable(_In_ otInstance *otCtx)
|
||||
{
|
||||
NT_ASSERT(otCtx);
|
||||
PMS_FILTER pFilter = otCtxToFilter(otCtx);
|
||||
|
||||
NTSTATUS status;
|
||||
|
||||
NT_ASSERT(pFilter->otPhyState <= kStateSleep);
|
||||
if (pFilter->otPhyState > kStateSleep) return kThreadError_Busy;
|
||||
|
||||
pFilter->otPhyState = kStateSleep;
|
||||
|
||||
|
||||
// Indicate to the miniport
|
||||
status =
|
||||
otLwfCmdSetProp(
|
||||
pFilter,
|
||||
SPINEL_PROP_PHY_ENABLED,
|
||||
SPINEL_DATATYPE_BOOL_S,
|
||||
TRUE
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Set SPINEL_PROP_PHY_ENABLED (true) failed, %!STATUS!", status);
|
||||
}
|
||||
|
||||
LogInfo(DRIVER_DEFAULT, "Filter %p PhyState = kStateSleep.", pFilter);
|
||||
|
||||
return kThreadError_None;
|
||||
return NT_SUCCESS(status) ? kThreadError_None : kThreadError_Failed;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioDisable(_In_ otInstance *otCtx)
|
||||
{
|
||||
NT_ASSERT(otCtx);
|
||||
PMS_FILTER pFilter = otCtxToFilter(otCtx);
|
||||
|
||||
NT_ASSERT(pFilter->otPhyState <= kStateSleep);
|
||||
if (pFilter->otPhyState > kStateSleep) return kThreadError_Busy;
|
||||
NTSTATUS status;
|
||||
|
||||
// First make sure we are in the Sleep state if we weren't already
|
||||
if (pFilter->otPhyState > kStateSleep)
|
||||
{
|
||||
(void)otPlatRadioSleep(otCtx);
|
||||
}
|
||||
|
||||
pFilter->otPhyState = kStateDisabled;
|
||||
|
||||
|
||||
// Indicate to the miniport
|
||||
status =
|
||||
otLwfCmdSetProp(
|
||||
pFilter,
|
||||
SPINEL_PROP_PHY_ENABLED,
|
||||
SPINEL_DATATYPE_BOOL_S,
|
||||
FALSE
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Set SPINEL_PROP_PHY_ENABLED (false) failed, %!STATUS!", status);
|
||||
}
|
||||
|
||||
LogInfo(DRIVER_DEFAULT, "Filter %p PhyState = kStateDisabled.", pFilter);
|
||||
|
||||
return kThreadError_None;
|
||||
return NT_SUCCESS(status) ? kThreadError_None : kThreadError_Failed;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioSleep(_In_ otInstance *otCtx)
|
||||
{
|
||||
NT_ASSERT(otCtx);
|
||||
PMS_FILTER pFilter = otCtxToFilter(otCtx);
|
||||
|
||||
NT_ASSERT(pFilter->otPhyState != kStateDisabled);
|
||||
//NT_ASSERT(pFilter->otPhyState == kStateSleep || pFilter->otPhyState == kStateReceive);
|
||||
if (pFilter->otPhyState != kStateSleep && pFilter->otPhyState != kStateReceive)
|
||||
return kThreadError_Busy;
|
||||
|
||||
// If we were in the transmit state, cancel the transmit
|
||||
if (pFilter->otPhyState == kStateTransmit)
|
||||
{
|
||||
pFilter->otLastTransmitError = kThreadError_Abort;
|
||||
otLwfRadioTransmitFrameDone(pFilter);
|
||||
}
|
||||
|
||||
if (pFilter->otPhyState != kStateSleep)
|
||||
{
|
||||
pFilter->otPhyState = kStateSleep;
|
||||
LogInfo(DRIVER_DEFAULT, "Filter %p PhyState = kStateSleep.", pFilter);
|
||||
|
||||
if ((pFilter->MiniportCapabilities.RadioCapabilities & OT_RADIO_CAP_SLEEP) != 0)
|
||||
|
||||
if ((pFilter->DeviceCapabilities & OTLWF_DEVICE_CAP_RADIO_SLEEP) != 0)
|
||||
{
|
||||
/* TODO
|
||||
NDIS_STATUS status;
|
||||
ULONG bytesProcessed;
|
||||
OT_SLEEP_MODE OidBuffer = { {NDIS_OBJECT_TYPE_DEFAULT, OT_SLEEP_MODE_REVISION_1, SIZEOF_OT_SLEEP_MODE_REVISION_1}, TRUE };
|
||||
@@ -342,7 +368,20 @@ ThreadError otPlatRadioSleep(_In_ otInstance *otCtx)
|
||||
if (status != NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Set for OID_OT_SLEEP_MODE failed, %!NDIS_STATUS!", status);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
// Indicate to the miniport
|
||||
NTSTATUS status =
|
||||
otLwfCmdSetProp(
|
||||
pFilter,
|
||||
SPINEL_PROP_MAC_RAW_STREAM_ENABLED,
|
||||
SPINEL_DATATYPE_BOOL_S,
|
||||
FALSE
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Set SPINEL_PROP_MAC_RAW_STREAM_ENABLED (false) failed, %!STATUS!", status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,9 +401,10 @@ ThreadError otPlatRadioReceive(_In_ otInstance *otCtx, uint8_t aChannel)
|
||||
// If we are currently in the sleep state and the minport supports sleep
|
||||
// mode, come out of sleep mode now.
|
||||
if (pFilter->otPhyState == kStateSleep)
|
||||
{
|
||||
if ((pFilter->MiniportCapabilities.RadioCapabilities & OT_RADIO_CAP_SLEEP) != 0)
|
||||
{
|
||||
if ((pFilter->DeviceCapabilities & OTLWF_DEVICE_CAP_RADIO_SLEEP) != 0)
|
||||
{
|
||||
/* TODO
|
||||
NDIS_STATUS status;
|
||||
ULONG bytesProcessed;
|
||||
OT_SLEEP_MODE OidBuffer = { {NDIS_OBJECT_TYPE_DEFAULT, OT_SLEEP_MODE_REVISION_1, SIZEOF_OT_SLEEP_MODE_REVISION_1}, FALSE };
|
||||
@@ -382,35 +422,31 @@ ThreadError otPlatRadioReceive(_In_ otInstance *otCtx, uint8_t aChannel)
|
||||
if (status != NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Set for OID_OT_SLEEP_MODE failed, %!NDIS_STATUS!", status);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
// Update current channel if different
|
||||
if (pFilter->otCurrentListenChannel != aChannel)
|
||||
{
|
||||
NDIS_STATUS status;
|
||||
ULONG bytesProcessed;
|
||||
OT_CURRENT_CHANNEL OidBuffer = { {NDIS_OBJECT_TYPE_DEFAULT, OT_CURRENT_CHANNEL_REVISION_1, SIZEOF_OT_CURRENT_CHANNEL_REVISION_1}, aChannel };
|
||||
|
||||
NTSTATUS status;
|
||||
|
||||
NT_ASSERT(aChannel >= 11 && aChannel <= 26);
|
||||
|
||||
LogInfo(DRIVER_DEFAULT, "Filter %p new Listen Channel = %u.", pFilter, aChannel);
|
||||
pFilter->otCurrentListenChannel = aChannel;
|
||||
|
||||
|
||||
// Indicate to the miniport
|
||||
status =
|
||||
otLwfSendInternalRequest(
|
||||
status =
|
||||
otLwfCmdSetProp(
|
||||
pFilter,
|
||||
NdisRequestSetInformation,
|
||||
OID_OT_CURRENT_CHANNEL,
|
||||
&OidBuffer,
|
||||
sizeof(OidBuffer),
|
||||
&bytesProcessed
|
||||
);
|
||||
if (status != NDIS_STATUS_SUCCESS)
|
||||
SPINEL_PROP_PHY_CHAN,
|
||||
SPINEL_DATATYPE_UINT8_S,
|
||||
aChannel
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Set for OID_OT_CURRENT_CHANNEL failed, %!NDIS_STATUS!", status);
|
||||
LogError(DRIVER_DEFAULT, "Set SPINEL_PROP_PHY_CHAN failed, %!STATUS!", status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,7 +456,19 @@ ThreadError otPlatRadioReceive(_In_ otInstance *otCtx, uint8_t aChannel)
|
||||
{
|
||||
pFilter->otPhyState = kStateReceive;
|
||||
LogInfo(DRIVER_DEFAULT, "Filter %p PhyState = kStateReceive.", pFilter);
|
||||
|
||||
|
||||
NTSTATUS status =
|
||||
otLwfCmdSetProp(
|
||||
pFilter,
|
||||
SPINEL_PROP_MAC_RAW_STREAM_ENABLED,
|
||||
SPINEL_DATATYPE_BOOL_S,
|
||||
TRUE
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Set SPINEL_PROP_MAC_RAW_STREAM_ENABLED (true) failed, %!STATUS!", status);
|
||||
}
|
||||
|
||||
// Set the event to indicate we can process NBLs
|
||||
KeSetEvent(&pFilter->EventWorkerThreadProcessNBLs, 0, FALSE);
|
||||
}
|
||||
@@ -461,19 +509,18 @@ bool otPlatRadioGetPromiscuous(_In_ otInstance *otCtx)
|
||||
VOID
|
||||
otLwfRadioReceiveFrame(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ PNET_BUFFER_LIST NetBufferList
|
||||
_In_ ThreadError errorCode
|
||||
)
|
||||
{
|
||||
NT_ASSERT(pFilter->otReceiveFrame.mChannel >= 11 && pFilter->otReceiveFrame.mChannel <= 26);
|
||||
|
||||
LogFuncEntryMsg(DRIVER_DATA_PATH, "Filter: %p", pFilter);
|
||||
|
||||
LogMacRecv(pFilter, NetBufferList, pFilter->otReceiveFrame.mLength, pFilter->otReceiveFrame.mPsdu);
|
||||
LogMacRecv(pFilter, pFilter->otReceiveFrame.mLength, pFilter->otReceiveFrame.mPsdu);
|
||||
|
||||
NT_ASSERT(pFilter->otPhyState > kStateDisabled);
|
||||
if (pFilter->otPhyState > kStateDisabled)
|
||||
{
|
||||
otPlatRadioReceiveDone(pFilter->otCtx, &pFilter->otReceiveFrame, kThreadError_None);
|
||||
otPlatRadioReceiveDone(pFilter->otCtx, &pFilter->otReceiveFrame, errorCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -511,59 +558,15 @@ VOID otLwfRadioTransmitFrame(_In_ PMS_FILTER pFilter)
|
||||
{
|
||||
NT_ASSERT(pFilter->otPhyState == kStateTransmit);
|
||||
|
||||
LogMacSend(pFilter, pFilter->otTransmitFrame.mLength, pFilter->otTransmitFrame.mPsdu);
|
||||
|
||||
LogFuncEntryMsg(DRIVER_DATA_PATH, "Filter: %p", pFilter);
|
||||
|
||||
otLwfRadioSendPacket(pFilter, &pFilter->otTransmitFrame);
|
||||
otLwfCmdSendMacFrameAsync(pFilter, &pFilter->otTransmitFrame);
|
||||
|
||||
LogFuncExit(DRIVER_DATA_PATH);
|
||||
}
|
||||
|
||||
VOID
|
||||
otLwfRadioSendPacket(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ RadioPacket* Packet
|
||||
)
|
||||
{
|
||||
SIZE_T BytesCopied = 0;
|
||||
PNET_BUFFER SendNetBuffer = NET_BUFFER_LIST_FIRST_NB(pFilter->SendNetBufferList);
|
||||
OT_NBL_CONTEXT NblContext = { 0 /* Flags */, Packet->mChannel, Packet->mPower, 0 /* Lqi */ };
|
||||
|
||||
NT_ASSERT(NblContext.Channel >= 11 && NblContext.Channel <= 26);
|
||||
NT_ASSERT(!pFilter->SendPending);
|
||||
|
||||
NT_ASSERT(Packet->mLength <= kMaxPHYPacketSize);
|
||||
|
||||
LogMacSend(pFilter, pFilter->SendNetBufferList, Packet->mLength, Packet->mPsdu);
|
||||
|
||||
// Copy to the NetBufferList
|
||||
RtlCopyBufferToMdl(
|
||||
Packet->mPsdu,
|
||||
SendNetBuffer->CurrentMdl,
|
||||
SendNetBuffer->CurrentMdlOffset,
|
||||
Packet->mLength,
|
||||
&BytesCopied
|
||||
);
|
||||
NT_ASSERT(BytesCopied == Packet->mLength);
|
||||
|
||||
// Set the length field
|
||||
NET_BUFFER_DATA_LENGTH(SendNetBuffer) = Packet->mLength;
|
||||
|
||||
// Set the context
|
||||
SetNBLContext(pFilter->SendNetBufferList, &NblContext);
|
||||
|
||||
// Reset the completion event
|
||||
KeResetEvent(&pFilter->SendNetBufferListComplete);
|
||||
pFilter->SendPending = TRUE;
|
||||
|
||||
// Send the NetBufferList
|
||||
NdisFSendNetBufferLists(
|
||||
pFilter->FilterHandle,
|
||||
pFilter->SendNetBufferList,
|
||||
NDIS_DEFAULT_PORT_NUMBER,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
VOID
|
||||
otLwfRadioTransmitFrameDone(
|
||||
_In_ PMS_FILTER pFilter
|
||||
@@ -571,33 +574,23 @@ otLwfRadioTransmitFrameDone(
|
||||
{
|
||||
LogFuncEntryMsg(DRIVER_DATA_PATH, "Filter: %p", pFilter);
|
||||
|
||||
pFilter->SendPending = FALSE;
|
||||
|
||||
NT_ASSERT(pFilter->otPhyState == kStateTransmit);
|
||||
if (pFilter->otPhyState == kStateTransmit)
|
||||
{
|
||||
pFilter->SendPending = FALSE;
|
||||
|
||||
// Now that we are completing a send, fall back to receive state and set the event
|
||||
pFilter->otPhyState = kStateReceive;
|
||||
LogInfo(DRIVER_DEFAULT, "Filter %p PhyState = kStateReceive.", pFilter);
|
||||
KeSetEvent(&pFilter->EventWorkerThreadProcessNBLs, 0, FALSE);
|
||||
// Now that we are completing a send, fall back to receive state and set the event
|
||||
pFilter->otPhyState = kStateReceive;
|
||||
LogInfo(DRIVER_DEFAULT, "Filter %p PhyState = kStateReceive.", pFilter);
|
||||
KeSetEvent(&pFilter->EventWorkerThreadProcessNBLs, 0, FALSE);
|
||||
|
||||
if (STATUS_SUCCESS == pFilter->SendNetBufferList->Status)
|
||||
{
|
||||
POT_NBL_CONTEXT SendNblContext = GetNBLContext(pFilter->SendNetBufferList);
|
||||
BOOLEAN FramePending = (SendNblContext->Flags & OT_NBL_FLAG_ACK_FRAME_PENDING) != 0 || pFilter->CountPendingRecvNBLs != 0;
|
||||
if (pFilter->otLastTransmitError != kThreadError_None &&
|
||||
pFilter->otLastTransmitError != kThreadError_ChannelAccessFailure &&
|
||||
pFilter->otLastTransmitError != kThreadError_NoAck)
|
||||
{
|
||||
pFilter->otLastTransmitError = kThreadError_Abort;
|
||||
}
|
||||
|
||||
otPlatRadioTransmitDone(pFilter->otCtx, &pFilter->otTransmitFrame, FramePending, kThreadError_None);
|
||||
}
|
||||
else if (STATUS_DEVICE_BUSY == pFilter->SendNetBufferList->Status)
|
||||
{
|
||||
otPlatRadioTransmitDone(pFilter->otCtx, &pFilter->otTransmitFrame, false, kThreadError_ChannelAccessFailure);
|
||||
}
|
||||
else if (STATUS_TIMEOUT == pFilter->SendNetBufferList->Status)
|
||||
{
|
||||
otPlatRadioTransmitDone(pFilter->otCtx, &pFilter->otTransmitFrame, false, kThreadError_NoAck);
|
||||
}
|
||||
else
|
||||
{
|
||||
otPlatRadioTransmitDone(pFilter->otCtx, &pFilter->otTransmitFrame, false, kThreadError_Abort);
|
||||
otPlatRadioTransmitDone(pFilter->otCtx, &pFilter->otTransmitFrame, pFilter->otLastTransmitFramePending, pFilter->otLastTransmitError);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DATA_PATH);
|
||||
@@ -608,7 +601,10 @@ otPlatRadioSendPendingMacOffload(
|
||||
_In_ PMS_FILTER pFilter
|
||||
)
|
||||
{
|
||||
NDIS_STATUS status;
|
||||
// TODO
|
||||
UNREFERENCED_PARAMETER(pFilter);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
/*NDIS_STATUS status;
|
||||
ULONG bytesProcessed;
|
||||
UCHAR ShortAddressCount = pFilter->otPendingMacOffloadEnabled == TRUE ? pFilter->otPendingShortAddressCount : 0;
|
||||
UCHAR ExtendedAddressCount = pFilter->otPendingMacOffloadEnabled == TRUE ? pFilter->otPendingExtendedAddressCount : 0;
|
||||
@@ -655,7 +651,7 @@ otPlatRadioSendPendingMacOffload(
|
||||
|
||||
FILTER_FREE_MEM(OidBuffer);
|
||||
|
||||
return status;
|
||||
return status;*/
|
||||
}
|
||||
|
||||
void otPlatRadioEnableSrcMatch(_In_ otInstance *otCtx, bool aEnable)
|
||||
@@ -675,11 +671,6 @@ ThreadError otPlatRadioAddSrcMatchShortEntry(_In_ otInstance *otCtx, const uint1
|
||||
{
|
||||
NT_ASSERT(otCtx);
|
||||
PMS_FILTER pFilter = otCtxToFilter(otCtx);
|
||||
|
||||
// Make sure we are enabled
|
||||
NT_ASSERT(pFilter->otPendingMacOffloadEnabled);
|
||||
if (pFilter->otPendingMacOffloadEnabled == FALSE)
|
||||
return kThreadError_InvalidState;
|
||||
|
||||
// Check to see if it is in the list
|
||||
BOOLEAN Found = false;
|
||||
@@ -702,8 +693,11 @@ ThreadError otPlatRadioAddSrcMatchShortEntry(_In_ otInstance *otCtx, const uint1
|
||||
pFilter->otPendingShortAddresses[pFilter->otPendingShortAddressCount] = aShortAddress;
|
||||
pFilter->otPendingShortAddressCount++;
|
||||
|
||||
// Update the miniport
|
||||
otPlatRadioSendPendingMacOffload(pFilter);
|
||||
// Update the miniport if enabled
|
||||
if (pFilter->otPendingMacOffloadEnabled)
|
||||
{
|
||||
otPlatRadioSendPendingMacOffload(pFilter);
|
||||
}
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
@@ -712,11 +706,6 @@ ThreadError otPlatRadioAddSrcMatchExtEntry(_In_ otInstance *otCtx, const uint8_t
|
||||
{
|
||||
NT_ASSERT(otCtx);
|
||||
PMS_FILTER pFilter = otCtxToFilter(otCtx);
|
||||
|
||||
// Make sure we are enabled
|
||||
NT_ASSERT(pFilter->otPendingMacOffloadEnabled);
|
||||
if (pFilter->otPendingMacOffloadEnabled == FALSE)
|
||||
return kThreadError_InvalidState;
|
||||
|
||||
// Check to see if it is in the list
|
||||
BOOLEAN Found = false;
|
||||
@@ -739,8 +728,11 @@ ThreadError otPlatRadioAddSrcMatchExtEntry(_In_ otInstance *otCtx, const uint8_t
|
||||
memcpy(&pFilter->otPendingExtendedAddresses[pFilter->otPendingExtendedAddressCount], aExtAddress, sizeof(ULONGLONG));
|
||||
pFilter->otPendingExtendedAddressCount++;
|
||||
|
||||
// Update the miniport
|
||||
otPlatRadioSendPendingMacOffload(pFilter);
|
||||
// Update the miniport if enabled
|
||||
if (pFilter->otPendingMacOffloadEnabled)
|
||||
{
|
||||
otPlatRadioSendPendingMacOffload(pFilter);
|
||||
}
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
@@ -749,11 +741,6 @@ ThreadError otPlatRadioClearSrcMatchShortEntry(_In_ otInstance *otCtx, const uin
|
||||
{
|
||||
NT_ASSERT(otCtx);
|
||||
PMS_FILTER pFilter = otCtxToFilter(otCtx);
|
||||
|
||||
// Make sure we are enabled
|
||||
NT_ASSERT(pFilter->otPendingMacOffloadEnabled);
|
||||
if (pFilter->otPendingMacOffloadEnabled == FALSE)
|
||||
return kThreadError_InvalidState;
|
||||
|
||||
// Check to see if it is in the list
|
||||
BOOLEAN Found = false;
|
||||
@@ -773,8 +760,11 @@ ThreadError otPlatRadioClearSrcMatchShortEntry(_In_ otInstance *otCtx, const uin
|
||||
// Wasn't in the list, return failure
|
||||
if (Found == FALSE) return kThreadError_NotFound;
|
||||
|
||||
// Update the miniport
|
||||
otPlatRadioSendPendingMacOffload(pFilter);
|
||||
// Update the miniport if enabled
|
||||
if (pFilter->otPendingMacOffloadEnabled)
|
||||
{
|
||||
otPlatRadioSendPendingMacOffload(pFilter);
|
||||
}
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
@@ -783,11 +773,6 @@ ThreadError otPlatRadioClearSrcMatchExtEntry(_In_ otInstance *otCtx, const uint8
|
||||
{
|
||||
NT_ASSERT(otCtx);
|
||||
PMS_FILTER pFilter = otCtxToFilter(otCtx);
|
||||
|
||||
// Make sure we are enabled
|
||||
NT_ASSERT(pFilter->otPendingMacOffloadEnabled);
|
||||
if (pFilter->otPendingMacOffloadEnabled == FALSE)
|
||||
return kThreadError_InvalidState;
|
||||
|
||||
// Check to see if it is in the list
|
||||
BOOLEAN Found = false;
|
||||
@@ -807,8 +792,11 @@ ThreadError otPlatRadioClearSrcMatchExtEntry(_In_ otInstance *otCtx, const uint8
|
||||
// Wasn't in the list, return failure
|
||||
if (Found == FALSE) return kThreadError_NotFound;
|
||||
|
||||
// Update the miniport
|
||||
otPlatRadioSendPendingMacOffload(pFilter);
|
||||
// Update the miniport if enabled
|
||||
if (pFilter->otPendingMacOffloadEnabled)
|
||||
{
|
||||
otPlatRadioSendPendingMacOffload(pFilter);
|
||||
}
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
@@ -843,30 +831,48 @@ ThreadError otPlatRadioEnergyScan(_In_ otInstance *otCtx, uint8_t aScanChannel,
|
||||
{
|
||||
NT_ASSERT(otCtx);
|
||||
PMS_FILTER pFilter = otCtxToFilter(otCtx);
|
||||
NDIS_STATUS status;
|
||||
ULONG bytesProcessed;
|
||||
OT_ENERGY_SCAN OidBuffer = { {NDIS_OBJECT_TYPE_DEFAULT, OT_ENERGY_SCAN_REVISION_1, SIZEOF_OT_ENERGY_SCAN_REVISION_1}, aScanChannel, aScanDuration };
|
||||
|
||||
LogInfo(DRIVER_DEFAULT, "Filter %p starting energy scan on channel %d (%d ms).", pFilter, aScanChannel, aScanDuration);
|
||||
|
||||
// Cache the listening channel
|
||||
pFilter->otCurrentListenChannel = aScanChannel;
|
||||
|
||||
// Indicate to the miniport
|
||||
status =
|
||||
otLwfSendInternalRequest(
|
||||
NTSTATUS status =
|
||||
otLwfCmdSetProp(
|
||||
pFilter,
|
||||
NdisRequestSetInformation,
|
||||
OID_OT_ENERGY_SCAN,
|
||||
&OidBuffer,
|
||||
sizeof(OidBuffer),
|
||||
&bytesProcessed
|
||||
);
|
||||
if (status != NDIS_STATUS_SUCCESS)
|
||||
SPINEL_PROP_MAC_SCAN_MASK,
|
||||
SPINEL_DATATYPE_UINT8_S,
|
||||
aScanChannel
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Set for OID_OT_ENERGY_SCAN failed, %!NDIS_STATUS!", status);
|
||||
LogError(DRIVER_DEFAULT, "Set SPINEL_PROP_MAC_SCAN_MASK failed, %!STATUS!", status);
|
||||
goto error;
|
||||
}
|
||||
|
||||
status =
|
||||
otLwfCmdSetProp(
|
||||
pFilter,
|
||||
SPINEL_PROP_MAC_SCAN_PERIOD,
|
||||
SPINEL_DATATYPE_UINT16_S,
|
||||
aScanDuration
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Set SPINEL_PROP_MAC_SCAN_PERIOD failed, %!STATUS!", status);
|
||||
goto error;
|
||||
}
|
||||
|
||||
status =
|
||||
otLwfCmdSetProp(
|
||||
pFilter,
|
||||
SPINEL_PROP_MAC_SCAN_STATE,
|
||||
SPINEL_DATATYPE_UINT8_S,
|
||||
SPINEL_SCAN_STATE_ENERGY
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
LogError(DRIVER_DEFAULT, "Set SPINEL_PROP_MAC_SCAN_STATE failed, %!STATUS!", status);
|
||||
goto error;
|
||||
}
|
||||
|
||||
error:
|
||||
|
||||
return NT_SUCCESS(status) ? kThreadError_None : kThreadError_Failed;
|
||||
}
|
||||
|
||||
@@ -894,7 +900,6 @@ void
|
||||
LogMac(
|
||||
_In_ PCSTR szDir,
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ PNET_BUFFER_LIST NetBufferList,
|
||||
ULONG frameLength,
|
||||
_In_reads_bytes_(frameLength) PUCHAR frame
|
||||
)
|
||||
@@ -909,42 +914,42 @@ LogMac(
|
||||
switch (frame[1] & (IEEE802154_DST_ADDR_MASK | IEEE802154_SRC_ADDR_MASK))
|
||||
{
|
||||
case IEEE802154_DST_ADDR_NONE | IEEE802154_SRC_ADDR_NONE:
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, %s: %p : null => null (%u bytes, AckReq=%u, FramePending=%u)",
|
||||
pFilter, szDir, NetBufferList, frameLength, AckRequested, FramePending);
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, %s: null => null (%u bytes, AckReq=%u, FramePending=%u)",
|
||||
pFilter, szDir, frameLength, AckRequested, FramePending);
|
||||
break;
|
||||
case IEEE802154_DST_ADDR_NONE | IEEE802154_SRC_ADDR_SHORT:
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, %s: %p : %X => null (%u bytes, AckReq=%u, FramePending=%u)",
|
||||
pFilter, szDir, NetBufferList, getSrcShortAddress(frameLength, frame, IEEE802154_DSTADDR_OFFSET), frameLength, AckRequested, FramePending);
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, %s: %X => null (%u bytes, AckReq=%u, FramePending=%u)",
|
||||
pFilter, szDir, getSrcShortAddress(frameLength, frame, IEEE802154_DSTADDR_OFFSET), frameLength, AckRequested, FramePending);
|
||||
break;
|
||||
case IEEE802154_DST_ADDR_NONE | IEEE802154_SRC_ADDR_EXT:
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, %s: %p : %llX => null (%u bytes, AckReq=%u, FramePending=%u)",
|
||||
pFilter, szDir, NetBufferList, getSrcExtAddress(frameLength, frame, IEEE802154_DSTADDR_OFFSET), frameLength, AckRequested, FramePending);
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, %s: %llX => null (%u bytes, AckReq=%u, FramePending=%u)",
|
||||
pFilter, szDir, getSrcExtAddress(frameLength, frame, IEEE802154_DSTADDR_OFFSET), frameLength, AckRequested, FramePending);
|
||||
break;
|
||||
|
||||
case IEEE802154_DST_ADDR_SHORT | IEEE802154_SRC_ADDR_NONE:
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, %s: %p : null => %X (%u bytes, AckReq=%u, FramePending=%u)",
|
||||
pFilter, szDir, NetBufferList, getDstShortAddress(frame), frameLength, AckRequested, FramePending);
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, %s: null => %X (%u bytes, AckReq=%u, FramePending=%u)",
|
||||
pFilter, szDir, getDstShortAddress(frame), frameLength, AckRequested, FramePending);
|
||||
break;
|
||||
case IEEE802154_DST_ADDR_SHORT | IEEE802154_SRC_ADDR_SHORT:
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, %s: %p : %X => %X (%u bytes, AckReq=%u, FramePending=%u)",
|
||||
pFilter, szDir, NetBufferList, getSrcShortAddress(frameLength, frame, IEEE802154_DSTADDR_OFFSET+2), getDstShortAddress(frame), frameLength, AckRequested, FramePending);
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, %s: %X => %X (%u bytes, AckReq=%u, FramePending=%u)",
|
||||
pFilter, szDir, getSrcShortAddress(frameLength, frame, IEEE802154_DSTADDR_OFFSET+2), getDstShortAddress(frame), frameLength, AckRequested, FramePending);
|
||||
break;
|
||||
case IEEE802154_DST_ADDR_SHORT | IEEE802154_SRC_ADDR_EXT:
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, %s: %p : %llX => %X (%u bytes, AckReq=%u, FramePending=%u)",
|
||||
pFilter, szDir, NetBufferList, getSrcExtAddress(frameLength, frame, IEEE802154_DSTADDR_OFFSET+2), getDstShortAddress(frame), frameLength, AckRequested, FramePending);
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, %s: %llX => %X (%u bytes, AckReq=%u, FramePending=%u)",
|
||||
pFilter, szDir, getSrcExtAddress(frameLength, frame, IEEE802154_DSTADDR_OFFSET+2), getDstShortAddress(frame), frameLength, AckRequested, FramePending);
|
||||
break;
|
||||
|
||||
case IEEE802154_DST_ADDR_EXT | IEEE802154_SRC_ADDR_NONE:
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, %s: %p : null => %llX (%u bytes, AckReq=%u, FramePending=%u)",
|
||||
pFilter, szDir, NetBufferList, getDstExtAddress(frame), frameLength, AckRequested, FramePending);
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, %s: null => %llX (%u bytes, AckReq=%u, FramePending=%u)",
|
||||
pFilter, szDir, getDstExtAddress(frame), frameLength, AckRequested, FramePending);
|
||||
break;
|
||||
case IEEE802154_DST_ADDR_EXT | IEEE802154_SRC_ADDR_SHORT:
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filt: %p, %s: %p : %X => %llX (%u bytes, AckReq=%u, FramePending=%u)",
|
||||
pFilter, szDir, NetBufferList, getSrcShortAddress(frameLength, frame, IEEE802154_DSTADDR_OFFSET+8), getDstExtAddress(frame), frameLength, AckRequested, FramePending);
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, %s: %X => %llX (%u bytes, AckReq=%u, FramePending=%u)",
|
||||
pFilter, szDir, getSrcShortAddress(frameLength, frame, IEEE802154_DSTADDR_OFFSET+8), getDstExtAddress(frame), frameLength, AckRequested, FramePending);
|
||||
break;
|
||||
case IEEE802154_DST_ADDR_EXT | IEEE802154_SRC_ADDR_EXT:
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, %s: %p : %llX => %llX (%u bytes, AckReq=%u, FramePending=%u)",
|
||||
pFilter, szDir, NetBufferList, getSrcExtAddress(frameLength, frame, IEEE802154_DSTADDR_OFFSET+8), getDstExtAddress(frame), frameLength, AckRequested, FramePending);
|
||||
LogVerbose(DRIVER_DATA_PATH, "Filter: %p, %s: %llX => %llX (%u bytes, AckReq=%u, FramePending=%u)",
|
||||
pFilter, szDir, getSrcExtAddress(frameLength, frame, IEEE802154_DSTADDR_OFFSET+8), getDstExtAddress(frame), frameLength, AckRequested, FramePending);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ enum
|
||||
VOID otLwfRadioInit(_In_ PMS_FILTER pFilter);
|
||||
|
||||
// Indicates a received frame from the radio layer
|
||||
VOID otLwfRadioReceiveFrame(_In_ PMS_FILTER pFilter, _In_ PNET_BUFFER_LIST NetBufferList);
|
||||
VOID otLwfRadioReceiveFrame(_In_ PMS_FILTER pFilter, _In_ ThreadError errorCode);
|
||||
|
||||
// Indicates the transmit frame is ready to send to the radio layer
|
||||
VOID otLwfRadioTransmitFrame(_In_ PMS_FILTER pFilter);
|
||||
|
||||
@@ -42,45 +42,13 @@ otLwfInitializeThreadMode(
|
||||
)
|
||||
{
|
||||
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
||||
PNET_BUFFER SendNetBuffer;
|
||||
|
||||
LogFuncEntry(DRIVER_DEFAULT);
|
||||
|
||||
NT_ASSERT(pFilter->DeviceCapabilities & OTLWF_DEVICE_CAP_RADIO);
|
||||
|
||||
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
|
||||
@@ -92,6 +60,7 @@ otLwfInitializeThreadMode(
|
||||
NdisAllocateSpinLock(&pFilter->EventsLock);
|
||||
InitializeListHead(&pFilter->AddressChangesHead);
|
||||
InitializeListHead(&pFilter->NBLsHead);
|
||||
InitializeListHead(&pFilter->MacFramesHead);
|
||||
InitializeListHead(&pFilter->EventIrpListHead);
|
||||
KeInitializeEvent(
|
||||
&pFilter->EventWorkerThreadStopEvent,
|
||||
@@ -118,6 +87,11 @@ otLwfInitializeThreadMode(
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
FALSE // event initially non-signalled
|
||||
);
|
||||
KeInitializeEvent(
|
||||
&pFilter->EventWorkerThreadProcessMacFrames,
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
FALSE // event initially non-signalled
|
||||
);
|
||||
KeInitializeEvent(
|
||||
&pFilter->EventWorkerThreadProcessIrp,
|
||||
SynchronizationEvent, // auto-clearing event
|
||||
@@ -140,6 +114,19 @@ otLwfInitializeThreadMode(
|
||||
break;
|
||||
}
|
||||
|
||||
// Query the interface state (best effort, since it might not be supported)
|
||||
BOOLEAN IfUp = FALSE;
|
||||
Status = otLwfCmdGetProp(pFilter, NULL, SPINEL_PROP_NET_IF_UP, SPINEL_DATATYPE_BOOL_S, &IfUp);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
LogVerbose(DRIVER_DEFAULT, "Failed to query SPINEL_PROP_INTERFACE_TYPE, %!STATUS!", Status);
|
||||
Status = NDIS_STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
NT_ASSERT(IfUp == FALSE);
|
||||
}
|
||||
|
||||
// Initialize the event processing thread
|
||||
if (!NT_SUCCESS(otLwfEventProcessingStart(pFilter)))
|
||||
{
|
||||
@@ -159,13 +146,6 @@ otLwfInitializeThreadMode(
|
||||
{
|
||||
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);
|
||||
@@ -185,11 +165,10 @@ otLwfUninitializeThreadMode(
|
||||
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);
|
||||
if (pFilter->EventHighPrecisionTimer)
|
||||
{
|
||||
ExDeleteTimer(pFilter->EventHighPrecisionTimer, TRUE, FALSE, NULL);
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
@@ -551,3 +530,110 @@ void otLwfCommissionerPanIdConflictCallback(uint16_t aPanId, uint32_t aChannelMa
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
void
|
||||
otLwfThreadValueIs(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_ spinel_prop_key_t key,
|
||||
_In_reads_bytes_(value_data_len) const uint8_t* value_data_ptr,
|
||||
_In_ spinel_size_t value_data_len
|
||||
)
|
||||
{
|
||||
LogFuncEntryMsg(DRIVER_DEFAULT, "[%p] received Value for %s", pFilter, spinel_prop_key_to_cstr(key));
|
||||
|
||||
if (key == SPINEL_PROP_LAST_STATUS)
|
||||
{
|
||||
spinel_status_t status = SPINEL_STATUS_OK;
|
||||
spinel_datatype_unpack(value_data_ptr, value_data_len, "i", &status);
|
||||
|
||||
if ((status >= SPINEL_STATUS_RESET__BEGIN) && (status <= SPINEL_STATUS_RESET__END))
|
||||
{
|
||||
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! was reset (status %d).", &pFilter->InterfaceGuid, status);
|
||||
// TODO - Handle reset
|
||||
}
|
||||
}
|
||||
else if (key == SPINEL_PROP_MAC_ENERGY_SCAN_RESULT)
|
||||
{
|
||||
uint8_t scanChannel;
|
||||
int8_t maxRssi;
|
||||
spinel_ssize_t ret;
|
||||
|
||||
ret = spinel_datatype_unpack(
|
||||
value_data_ptr,
|
||||
value_data_len,
|
||||
"Cc",
|
||||
&scanChannel,
|
||||
&maxRssi);
|
||||
|
||||
NT_ASSERT(ret > 0);
|
||||
if (ret > 0)
|
||||
{
|
||||
LogInfo(DRIVER_DEFAULT, "Filter: %p, completed energy scan: Rssi:%d", pFilter, maxRssi);
|
||||
otLwfEventProcessingIndicateEnergyScanResult(pFilter, maxRssi);
|
||||
}
|
||||
}
|
||||
else if (key == SPINEL_PROP_STREAM_RAW)
|
||||
{
|
||||
if (value_data_len < 256)
|
||||
{
|
||||
otLwfEventProcessingIndicateNewMacFrameCommand(
|
||||
pFilter,
|
||||
DispatchLevel,
|
||||
value_data_ptr,
|
||||
(uint8_t)value_data_len);
|
||||
}
|
||||
}
|
||||
else if (key == SPINEL_PROP_STREAM_DEBUG)
|
||||
{
|
||||
const uint8_t* output = NULL;
|
||||
UINT output_len = 0;
|
||||
spinel_ssize_t ret;
|
||||
|
||||
ret = spinel_datatype_unpack(
|
||||
value_data_ptr,
|
||||
value_data_len,
|
||||
SPINEL_DATATYPE_DATA_S,
|
||||
&output,
|
||||
&output_len);
|
||||
|
||||
NT_ASSERT(ret > 0);
|
||||
if (ret > 0 && output && output_len <= (UINT)ret)
|
||||
{
|
||||
if (strnlen((char*)output, output_len) != output_len)
|
||||
{
|
||||
LogInfo(DRIVER_DEFAULT, "DEVICE: %s", (char*)output);
|
||||
}
|
||||
else if (output_len < 128)
|
||||
{
|
||||
char strOutput[128] = { 0 };
|
||||
memcpy(strOutput, output, output_len);
|
||||
LogInfo(DRIVER_DEFAULT, "DEVICE: %s", strOutput);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
void
|
||||
otLwfThreadValueInserted(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_ spinel_prop_key_t key,
|
||||
_In_reads_bytes_(value_data_len) const uint8_t* value_data_ptr,
|
||||
_In_ spinel_size_t value_data_len
|
||||
)
|
||||
{
|
||||
LogFuncEntryMsg(DRIVER_DEFAULT, "[%p] received Value Inserted for %s", pFilter, spinel_prop_key_to_cstr(key));
|
||||
|
||||
UNREFERENCED_PARAMETER(pFilter);
|
||||
UNREFERENCED_PARAMETER(DispatchLevel);
|
||||
UNREFERENCED_PARAMETER(key);
|
||||
UNREFERENCED_PARAMETER(value_data_ptr);
|
||||
UNREFERENCED_PARAMETER(value_data_len);
|
||||
|
||||
LogFuncExit(DRIVER_DEFAULT);
|
||||
}
|
||||
|
||||
@@ -107,11 +107,19 @@ 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
|
||||
otLwfEventProcessingIndicateNewMacFrameCommand(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_reads_bytes_(BufferLength)
|
||||
const uint8_t* Buffer,
|
||||
_In_ uint8_t BufferLength
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
VOID
|
||||
otLwfEventProcessingIndicateNetBufferListsCancelled(
|
||||
@@ -145,4 +153,28 @@ 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);
|
||||
|
||||
//
|
||||
// Value Callbacks
|
||||
//
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
void
|
||||
otLwfThreadValueIs(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_ spinel_prop_key_t key,
|
||||
_In_reads_bytes_(value_data_len) const uint8_t* value_data_ptr,
|
||||
_In_ spinel_size_t value_data_len
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
void
|
||||
otLwfThreadValueInserted(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_ spinel_prop_key_t key,
|
||||
_In_reads_bytes_(value_data_len) const uint8_t* value_data_ptr,
|
||||
_In_ spinel_size_t value_data_len
|
||||
);
|
||||
|
||||
#endif //_THREAD_H_
|
||||
|
||||
+252
-1317
File diff suppressed because it is too large
Load Diff
@@ -35,117 +35,29 @@
|
||||
#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
|
||||
// Initialization
|
||||
//
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NDIS_STATUS
|
||||
otLwfInitializeTunnelMode(
|
||||
otLwfTunInitialize(
|
||||
_In_ PMS_FILTER pFilter
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
void
|
||||
otLwfUninitializeTunnelMode(
|
||||
otLwfTunUninitialize(
|
||||
_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(
|
||||
otLwfTunSendCommandForIrp(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ PIRP Irp,
|
||||
_In_opt_ SPINEL_IRP_CMD_HANDLER *Handler,
|
||||
@@ -157,39 +69,38 @@ otLwfSendTunnelCommandForIrp(
|
||||
);
|
||||
|
||||
//
|
||||
// Spinel Helper Functions
|
||||
// Value Callbacks
|
||||
//
|
||||
|
||||
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(
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
void
|
||||
otLwfTunValueIs(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_Out_opt_ PVOID *DataBuffer,
|
||||
_In_ spinel_prop_key_t Key,
|
||||
_In_ const char *pack_format,
|
||||
...
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_ spinel_prop_key_t key,
|
||||
_In_reads_bytes_(value_data_len) const uint8_t* value_data_ptr,
|
||||
_In_ spinel_size_t value_data_len
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
otLwfSetTunProp(
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
void
|
||||
otLwfTunValueInserted(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ spinel_prop_key_t Key,
|
||||
_In_ const char *pack_format,
|
||||
...
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_ spinel_prop_key_t key,
|
||||
_In_reads_bytes_(value_data_len) const uint8_t* value_data_ptr,
|
||||
_In_ spinel_size_t value_data_len
|
||||
);
|
||||
|
||||
// Called in response to receiving a Spinel Ip6 packet command
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
void
|
||||
otLwfTunReceiveIp6Packet(
|
||||
_In_ PMS_FILTER pFilter,
|
||||
_In_ BOOLEAN DispatchLevel,
|
||||
_In_ BOOLEAN Secure,
|
||||
_In_reads_bytes_(BufferLength) const uint8_t* Buffer,
|
||||
_In_ UINT BufferLength
|
||||
);
|
||||
|
||||
#endif //_TUNNEL_H_
|
||||
|
||||
@@ -404,7 +404,7 @@ Return Value:
|
||||
|
||||
// Xon and Xoff characters
|
||||
{
|
||||
const SERIAL_CHARS sc = { 0, 0, 0, 0, 11, 13 };
|
||||
const SERIAL_CHARS sc = { 0, 0, 0, 0, 0x11, 0x13 };
|
||||
WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&inputDesc, (PVOID)&sc, sizeof(sc));
|
||||
|
||||
status = SerialSendIoctl(AdapterContext, IOCTL_SERIAL_SET_CHARS, &wrso, &inputDesc);
|
||||
|
||||
Reference in New Issue
Block a user