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:
Nick Banks
2017-02-01 10:15:32 -08:00
committed by Jonathan Hui
parent f2d41102dd
commit 8a8c8cde41
22 changed files with 3219 additions and 2586 deletions
+2
View File
@@ -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" />
+3
View File
@@ -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">
+176 -13
View File
@@ -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;
+15 -8
View File
@@ -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
+179
View File
@@ -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_
+207 -201
View File
@@ -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);
}
}
+6 -18
View File
@@ -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
//
-8
View File
@@ -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
//
+52 -51
View File
@@ -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));
+182 -127
View File
@@ -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);
+253 -267
View File
@@ -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(
+63 -40
View File
@@ -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
//
+75 -91
View File
@@ -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,
+2 -3
View File
@@ -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"
+278 -273
View File
@@ -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;
}
+1 -1
View File
@@ -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);
+132 -46
View File
@@ -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);
}
+34 -2
View File
@@ -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_
File diff suppressed because it is too large Load Diff
+30 -119
View File
@@ -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_
+1 -1
View File
@@ -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);