Spinel: Radio Source Match Support (#1371)

* Add Spinel Source Match Properties

* Wrap Source Match NCP code with OPENTHREAD_ENABLE_RAW_LINK_API

* Update spinel docs

* Handle SendPropertyUpdate errors
This commit is contained in:
Nick Banks
2017-02-28 21:52:41 -08:00
committed by Jonathan Hui
parent ffeeeb96d2
commit 95ff7b55dc
10 changed files with 611 additions and 203 deletions
+78 -14
View File
@@ -1113,6 +1113,7 @@ otLwfCmdGetProp(
typedef struct _SPINEL_SET_PROP_CONTEXT
{
KEVENT CompletionEvent;
UINT ExpectedResultCommand;
spinel_prop_key_t Key;
NTSTATUS Status;
} SPINEL_SET_PROP_CONTEXT;
@@ -1138,11 +1139,7 @@ otLwfSetPropHandler(
{
CmdContext->Status = STATUS_CANCELLED;
}
else if (Command != SPINEL_CMD_PROP_VALUE_IS)
{
CmdContext->Status = STATUS_INVALID_PARAMETER;
}
else if (Key == SPINEL_PROP_LAST_STATUS)
else if (Command == SPINEL_CMD_PROP_VALUE_IS && Key == SPINEL_PROP_LAST_STATUS)
{
spinel_status_t spinel_status = SPINEL_STATUS_OK;
spinel_ssize_t packed_len = spinel_datatype_unpack(Data, DataLength, "i", &spinel_status);
@@ -1157,12 +1154,18 @@ otLwfSetPropHandler(
CmdContext->Status = ThreadErrorToNtstatus(errorCode);
}
}
else if (Command != CmdContext->ExpectedResultCommand)
{
NT_ASSERT(FALSE);
CmdContext->Status = STATUS_INVALID_PARAMETER;
}
else if (Key == CmdContext->Key)
{
CmdContext->Status = STATUS_SUCCESS;
}
else
{
NT_ASSERT(FALSE);
CmdContext->Status = STATUS_INVALID_PARAMETER;
}
@@ -1174,11 +1177,12 @@ otLwfSetPropHandler(
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
otLwfCmdSetProp(
otLwfCmdSetPropV(
_In_ PMS_FILTER pFilter,
_In_ UINT Command,
_In_ spinel_prop_key_t Key,
_In_ const char *pack_format,
...
_In_opt_ const char *pack_format,
_In_opt_ va_list args
)
{
NTSTATUS status;
@@ -1191,10 +1195,24 @@ otLwfCmdSetProp(
Context.Key = Key;
Context.Status = STATUS_SUCCESS;
LogFuncEntryMsg(DRIVER_DEFAULT, "Key=%u", (ULONG)Key);
LogFuncEntryMsg(DRIVER_DEFAULT, "Cmd=%u Key=%u", Command, (ULONG)Key);
va_list args;
va_start(args, pack_format);
if (Command == SPINEL_CMD_PROP_VALUE_SET)
{
Context.ExpectedResultCommand = SPINEL_CMD_PROP_VALUE_IS;
}
else if (Command == SPINEL_CMD_PROP_VALUE_INSERT)
{
Context.ExpectedResultCommand = SPINEL_CMD_PROP_VALUE_INSERTED;
}
else if (Command == SPINEL_CMD_PROP_VALUE_REMOVE)
{
Context.ExpectedResultCommand = SPINEL_CMD_PROP_VALUE_REMOVED;
}
else
{
ASSERT(FALSE);
}
// Send the request transaction
status =
@@ -1203,7 +1221,7 @@ otLwfCmdSetProp(
otLwfSetPropHandler,
&Context,
&tid,
SPINEL_CMD_PROP_VALUE_SET,
Command,
Key,
8,
pack_format,
@@ -1236,14 +1254,60 @@ otLwfCmdSetProp(
{
Context.Status = status;
}
va_end(args);
LogFuncExitNT(DRIVER_DEFAULT, Context.Status);
return Context.Status;
}
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
otLwfCmdSetProp(
_In_ PMS_FILTER pFilter,
_In_ spinel_prop_key_t Key,
_In_opt_ const char *pack_format,
...
)
{
va_list args;
va_start(args, pack_format);
NTSTATUS status = otLwfCmdSetPropV(pFilter, SPINEL_CMD_PROP_VALUE_SET, Key, pack_format, args);
va_end(args);
return status;
}
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
otLwfCmdInsertProp(
_In_ PMS_FILTER pFilter,
_In_ spinel_prop_key_t Key,
_In_opt_ const char *pack_format,
...
)
{
va_list args;
va_start(args, pack_format);
NTSTATUS status = otLwfCmdSetPropV(pFilter, SPINEL_CMD_PROP_VALUE_INSERT, Key, pack_format, args);
va_end(args);
return status;
}
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
otLwfCmdRemoveProp(
_In_ PMS_FILTER pFilter,
_In_ spinel_prop_key_t Key,
_In_opt_ const char *pack_format,
...
)
{
va_list args;
va_start(args, pack_format);
NTSTATUS status = otLwfCmdSetPropV(pFilter, SPINEL_CMD_PROP_VALUE_REMOVE, Key, pack_format, args);
va_end(args);
return status;
}
//
// General Spinel Helpers
//
+19 -1
View File
@@ -162,7 +162,25 @@ NTSTATUS
otLwfCmdSetProp(
_In_ PMS_FILTER pFilter,
_In_ spinel_prop_key_t Key,
_In_ const char *pack_format,
_In_opt_ const char *pack_format,
...
);
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
otLwfCmdInsertProp(
_In_ PMS_FILTER pFilter,
_In_ spinel_prop_key_t Key,
_In_opt_ const char *pack_format,
...
);
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
otLwfCmdRemoveProp(
_In_ PMS_FILTER pFilter,
_In_ spinel_prop_key_t Key,
_In_opt_ const char *pack_format,
...
);
-6
View File
@@ -111,8 +111,6 @@ typedef enum OTLWF_DEVICE_STATUS
#define OT_EVENT_TIMER_RUNNING 1
#define OT_EVENT_TIMER_FIRED 2
#define MAX_PENDING_MAC_SIZE 32 // TODO
//
// Define the filter struct
//
@@ -245,10 +243,6 @@ typedef struct _MS_FILTER
uint16_t otShortAddress;
BOOLEAN otPendingMacOffloadEnabled;
uint8_t otPendingShortAddressCount;
uint16_t otPendingShortAddresses[MAX_PENDING_MAC_SIZE];
uint8_t otPendingExtendedAddressCount;
uint64_t otPendingExtendedAddresses[MAX_PENDING_MAC_SIZE];
#if DEBUG_ALLOC
// Used for tracking memory allocations
+80 -170
View File
@@ -73,8 +73,6 @@ otPlatReset(
pFilter->otCurrentListenChannel = 0xFF;
pFilter->otPromiscuous = false;
pFilter->otPendingMacOffloadEnabled = FALSE;
pFilter->otPendingShortAddressCount = 0;
pFilter->otPendingExtendedAddressCount = 0;
// Reinitialize the OpenThread library
pFilter->otCachedRole = kDeviceRoleDisabled;
@@ -169,8 +167,6 @@ otLwfRadioInit(
pFilter->otTransmitFrame.mPsdu = pFilter->otTransmitMessage;
pFilter->otPendingMacOffloadEnabled = FALSE;
pFilter->otPendingShortAddressCount = 0;
pFilter->otPendingExtendedAddressCount = 0;
// Cache the factory address
otLwfRadioGetFactoryAddress(pFilter);
@@ -569,64 +565,6 @@ otLwfRadioTransmitFrameDone(
LogFuncExit(DRIVER_DATA_PATH);
}
NDIS_STATUS
otPlatRadioSendPendingMacOffload(
_In_ PMS_FILTER pFilter
)
{
// 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;
USHORT OidBufferSize = COMPLETE_SIZEOF_OT_PENDING_MAC_OFFLOAD_REVISION_1(ShortAddressCount, ExtendedAddressCount);
POT_PENDING_MAC_OFFLOAD OidBuffer = (POT_PENDING_MAC_OFFLOAD)FILTER_ALLOC_MEM(pFilter->FilterHandle, OidBufferSize);
PUCHAR Offset = (PUCHAR)(OidBuffer + 1);
ULONG BufferSizeLeft = OidBufferSize - sizeof(OT_PENDING_MAC_OFFLOAD);
OidBuffer->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
OidBuffer->Header.Revision = OT_PENDING_MAC_OFFLOAD_REVISION_1;
OidBuffer->Header.Size = OidBufferSize;
OidBuffer->ShortAddressCount = ShortAddressCount;
OidBuffer->ExtendedAddressCount = ExtendedAddressCount;
if (ShortAddressCount != 0)
{
memcpy_s(Offset, BufferSizeLeft, pFilter->otPendingShortAddresses, sizeof(USHORT) * ShortAddressCount);
Offset += sizeof(USHORT) * ShortAddressCount;
BufferSizeLeft -= sizeof(USHORT) * ShortAddressCount;
}
if (ExtendedAddressCount != 0)
{
memcpy_s(Offset, BufferSizeLeft, pFilter->otPendingExtendedAddresses, sizeof(ULONGLONG) * ExtendedAddressCount);
}
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! indicating updated Pending Mac Offload", &pFilter->InterfaceGuid);
// Indicate to the miniport
status =
otLwfSendInternalRequest(
pFilter,
NdisRequestSetInformation,
OID_OT_PENDING_MAC_OFFLOAD,
OidBuffer,
OidBufferSize,
&bytesProcessed
);
if (status != NDIS_STATUS_SUCCESS)
{
LogError(DRIVER_DEFAULT, "Set for OID_OT_PENDING_MAC_OFFLOAD failed, %!NDIS_STATUS!", status);
}
FILTER_FREE_MEM(OidBuffer);
return status;*/
}
void otPlatRadioEnableSrcMatch(_In_ otInstance *otCtx, bool aEnable)
{
NT_ASSERT(otCtx);
@@ -635,9 +573,21 @@ void otPlatRadioEnableSrcMatch(_In_ otInstance *otCtx, bool aEnable)
// Ignore if we are already in the correct state
if (aEnable == pFilter->otPendingMacOffloadEnabled) return;
// Set the new value and update the miniport
// Cache the new value
pFilter->otPendingMacOffloadEnabled = aEnable ? TRUE : FALSE;
otPlatRadioSendPendingMacOffload(pFilter);
// Indicate to the miniport
NTSTATUS status =
otLwfCmdSetProp(
pFilter,
SPINEL_PROP_MAC_SRC_MATCH_ENABLED,
SPINEL_DATATYPE_BOOL_S,
(aEnable ? TRUE : FALSE)
);
if (!NT_SUCCESS(status))
{
LogError(DRIVER_DEFAULT, "Set SPINEL_PROP_MAC_SRC_MATCH_ENABLED failed, %!STATUS!", status);
}
}
ThreadError otPlatRadioAddSrcMatchShortEntry(_In_ otInstance *otCtx, const uint16_t aShortAddress)
@@ -645,34 +595,20 @@ ThreadError otPlatRadioAddSrcMatchShortEntry(_In_ otInstance *otCtx, const uint1
NT_ASSERT(otCtx);
PMS_FILTER pFilter = otCtxToFilter(otCtx);
// Check to see if it is in the list
BOOLEAN Found = false;
for (ULONG i = 0; i < pFilter->otPendingShortAddressCount; i++)
// Indicate to the miniport
NTSTATUS status =
otLwfCmdInsertProp(
pFilter,
SPINEL_PROP_MAC_SRC_MATCH_SHORT_ADDRESSES,
SPINEL_DATATYPE_UINT16_S,
aShortAddress
);
if (!NT_SUCCESS(status))
{
if (aShortAddress == pFilter->otPendingShortAddresses[i])
{
Found = TRUE;
break;
}
LogError(DRIVER_DEFAULT, "Insert SPINEL_PROP_MAC_SRC_MATCH_SHORT_ADDRESSES failed, %!STATUS!", status);
}
// Already in the list, return success
if (Found) return kThreadError_None;
// Make sure we have room
if (pFilter->otPendingShortAddressCount == MAX_PENDING_MAC_SIZE) return kThreadError_NoBufs;
// Copy to the list
pFilter->otPendingShortAddresses[pFilter->otPendingShortAddressCount] = aShortAddress;
pFilter->otPendingShortAddressCount++;
// Update the miniport if enabled
if (pFilter->otPendingMacOffloadEnabled)
{
otPlatRadioSendPendingMacOffload(pFilter);
}
return kThreadError_None;
return NT_SUCCESS(status) ? kThreadError_None : kThreadError_Failed;
}
ThreadError otPlatRadioAddSrcMatchExtEntry(_In_ otInstance *otCtx, const uint8_t *aExtAddress)
@@ -680,34 +616,20 @@ ThreadError otPlatRadioAddSrcMatchExtEntry(_In_ otInstance *otCtx, const uint8_t
NT_ASSERT(otCtx);
PMS_FILTER pFilter = otCtxToFilter(otCtx);
// Check to see if it is in the list
BOOLEAN Found = false;
for (ULONG i = 0; i < pFilter->otPendingExtendedAddressCount; i++)
// Indicate to the miniport
NTSTATUS status =
otLwfCmdInsertProp(
pFilter,
SPINEL_PROP_MAC_SRC_MATCH_EXTENDED_ADDRESSES,
SPINEL_DATATYPE_EUI64_S,
aExtAddress
);
if (!NT_SUCCESS(status))
{
if (memcmp(aExtAddress, &pFilter->otPendingExtendedAddresses[i], sizeof(ULONGLONG)) == 0)
{
Found = TRUE;
break;
}
LogError(DRIVER_DEFAULT, "Insert SPINEL_PROP_MAC_SRC_MATCH_EXTENDED_ADDRESSES failed, %!STATUS!", status);
}
// Already in the list, return success
if (Found) return kThreadError_None;
// Make sure we have room
if (pFilter->otPendingExtendedAddressCount == MAX_PENDING_MAC_SIZE) return kThreadError_NoBufs;
// Copy to the list
memcpy(&pFilter->otPendingExtendedAddresses[pFilter->otPendingExtendedAddressCount], aExtAddress, sizeof(ULONGLONG));
pFilter->otPendingExtendedAddressCount++;
// Update the miniport if enabled
if (pFilter->otPendingMacOffloadEnabled)
{
otPlatRadioSendPendingMacOffload(pFilter);
}
return kThreadError_None;
return NT_SUCCESS(status) ? kThreadError_None : kThreadError_Failed;
}
ThreadError otPlatRadioClearSrcMatchShortEntry(_In_ otInstance *otCtx, const uint16_t aShortAddress)
@@ -715,31 +637,20 @@ ThreadError otPlatRadioClearSrcMatchShortEntry(_In_ otInstance *otCtx, const uin
NT_ASSERT(otCtx);
PMS_FILTER pFilter = otCtxToFilter(otCtx);
// Check to see if it is in the list
BOOLEAN Found = false;
for (ULONG i = 0; i < pFilter->otPendingShortAddressCount; i++)
// Indicate to the miniport
NTSTATUS status =
otLwfCmdRemoveProp(
pFilter,
SPINEL_PROP_MAC_SRC_MATCH_SHORT_ADDRESSES,
SPINEL_DATATYPE_UINT16_S,
aShortAddress
);
if (!NT_SUCCESS(status))
{
if (aShortAddress == pFilter->otPendingShortAddresses[i])
{
// Remove it from the list
if (i + 1 != pFilter->otPendingShortAddressCount)
pFilter->otPendingShortAddresses[i] = pFilter->otPendingShortAddresses[pFilter->otPendingShortAddressCount - 1];
pFilter->otPendingShortAddressCount--;
Found = TRUE;
break;
}
LogError(DRIVER_DEFAULT, "Remove SPINEL_PROP_MAC_SRC_MATCH_SHORT_ADDRESSES failed, %!STATUS!", status);
}
// Wasn't in the list, return failure
if (Found == FALSE) return kThreadError_NotFound;
// Update the miniport if enabled
if (pFilter->otPendingMacOffloadEnabled)
{
otPlatRadioSendPendingMacOffload(pFilter);
}
return kThreadError_None;
return NT_SUCCESS(status) ? kThreadError_None : kThreadError_Failed;
}
ThreadError otPlatRadioClearSrcMatchExtEntry(_In_ otInstance *otCtx, const uint8_t *aExtAddress)
@@ -747,31 +658,20 @@ ThreadError otPlatRadioClearSrcMatchExtEntry(_In_ otInstance *otCtx, const uint8
NT_ASSERT(otCtx);
PMS_FILTER pFilter = otCtxToFilter(otCtx);
// Check to see if it is in the list
BOOLEAN Found = false;
for (ULONG i = 0; i < pFilter->otPendingExtendedAddressCount; i++)
// Indicate to the miniport
NTSTATUS status =
otLwfCmdRemoveProp(
pFilter,
SPINEL_PROP_MAC_SRC_MATCH_EXTENDED_ADDRESSES,
SPINEL_DATATYPE_EUI64_S,
aExtAddress
);
if (!NT_SUCCESS(status))
{
if (memcmp(aExtAddress, &pFilter->otPendingExtendedAddresses[i], sizeof(ULONGLONG)) == 0)
{
// Remove it from the list
if (i + 1 != pFilter->otPendingExtendedAddressCount)
pFilter->otPendingExtendedAddresses[i] = pFilter->otPendingExtendedAddresses[pFilter->otPendingExtendedAddressCount - 1];
pFilter->otPendingExtendedAddressCount--;
Found = TRUE;
break;
}
}
// Wasn't in the list, return failure
if (Found == FALSE) return kThreadError_NotFound;
// Update the miniport if enabled
if (pFilter->otPendingMacOffloadEnabled)
{
otPlatRadioSendPendingMacOffload(pFilter);
LogError(DRIVER_DEFAULT, "Remove SPINEL_PROP_MAC_SRC_MATCH_EXTENDED_ADDRESSES failed, %!STATUS!", status);
}
return kThreadError_None;
return NT_SUCCESS(status) ? kThreadError_None : kThreadError_Failed;
}
void otPlatRadioClearSrcMatchShortEntries(_In_ otInstance *otCtx)
@@ -779,12 +679,17 @@ void otPlatRadioClearSrcMatchShortEntries(_In_ otInstance *otCtx)
NT_ASSERT(otCtx);
PMS_FILTER pFilter = otCtxToFilter(otCtx);
// Ignore if we are already in the correct state
if (pFilter->otPendingShortAddressCount == 0) return;
// Set the new value and update the miniport
pFilter->otPendingShortAddressCount = 0;
otPlatRadioSendPendingMacOffload(pFilter);
// Indicate to the miniport
NTSTATUS status =
otLwfCmdSetProp(
pFilter,
SPINEL_PROP_MAC_SRC_MATCH_SHORT_ADDRESSES,
NULL
);
if (!NT_SUCCESS(status))
{
LogError(DRIVER_DEFAULT, "Set SPINEL_PROP_MAC_SRC_MATCH_SHORT_ADDRESSES failed, %!STATUS!", status);
}
}
void otPlatRadioClearSrcMatchExtEntries(_In_ otInstance *otCtx)
@@ -792,12 +697,17 @@ void otPlatRadioClearSrcMatchExtEntries(_In_ otInstance *otCtx)
NT_ASSERT(otCtx);
PMS_FILTER pFilter = otCtxToFilter(otCtx);
// Ignore if we are already in the correct state
if (pFilter->otPendingExtendedAddressCount == 0) return;
// Set the new value and update the miniport
pFilter->otPendingExtendedAddressCount = 0;
otPlatRadioSendPendingMacOffload(pFilter);
// Indicate to the miniport
NTSTATUS status =
otLwfCmdSetProp(
pFilter,
SPINEL_PROP_MAC_SRC_MATCH_EXTENDED_ADDRESSES,
NULL
);
if (!NT_SUCCESS(status))
{
LogError(DRIVER_DEFAULT, "Set SPINEL_PROP_MAC_SRC_MATCH_EXTENDED_ADDRESSES failed, %!STATUS!", status);
}
}
ThreadError otPlatRadioEnergyScan(_In_ otInstance *otCtx, uint8_t aScanChannel, uint16_t aScanDuration)