From 4d28e765fefbc7acf0daf44fedfbbc58bbc492de Mon Sep 17 00:00:00 2001 From: Nick Banks Date: Thu, 9 Feb 2017 13:11:02 -0800 Subject: [PATCH] Fixes for otJoinerStart on Windows (#1294) --- examples/drivers/windows/include/otLwfIoctl.h | 21 ++++-- examples/drivers/windows/otApi/otApi.cpp | 72 +++++++++++++++++-- examples/drivers/windows/otLwf/filter.h | 8 +++ examples/drivers/windows/otLwf/iocontrol.c | 44 ++++++++---- examples/drivers/windows/otLwf/thread.c | 20 ++++++ examples/drivers/windows/otLwf/thread.h | 1 + 6 files changed, 140 insertions(+), 26 deletions(-) diff --git a/examples/drivers/windows/include/otLwfIoctl.h b/examples/drivers/windows/include/otLwfIoctl.h index 94d09a91e..2b2c3d025 100644 --- a/examples/drivers/windows/include/otLwfIoctl.h +++ b/examples/drivers/windows/include/otLwfIoctl.h @@ -59,7 +59,8 @@ typedef enum _OTLWF_NOTIF_TYPE OTLWF_NOTIF_ACTIVE_SCAN, OTLWF_NOTIF_ENERGY_SCAN, OTLWF_NOTIF_COMMISSIONER_ENERGY_REPORT, - OTLWF_NOTIF_COMMISSIONER_PANID_QUERY + OTLWF_NOTIF_COMMISSIONER_PANID_QUERY, + OTLWF_NOTIF_JOINER_COMPLETE } OTLWF_NOTIF_TYPE; @@ -123,6 +124,12 @@ typedef enum _OTLWF_NOTIF_TYPE uint16_t PanId; uint32_t ChannelMask; } CommissionerPanIdQueryPayload; + + // Payload for OTLWF_NOTIF_JOINER_COMPLETE + struct + { + ThreadError Error; + } JoinerCompletePayload; }; } OTLWF_NOTIFICATION, *POTLWF_NOTIFICATION; @@ -517,12 +524,12 @@ typedef enum _OTLWF_NOTIF_TYPE #define OPENTHREAD_VENDOR_DATA_MAX_LENGTH 64 typedef struct otCommissionConfig { - uint8_t PSKd[OPENTHREAD_PSK_MAX_LENGTH + 1]; - uint8_t ProvisioningUrl[OPENTHREAD_PROV_URL_MAX_LENGTH + 1]; - uint8_t VendorName[OPENTHREAD_VENDOR_NAME_MAX_LENGTH + 1]; - uint8_t VendorModel[OPENTHREAD_VENDOR_MODEL_MAX_LENGTH + 1]; - uint8_t VendorSwVersion[OPENTHREAD_VENDOR_SW_VERSION_MAX_LENGTH + 1]; - uint8_t VendorData[OPENTHREAD_VENDOR_DATA_MAX_LENGTH + 1]; + char PSKd[OPENTHREAD_PSK_MAX_LENGTH + 1]; + char ProvisioningUrl[OPENTHREAD_PROV_URL_MAX_LENGTH + 1]; + char VendorName[OPENTHREAD_VENDOR_NAME_MAX_LENGTH + 1]; + char VendorModel[OPENTHREAD_VENDOR_MODEL_MAX_LENGTH + 1]; + char VendorSwVersion[OPENTHREAD_VENDOR_SW_VERSION_MAX_LENGTH + 1]; + char VendorData[OPENTHREAD_VENDOR_DATA_MAX_LENGTH + 1]; } otCommissionConfig; #define IOCTL_OTLWF_OT_JOINER_START \ diff --git a/examples/drivers/windows/otApi/otApi.cpp b/examples/drivers/windows/otApi/otApi.cpp index 4844bbfa0..c044a6694 100644 --- a/examples/drivers/windows/otApi/otApi.cpp +++ b/examples/drivers/windows/otApi/otApi.cpp @@ -105,6 +105,7 @@ typedef otCallback otApiEnergyScanCallback; typedef otCallback otApiStateChangeCallback; typedef otCallback otApiCommissionerEnergyReportCallback; typedef otCallback otApiCommissionerPanIdConflictCallback; +typedef otCallback otApiJoinerCallback; typedef struct otApiInstance { @@ -127,6 +128,7 @@ typedef struct otApiInstance vector StateChangedCallbacks; vector CommissionerEnergyReportCallbacks; vector CommissionerPanIdConflictCallbacks; + vector JoinerCallbacks; // Constructor otApiInstance() : @@ -358,6 +360,9 @@ otApiFinalize( vector CommissionerPanIdConflictCallbacks(aApitInstance->CommissionerPanIdConflictCallbacks); aApitInstance->CommissionerPanIdConflictCallbacks.clear(); + vector JoinerCallbacks(aApitInstance->JoinerCallbacks); + aApitInstance->JoinerCallbacks.clear(); + #ifdef DEBUG_ASYNC_IO otLogDebgApi("Clearing Threadpool Wait"); #endif @@ -404,6 +409,11 @@ otApiFinalize( CommissionerPanIdConflictCallbacks[i]->Release(true); delete CommissionerPanIdConflictCallbacks[i]; } + for (size_t i = 0; i < JoinerCallbacks.size(); i++) + { + JoinerCallbacks[i]->Release(true); + delete JoinerCallbacks[i]; + } // Clean up threadpool wait if (tpWait) @@ -654,6 +664,39 @@ ProcessNotification( Callback->Release(); } } + else if (Notif->NotifType == OTLWF_NOTIF_JOINER_COMPLETE) + { + otCallback* Callback = nullptr; + + EnterCriticalSection(&aApitInstance->CallbackLock); + + for (size_t i = 0; i < aApitInstance->JoinerCallbacks.size(); i++) + { + if (aApitInstance->JoinerCallbacks[i]->InterfaceGuid == Notif->InterfaceGuid) + { + aApitInstance->JoinerCallbacks[i]->AddRef(); + Callback = aApitInstance->JoinerCallbacks[i]; + break; + } + } + + LeaveCriticalSection(&aApitInstance->CallbackLock); + + // Invoke the callback outside the lock and release ref when done + if (Callback) + { + aApitInstance->SetCallback( + aApitInstance->JoinerCallbacks, + Notif->InterfaceGuid, (otJoinerCallback)nullptr, (PVOID)nullptr + ); + + Callback->Callback( + Notif->JoinerCompletePayload.Error, + Callback->CallbackContext); + + Callback->Release(); + } + } else { // Unexpected notif type @@ -3652,12 +3695,12 @@ ThreadError OTCALL otJoinerStart( _In_ otInstance *aInstance, - const char *aPSKd, - const char *aProvisioningUrl, - const char *aVendorName, - const char *aVendorModel, - const char *aVendorSwVersion, - const char *aVendorData, + _Null_terminated_ const char *aPSKd, + _Null_terminated_ const char *aProvisioningUrl, + _Null_terminated_ const char *aVendorName, + _Null_terminated_ const char *aVendorModel, + _Null_terminated_ const char *aVendorSwVersion, + _Null_terminated_ const char *aVendorData, _In_ otJoinerCallback aCallback, _In_ void *aCallbackContext ) @@ -3690,7 +3733,22 @@ otJoinerStart( memcpy_s(config.VendorSwVersion, sizeof(config.VendorSwVersion), aVendorSwVersion, aVendorSwVersionLength); memcpy_s(config.VendorData, sizeof(config.VendorData), aVendorData, aVendorDataLength); - return DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_JOINER_START, (const otCommissionConfig*)&config)); + aInstance->ApiHandle->SetCallback( + aInstance->ApiHandle->JoinerCallbacks, + aInstance->InterfaceGuid, aCallback, aCallbackContext + ); + + auto ret = DwordToThreadError(SetIOCTL(aInstance, IOCTL_OTLWF_OT_JOINER_START, (const otCommissionConfig*)&config)); + + if (ret != kThreadError_None) + { + aInstance->ApiHandle->SetCallback( + aInstance->ApiHandle->JoinerCallbacks, + aInstance->InterfaceGuid, (otJoinerCallback)nullptr, (PVOID)nullptr + ); + } + + return ret; } OTAPI diff --git a/examples/drivers/windows/otLwf/filter.h b/examples/drivers/windows/otLwf/filter.h index 6e23d3350..f835f2a03 100644 --- a/examples/drivers/windows/otLwf/filter.h +++ b/examples/drivers/windows/otLwf/filter.h @@ -252,6 +252,14 @@ typedef struct _MS_FILTER ULONG otAllocationID; #endif + // + // OpenThread Joiner Vendor Info + // + char otVendorName[OPENTHREAD_VENDOR_NAME_MAX_LENGTH + 1]; + char otVendorModel[OPENTHREAD_VENDOR_MODEL_MAX_LENGTH + 1]; + char otVendorSwVersion[OPENTHREAD_VENDOR_SW_VERSION_MAX_LENGTH + 1]; + char otVendorData[OPENTHREAD_VENDOR_DATA_MAX_LENGTH + 1]; + // // OpenThread context buffer // diff --git a/examples/drivers/windows/otLwf/iocontrol.c b/examples/drivers/windows/otLwf/iocontrol.c index d86ceb64d..d2e3843d3 100644 --- a/examples/drivers/windows/otLwf/iocontrol.c +++ b/examples/drivers/windows/otLwf/iocontrol.c @@ -5254,18 +5254,38 @@ otLwfIoCtl_otJoinerStart( if (InBufferLength >= sizeof(otCommissionConfig)) { otCommissionConfig *aConfig = (otCommissionConfig*)InBuffer; - status = ThreadErrorToNtstatus( - otJoinerStart( - pFilter->otCtx, - (const char*)aConfig->PSKd, - (const char*)aConfig->ProvisioningUrl, - (const char*)aConfig->VendorName, - (const char*)aConfig->VendorModel, - (const char*)aConfig->VendorSwVersion, - (const char*)aConfig->VendorData, - NULL, // TODO: handle the joiner completion callback - NULL) - ); + +#define IsNotNullTerminated(buf) (strnlen(buf, sizeof(buf)) == sizeof(buf)) + + if (IsNotNullTerminated(aConfig->PSKd) || + IsNotNullTerminated(aConfig->ProvisioningUrl) || + IsNotNullTerminated(aConfig->VendorName) || + IsNotNullTerminated(aConfig->VendorModel) || + IsNotNullTerminated(aConfig->VendorSwVersion) || + IsNotNullTerminated(aConfig->VendorData)) + { + status = STATUS_INVALID_PARAMETER; + } + else + { + strcpy_s(pFilter->otVendorName, sizeof(pFilter->otVendorName), aConfig->VendorName); + strcpy_s(pFilter->otVendorModel, sizeof(pFilter->otVendorModel), aConfig->VendorModel); + strcpy_s(pFilter->otVendorSwVersion, sizeof(pFilter->otVendorSwVersion), aConfig->VendorSwVersion); + strcpy_s(pFilter->otVendorData, sizeof(pFilter->otVendorData), aConfig->VendorData); + + status = ThreadErrorToNtstatus( + otJoinerStart( + pFilter->otCtx, + aConfig->PSKd, + aConfig->ProvisioningUrl, + pFilter->otVendorName, + pFilter->otVendorModel, + pFilter->otVendorSwVersion, + pFilter->otVendorData, + otLwfJoinerCallback, + pFilter) + ); + } } return status; diff --git a/examples/drivers/windows/otLwf/thread.c b/examples/drivers/windows/otLwf/thread.c index acbf93818..093860e33 100644 --- a/examples/drivers/windows/otLwf/thread.c +++ b/examples/drivers/windows/otLwf/thread.c @@ -531,6 +531,26 @@ void otLwfCommissionerPanIdConflictCallback(uint16_t aPanId, uint32_t aChannelMa LogFuncExit(DRIVER_DEFAULT); } +void otLwfJoinerCallback(ThreadError aError, _In_ void *aContext) +{ + LogFuncEntry(DRIVER_DEFAULT); + + PMS_FILTER pFilter = (PMS_FILTER)aContext; + PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter); + if (NotifEntry) + { + RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY)); + NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid; + NotifEntry->Notif.NotifType = OTLWF_NOTIF_JOINER_COMPLETE; + + NotifEntry->Notif.JoinerCompletePayload.Error = aError; + + otLwfIndicateNotification(NotifEntry); + } + + LogFuncExit(DRIVER_DEFAULT); +} + _IRQL_requires_max_(DISPATCH_LEVEL) void otLwfThreadValueIs( diff --git a/examples/drivers/windows/otLwf/thread.h b/examples/drivers/windows/otLwf/thread.h index fe3377f98..965349c55 100644 --- a/examples/drivers/windows/otLwf/thread.h +++ b/examples/drivers/windows/otLwf/thread.h @@ -152,6 +152,7 @@ void otLwfEnergyScanCallback(_In_ otEnergyScanResult *aResult, _In_ void *aConte 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); +void otLwfJoinerCallback(ThreadError aError, _In_ void *aContext); // // Value Callbacks