From c81d7098552d64717377b8b60f03655e0e380061 Mon Sep 17 00:00:00 2001 From: Ajay Barboza Date: Thu, 7 Feb 2019 17:39:04 -0800 Subject: [PATCH 1/7] initial cmake changes --- PnpBridge/CMakeLists.txt | 44 +++++++++++++++++++ PnpBridge/src/CMakeLists.txt | 3 ++ PnpBridge/src/PnpBridge/ConfigurationParser.c | 8 ++-- PnpBridge/src/PnpBridge/PnpAdapterManger.c | 5 ++- PnpBridge/src/PnpBridge/PnpBridge.c | 3 +- PnpBridge/src/PnpBridge/utility.c | 2 +- 6 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 PnpBridge/CMakeLists.txt create mode 100644 PnpBridge/src/CMakeLists.txt diff --git a/PnpBridge/CMakeLists.txt b/PnpBridge/CMakeLists.txt new file mode 100644 index 0000000..1d1f8ec --- /dev/null +++ b/PnpBridge/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 2.8.11) +project(azure_iot_pnp_bridge) + +if (POLICY CMP0042) + cmake_policy(SET CMP0042 NEW) +endif() + +# +#making a global variable to know if we are on linux, windows, or macosx. +if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + set(WINDOWS TRUE) +elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") + set(LINUX TRUE) + # on Linux, enable valgrind + # these commands (MEMORYCHECK...) need to apear BEFORE include(CTest) or they will not have any effect + find_program(MEMORYCHECK_COMMAND valgrind) + set(MEMORYCHECK_COMMAND_OPTIONS "--leak-check=full --error-exitcode=1") +elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(MACOSX TRUE) + add_definitions(-DMACOSX) +endif() + + +if (MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /wd4232") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4 /wd4232") + # Make warning as error + add_definitions(/WX) +else() + # Make warning as error + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") +endif() + + +IF(WIN32) + # windows needs this define + add_definitions(-D_CRT_SECURE_NO_WARNINGS) +endif() + +set(skip_samples ON) + +add_subdirectory(src) +add_subdirectory(deps/azure-iot-sdk-c-pnp) \ No newline at end of file diff --git a/PnpBridge/src/CMakeLists.txt b/PnpBridge/src/CMakeLists.txt new file mode 100644 index 0000000..babd373 --- /dev/null +++ b/PnpBridge/src/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.11) + +add_subdirectory(PnpBridge) \ No newline at end of file diff --git a/PnpBridge/src/PnpBridge/ConfigurationParser.c b/PnpBridge/src/PnpBridge/ConfigurationParser.c index b1cb32d..ff150f1 100644 --- a/PnpBridge/src/PnpBridge/ConfigurationParser.c +++ b/PnpBridge/src/PnpBridge/ConfigurationParser.c @@ -104,7 +104,7 @@ PNPBRIDGE_RESULT Configuration_IsDeviceConfigured(JSON_Value* config, JSON_Objec int res = -1; bool foundMatch = false; - const char* formatId = json_object_dotget_string(Message, "Identity"); + // const char* formatId = json_object_dotget_string(Message, "Identity"); discMatchParams = json_object_get_object(Message, "MatchParameters"); // There needs to be only one match at the end. @@ -115,7 +115,7 @@ PNPBRIDGE_RESULT Configuration_IsDeviceConfigured(JSON_Value* config, JSON_Objec continue; } - const char* deviceFormatId = json_object_dotget_string(moduleParams, "Identity"); +// const char* deviceFormatId = json_object_dotget_string(moduleParams, "Identity"); if (true) { //strcmp(deviceFormatId, formatId) == 0) { JSON_Object* matchCriteria = json_object_dotget_object(device, "MatchFilters"); const char* matchType = json_object_get_string(matchCriteria, "MatchType"); @@ -138,8 +138,8 @@ PNPBRIDGE_RESULT Configuration_IsDeviceConfigured(JSON_Value* config, JSON_Objec JSON_Object* matchParameters = json_object_dotget_object(matchCriteria, "MatchParameters"); const size_t matchParameterCount = json_object_get_count(matchParameters); - for (int i = 0; i < (int)matchParameterCount; i++) { - const char* name = json_object_get_name(matchParameters, i); + for (int j = 0; j < (int)matchParameterCount; j++) { + const char* name = json_object_get_name(matchParameters, j); const char* value = json_object_get_string(matchParameters, name); if (!json_object_dothas_value(discMatchParams, name)) { diff --git a/PnpBridge/src/PnpBridge/PnpAdapterManger.c b/PnpBridge/src/PnpBridge/PnpAdapterManger.c index 063f3b8..752bc1e 100644 --- a/PnpBridge/src/PnpBridge/PnpAdapterManger.c +++ b/PnpBridge/src/PnpBridge/PnpAdapterManger.c @@ -113,7 +113,6 @@ void PnpAdapterManager_Release(PPNP_ADAPTER_MANAGER adapter) { PNPBRIDGE_RESULT PnpAdapterManager_SupportsIdentity(PPNP_ADAPTER_MANAGER adapter, JSON_Object* Message, bool* supported, int* key) { bool containsMessageKey = false; - char* interfaceId = NULL; JSON_Object* pnpParams = json_object_get_object(Message, "PnpParameters"); char* getIdentity = (char*) json_object_get_string(pnpParams, "Identity"); MAP_RESULT mapResult; @@ -143,6 +142,8 @@ PNPBRIDGE_RESULT PnpAdapterManager_CreatePnpInterface(PPNP_ADAPTER_MANAGER adapt // Get the module using the key as index PPNP_ADAPTER pnpAdapter = PNP_ADAPTER_MANIFEST[key]; + AZURE_UNREFERENCED_PARAMETER(adapter); + PPNPADAPTER_INTERFACE pnpInterface = malloc(sizeof(PNPADAPTER_INTERFACE)); //pnpInterface->Interface = InterfaceClient; @@ -164,6 +165,8 @@ PNPBRIDGE_RESULT PnpAdapterManager_ReleasePnpInterface(PPNP_ADAPTER_MANAGER adap return PNPBRIDGE_INVALID_ARGS; } + AZURE_UNREFERENCED_PARAMETER(adapter); + PPNPADAPTER_INTERFACE pnpInterface = (PPNPADAPTER_INTERFACE)interfaceClient; // Get the module index diff --git a/PnpBridge/src/PnpBridge/PnpBridge.c b/PnpBridge/src/PnpBridge/PnpBridge.c index 8d0bd33..567a019 100644 --- a/PnpBridge/src/PnpBridge/PnpBridge.c +++ b/PnpBridge/src/PnpBridge/PnpBridge.c @@ -166,6 +166,7 @@ void PnpBridge_Release() { int PnpBridge_Worker_Thread(void* threadArgument) { + AZURE_UNREFERENCED_PARAMETER(threadArgument); PNPBRIDGE_RESULT result = PNPBRIDGE_OK; // Start Device Discovery @@ -312,7 +313,7 @@ PNPBRIDGE_RESULT PnpBridge_DeviceChangeCallback(PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD id[idSize - 1] = '\0'; // check if interface is already published - PPNPBRIDGE_INTERFACE_TAG* interfaceTags = malloc(sizeof(PPNPBRIDGE_INTERFACE_TAG)*g_PnpBridge->publishedInterfaceCount); + //PPNPBRIDGE_INTERFACE_TAG* interfaceTags = malloc(sizeof(PPNPBRIDGE_INTERFACE_TAG)*g_PnpBridge->publishedInterfaceCount); LIST_ITEM_HANDLE interfaceItem = singlylinkedlist_get_head_item(g_PnpBridge->publishedInterfaces); while (interfaceItem != NULL) { PPNPBRIDGE_INTERFACE_TAG interface = (PPNPBRIDGE_INTERFACE_TAG) singlylinkedlist_item_get_value(interfaceItem); diff --git a/PnpBridge/src/PnpBridge/utility.c b/PnpBridge/src/PnpBridge/utility.c index a8a9682..68d95d8 100644 --- a/PnpBridge/src/PnpBridge/utility.c +++ b/PnpBridge/src/PnpBridge/utility.c @@ -9,7 +9,7 @@ MAP_RESULT Map_Add_Index(MAP_HANDLE handle, const char* key, int value) { char a[2] = { 0 }; - a[0] = value; + a[0] = (char)value; return Map_Add(handle, key, a); } From 880e01cb7729b1bfd63a2f1a77236dca4e024048 Mon Sep 17 00:00:00 2001 From: Ajay Barboza Date: Thu, 7 Feb 2019 17:40:16 -0800 Subject: [PATCH 2/7] missing cmake --- PnpBridge/src/PnpBridge/CMakeLists.txt | 99 ++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 PnpBridge/src/PnpBridge/CMakeLists.txt diff --git a/PnpBridge/src/PnpBridge/CMakeLists.txt b/PnpBridge/src/PnpBridge/CMakeLists.txt new file mode 100644 index 0000000..2b910c8 --- /dev/null +++ b/PnpBridge/src/PnpBridge/CMakeLists.txt @@ -0,0 +1,99 @@ +#Copyright (c) Microsoft. All rights reserved. +#Licensed under the MIT license. See LICENSE file in the project root for full license information. + +cmake_minimum_required(VERSION 2.8.11) +#this is CMakeLists for pnp_bridge + +set(PROJECT_NAME PnpBridge) + +if(POLICY CMP0042) + cmake_policy(SET CMP0042 NEW) +endif() + +# compileAsC99() + +set(pnp_bridge_c_files + ./ConfigurationParser.c + ./DiscoveryManager.c + ./PnpAdapterManger.c + ./PnpBridge.c + ./utility.c + ./Adapters/AdapterManifest.c +) + + # ./PnpBridgeService.c + # ./Adapters/SerialPnp/SerialPnp.c + # ./Adapters/Camera/CameraIotPnpAPIs.cpp + # ./Adapters/Camera/CameraPnpDiscovery.cpp + # ./Adapters/Camera/CameraStatConsumer.cpp + # ./Adapters/Camera/JsonWrapper.cpp + # ./Adapters/Camera/CameraIotPnpDevice.cpp + # ./Adapters/CoreDeviceHealth/CoreDeviceHealth.h + # ./Adapters/CoreDeviceHealth/WindowsPnpDeviceDiscovery.h + +set(pnp_bridge_h_files + ./CmdAndPropHandler.h + ./common.h + ./ConfigurationParser.h + ./DiscoveryAdapterInterface.h + ./DiscoveryManager.h + ./PnpAdapterInterface.h + ./PnpAdapterManager.h + ./PnpBridge.h + ./PnpBridgeh.h +) + + # ./Adapters/Camera/CameraIotPnpAPIs.h + # ./Adapters/Camera/CameraIotPnpDevice.h + # ./Adapters/Camera/CameraPnpDiscovery.h + # ./Adapters/Camera/CameraStatConsumer.h + # ./Adapters/JsonWrapper.h + # ./Adapters/pch.h + # ./Adapters/CoreDeviceHealth/CoreDeviceHealth.c + # ./Adapters/CoreDeviceHealth/WindowsPnPDeviceDiscovery.c + +set(pnp_bridge_libs) + +set(install_staticlibs + ${PROJECT_NAME} +) + +set(pnp_bridge_h_install_files + ${pnp_bridge_h_files} +) + +set(pnp_bridge_INC_FOLDER ${CMAKE_CURRENT_LIST_DIR} CACHE INTERNAL "this is what needs to be included if using pnp_bridge lib" FORCE) + +include_directories(../../deps/azure-iot-sdk-c-pnp/deps/parson) +include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/inc) +include_directories(../../deps/azure-iot-sdk-c-pnp/pnp_client/inc) +include_directories(../../deps/azure-iot-sdk-c-pnp/iothub_client/inc) +include_directories(${pnp_bridge_INC_FOLDER}) + +IF(WIN32) + #windows needs this define + add_definitions(-D_CRT_SECURE_NO_WARNINGS) + add_definitions(-DGB_MEASURE_MEMORY_FOR_THIS -DGB_DEBUG_ALLOC) +ENDIF(WIN32) + +add_definitions(-DPNP_LOGGING_ENABLED) + + +add_executable(${PROJECT_NAME} + ${pnp_bridge_c_files} + ${pnp_bridge_h_files} +) + +target_link_libraries(${PROJECT_NAME} ${pnp_bridge_libs}) +target_link_libraries(${PROJECT_NAME} iothub_client parson pnp_client iothub_client_http_transport iothub_client_amqp_transport iothub_client_amqp_ws_transport iothub_client_mqtt_transport iothub_client_mqtt_ws_transport umqtt aziotsharedutil) + +set(pnp_bridge_libs + ${PROJECT_NAME} + ${pnp_bridge_libs} +) + +# install(FILES ${pnp_bridge_h_install_files} + # DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/azureiot/pnp) +# install(TARGETS ${install_staticlibs} + # ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + # LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) \ No newline at end of file From d250c531fcee4cfcf265b0d2c0ead01b3d19d1c2 Mon Sep 17 00:00:00 2001 From: Ajay Barboza Date: Wed, 13 Feb 2019 09:03:40 -0800 Subject: [PATCH 3/7] Allow publishing multiple interfaces from a CreateInterface PnpAdapter callback --- .../Adapters/Camera/CameraIotPnpAPIs.cpp | 15 +- .../Adapters/Camera/CameraIotPnpAPIs.h | 2 +- .../{ => Adapters}/CmdAndPropHandler.h | 0 .../CoreDeviceHealth/CoreDeviceHealth.c | 42 +- .../PnpBridge/Adapters/SerialPnp/SerialPnp.c | 1739 +++++++++-------- .../PnpBridge/Adapters/SerialPnp/SerialPnp.h | 151 +- PnpBridge/src/PnpBridge/ConfigurationParser.c | 79 +- PnpBridge/src/PnpBridge/ConfigurationParser.h | 2 + PnpBridge/src/PnpBridge/DiscoveryManager.c | 143 +- PnpBridge/src/PnpBridge/DiscoveryManager.h | 2 + PnpBridge/src/PnpBridge/IotHubComms.c | 102 + PnpBridge/src/PnpBridge/IotHubComms.h | 17 + PnpBridge/src/PnpBridge/PnpAdapterInterface.h | 101 +- PnpBridge/src/PnpBridge/PnpAdapterManager.h | 43 +- PnpBridge/src/PnpBridge/PnpAdapterManger.c | 237 ++- PnpBridge/src/PnpBridge/PnpBridge.c | 308 +-- PnpBridge/src/PnpBridge/PnpBridge.h | 10 + PnpBridge/src/PnpBridge/PnpBridge.log | 1 + PnpBridge/src/PnpBridge/PnpBridge.vcxproj | 11 +- .../src/PnpBridge/PnpBridge.vcxproj.filters | 87 +- PnpBridge/src/PnpBridge/PnpBridgeCommon.h | 21 +- PnpBridge/src/PnpBridge/PnpBridgeh.h | 10 +- PnpBridge/src/PnpBridge/SamplePnpInteface.c | 7 - PnpBridge/src/PnpBridge/config.json | 14 + .../src/PnpBridge/core/PnpAdapterInterface.c | 114 ++ .../src/PnpBridge/core/PnpBridgeMemory.c | 41 + .../src/PnpBridge/core/PnpBridgeMemory.h | 39 + PnpBridge/src/PnpBridge/targetver.h | 8 - 28 files changed, 1975 insertions(+), 1371 deletions(-) rename PnpBridge/src/PnpBridge/{ => Adapters}/CmdAndPropHandler.h (100%) create mode 100644 PnpBridge/src/PnpBridge/IotHubComms.c create mode 100644 PnpBridge/src/PnpBridge/IotHubComms.h create mode 100644 PnpBridge/src/PnpBridge/PnpBridge.log delete mode 100644 PnpBridge/src/PnpBridge/SamplePnpInteface.c create mode 100644 PnpBridge/src/PnpBridge/core/PnpAdapterInterface.c create mode 100644 PnpBridge/src/PnpBridge/core/PnpBridgeMemory.c create mode 100644 PnpBridge/src/PnpBridge/core/PnpBridgeMemory.h delete mode 100644 PnpBridge/src/PnpBridge/targetver.h diff --git a/PnpBridge/src/PnpBridge/Adapters/Camera/CameraIotPnpAPIs.cpp b/PnpBridge/src/PnpBridge/Adapters/Camera/CameraIotPnpAPIs.cpp index da060bd..1e343cc 100644 --- a/PnpBridge/src/PnpBridge/Adapters/Camera/CameraIotPnpAPIs.cpp +++ b/PnpBridge/src/PnpBridge/Adapters/Camera/CameraIotPnpAPIs.cpp @@ -11,9 +11,9 @@ PNP_ADAPTER CameraPnpInterface = { "camera-health-monitor", CameraPnpInterfaceInitialize, CameraPnpInterfaceBind, - CameraPnpInterfaceRelease, CameraPnpInterfaceShutdown }; +// CameraPnpInterfaceRelease, // Camera discovery API entry points. CameraPnpDiscovery* g_pPnpDiscovery = nullptr; @@ -74,7 +74,7 @@ CameraPnpInterfaceShutdown( int CameraPnpInterfaceBind( - _In_ PNPADAPTER_INTERFACE_HANDLE Interface, + _In_ PNPADAPTER_CONTEXT adapterHandle, _In_ PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, _In_ PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload ) @@ -87,6 +87,7 @@ CameraPnpInterfaceBind( JSON_Value* jmsg; JSON_Object* jobj; + PNPADAPTER_INTERFACE_HANDLE Interface = NULL; if (nullptr == Interface || nullptr == payload || nullptr == payload->Context) { @@ -103,13 +104,13 @@ CameraPnpInterfaceBind( pnpInterfaceClient = PnP_InterfaceClient_Create(pnpDeviceClientHandle, interfaceId, nullptr, nullptr, nullptr); RETURN_HR_IF_NULL (E_UNEXPECTED, pnpInterfaceClient); - PnpAdapter_SetPnpInterfaceClient(Interface, pnpInterfaceClient); + //PnpAdapter_SetPnpInterfaceClient(Interface, pnpInterfaceClient); pIotPnp = std::make_unique(); - RETURN_IF_FAILED (pIotPnp->Initialize(PnpAdapter_GetPnpInterfaceClient(Interface), nullptr /* cameraName.c_str() */)); + RETURN_IF_FAILED (pIotPnp->Initialize(PnpAdapterInterface_GetPnpInterfaceClient(Interface), nullptr /* cameraName.c_str() */)); RETURN_IF_FAILED (pIotPnp->StartTelemetryWorker()); - RETURN_HR_IF (E_UNEXPECTED, 0 != PnpAdapter_SetContext(Interface, (void*)pIotPnp.get())); + RETURN_HR_IF (E_UNEXPECTED, 0 != PnpAdapterInterface_SetContext(Interface, (void*)pIotPnp.get())); // Our interface context now owns the object. pIotPnp.release(); @@ -122,7 +123,7 @@ CameraPnpInterfaceRelease( _In_ PNPADAPTER_INTERFACE_HANDLE Interface ) { - CameraIotPnpDevice* p = (CameraIotPnpDevice*)PnpAdapter_GetContext(Interface); + CameraIotPnpDevice* p = (CameraIotPnpDevice*)PnpAdapterInterface_GetContext(Interface); if (p != nullptr) { @@ -135,7 +136,7 @@ CameraPnpInterfaceRelease( // Clear our context to make sure we don't keep a stale // object around. - (void) PnpAdapter_SetContext(Interface, nullptr); + (void) PnpAdapterInterface_SetContext(Interface, nullptr); return S_OK; } diff --git a/PnpBridge/src/PnpBridge/Adapters/Camera/CameraIotPnpAPIs.h b/PnpBridge/src/PnpBridge/Adapters/Camera/CameraIotPnpAPIs.h index 5b7fa83..b6a171c 100644 --- a/PnpBridge/src/PnpBridge/Adapters/Camera/CameraIotPnpAPIs.h +++ b/PnpBridge/src/PnpBridge/Adapters/Camera/CameraIotPnpAPIs.h @@ -31,7 +31,7 @@ CameraPnpInterfaceShutdown( int CameraPnpInterfaceBind( - _In_ PNPADAPTER_INTERFACE_HANDLE Interface, + _In_ PNPADAPTER_CONTEXT adapterHandle, _In_ PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, _In_ PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload ); diff --git a/PnpBridge/src/PnpBridge/CmdAndPropHandler.h b/PnpBridge/src/PnpBridge/Adapters/CmdAndPropHandler.h similarity index 100% rename from PnpBridge/src/PnpBridge/CmdAndPropHandler.h rename to PnpBridge/src/PnpBridge/Adapters/CmdAndPropHandler.h diff --git a/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.c b/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.c index 2f4724e..1a04835 100644 --- a/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.c +++ b/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.c @@ -83,9 +83,14 @@ CoreDevice_OnDeviceNotification( return 0; } + +int CoreDevice_ReleaseInterface(PNPADAPTER_INTERFACE_HANDLE pnpInterface) { + return 0; +} + HCMNOTIFICATION CoreDevice_hNotifyCtx = NULL; -int CoreDevice_CreatePnpInterface(PNPADAPTER_INTERFACE_HANDLE Interface, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD param) { +int CoreDevice_CreatePnpInterface(PNPADAPTER_CONTEXT adapterHandle, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD param) { DWORD cmRet; CM_NOTIFY_FILTER cmFilter; PNP_INTERFACE_CLIENT_HANDLE pnpInterfaceClient; @@ -95,17 +100,30 @@ int CoreDevice_CreatePnpInterface(PNPADAPTER_INTERFACE_HANDLE Interface, PNP_DEV const char* interfaceId = json_object_get_string(args, "InterfaceId"); const char* hardwareId = json_object_get_string(args, "HardwareId"); const char* symbolicLink = json_object_get_string(args, "SymbolicLink"); + const char* persistent = json_object_get_string(args, "Persistent"); - if (Interface == NULL) { - return -1; - } + PNPADAPTER_INTERFACE_HANDLE Interface = NULL; pnpInterfaceClient = PnP_InterfaceClient_Create(pnpDeviceClientHandle, interfaceId, NULL, NULL, NULL); if (NULL == pnpInterfaceClient) { return -1; } - PnpAdapter_SetPnpInterfaceClient(Interface, pnpInterfaceClient); + // Create PnpAdapter Interface + { + PNPADPATER_INTERFACE_INIT_PARAMS interfaceParams = { 0 }; + interfaceParams.releaseInterface = CoreDevice_ReleaseInterface; + PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface; + + int result = PnpAdapterInterface_Create(adapterHandle, interfaceId, pnpInterfaceClient, &pnpAdapterInterface, &interfaceParams); + if (result < 0) { + return result; + } + } + + if (NULL != persistent && stricmp(persistent, "true") == 0) { + return 0; + } ZeroMemory(&cmFilter, sizeof(cmFilter)); cmFilter.cbSize = sizeof(cmFilter); @@ -181,10 +199,6 @@ int SendDeviceDisconnectedEventAsync(PNP_INTERFACE_CLIENT_HANDLE pnpInterfaceCor return result; } -int CoreDevice_ReleaseInterface(PNPADAPTER_INTERFACE_HANDLE pnpInterface) { - return 0; -} - int CoreDevice_Initialize(const char* adapterArgs) { g_coreDeviceWatchers = singlylinkedlist_create(); if (NULL == g_coreDeviceWatchers) { @@ -202,9 +216,9 @@ int CoreDevice_Shutdown() { } PNP_ADAPTER CoreDeviceHealthInterface = { - .Identity = "core-device-health", - .Initialize = CoreDevice_Initialize, - .Shutdown = CoreDevice_Shutdown, - .CreatePnpInterface = CoreDevice_CreatePnpInterface, - .ReleaseInterface = CoreDevice_ReleaseInterface, + .identity = "core-device-health", + .initialize = CoreDevice_Initialize, + .shutdown = CoreDevice_Shutdown, + .createPnpInterface = CoreDevice_CreatePnpInterface, + //.releaseInterface = CoreDevice_ReleaseInterface, }; \ No newline at end of file diff --git a/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.c b/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.c index 1835862..84ae264 100644 --- a/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.c +++ b/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.c @@ -23,509 +23,504 @@ // Temporary redirection for property and command handling since PnP C SDK property change // callback doesn't provide the command name. void SerialPnp_PropertyUpdateHandlerRedirect(int index, unsigned const char* propertyInitial, - size_t propertyInitialLen, unsigned const char* propertyDataUpdated, - size_t propertyDataUpdatedLen, int desiredVersion, void* userContextCallback); + size_t propertyInitialLen, unsigned const char* propertyDataUpdated, + size_t propertyDataUpdatedLen, int desiredVersion, void* userContextCallback); void SerialPnp_CommandUpdateHandlerRedirect(int index, - const PNP_CLIENT_COMMAND_REQUEST* pnpClientCommandContext, - PNP_CLIENT_COMMAND_RESPONSE* pnpClientCommandResponseContext, - void* userContextCallback); + const PNP_CLIENT_COMMAND_REQUEST* pnpClientCommandContext, + PNP_CLIENT_COMMAND_RESPONSE* pnpClientCommandResponseContext, + void* userContextCallback); #define CMD_PROP_HANDLER_ADAPTER_NAME SerialPnp #define PROP_HANDLER_ADAPTER_METHOD SerialPnp_PropertyUpdateHandlerRedirect #define CMD_HANDLER_ADAPTER_METHOD SerialPnp_CommandUpdateHandlerRedirect -#include +#include "adapters/CmdAndPropHandler.h" // END - PNPCSDK#20 -SINGLYLINKEDLIST_HANDLE g_InterfaceDefinitions = NULL; - int SerialPnp_UartReceiver(void* context) { - BYTE msgBuffer[2048]; - PBYTE p = msgBuffer; - UINT16 SizeToRead = 0; - int result = 0; - PSERIAL_DEVICE_CONTEXT deviceContext = (PSERIAL_DEVICE_CONTEXT) context; + BYTE msgBuffer[2048]; + PBYTE p = msgBuffer; + UINT16 SizeToRead = 0; + int result = 0; + PSERIAL_DEVICE_CONTEXT deviceContext = (PSERIAL_DEVICE_CONTEXT)context; - while (result >= 0) { - byte* desc = NULL; - DWORD length; + while (result >= 0) { + byte* desc = NULL; + DWORD length; - SerialPnp_RxPacket(deviceContext, &desc, &length, 0x00); - SerialPnp_UnsolicitedPacket(deviceContext, desc, length); + SerialPnp_RxPacket(deviceContext, &desc, &length, 0x00); + SerialPnp_UnsolicitedPacket(deviceContext, desc, length); - if (desc != NULL) { - free(desc); - } - } + if (desc != NULL) { + free(desc); + } + } - return 0; + return 0; } void SerialPnp_TxPacket(PSERIAL_DEVICE_CONTEXT serialDevice, byte* OutPacket, int Length) { - int txLength = 1 + Length; - // First iterate through and find out our new length - for (int i = 0; ihSerial, SerialPnp_TxPacket, txLength, &write_size, NULL)) - { - LogError("write failed"); - } + DWORD write_size = 0; + if (!WriteFile(serialDevice->hSerial, SerialPnp_TxPacket, txLength, &write_size, NULL)) + { + LogError("write failed"); + } - free(SerialPnp_TxPacket); + free(SerialPnp_TxPacket); } -const EventDefinition* SerialPnp_LookupEvent(char* EventName, int InterfaceId) +const EventDefinition* SerialPnp_LookupEvent(SINGLYLINKEDLIST_HANDLE interfaceDefinitions, char* EventName, int InterfaceId) { - const InterfaceDefinition* interfaceDef; - LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(g_InterfaceDefinitions); + const InterfaceDefinition* interfaceDef; + LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(interfaceDefinitions); - for(int i=0; iEvents; - LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(events); - const EventDefinition* ev; - while (eventDef != NULL) { - ev = singlylinkedlist_item_get_value(eventDef); - if (strcmp(ev->defintion.Name, EventName) == 0) { - return ev; - } - eventDef = singlylinkedlist_get_next_item(eventDef); - } + SINGLYLINKEDLIST_HANDLE events = interfaceDef->Events; + LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(events); + const EventDefinition* ev; + while (eventDef != NULL) { + ev = singlylinkedlist_item_get_value(eventDef); + if (strcmp(ev->defintion.Name, EventName) == 0) { + return ev; + } + eventDef = singlylinkedlist_get_next_item(eventDef); + } - return NULL; + return NULL; } byte* SerialPnp_StringSchemaToBinary(Schema Schema, byte* data, int* length) { - byte* bd = NULL; + byte* bd = NULL; - if ((Schema == Float) || (Schema == Int)) - { - bd = malloc(sizeof(byte)*4); - *length = 4; + if ((Schema == Float) || (Schema == Int)) + { + bd = malloc(sizeof(byte) * 4); + *length = 4; - if (Schema == Float) - { - float x = 0; - x = (float) atof(data); - memcpy(bd, &x, sizeof(float)); - } - else if (Schema == Int) - { - int x; - x = atoi(data); - memcpy(bd, &x, sizeof(int)); - } - } - else if (Schema == Boolean) - { - bd = malloc(sizeof(byte) * 1); - *length = 1; - if (stricmp(data, "true")) { - bd[0] = 1; - } - else if (stricmp(data, "false")) { - bd[0] = 1; - } - else { - free(bd); - *length = 0; - bd = NULL; - } - } + if (Schema == Float) + { + float x = 0; + x = (float)atof(data); + memcpy(bd, &x, sizeof(float)); + } + else if (Schema == Int) + { + int x; + x = atoi(data); + memcpy(bd, &x, sizeof(int)); + } + } + else if (Schema == Boolean) + { + bd = malloc(sizeof(byte) * 1); + *length = 1; + if (stricmp(data, "true")) { + bd[0] = 1; + } + else if (stricmp(data, "false")) { + bd[0] = 1; + } + else { + free(bd); + *length = 0; + bd = NULL; + } + } - return bd; + return bd; } char* SerialPnp_BinarySchemaToString(Schema Schema, byte* Data, byte length) { - char* rxstrdata = malloc(256); + char* rxstrdata = malloc(256); - if ((Schema == Float) && (length == 4)) - { - float *fa = malloc(sizeof(float)); - memcpy(fa, Data, 4); - sprintf_s(rxstrdata, 256, "%.6f", *fa); - } - else if (((Schema == Int) && (length == 4))) - { - int *fa = malloc(sizeof(int)); - memcpy(fa, Data, 4); - sprintf_s(rxstrdata, 256, "%d", *fa); - } + if ((Schema == Float) && (length == 4)) + { + float *fa = malloc(sizeof(float)); + memcpy(fa, Data, 4); + sprintf_s(rxstrdata, 256, "%.6f", *fa); + } + else if (((Schema == Int) && (length == 4))) + { + int *fa = malloc(sizeof(int)); + memcpy(fa, Data, 4); + sprintf_s(rxstrdata, 256, "%d", *fa); + } - return rxstrdata; + return rxstrdata; } void SerialPnp_UnsolicitedPacket(PSERIAL_DEVICE_CONTEXT device, byte* packet, DWORD length) { - // Got an event - if (packet[2] == 0x0A) { - byte rxNameLength = packet[5]; - byte rxInterfaceId = packet[4]; - DWORD rxDataSize = length - rxNameLength - 6; + // Got an event + if (packet[2] == 0x0A) { + byte rxNameLength = packet[5]; + byte rxInterfaceId = packet[4]; + DWORD rxDataSize = length - rxNameLength - 6; - //string event_name = Encoding.UTF8.GetString(packet, 6, rxNameLength); - char* event_name = malloc(sizeof(char)*(rxNameLength + 1)); - memcpy(event_name, packet + 6, rxNameLength); - event_name[rxNameLength] = '\0'; + //string event_name = Encoding.UTF8.GetString(packet, 6, rxNameLength); + char* event_name = malloc(sizeof(char)*(rxNameLength + 1)); + memcpy(event_name, packet + 6, rxNameLength); + event_name[rxNameLength] = '\0'; - const EventDefinition* ev = SerialPnp_LookupEvent(event_name, rxInterfaceId); + const EventDefinition* ev = SerialPnp_LookupEvent(device->InterfaceDefinitions, event_name, rxInterfaceId); - byte* rxData = malloc(sizeof(byte)*rxDataSize); - memcpy(rxData, packet + 6 + rxNameLength, rxDataSize); + byte* rxData = malloc(sizeof(byte)*rxDataSize); + memcpy(rxData, packet + 6 + rxNameLength, rxDataSize); - char* rxstrdata = SerialPnp_BinarySchemaToString(ev->DataSchema, rxData, (byte) rxDataSize); - LogInfo("%s: %s", ev->defintion.Name, rxstrdata); + char* rxstrdata = SerialPnp_BinarySchemaToString(ev->DataSchema, rxData, (byte)rxDataSize); + LogInfo("%s: %s", ev->defintion.Name, rxstrdata); - SerialPnp_SendEventAsync(device->InterfaceHandle, ev->defintion.Name, rxstrdata); + SerialPnp_SendEventAsync(PnpAdapterInterface_GetPnpInterfaceClient(device->pnpAdapterInterface), ev->defintion.Name, rxstrdata); - free(event_name); - free(rxData); - } - // Got a command update - else if (packet[2] == 0x08) - { - // TODO - } - else if (packet[2] == 0x08) { + free(event_name); + free(rxData); + } + // Got a command update + else if (packet[2] == 0x08) + { + // TODO + } + else if (packet[2] == 0x08) { - } + } } -const PropertyDefinition* SerialPnp_LookupProperty(const char* propertyName, int InterfaceId) +const PropertyDefinition* SerialPnp_LookupProperty(SINGLYLINKEDLIST_HANDLE interfaceDefinitions, const char* propertyName, int InterfaceId) { - LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(g_InterfaceDefinitions); - const InterfaceDefinition* interfaceDef; + LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(interfaceDefinitions); + const InterfaceDefinition* interfaceDef; - for (int i = 0; iProperties; - LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(property); - const PropertyDefinition* ev; - while (eventDef != NULL) { - ev = singlylinkedlist_item_get_value(eventDef); - if (strcmp(ev->defintion.Name, propertyName) == 0) { - return ev; - } - eventDef = singlylinkedlist_get_next_item(eventDef); - } + SINGLYLINKEDLIST_HANDLE property = interfaceDef->Properties; + LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(property); + const PropertyDefinition* ev; + while (eventDef != NULL) { + ev = singlylinkedlist_item_get_value(eventDef); + if (strcmp(ev->defintion.Name, propertyName) == 0) { + return ev; + } + eventDef = singlylinkedlist_get_next_item(eventDef); + } - return NULL; + return NULL; } -const CommandDefinition* SerialPnp_LookupCommand(const char* commandName, int InterfaceId) +const CommandDefinition* SerialPnp_LookupCommand(SINGLYLINKEDLIST_HANDLE interfaceDefinitions, const char* commandName, int InterfaceId) { - LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(g_InterfaceDefinitions); - const InterfaceDefinition* interfaceDef; + LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(interfaceDefinitions); + const InterfaceDefinition* interfaceDef; - for (int i = 0; iCommands; - LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(command); - const CommandDefinition* ev; - while (eventDef != NULL) { - ev = singlylinkedlist_item_get_value(eventDef); - if (strcmp(ev->defintion.Name, commandName) == 0) { - return ev; - } - eventDef = singlylinkedlist_get_next_item(eventDef); - } + SINGLYLINKEDLIST_HANDLE command = interfaceDef->Commands; + LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(command); + const CommandDefinition* ev; + while (eventDef != NULL) { + ev = singlylinkedlist_item_get_value(eventDef); + if (strcmp(ev->defintion.Name, commandName) == 0) { + return ev; + } + eventDef = singlylinkedlist_get_next_item(eventDef); + } - return NULL; + return NULL; } int SerialPnp_PropertyHandler(PSERIAL_DEVICE_CONTEXT serialDevice, const char* property, char* input) { - const PropertyDefinition* prop = SerialPnp_LookupProperty(property, 0); + const PropertyDefinition* prop = SerialPnp_LookupProperty(serialDevice->InterfaceDefinitions, property, 0); - if (prop == NULL) - { - return -1; - } + if (prop == NULL) + { + return -1; + } - // otherwise serialize data - int length = 0; - byte* inputPayload = SerialPnp_StringSchemaToBinary(prop->DataSchema, input, &length); + // otherwise serialize data + int length = 0; + byte* inputPayload = SerialPnp_StringSchemaToBinary(prop->DataSchema, input, &length); - int nameLength = (int)strlen(property); - int txlength = 6 + nameLength + length; - byte* txPacket = malloc(txlength); + int nameLength = (int)strlen(property); + int txlength = 6 + nameLength + length; + byte* txPacket = malloc(txlength); - txPacket[0] = (byte)(txlength & 0xFF); - txPacket[1] = (byte)(txlength >> 8); - txPacket[2] = 0x07; // command request - // [3] is reserved - txPacket[4] = (byte) 0; - txPacket[5] = (byte) nameLength; + txPacket[0] = (byte)(txlength & 0xFF); + txPacket[1] = (byte)(txlength >> 8); + txPacket[2] = 0x07; // command request + // [3] is reserved + txPacket[4] = (byte)0; + txPacket[5] = (byte)nameLength; - memcpy(txPacket+6, property, nameLength); - if (inputPayload != NULL) { - memcpy(txPacket + 6 + nameLength, inputPayload, length); - } + memcpy(txPacket + 6, property, nameLength); + if (inputPayload != NULL) { + memcpy(txPacket + 6 + nameLength, inputPayload, length); + } - LogInfo("Setting property %s to %s", property, input); + LogInfo("Setting property %s to %s", property, input); - SerialPnp_TxPacket(serialDevice, txPacket, txlength); + SerialPnp_TxPacket(serialDevice, txPacket, txlength); - //ThreadAPI_Sleep(2000); + //ThreadAPI_Sleep(2000); - if (inputPayload != NULL) { - free(inputPayload); - } + if (inputPayload != NULL) { + free(inputPayload); + } - free(txPacket); + free(txPacket); - return 0; + return 0; } int SerialPnp_CommandHandler(PSERIAL_DEVICE_CONTEXT serialDevice, const char* command, char* input, char** response) { - const CommandDefinition* cmd = SerialPnp_LookupCommand(command, 0); + const CommandDefinition* cmd = SerialPnp_LookupCommand(serialDevice->InterfaceDefinitions, command, 0); - if (cmd == NULL) - { - return -1; - } + if (cmd == NULL) + { + return -1; + } - // otherwise serialize data - int length = 0; - byte* inputPayload = SerialPnp_StringSchemaToBinary(cmd->RequestSchema, input, &length); + // otherwise serialize data + int length = 0; + byte* inputPayload = SerialPnp_StringSchemaToBinary(cmd->RequestSchema, input, &length); - int nameLength = (int)strlen(command); - int txlength = 6 + nameLength + length; - byte* txPacket = malloc(txlength); + int nameLength = (int)strlen(command); + int txlength = 6 + nameLength + length; + byte* txPacket = malloc(txlength); - txPacket[0] = (byte)(txlength & 0xFF); - txPacket[1] = (byte)(txlength >> 8); - txPacket[2] = 0x05; // command request - // [3] is reserved - txPacket[4] = (byte)0; - txPacket[5] = (byte)nameLength; + txPacket[0] = (byte)(txlength & 0xFF); + txPacket[1] = (byte)(txlength >> 8); + txPacket[2] = 0x05; // command request + // [3] is reserved + txPacket[4] = (byte)0; + txPacket[5] = (byte)nameLength; - memcpy(txPacket + 6, command, nameLength); - if (inputPayload != NULL) { - memcpy(txPacket + 6 + nameLength, inputPayload, length); - } + memcpy(txPacket + 6, command, nameLength); + if (inputPayload != NULL) { + memcpy(txPacket + 6 + nameLength, inputPayload, length); + } - LogInfo("Invoking command %s to %s", command, input); + LogInfo("Invoking command %s to %s", command, input); - SerialPnp_TxPacket(serialDevice, txPacket, txlength); + SerialPnp_TxPacket(serialDevice, txPacket, txlength); - byte* responsePacket; - SerialPnp_RxPacket(serialDevice, &responsePacket, &length, 0x02); + byte* responsePacket; + SerialPnp_RxPacket(serialDevice, &responsePacket, &length, 0x02); - char* stval = SerialPnp_BinarySchemaToString(cmd->ResponseSchema, responsePacket, length); - *response = responsePacket; + char* stval = SerialPnp_BinarySchemaToString(cmd->ResponseSchema, responsePacket, length); + *response = responsePacket; - if (inputPayload != NULL) { - free(inputPayload); - } + if (inputPayload != NULL) { + free(inputPayload); + } - free(txPacket); + free(txPacket); - return 0; + return 0; } -void SerialPnp_ParseDescriptor(byte* descriptor, DWORD length) +void SerialPnp_ParseDescriptor(SINGLYLINKEDLIST_HANDLE interfaceDefinitions, byte* descriptor, DWORD length) { - int c = 4; + int c = 4; - byte version = descriptor[c++]; - byte display_name_length = descriptor[c++]; + byte version = descriptor[c++]; + byte display_name_length = descriptor[c++]; - char display_name[128]; - memcpy(display_name, descriptor+c, display_name_length); - display_name[display_name_length] = '\0'; + char display_name[128]; + memcpy(display_name, descriptor + c, display_name_length); + display_name[display_name_length] = '\0'; - LogInfo("Device Version : %d", version); - LogInfo("Device Name : %s", display_name); + LogInfo("Device Version : %d", version); + LogInfo("Device Name : %s", display_name); + c += display_name_length; - g_InterfaceDefinitions = singlylinkedlist_create(); + while (c < (int)length) + { + if (descriptor[c++] == 0x05) + { + // inline interface + InterfaceDefinition* indef = calloc(1, sizeof(InterfaceDefinition)); + indef->Events = singlylinkedlist_create(); + indef->Properties = singlylinkedlist_create(); + indef->Commands = singlylinkedlist_create(); - c += display_name_length; + // parse ID5 + UINT16 interface_id_length = descriptor[c] | (descriptor[c + 1] << 8); + c += 2; - while (c < (int)length) - { - if (descriptor[c++] == 0x05) - { - // inline interface - InterfaceDefinition* indef = calloc(1, sizeof(InterfaceDefinition)); - indef->Events = singlylinkedlist_create(); - indef->Properties = singlylinkedlist_create(); - indef->Commands = singlylinkedlist_create(); + char* interface_id = malloc(sizeof(char)*(interface_id_length + 1)); + memcpy(interface_id, descriptor + c, interface_id_length); + interface_id[interface_id_length] = '\0'; + LogInfo("Interface ID : %s", interface_id); + c += interface_id_length; - // parse ID5 - UINT16 interface_id_length = descriptor[c] | (descriptor[c+1] << 8); - c += 2; + indef->Id = interface_id; - char* interface_id = malloc(sizeof(char)*(interface_id_length+1)); - memcpy(interface_id, descriptor + c, interface_id_length); - interface_id[interface_id_length] = '\0'; - LogInfo("Interface ID : %s", interface_id); - c += interface_id_length; + // now process the different types + while (c < (int)length) + { + if (descriptor[c] > 0x03) break; // not in a type of nested entry anymore - indef->Id = interface_id; + FieldDefinition fielddef = { 0 }; - // now process the different types - while (c < (int)length) - { - if (descriptor[c] > 0x03) break; // not in a type of nested entry anymore + // extract common field properties + byte ptype = descriptor[c++]; - FieldDefinition fielddef = { 0 }; + byte pname_length = descriptor[c++]; + char* pname = malloc(sizeof(char)*(pname_length + 1)); + memcpy(pname, descriptor + c, pname_length); + pname[pname_length] = '\0'; + c += pname_length; - // extract common field properties - byte ptype = descriptor[c++]; + byte pdisplay_name_length = descriptor[c++]; + char* pdisplay_name = malloc(sizeof(char)*(pdisplay_name_length + 1)); + memcpy(pdisplay_name, descriptor + c, pdisplay_name_length); + pdisplay_name[pdisplay_name_length] = '\0'; + c += pdisplay_name_length; - byte pname_length = descriptor[c++]; - char* pname = malloc(sizeof(char)*(pname_length + 1)); - memcpy(pname, descriptor + c, pname_length); - pname[pname_length] = '\0'; - c += pname_length; + byte pdescription_length = descriptor[c++]; + char* pdescription = malloc(sizeof(char)*(pdescription_length + 1)); + memcpy(pdescription, descriptor + c, pdescription_length); + pdescription[pdescription_length] = '\0'; + c += pdescription_length; - byte pdisplay_name_length = descriptor[c++]; - char* pdisplay_name = malloc(sizeof(char)*(pdisplay_name_length + 1)); - memcpy(pdisplay_name, descriptor + c, pdisplay_name_length); - pdisplay_name[pdisplay_name_length] = '\0'; - c += pdisplay_name_length; + LogInfo("\tProperty type : %d", ptype); + LogInfo("\tName : %s", pname); + LogInfo("\tDisplay Name : %s", pdisplay_name); + LogInfo("\tDescription : %s", pdescription); - byte pdescription_length = descriptor[c++]; - char* pdescription = malloc(sizeof(char)*(pdescription_length + 1)); - memcpy(pdescription, descriptor + c, pdescription_length); - pdescription[pdescription_length] = '\0'; - c += pdescription_length; + fielddef.Name = pname; + fielddef.DisplayName = pdisplay_name; + fielddef.Description = pdescription; - LogInfo("\tProperty type : %d", ptype); - LogInfo("\tName : %s", pname); - LogInfo("\tDisplay Name : %s", pdisplay_name); - LogInfo("\tDescription : %s", pdescription); + if (ptype == 0x01) // command + { + CommandDefinition* tfdef = calloc(1, sizeof(CommandDefinition)); + tfdef->defintion = fielddef; - fielddef.Name = pname; - fielddef.DisplayName = pdisplay_name; - fielddef.Description = pdescription; + UINT16 prequest_schema = (UINT16)(descriptor[c] | (descriptor[c + 1] << 8)); + c += 2; + UINT16 presponse_schema = (UINT16)(descriptor[c] | (descriptor[c + 1] << 8)); + c += 2; - if (ptype == 0x01) // command - { - CommandDefinition* tfdef = calloc(1, sizeof(CommandDefinition)); - tfdef->defintion = fielddef; + tfdef->RequestSchema = prequest_schema; + tfdef->ResponseSchema = presponse_schema; - UINT16 prequest_schema = (UINT16)(descriptor[c] | (descriptor[c+1] << 8)); - c += 2; - UINT16 presponse_schema = (UINT16)(descriptor[c] | (descriptor[c+1] << 8)); - c += 2; + singlylinkedlist_add(indef->Commands, tfdef); + } + else if (ptype == 0x02) // command + { + PropertyDefinition* tfdef = calloc(1, sizeof(PropertyDefinition)); + tfdef->defintion = fielddef; - tfdef->RequestSchema = prequest_schema; - tfdef->ResponseSchema = presponse_schema; + byte punit_length = descriptor[c++]; + char* punit = malloc(sizeof(char)*(punit_length + 1)); + memcpy(punit, descriptor + c, punit_length); + punit[punit_length] = '\0'; + c += punit_length; - singlylinkedlist_add(indef->Commands, tfdef); - } - else if (ptype == 0x02) // command - { - PropertyDefinition* tfdef = calloc(1, sizeof(PropertyDefinition)); - tfdef->defintion = fielddef; + LogInfo("\tUnit : %s", punit); - byte punit_length = descriptor[c++]; - char* punit = malloc(sizeof(char)*(punit_length + 1)); - memcpy(punit, descriptor + c, punit_length); - punit[punit_length] = '\0'; - c += punit_length; + UINT16 schema = descriptor[c] | (descriptor[c + 1] << 8); + c += 2; + tfdef->DataSchema = schema; - LogInfo("\tUnit : %s", punit); + byte flags = descriptor[c++]; - UINT16 schema = descriptor[c] | (descriptor[c+1] << 8); - c += 2; - tfdef->DataSchema = schema; + bool prequired = (flags & (1 << 1)) != 0; + bool pwriteable = (flags & (1 << 0)) != 0; - byte flags = descriptor[c++]; + tfdef->Units = punit; + tfdef->Required = prequired; + tfdef->Writeable = pwriteable; - bool prequired = (flags & (1 << 1)) != 0; - bool pwriteable = (flags & (1 << 0)) != 0; + singlylinkedlist_add(indef->Properties, tfdef); + } + else if (ptype == 0x03) // event + { + EventDefinition* tfdef = calloc(1, sizeof(EventDefinition)); + tfdef->defintion = fielddef; - tfdef->Units = punit; - tfdef->Required = prequired; - tfdef->Writeable = pwriteable; + byte punit_length = descriptor[c++]; + char* punit = malloc(sizeof(char)*(punit_length + 1)); + memcpy(punit, descriptor + c, punit_length); + punit[punit_length] = '\0'; + c += punit_length; - singlylinkedlist_add(indef->Properties, tfdef); - } - else if (ptype == 0x03) // event - { - EventDefinition* tfdef = calloc(1, sizeof(EventDefinition)); - tfdef->defintion = fielddef; + LogInfo("\tUnit : %s", punit); - byte punit_length = descriptor[c++]; - char* punit = malloc(sizeof(char)*(punit_length + 1)); - memcpy(punit, descriptor + c, punit_length); - punit[punit_length] = '\0'; - c += punit_length; + UINT16 schema = (UINT16)(descriptor[c] | (descriptor[c + 1] << 8)); + c += 2; + tfdef->DataSchema = schema; - LogInfo("\tUnit : %s", punit); + tfdef->Units = punit; - UINT16 schema = (UINT16)(descriptor[c] | (descriptor[c+1] << 8)); - c += 2; - tfdef->DataSchema = schema; + singlylinkedlist_add(indef->Events, tfdef); + } + } - tfdef->Units = punit; - - singlylinkedlist_add(indef->Events, tfdef); - } - } - - singlylinkedlist_add(g_InterfaceDefinitions, indef); - } - else - { - LogError("Unsupported descriptor\n"); - } - } + singlylinkedlist_add(interfaceDefinitions, indef); + } + else + { + LogError("Unsupported descriptor\n"); + } + } } typedef struct _SERIAL_DEVICE { - char* InterfaceName; + char* InterfaceName; } SERIAL_DEVICE, *PSERIAL_DEVICE; SINGLYLINKEDLIST_HANDLE SerialDeviceList = NULL; @@ -533,45 +528,45 @@ int SerialDeviceCount = 0; int SerialPnp_FindSerialDevices() { - CONFIGRET cmResult = CR_SUCCESS; - char* deviceInterfaceList; - ULONG bufferSize = 0; + CONFIGRET cmResult = CR_SUCCESS; + char* deviceInterfaceList; + ULONG bufferSize = 0; - SerialDeviceList = singlylinkedlist_create(); + SerialDeviceList = singlylinkedlist_create(); - cmResult = CM_Get_Device_Interface_List_Size( - &bufferSize, - (LPGUID) &GUID_DEVINTERFACE_COMPORT, - NULL, - CM_GET_DEVICE_INTERFACE_LIST_PRESENT); - if (CR_SUCCESS != cmResult) { - return -1; - } + cmResult = CM_Get_Device_Interface_List_Size( + &bufferSize, + (LPGUID)&GUID_DEVINTERFACE_COMPORT, + NULL, + CM_GET_DEVICE_INTERFACE_LIST_PRESENT); + if (CR_SUCCESS != cmResult) { + return -1; + } - deviceInterfaceList = malloc(bufferSize*sizeof(char)); + deviceInterfaceList = malloc(bufferSize * sizeof(char)); - cmResult = CM_Get_Device_Interface_ListA( - (LPGUID) &GUID_DEVINTERFACE_COMPORT, - NULL, - deviceInterfaceList, - bufferSize, - CM_GET_DEVICE_INTERFACE_LIST_PRESENT); - if (CR_SUCCESS != cmResult) { - return -1; - } + cmResult = CM_Get_Device_Interface_ListA( + (LPGUID)&GUID_DEVINTERFACE_COMPORT, + NULL, + deviceInterfaceList, + bufferSize, + CM_GET_DEVICE_INTERFACE_LIST_PRESENT); + if (CR_SUCCESS != cmResult) { + return -1; + } - for (PCHAR currentDeviceInterface = deviceInterfaceList; - *currentDeviceInterface != '\0'; - currentDeviceInterface += strlen(currentDeviceInterface) + 1) - { - PSERIAL_DEVICE serialDevs = malloc(sizeof(SERIAL_DEVICE)); - serialDevs->InterfaceName = malloc((strlen(currentDeviceInterface)+1)*sizeof(char)); - strcpy_s(serialDevs->InterfaceName, strlen(currentDeviceInterface)+1, currentDeviceInterface); - singlylinkedlist_add(SerialDeviceList, serialDevs); - SerialDeviceCount++; - } + for (PCHAR currentDeviceInterface = deviceInterfaceList; + *currentDeviceInterface != '\0'; + currentDeviceInterface += strlen(currentDeviceInterface) + 1) + { + PSERIAL_DEVICE serialDevs = malloc(sizeof(SERIAL_DEVICE)); + serialDevs->InterfaceName = malloc((strlen(currentDeviceInterface) + 1) * sizeof(char)); + strcpy_s(serialDevs->InterfaceName, strlen(currentDeviceInterface) + 1, currentDeviceInterface); + singlylinkedlist_add(SerialDeviceList, serialDevs); + SerialDeviceCount++; + } - return 0; + return 0; } const char* serialDeviceChangeMessageformat = "{ \ @@ -579,564 +574,694 @@ const char* serialDeviceChangeMessageformat = "{ \ }"; int SerialPnp_OpenDeviceWorker(void* context) { - byte* desc; - DWORD length; - PNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload = {0}; - PSERIAL_DEVICE_CONTEXT deviceContext = context; + byte* desc; + DWORD length; + PNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload = { 0 }; + PSERIAL_DEVICE_CONTEXT deviceContext = context; - SerialPnp_ResetDevice(deviceContext); - SerialPnp_DeviceDescriptorRequest(deviceContext, &desc, &length); + SerialPnp_ResetDevice(deviceContext); + SerialPnp_DeviceDescriptorRequest(deviceContext, &desc, &length); - SerialPnp_ParseDescriptor(desc, length); - SerialPnp_PropertyHandler(deviceContext, "sample_rate", "5000"); + SerialPnp_ParseDescriptor(deviceContext->InterfaceDefinitions, desc, length); - STRING_HANDLE asJson = STRING_new_JSON(serialDeviceChangeMessageformat); - JSON_Value* json = json_parse_string(serialDeviceChangeMessageformat); - JSON_Object* jsonObject = json_value_get_object(json); + STRING_HANDLE asJson = STRING_new_JSON(serialDeviceChangeMessageformat); + JSON_Value* json = json_parse_string(serialDeviceChangeMessageformat); + JSON_Object* jsonObject = json_value_get_object(json); - LIST_ITEM_HANDLE interfaceItem = singlylinkedlist_get_head_item(g_InterfaceDefinitions); - while (interfaceItem != NULL) { - const InterfaceDefinition* def = (const InterfaceDefinition*)singlylinkedlist_item_get_value(interfaceItem); - json_object_set_string(jsonObject, "InterfaceId", def->Id); - payload.Message = json_serialize_to_string(json_object_get_wrapping_value(jsonObject)); - payload.MessageLength = (int)json_serialization_size(json_object_get_wrapping_value(jsonObject)); - payload.Context = deviceContext; - deviceContext->SerialDeviceChangeCallback(&payload); - interfaceItem = singlylinkedlist_get_next_item(interfaceItem); - } + LIST_ITEM_HANDLE interfaceItem = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions); + while (interfaceItem != NULL) { + const InterfaceDefinition* def = (const InterfaceDefinition*)singlylinkedlist_item_get_value(interfaceItem); + json_object_set_string(jsonObject, "InterfaceId", def->Id); + payload.Message = json_serialize_to_string(json_object_get_wrapping_value(jsonObject)); + payload.MessageLength = (int)json_serialization_size(json_object_get_wrapping_value(jsonObject)); + payload.Context = deviceContext; + deviceContext->SerialDeviceChangeCallback(&payload); + interfaceItem = singlylinkedlist_get_next_item(interfaceItem); + } - SerialPnp_UartReceiver(deviceContext); + SerialPnp_UartReceiver(deviceContext); - return 0; + return 0; } int SerialPnp_OpenDevice(const char* port, DWORD baudRate, PNPBRIDGE_NOTIFY_DEVICE_CHANGE DeviceChangeCallback) { - BOOL status = FALSE; - HANDLE hSerial = CreateFileA(port, - GENERIC_READ | GENERIC_WRITE, - 0, // must be opened with exclusive-access - 0, //NULL, no security attributes - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - 0); + BOOL status = FALSE; + HANDLE hSerial = CreateFileA(port, + GENERIC_READ | GENERIC_WRITE, + 0, // must be opened with exclusive-access + 0, //NULL, no security attributes + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + 0); - if (hSerial == INVALID_HANDLE_VALUE) { - // Handle the error - int error = GetLastError(); - LogError("Failed to open com port %s, %x", port, error); - if (error == ERROR_FILE_NOT_FOUND) { - return -1; - } + if (hSerial == INVALID_HANDLE_VALUE) { + // Handle the error + int error = GetLastError(); + LogError("Failed to open com port %s, %x", port, error); + if (error == ERROR_FILE_NOT_FOUND) { + return -1; + } - return -1; - } + return -1; + } - DCB dcbSerialParams = { 0 }; - dcbSerialParams.DCBlength = sizeof(dcbSerialParams); - if (!GetCommState(hSerial, &dcbSerialParams)) { - return -1; - } - dcbSerialParams.BaudRate = baudRate; - dcbSerialParams.ByteSize = 8; - dcbSerialParams.StopBits = ONESTOPBIT; - dcbSerialParams.Parity = NOPARITY; - if (!SetCommState(hSerial, &dcbSerialParams)) { - //error setting serial port state - return -1; - } + DCB dcbSerialParams = { 0 }; + dcbSerialParams.DCBlength = sizeof(dcbSerialParams); + if (!GetCommState(hSerial, &dcbSerialParams)) { + return -1; + } + dcbSerialParams.BaudRate = baudRate; + dcbSerialParams.ByteSize = 8; + dcbSerialParams.StopBits = ONESTOPBIT; + dcbSerialParams.Parity = NOPARITY; + if (!SetCommState(hSerial, &dcbSerialParams)) { + //error setting serial port state + return -1; + } - PSERIAL_DEVICE_CONTEXT deviceContext = malloc(sizeof(SERIAL_DEVICE_CONTEXT)); - deviceContext->hSerial = hSerial; - deviceContext->InterfaceHandle = NULL; - deviceContext->SerialDeviceChangeCallback = DeviceChangeCallback; + PSERIAL_DEVICE_CONTEXT deviceContext = malloc(sizeof(SERIAL_DEVICE_CONTEXT)); + deviceContext->hSerial = hSerial; + deviceContext->pnpAdapterInterface = NULL; + deviceContext->SerialDeviceChangeCallback = DeviceChangeCallback; + deviceContext->InterfaceDefinitions = singlylinkedlist_create(); - if (ThreadAPI_Create(&deviceContext->SerialDeviceWorker, SerialPnp_OpenDeviceWorker, deviceContext) != THREADAPI_OK) { - LogError("ThreadAPI_Create failed"); - } + //deviceContext->osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - return 0; + // TODO error handling + // https://docs.microsoft.com/en-us/previous-versions/ff802693(v=msdn.10) + + if (ThreadAPI_Create(&deviceContext->SerialDeviceWorker, SerialPnp_OpenDeviceWorker, deviceContext) != THREADAPI_OK) { + LogError("ThreadAPI_Create failed"); + } + + return 0; } void SerialPnp_RxPacket(PSERIAL_DEVICE_CONTEXT serialDevice, byte** receivedPacket, DWORD* length, char packetType) { - BYTE inb = 0; - DWORD dwRead = 0; - *receivedPacket = NULL; + BYTE inb = 0; + DWORD dwRead = 0; + *receivedPacket = NULL; + *length = 0; - while (ReadFile(serialDevice->hSerial, &inb, 1, &dwRead, NULL)) { - // Check for a start of packet byte - if (inb == 0x5A) - { - serialDevice->RxBufferIndex = 0; - serialDevice->RxEscaped = false; - continue; - } + while (ReadFile(serialDevice->hSerial, &inb, 1, &dwRead, NULL)) { + // Check for a start of packet byte + if (inb == 0x5A) + { + serialDevice->RxBufferIndex = 0; + serialDevice->RxEscaped = false; + continue; + } - // Check for an escape byte - if (inb == 0xEF) - { - serialDevice->RxEscaped = true; - continue; - } + // Check for an escape byte + if (inb == 0xEF) + { + serialDevice->RxEscaped = true; + continue; + } - // If last byte was an escape byte, increment current byte by 1 - if (serialDevice->RxEscaped) - { - inb++; - serialDevice->RxEscaped = false; - } + // If last byte was an escape byte, increment current byte by 1 + if (serialDevice->RxEscaped) + { + inb++; + serialDevice->RxEscaped = false; + } - serialDevice->RxBuffer[serialDevice->RxBufferIndex++] = (byte)inb; + serialDevice->RxBuffer[serialDevice->RxBufferIndex++] = (byte)inb; - if (serialDevice->RxBufferIndex >= 4096) - { - LogError("Filled Rx buffer. Protocol is bad."); - break; - } + if (serialDevice->RxBufferIndex >= 4096) + { + LogError("Filled Rx buffer. Protocol is bad."); + break; + } - // Minimum packet length is 4, so once we are >= 4 begin checking - // the receieve buffer length against the length field. - if (serialDevice->RxBufferIndex >= 4) - { - int PacketLength = (int)((serialDevice->RxBuffer[0]) | (serialDevice->RxBuffer[1] << 8)); // LSB first, L-endian + // Minimum packet length is 4, so once we are >= 4 begin checking + // the receieve buffer length against the length field. + if (serialDevice->RxBufferIndex >= 4) + { + int PacketLength = (int)((serialDevice->RxBuffer[0]) | (serialDevice->RxBuffer[1] << 8)); // LSB first, L-endian - if (serialDevice->RxBufferIndex == PacketLength && (packetType == 0x00 || packetType == serialDevice->RxBuffer[2])) - { - *receivedPacket = malloc(serialDevice->RxBufferIndex * sizeof(byte)); - *length = serialDevice->RxBufferIndex; - memcpy(*receivedPacket, serialDevice->RxBuffer, serialDevice->RxBufferIndex); - serialDevice->RxBufferIndex = 0; // This should be reset anyway - // Deliver the newly receieved packet - //Console.Out.Write("\n"); - break; - } - } - } + if (serialDevice->RxBufferIndex == PacketLength && (packetType == 0x00 || packetType == serialDevice->RxBuffer[2])) + { + *receivedPacket = malloc(serialDevice->RxBufferIndex * sizeof(byte)); + *length = serialDevice->RxBufferIndex; + memcpy(*receivedPacket, serialDevice->RxBuffer, serialDevice->RxBufferIndex); + serialDevice->RxBufferIndex = 0; // This should be reset anyway + // Deliver the newly receieved packet + //Console.Out.Write("\n"); + break; + } + } + } } void SerialPnp_ResetDevice(PSERIAL_DEVICE_CONTEXT serialDevice) { - // Prepare packet - byte* resetPacket = calloc(4, sizeof(byte)); // packet header - byte* responsePacket = NULL; - resetPacket[0] = 4; // length 4 - resetPacket[1] = 0; - resetPacket[2] = 0x01; // type reset + // Prepare packet + byte* resetPacket = calloc(4, sizeof(byte)); // packet header + byte* responsePacket = NULL; + resetPacket[0] = 4; // length 4 + resetPacket[1] = 0; + resetPacket[2] = 0x01; // type reset - ThreadAPI_Sleep(2000); + ThreadAPI_Sleep(2000); - // Send the new packet - SerialPnp_TxPacket(serialDevice, resetPacket, 4); + // Send the new packet + SerialPnp_TxPacket(serialDevice, resetPacket, 4); - ThreadAPI_Sleep(2000); + ThreadAPI_Sleep(2000); - DWORD length; - SerialPnp_RxPacket(serialDevice, &responsePacket, &length, 0x02); + DWORD length; + SerialPnp_RxPacket(serialDevice, &responsePacket, &length, 0x02); - if (responsePacket == NULL) { - LogError("received NULL for response packet"); - return; - } + if (responsePacket == NULL) { + LogError("received NULL for response packet"); + return; + } - if (responsePacket[2] != 0x02) - { - LogError("Bad reset response"); - } + if (responsePacket[2] != 0x02) + { + LogError("Bad reset response"); + } - LogInfo("Receieved reset response"); + LogInfo("Receieved reset response"); } void SerialPnp_DeviceDescriptorRequest(PSERIAL_DEVICE_CONTEXT serialDevice, byte** desc, DWORD* length) { - // Prepare packet - byte txPacket[4] = { 0 }; // packet header - txPacket[0] = 4; // length 4 - txPacket[1] = 0; - txPacket[2] = 0x03; // type descriptor request + // Prepare packet + byte txPacket[4] = { 0 }; // packet header + txPacket[0] = 4; // length 4 + txPacket[1] = 0; + txPacket[2] = 0x03; // type descriptor request - // Get ready to receieve a reset response + // Get ready to receieve a reset response - // Send the new packets - SerialPnp_TxPacket(serialDevice, txPacket, 4); - LogInfo("Sent descriptor request"); + // Send the new packets + SerialPnp_TxPacket(serialDevice, txPacket, 4); + LogInfo("Sent descriptor request"); - SerialPnp_RxPacket(serialDevice, desc, length, 0x04); + SerialPnp_RxPacket(serialDevice, desc, length, 0x04); - if ((*desc)[2] != 0x04) - { - LogError("Bad descriptor response"); - return; - } + if ((*desc)[2] != 0x04) + { + LogError("Bad descriptor response"); + return; + } - LogInfo("Receieved descriptor response, of length %d", *length); + LogInfo("Receieved descriptor response, of length %d", *length); } int SerialPnp_StartDiscovery(PNPBRIDGE_NOTIFY_DEVICE_CHANGE DeviceChangeCallback, const char* deviceArgs, const char* adapterArgs) { - if (deviceArgs == NULL) { - return -1; - } + if (deviceArgs == NULL) { + return -1; + } - const char* port = NULL; - const char* useComDevInterfaceStr; - const char* baudRateParam; - bool useComDeviceInterface = false; - JSON_Value* jvalue = json_parse_string(deviceArgs); - JSON_Object* args = json_value_get_object(jvalue); + const char* port = NULL; + const char* useComDevInterfaceStr; + const char* baudRateParam; + bool useComDeviceInterface = false; + JSON_Value* jvalue = json_parse_string(deviceArgs); + JSON_Object* args = json_value_get_object(jvalue); - useComDevInterfaceStr = (const char*)json_object_dotget_string(args, "UseComDeviceInterface"); - if ((NULL != useComDevInterfaceStr) && (0 == stricmp(useComDevInterfaceStr, "true"))) { - useComDeviceInterface = true; - } + useComDevInterfaceStr = (const char*)json_object_dotget_string(args, "UseComDeviceInterface"); + if ((NULL != useComDevInterfaceStr) && (0 == stricmp(useComDevInterfaceStr, "true"))) { + useComDeviceInterface = true; + } - if (!useComDeviceInterface) { - port = (const char*)json_object_dotget_string(args, "ComPort"); - if (NULL == port) { - LogError("ComPort parameter is missing in configuration"); - return -1; - } - } + if (!useComDeviceInterface) { + port = (const char*)json_object_dotget_string(args, "ComPort"); + if (NULL == port) { + LogError("ComPort parameter is missing in configuration"); + return -1; + } + } - JSON_Object* SerialDeviceInterfaceInfo = args; + JSON_Object* SerialDeviceInterfaceInfo = args; - baudRateParam = (const char*) json_object_dotget_string(args, "BaudRate"); - if (NULL == baudRateParam) { - LogError("BaudRate parameter is missing in configuration"); - return -1; - } + baudRateParam = (const char*)json_object_dotget_string(args, "BaudRate"); + if (NULL == baudRateParam) { + LogError("BaudRate parameter is missing in configuration"); + return -1; + } - PSERIAL_DEVICE seriaDevice = NULL; - DWORD baudRate = atoi(baudRateParam); - if (useComDeviceInterface) { - if (SerialPnp_FindSerialDevices() < 0) { - LogError("Failed to get com port %s", port); - } + PSERIAL_DEVICE seriaDevice = NULL; + DWORD baudRate = atoi(baudRateParam); + if (useComDeviceInterface) { + if (SerialPnp_FindSerialDevices() < 0) { + LogError("Failed to get com port %s", port); + } - LIST_ITEM_HANDLE item = singlylinkedlist_get_head_item(SerialDeviceList); - if (item == NULL) { - LogError("No serial device was found %s", port); - return -1; - } + LIST_ITEM_HANDLE item = singlylinkedlist_get_head_item(SerialDeviceList); + if (item == NULL) { + LogError("No serial device was found %s", port); + return -1; + } - seriaDevice = (PSERIAL_DEVICE)singlylinkedlist_item_get_value(item); - } + seriaDevice = (PSERIAL_DEVICE)singlylinkedlist_item_get_value(item); + } - LogInfo("Opening com port %s", useComDeviceInterface ? seriaDevice->InterfaceName : port); + LogInfo("Opening com port %s", useComDeviceInterface ? seriaDevice->InterfaceName : port); - SerialPnp_OpenDevice(useComDeviceInterface ? seriaDevice->InterfaceName : port, baudRate, DeviceChangeCallback); - return 0; + SerialPnp_OpenDevice(useComDeviceInterface ? seriaDevice->InterfaceName : port, baudRate, DeviceChangeCallback); + return 0; } int SerialPnp_StopDiscovery() { - return 0; + return 0; } void SerialPnp_SendEventCallback(PNP_SEND_TELEMETRY_STATUS pnpSendEventStatus, void* userContextCallback) { - LogInfo("SerialDataSendEventCallback called, result=%d, userContextCallback=%p", pnpSendEventStatus, userContextCallback); + LogInfo("SerialDataSendEventCallback called, result=%d, userContextCallback=%p", pnpSendEventStatus, userContextCallback); } int SerialPnp_SendEventAsync(PNP_INTERFACE_CLIENT_HANDLE pnpInterface, char* eventName, char* data) { - int result; - PNP_CLIENT_RESULT pnpClientResult; + int result; + PNP_CLIENT_RESULT pnpClientResult; - if (pnpInterface == NULL) { - return 0; - } + if (pnpInterface == NULL) { + return 0; + } - char msg[512]; - sprintf_s(msg, 512, "{\"%s\":\"%s\"}", eventName, data); + if ((pnpClientResult = PnP_InterfaceClient_SendTelemetryAsync(pnpInterface, eventName, (const unsigned char*)data, strlen(data), SerialPnp_SendEventCallback, NULL)) != PNP_CLIENT_OK) + { + LogError("PnP_InterfaceClient_SendEventAsync failed, result=%d\n", pnpClientResult); + result = __FAILURE__; + } + else + { + result = 0; + } - if ((pnpClientResult = PnP_InterfaceClient_SendTelemetryAsync(pnpInterface, "temp", (const unsigned char*)msg, strlen(msg), SerialPnp_SendEventCallback, NULL)) != PNP_CLIENT_OK) - { - LogError("PnP_InterfaceClient_SendEventAsync failed, result=%d\n", pnpClientResult); - result = __FAILURE__; - } - else - { - result = 0; - } - - return result; + return result; } static void SerialPnp_PropertyUpdateHandler(const char* propertyName, unsigned const char* propertyInitial, size_t propertyInitialLen, unsigned const char* propertyDataUpdated, size_t propertyDataUpdatedLen, int desiredVersion, void* userContextCallback) { - PNP_CLIENT_RESULT pnpClientResult; - PNP_CLIENT_READWRITE_PROPERTY_RESPONSE propertyResponse; - PSERIAL_DEVICE_CONTEXT deviceContext; + PNP_CLIENT_RESULT pnpClientResult; + PNP_CLIENT_READWRITE_PROPERTY_RESPONSE propertyResponse; + PSERIAL_DEVICE_CONTEXT deviceContext; - LogInfo("Processed property. propertyUpdated = %.*s", (int)propertyDataUpdatedLen, propertyDataUpdated); + LogInfo("Processed property. propertyUpdated = %.*s", (int)propertyDataUpdatedLen, propertyDataUpdated); - deviceContext = (PSERIAL_DEVICE_CONTEXT)userContextCallback; + deviceContext = (PSERIAL_DEVICE_CONTEXT)userContextCallback; - SerialPnp_PropertyHandler(deviceContext, propertyName, (char*)propertyDataUpdated); + SerialPnp_PropertyHandler(deviceContext, propertyName, (char*)propertyDataUpdated); - // TODO: Send the correct response code below - propertyResponse.version = 1; - propertyResponse.propertyData = propertyDataUpdated; - propertyResponse.propertyDataLen = propertyDataUpdatedLen; - propertyResponse.responseVersion = desiredVersion; - propertyResponse.statusCode = 200; - propertyResponse.statusDescription = "Property Updated Successfully"; + // TODO: Send the correct response code below + propertyResponse.version = 1; + propertyResponse.propertyData = propertyDataUpdated; + propertyResponse.propertyDataLen = propertyDataUpdatedLen; + propertyResponse.responseVersion = desiredVersion; + propertyResponse.statusCode = 200; + propertyResponse.statusDescription = "Property Updated Successfully"; - pnpClientResult = PnP_InterfaceClient_ReportReadWritePropertyStatusAsync(deviceContext->InterfaceHandle, propertyName, &propertyResponse, NULL, NULL); + pnpClientResult = PnP_InterfaceClient_ReportReadWritePropertyStatusAsync(deviceContext->pnpAdapterInterface, propertyName, &propertyResponse, NULL, NULL); } // PnPSampleEnvironmentalSensor_SetCommandResponse is a helper that fills out a PNP_CLIENT_COMMAND_RESPONSE static void SerialPnp_SetCommandResponse(PNP_CLIENT_COMMAND_RESPONSE* pnpClientCommandResponseContext, const char* responseData, int status) { - size_t responseLen = strlen(responseData); - memset(pnpClientCommandResponseContext, 0, sizeof(*pnpClientCommandResponseContext)); - pnpClientCommandResponseContext->version = PNP_CLIENT_COMMAND_RESPONSE_VERSION_1; + size_t responseLen = strlen(responseData); + memset(pnpClientCommandResponseContext, 0, sizeof(*pnpClientCommandResponseContext)); + pnpClientCommandResponseContext->version = PNP_CLIENT_COMMAND_RESPONSE_VERSION_1; - // Allocate a copy of the response data to return to the invoker. The PnP layer that invoked PnPSampleEnvironmentalSensor_Blink - // takes responsibility for freeing this data. - if ((pnpClientCommandResponseContext->responseData = malloc(responseLen + 1)) == NULL) - { - LogError("ENVIRONMENTAL_SENSOR_INTERFACE: Unable to allocate response data"); - pnpClientCommandResponseContext->status = 500; - } - else - { - pnpClientCommandResponseContext->responseData = (unsigned char*)responseData; - //strcpy_s((char*)pnpClientCommandResponseContext->responseData, responseData); - pnpClientCommandResponseContext->responseDataLen = responseLen; - pnpClientCommandResponseContext->status = status; - } + // Allocate a copy of the response data to return to the invoker. The PnP layer that invoked PnPSampleEnvironmentalSensor_Blink + // takes responsibility for freeing this data. + if ((pnpClientCommandResponseContext->responseData = malloc(responseLen + 1)) == NULL) + { + LogError("ENVIRONMENTAL_SENSOR_INTERFACE: Unable to allocate response data"); + pnpClientCommandResponseContext->status = 500; + } + else + { + pnpClientCommandResponseContext->responseData = (unsigned char*)responseData; + //strcpy_s((char*)pnpClientCommandResponseContext->responseData, responseData); + pnpClientCommandResponseContext->responseDataLen = responseLen; + pnpClientCommandResponseContext->status = status; + } } void SerialPnp_CommandUpdateHandler(const char* commandName, const PNP_CLIENT_COMMAND_REQUEST* pnpClientCommandContext, PNP_CLIENT_COMMAND_RESPONSE* pnpClientCommandResponseContext, void* userContextCallback) { - PSERIAL_DEVICE_CONTEXT deviceContext; + PSERIAL_DEVICE_CONTEXT deviceContext; - // LogInfo("Processed command frequency property updated. propertyUpdated = %.*s", (int)propertyDataUpdatedLen, propertyDataUpdated); + // LogInfo("Processed command frequency property updated. propertyUpdated = %.*s", (int)propertyDataUpdatedLen, propertyDataUpdated); - deviceContext = (PSERIAL_DEVICE_CONTEXT)userContextCallback; + deviceContext = (PSERIAL_DEVICE_CONTEXT)userContextCallback; - char* response; - SerialPnp_CommandHandler(deviceContext, commandName, (char*)pnpClientCommandContext->requestData, &response); - SerialPnp_SetCommandResponse(pnpClientCommandResponseContext, response, 200); + char* response; + SerialPnp_CommandHandler(deviceContext, commandName, (char*)pnpClientCommandContext->requestData, &response); + SerialPnp_SetCommandResponse(pnpClientCommandResponseContext, response, 200); } void SerialPnp_PropertyUpdateHandlerRedirect(int index, unsigned const char* propertyInitial, - size_t propertyInitialLen, unsigned const char* propertyDataUpdated, - size_t propertyDataUpdatedLen, int desiredVersion, void* userContextCallback) + size_t propertyInitialLen, unsigned const char* propertyDataUpdated, + size_t propertyDataUpdatedLen, int desiredVersion, void* userContextCallback) { - LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(g_InterfaceDefinitions); - const InterfaceDefinition* interfaceDef; + PSERIAL_DEVICE_CONTEXT deviceContext = userContextCallback; + LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions); + const InterfaceDefinition* interfaceDef; - for (int i = 0; i<0 - 1; i++) - { - interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); - } - interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); + for (int i = 0; i < 0 - 1; i++) + { + interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); + } + interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); - SINGLYLINKEDLIST_HANDLE property = interfaceDef->Properties; - LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(property); - const PropertyDefinition* ev = NULL; - eventDef = singlylinkedlist_get_head_item(property); - for (int i = 0; i < index + 1; i++) { - ev = singlylinkedlist_item_get_value(eventDef); - eventDef = singlylinkedlist_get_next_item(eventDef); - } - if (NULL != ev) { - SerialPnp_PropertyUpdateHandler(ev->defintion.Name, propertyInitial, propertyInitialLen, propertyDataUpdated, propertyDataUpdatedLen, - desiredVersion, userContextCallback); - } + SINGLYLINKEDLIST_HANDLE property = interfaceDef->Properties; + LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(property); + const PropertyDefinition* ev = NULL; + eventDef = singlylinkedlist_get_head_item(property); + for (int i = 0; i < index + 1; i++) { + ev = singlylinkedlist_item_get_value(eventDef); + eventDef = singlylinkedlist_get_next_item(eventDef); + } + if (NULL != ev) { + SerialPnp_PropertyUpdateHandler(ev->defintion.Name, propertyInitial, propertyInitialLen, propertyDataUpdated, propertyDataUpdatedLen, + desiredVersion, userContextCallback); + } } void SerialPnp_CommandUpdateHandlerRedirect(int index, - const PNP_CLIENT_COMMAND_REQUEST* pnpClientCommandContext, - PNP_CLIENT_COMMAND_RESPONSE* pnpClientCommandResponseContext, - void* userContextCallback) + const PNP_CLIENT_COMMAND_REQUEST* pnpClientCommandContext, + PNP_CLIENT_COMMAND_RESPONSE* pnpClientCommandResponseContext, + void* userContextCallback) { - LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(g_InterfaceDefinitions); - const InterfaceDefinition* interfaceDef; + PSERIAL_DEVICE_CONTEXT deviceContext = userContextCallback; + LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions); + const InterfaceDefinition* interfaceDef; - for (int i = 0; i<0 - 1; i++) - { - interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); - } - interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); + for (int i = 0; i < 0 - 1; i++) + { + interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); + } + interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); - SINGLYLINKEDLIST_HANDLE command = interfaceDef->Commands; - LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(command); - const CommandDefinition* ev = NULL; - eventDef = singlylinkedlist_get_head_item(command); - for (int i = 0; i < index + 1; i++) { - ev = singlylinkedlist_item_get_value(eventDef); - eventDef = singlylinkedlist_get_next_item(eventDef); - } - if (NULL != ev) { - SerialPnp_CommandUpdateHandler(ev->defintion.Name, pnpClientCommandContext, pnpClientCommandResponseContext, userContextCallback); - } + SINGLYLINKEDLIST_HANDLE command = interfaceDef->Commands; + LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(command); + const CommandDefinition* ev = NULL; + eventDef = singlylinkedlist_get_head_item(command); + for (int i = 0; i < index + 1; i++) { + ev = singlylinkedlist_item_get_value(eventDef); + eventDef = singlylinkedlist_get_next_item(eventDef); + } + if (NULL != ev) { + SerialPnp_CommandUpdateHandler(ev->defintion.Name, pnpClientCommandContext, pnpClientCommandResponseContext, userContextCallback); + } } -const InterfaceDefinition* SerialPnp_GetInterface(const char* interfaceId) { - LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(g_InterfaceDefinitions); - while (interfaceDefHandle != NULL) { - const InterfaceDefinition* interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); - if (stricmp(interfaceDef->Id, interfaceId) == 0) { - return interfaceDef; - } - interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); - } - return NULL; +const InterfaceDefinition* SerialPnp_GetInterface(PSERIAL_DEVICE_CONTEXT deviceContext, const char* interfaceId) { + LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions); + while (interfaceDefHandle != NULL) { + const InterfaceDefinition* interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); + if (stricmp(interfaceDef->Id, interfaceId) == 0) { + return interfaceDef; + } + interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); + } + return NULL; } int SerialPnp_GetListCount(SINGLYLINKEDLIST_HANDLE list) { - if (NULL == list) { - return 0; - } + if (NULL == list) { + return 0; + } - LIST_ITEM_HANDLE item = singlylinkedlist_get_head_item(list); - int count = 0; - while (NULL != item) { - count++; - item = singlylinkedlist_get_next_item(item); - } - return count; + LIST_ITEM_HANDLE item = singlylinkedlist_get_head_item(list); + int count = 0; + while (NULL != item) { + count++; + item = singlylinkedlist_get_next_item(item); + } + return count; } -int SerialPnp_CreatePnpInterface(PNPADAPTER_INTERFACE_HANDLE Interface, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD args) { - PSERIAL_DEVICE_CONTEXT deviceContext = (PSERIAL_DEVICE_CONTEXT) args->Context; - JSON_Value* jvalue = json_parse_string(args->Message); - JSON_Object* jmsg = json_value_get_object(jvalue); - PNP_INTERFACE_CLIENT_HANDLE pnpInterfaceClient; - const char* interfaceId = json_object_get_string(jmsg, "InterfaceId"); - const InterfaceDefinition* interfaceDef = SerialPnp_GetInterface(interfaceId); - PNP_CLIENT_READWRITE_PROPERTY_UPDATED_CALLBACK_TABLE serialPropertyTable = { 0 }; - PNP_CLIENT_COMMAND_CALLBACK_TABLE serialCommandTable = { 0 }; - PNP_COMMAND_EXECUTE_CALLBACK* commandUpdateTable = NULL; - char** propertyNames = NULL; - PNP_READWRITE_PROPERTY_UPDATE_CALLBACK* propertyUpdateTable = NULL; - char** commandNames = NULL; - int propertyCount = 0; - int commandCount = 0; +int SerialPnp_CreatePnpInterface(PNPADAPTER_CONTEXT adapterHandle, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD args) { + PSERIAL_DEVICE_CONTEXT deviceContext = (PSERIAL_DEVICE_CONTEXT)args->Context; + JSON_Value* jvalue = json_parse_string(args->Message); + JSON_Object* jmsg = json_value_get_object(jvalue); - if (NULL == interfaceDef) { - return -1; - } + const char* interfaceId = json_object_get_string(jmsg, "InterfaceId"); + int result = 0; - // Construct property table - { - SINGLYLINKEDLIST_HANDLE property = interfaceDef->Properties; - propertyCount = SerialPnp_GetListCount(interfaceDef->Properties); + // Create an Azure Pnp interface for each interface in the SerialPnp descriptor + LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions); + while (interfaceDefHandle != NULL) { + PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface = NULL; + PNP_INTERFACE_CLIENT_HANDLE pnpInterfaceClient = NULL; + char** propertyNames = NULL; + int propertyCount = 0; + PNP_READWRITE_PROPERTY_UPDATE_CALLBACK* propertyUpdateTable = NULL; + PNP_CLIENT_READWRITE_PROPERTY_UPDATED_CALLBACK_TABLE serialPropertyTable = { 0 }; + char** commandNames = NULL; + int commandCount = 0; + PNP_COMMAND_EXECUTE_CALLBACK* commandUpdateTable = NULL; + PNP_CLIENT_COMMAND_CALLBACK_TABLE serialCommandTable = { 0 }; + const InterfaceDefinition* interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); - if (propertyCount > 0) { - LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(property); - const PropertyDefinition* ev; + // Construct property table + { + SINGLYLINKEDLIST_HANDLE property = interfaceDef->Properties; + propertyCount = SerialPnp_GetListCount(interfaceDef->Properties); - propertyNames = malloc(sizeof(char*)*propertyCount); - propertyUpdateTable = malloc(sizeof(PNP_READWRITE_PROPERTY_UPDATE_CALLBACK*)*propertyCount); - eventDef = singlylinkedlist_get_head_item(property); - int x = 0; - while (eventDef != NULL) { - ev = singlylinkedlist_item_get_value(eventDef); - propertyNames[x] = ev->defintion.Name; - propertyUpdateTable[x] = PredefinedPropertyHandlerTables[x]; - x++; - eventDef = singlylinkedlist_get_next_item(eventDef); + if (propertyCount > 0) { + LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(property); + const PropertyDefinition* ev; + + propertyNames = malloc(sizeof(char*)*propertyCount); + if (NULL == propertyNames) { + result = -1; + goto exit; + } + + propertyUpdateTable = malloc(sizeof(PNP_READWRITE_PROPERTY_UPDATE_CALLBACK*)*propertyCount); + if (NULL == propertyUpdateTable) { + result = -1; + goto exit; + } + + eventDef = singlylinkedlist_get_head_item(property); + int x = 0; + while (eventDef != NULL) { + ev = singlylinkedlist_item_get_value(eventDef); + propertyNames[x] = ev->defintion.Name; + propertyUpdateTable[x] = PredefinedPropertyHandlerTables[x]; + x++; + eventDef = singlylinkedlist_get_next_item(eventDef); + } + + serialPropertyTable.numCallbacks = propertyCount; + serialPropertyTable.propertyNames = propertyNames; + serialPropertyTable.callbacks = propertyUpdateTable; + serialPropertyTable.version = 1; + } + } + + // Construct command table + { + SINGLYLINKEDLIST_HANDLE command = interfaceDef->Commands; + int commandCount = SerialPnp_GetListCount(command); + + if (commandCount > 0) { + LIST_ITEM_HANDLE cmdDef; + int x = 0; + const CommandDefinition* cv; + + commandNames = malloc(sizeof(char*)*commandCount); + if (NULL == commandNames) { + result = -1; + goto exit; + } + + commandUpdateTable = malloc(sizeof(PNP_COMMAND_EXECUTE_CALLBACK*)*commandCount); + if (NULL == commandUpdateTable) { + result = -1; + goto exit; + } + + cmdDef = singlylinkedlist_get_head_item(command); + while (cmdDef != NULL) { + cv = singlylinkedlist_item_get_value(cmdDef); + commandNames[x] = cv->defintion.Name; + commandUpdateTable[x] = PredefinedCommandHandlerTables[x]; + x++; + cmdDef = singlylinkedlist_get_next_item(cmdDef); + } + + serialCommandTable.numCommandCallbacks = commandCount; + serialCommandTable.commandNames = commandNames; + serialCommandTable.commandCallbacks = commandUpdateTable; + serialCommandTable.version = 1; + } + } + + pnpInterfaceClient = PnP_InterfaceClient_Create(pnpDeviceClientHandle, interfaceId, + propertyCount > 0 ? &serialPropertyTable : NULL, + commandCount > 0 ? &serialCommandTable : NULL, + deviceContext); + if (NULL == pnpInterfaceClient) { + result = -1; + goto exit; + } + + // Create PnpAdapter Interface + { + PNPADPATER_INTERFACE_INIT_PARAMS interfaceParams = { 0 }; + interfaceParams.releaseInterface = SerialPnp_ReleasePnpInterface; + //interfaceParams.pnpInterface = pnpInterfaceClient; + + result = PnpAdapterInterface_Create(adapterHandle, interfaceId, pnpInterfaceClient, &pnpAdapterInterface, &interfaceParams); + if (result < 0) { + goto exit; } - - serialPropertyTable.numCallbacks = propertyCount; - serialPropertyTable.propertyNames = propertyNames; - serialPropertyTable.callbacks = propertyUpdateTable; - serialPropertyTable.version = 1; } - } - // Construct command table - { - SINGLYLINKEDLIST_HANDLE command = interfaceDef->Commands; - int commandCount = SerialPnp_GetListCount(command); - - if (commandCount > 0) { - LIST_ITEM_HANDLE cmdDef; - int x = 0; - const CommandDefinition* cv; - - commandNames = malloc(sizeof(char*)*commandCount); - commandUpdateTable = malloc(sizeof(PNP_COMMAND_EXECUTE_CALLBACK*)*commandCount); - cmdDef = singlylinkedlist_get_head_item(command); - while (cmdDef != NULL) { - cv = singlylinkedlist_item_get_value(cmdDef); - commandNames[x] = cv->defintion.Name; - commandUpdateTable[x] = PredefinedCommandHandlerTables[x]; - x++; - cmdDef = singlylinkedlist_get_next_item(cmdDef); - } - - serialCommandTable.numCommandCallbacks = commandCount; - serialCommandTable.commandNames = commandNames; - serialCommandTable.commandCallbacks = commandUpdateTable; - serialCommandTable.version = 1; + if (NULL != propertyUpdateTable) { + free(propertyUpdateTable); } + if (NULL != propertyNames) { + free(propertyNames); + } + + if (NULL != commandUpdateTable) { + free(commandUpdateTable); + } + if (NULL != commandNames) { + free(commandNames); + } + + // Save the PnpAdapterInterface in device context + deviceContext->pnpAdapterInterface = pnpAdapterInterface; + + interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); } - pnpInterfaceClient = PnP_InterfaceClient_Create(pnpDeviceClientHandle, interfaceId, propertyCount > 0 ? &serialPropertyTable : NULL, commandCount > 0 ? &serialCommandTable : NULL, deviceContext); - if (NULL == pnpInterfaceClient) { - return -1; - } +exit: - if (NULL != propertyUpdateTable) { - free(propertyUpdateTable); - } - if (NULL != propertyNames) { - free(propertyNames); + // Cleanup incase of failure + if (result < 0) { + // Destroy PnpInterfaceClient + //if (NULL != pnpInterfaceClient) { + // PnP_InterfaceClient_Destroy(pnpInterfaceClient); + //} } + + return 0; +} - if (NULL != commandUpdateTable) { - free(commandUpdateTable); - } - if (NULL != commandNames) { - free(commandNames); - } +void SerialPnp_FreeFieldDefinition(FieldDefinition* fdef) { + if (NULL != fdef->Description) { + free(fdef->Description); + } - PnpAdapter_SetPnpInterfaceClient(Interface, pnpInterfaceClient); - deviceContext->InterfaceHandle = PnpAdapter_GetPnpInterfaceClient(Interface); + if (NULL != fdef->DisplayName) { + free(fdef->DisplayName); + } - return 0; + if (NULL != fdef->Name) { + free(fdef->Name); + } +} + +void SerialPnp_FreeEventDefinition(SINGLYLINKEDLIST_HANDLE events) { + if (NULL == events) { + return; + } + + LIST_ITEM_HANDLE eventItem = singlylinkedlist_get_head_item(events); + while (NULL != eventItem) { + EventDefinition* e = (EventDefinition*)singlylinkedlist_item_get_value(eventItem); + SerialPnp_FreeFieldDefinition(&e->defintion); + if (NULL != e->Units) { + free(e->Units); + } + free(e); + eventItem = singlylinkedlist_get_next_item(eventItem); + } +} + +void SerialPnp_FreeCommandDefinition(SINGLYLINKEDLIST_HANDLE cmds) { + if (NULL == cmds) { + return; + } + + LIST_ITEM_HANDLE cmdItem = singlylinkedlist_get_head_item(cmds); + while (NULL != cmdItem) { + CommandDefinition* c = (CommandDefinition*)singlylinkedlist_item_get_value(cmdItem); + free(c); + cmdItem = singlylinkedlist_get_next_item(cmdItem); + } +} + +void SerialPnp_FreePropertiesDefinition(SINGLYLINKEDLIST_HANDLE props) { + if (NULL == props) { + return; + } + + LIST_ITEM_HANDLE propItem = singlylinkedlist_get_head_item(props); + while (NULL != propItem) { + PropertyDefinition* p = (PropertyDefinition*)singlylinkedlist_item_get_value(propItem); + SerialPnp_FreeFieldDefinition(&p->defintion); + if (NULL != p->Units) { + free(p->Units); + } + free(p); + propItem = singlylinkedlist_get_next_item(propItem); + } } int SerialPnp_ReleasePnpInterface(PNPADAPTER_INTERFACE_HANDLE pnpInterface) { - PSERIAL_DEVICE_CONTEXT deviceContext = PnpAdapter_GetContext(pnpInterface); + PSERIAL_DEVICE_CONTEXT deviceContext = PnpAdapterInterface_GetContext(pnpInterface); - if (NULL != deviceContext) { - return 0; - } + if (NULL == deviceContext) { + return 0; + } - // BUG: If a serial device has multiple interface, this wont work - if (deviceContext->hSerial) { - CloseHandle(deviceContext->hSerial); - } + if (NULL != deviceContext->hSerial) { + CloseHandle(deviceContext->hSerial); + } - free(deviceContext); + if (deviceContext->InterfaceDefinitions) { + LIST_ITEM_HANDLE interfaceItem = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions); + while (interfaceItem != NULL) { + InterfaceDefinition* def = (InterfaceDefinition*)singlylinkedlist_item_get_value(interfaceItem); + SerialPnp_FreeEventDefinition(def->Events); + SerialPnp_FreeCommandDefinition(def->Commands); + SerialPnp_FreePropertiesDefinition(def->Properties); - return 0; + free(def); + interfaceItem = singlylinkedlist_get_next_item(interfaceItem); + } + singlylinkedlist_destroy(deviceContext->InterfaceDefinitions); + } + + free(deviceContext); + + return 0; } int SerialPnp_Initialize(const char* adapterArgs) { - return 0; + return 0; } int SerialPnp_Shutdown() { - return 0; + return 0; } DISCOVERY_ADAPTER SerialPnpDiscovery = { - .Identity = "serial-pnp-discovery", - .StartDiscovery = SerialPnp_StartDiscovery, - .StopDiscovery = SerialPnp_StopDiscovery + .Identity = "serial-pnp-discovery", + .StartDiscovery = SerialPnp_StartDiscovery, + .StopDiscovery = SerialPnp_StopDiscovery }; PNP_ADAPTER SerialPnpInterface = { - .Identity = "serial-pnp-interface", - .Initialize = SerialPnp_Initialize, - .Shutdown = SerialPnp_Shutdown, - .CreatePnpInterface = SerialPnp_CreatePnpInterface, - .ReleaseInterface = SerialPnp_ReleasePnpInterface + .identity = "serial-pnp-interface", + .initialize = SerialPnp_Initialize, + .shutdown = SerialPnp_Shutdown, + .createPnpInterface = SerialPnp_CreatePnpInterface }; diff --git a/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.h b/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.h index 6c5719a..9f8d8a5 100644 --- a/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.h +++ b/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.h @@ -5,94 +5,101 @@ extern "C" { #endif -typedef struct SerialPnPPacketHeader -{ - byte StartOfFrame; - USHORT Length; - byte PacketType; -} SerialPnPPacketHeader; + typedef struct SerialPnPPacketHeader + { + byte StartOfFrame; + USHORT Length; + byte PacketType; + } SerialPnPPacketHeader; -typedef enum Schema -{ - Invalid = 0, - Byte, - Float, - Double, - Int, - Long, - Boolean, - String -} Schema; + typedef enum Schema + { + Invalid = 0, + Byte, + Float, + Double, + Int, + Long, + Boolean, + String + } Schema; -typedef struct FieldDefinition -{ - char* Name; - char* DisplayName; - char* Description; -} FieldDefinition; + typedef struct FieldDefinition + { + char* Name; + char* DisplayName; + char* Description; + } FieldDefinition; -typedef struct EventDefinition -{ - FieldDefinition defintion; - Schema DataSchema; - char* Units; -} EventDefinition; + typedef struct EventDefinition + { + FieldDefinition defintion; + Schema DataSchema; + char* Units; + } EventDefinition; -typedef struct PropertyDefinition -{ - FieldDefinition defintion; - char* Units; - bool Required; - bool Writeable; - Schema DataSchema; -} PropertyDefinition; + typedef struct PropertyDefinition + { + FieldDefinition defintion; + char* Units; + bool Required; + bool Writeable; + Schema DataSchema; + } PropertyDefinition; -typedef struct CommandDefinition -{ - FieldDefinition defintion; - Schema RequestSchema; - Schema ResponseSchema; -} CommandDefinition; + typedef struct CommandDefinition + { + FieldDefinition defintion; + Schema RequestSchema; + Schema ResponseSchema; + } CommandDefinition; -typedef struct InterfaceDefinition -{ - char* Id; - int Index; - SINGLYLINKEDLIST_HANDLE Events; - SINGLYLINKEDLIST_HANDLE Properties; - SINGLYLINKEDLIST_HANDLE Commands; -} InterfaceDefinition; + typedef struct InterfaceDefinition + { + char* Id; + int Index; + SINGLYLINKEDLIST_HANDLE Events; + SINGLYLINKEDLIST_HANDLE Properties; + SINGLYLINKEDLIST_HANDLE Commands; + } InterfaceDefinition; -typedef enum DefinitionType { - Telemetry, - Property, - Command -} DefinitionType; + typedef enum DefinitionType { + Telemetry, + Property, + Command + } DefinitionType; -typedef struct _SERIAL_DEVICE_CONTEXT { - HANDLE hSerial; - PNP_INTERFACE_CLIENT_HANDLE* InterfaceHandle; - byte RxBuffer[4096]; // Todo: maximum buffer size - unsigned int RxBufferIndex; - bool RxEscaped; - THREAD_HANDLE SerialDeviceWorker; - PNPBRIDGE_NOTIFY_DEVICE_CHANGE SerialDeviceChangeCallback; -} SERIAL_DEVICE_CONTEXT, *PSERIAL_DEVICE_CONTEXT; + typedef struct _SERIAL_DEVICE_CONTEXT { + HANDLE hSerial; + PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface; -void SerialPnp_RxPacket(PSERIAL_DEVICE_CONTEXT serialDevice, byte** receivedPacket, DWORD* length, char packetType); + byte RxBuffer[4096]; // Todo: maximum buffer size + unsigned int RxBufferIndex; + bool RxEscaped; + //OVERLAPPED osReader; + THREAD_HANDLE SerialDeviceWorker; + PNPBRIDGE_NOTIFY_DEVICE_CHANGE SerialDeviceChangeCallback; + + // list of interface definitions on this serial device + SINGLYLINKEDLIST_HANDLE InterfaceDefinitions; + } SERIAL_DEVICE_CONTEXT, *PSERIAL_DEVICE_CONTEXT; -void SerialPnp_TxPacket(PSERIAL_DEVICE_CONTEXT serialDevice, byte* OutPacket, int Length); + void SerialPnp_RxPacket(PSERIAL_DEVICE_CONTEXT serialDevice, byte** receivedPacket, DWORD* length, char packetType); -void SerialPnp_UnsolicitedPacket(PSERIAL_DEVICE_CONTEXT device, byte* packet, DWORD length); + void SerialPnp_TxPacket(PSERIAL_DEVICE_CONTEXT serialDevice, byte* OutPacket, int Length); -void SerialPnp_ResetDevice(PSERIAL_DEVICE_CONTEXT serialDevice); + void SerialPnp_UnsolicitedPacket(PSERIAL_DEVICE_CONTEXT device, byte* packet, DWORD length); -void SerialPnp_DeviceDescriptorRequest(PSERIAL_DEVICE_CONTEXT serialDevice, byte** desc, DWORD* length); + void SerialPnp_ResetDevice(PSERIAL_DEVICE_CONTEXT serialDevice); -byte* SerialPnp_StringSchemaToBinary(Schema Schema, byte* data, int* length); + void SerialPnp_DeviceDescriptorRequest(PSERIAL_DEVICE_CONTEXT serialDevice, byte** desc, DWORD* length); -int SerialPnp_SendEventAsync(PNP_INTERFACE_CLIENT_HANDLE pnpInterface, char* eventName, char* data); + byte* SerialPnp_StringSchemaToBinary(Schema Schema, byte* data, int* length); + + int SerialPnp_SendEventAsync(PNP_INTERFACE_CLIENT_HANDLE pnpInterface, char* eventName, char* data); + + int SerialPnp_ReleasePnpInterface(PNPADAPTER_INTERFACE_HANDLE pnpInterface); #ifdef __cplusplus diff --git a/PnpBridge/src/PnpBridge/ConfigurationParser.c b/PnpBridge/src/PnpBridge/ConfigurationParser.c index ff150f1..2444d7a 100644 --- a/PnpBridge/src/PnpBridge/ConfigurationParser.c +++ b/PnpBridge/src/PnpBridge/ConfigurationParser.c @@ -41,10 +41,19 @@ JSON_Object* Configuration_GetPnpParametersForDevice(JSON_Object* device) { return NULL; } - JSON_Object* discoveryParams = json_object_dotget_object(device, "PnpParameters"); - return discoveryParams; + JSON_Object* pnpParams = json_object_dotget_object(device, "PnpParameters"); + return pnpParams; } +JSON_Object* Configuration_GetMatchParametersForDevice(JSON_Object* device) { + if (device == NULL) { + return NULL; + } + + JSON_Object* filterParams = json_object_dotget_object(device, "MatchFilters"); + JSON_Object* matchParams = json_object_dotget_object(filterParams, "MatchParameters"); + return matchParams; +} JSON_Object* Configuration_GetDiscoveryParametersForDevice(JSON_Object* device) { if (device == NULL) { @@ -79,7 +88,7 @@ JSON_Object* Configuration_GetAdapterParameters(JSON_Value* config, const char* for (int j = 0; j < (int)json_array_get_count(params); j++) { JSON_Object *param = json_array_get_object(params, j); - const char* id = json_object_dotget_string(param, "Identity"); + const char* id = json_object_dotget_string(param, PNP_CONFIG_IDENTITY_NAME); if (NULL != id) { if (strcmp(id, identity) == 0) { return param; @@ -91,21 +100,22 @@ JSON_Object* Configuration_GetAdapterParameters(JSON_Value* config, const char* } JSON_Object* Configuration_GetPnpParameters(JSON_Value* config, const char* identity) { - return Configuration_GetAdapterParameters(config, identity, "PnpAdapters"); + return Configuration_GetAdapterParameters(config, identity, PNP_CONFIG_NAME_PNP_ADAPTERS); } JSON_Object* Configuration_GetDiscoveryParameters(JSON_Value* config,const char* identity) { - return Configuration_GetAdapterParameters(config, identity, "DiscoveryAdapters"); + return Configuration_GetAdapterParameters(config, identity, PNP_CONFIG_NAME_DISCOVERY_ADAPTERS); } PNPBRIDGE_RESULT Configuration_IsDeviceConfigured(JSON_Value* config, JSON_Object* Message, JSON_Object** Device) { JSON_Array *devices = Configuration_GetConfiguredDevices(config); JSON_Object* discMatchParams; + char* pnpAdapterIdentity = NULL; int res = -1; bool foundMatch = false; - // const char* formatId = json_object_dotget_string(Message, "Identity"); - discMatchParams = json_object_get_object(Message, "MatchParameters"); +// const char* formatId = json_object_dotget_string(Message, "Identity"); + discMatchParams = json_object_get_object(Message, PNP_CONFIG_NAME_MATCH_PARAMETERS); // There needs to be only one match at the end. for (int i = 0; i < (int)json_array_get_count(devices); i++) { @@ -117,18 +127,23 @@ PNPBRIDGE_RESULT Configuration_IsDeviceConfigured(JSON_Value* config, JSON_Objec // const char* deviceFormatId = json_object_dotget_string(moduleParams, "Identity"); if (true) { //strcmp(deviceFormatId, formatId) == 0) { - JSON_Object* matchCriteria = json_object_dotget_object(device, "MatchFilters"); - const char* matchType = json_object_get_string(matchCriteria, "MatchType"); + JSON_Object* matchCriteria = json_object_dotget_object(device, PNP_CONFIG_MATCH_FILTERS_NAME); + const char* matchType = json_object_get_string(matchCriteria, PNP_CONFIG_MATCH_TYPE_NAME); + const char* currPnpAdapterId = json_object_get_string(moduleParams, PNP_CONFIG_IDENTITY_NAME); if (strcmp(matchType, "*") == 0) { if (true == foundMatch) { - LogError("Found multiple devices in the config that match the filter"); - res = -1; - goto end; + if (0 == stricmp(pnpAdapterIdentity, currPnpAdapterId)) { + LogError("Found multiple devices in the config that match the filter"); + res = -1; + goto end; + } + } + else { + foundMatch = true; + pnpAdapterIdentity = (char*) currPnpAdapterId; + res = 0; + *Device = device; } - - foundMatch = true; - res = 0; - *Device = device; continue; } @@ -136,7 +151,7 @@ PNPBRIDGE_RESULT Configuration_IsDeviceConfigured(JSON_Value* config, JSON_Objec continue; } - JSON_Object* matchParameters = json_object_dotget_object(matchCriteria, "MatchParameters"); + JSON_Object* matchParameters = json_object_dotget_object(matchCriteria, PNP_CONFIG_NAME_MATCH_PARAMETERS); const size_t matchParameterCount = json_object_get_count(matchParameters); for (int j = 0; j < (int)matchParameterCount; j++) { const char* name = json_object_get_name(matchParameters, j); @@ -148,26 +163,24 @@ PNPBRIDGE_RESULT Configuration_IsDeviceConfigured(JSON_Value* config, JSON_Objec } const char* value2 = json_object_get_string(discMatchParams, name); - if (strstr(value2, value) == 0) { - res = -1; - goto end; - } - else { + if (strstr(value2, value) != 0) { if (true == foundMatch) { - LogError("Found multiple devices in the config that match the filter"); - res = -1; - goto end; + if (0 == stricmp(pnpAdapterIdentity, currPnpAdapterId)) { + LogError("Found multiple devices in the config that match the filter"); + res = -1; + goto end; + } + } + else { + const char* interfaceId = json_object_dotget_string(device, PNP_CONFIG_INTERFACE_ID_NAME); + json_object_set_string(Message, PNP_CONFIG_INTERFACE_ID_NAME, interfaceId); + foundMatch = true; + pnpAdapterIdentity = (char*) currPnpAdapterId; + *Device = device; + res = 0; } - - const char* interfaceId = json_object_dotget_string(device, "InterfaceId"); - json_object_set_string(Message, "InterfaceId", interfaceId); - foundMatch = true; - *Device = device; - res = 0; } } - res = 0; - goto end; } } diff --git a/PnpBridge/src/PnpBridge/ConfigurationParser.h b/PnpBridge/src/PnpBridge/ConfigurationParser.h index 521f02a..7b18108 100644 --- a/PnpBridge/src/PnpBridge/ConfigurationParser.h +++ b/PnpBridge/src/PnpBridge/ConfigurationParser.h @@ -26,6 +26,8 @@ PNPBRIDGE_RESULT PnpBridgeConfig_ReadConfigurationFromFile(const char *filename, */ PNPBRIDGE_RESULT PnpBridgeConfig_ReadConfigurationFromString(const char *configString, JSON_Value** config); +JSON_Object* Configuration_GetMatchParametersForDevice(JSON_Object* device); + JSON_Object* Configuration_GetDiscoveryParametersForDevice(JSON_Object* device); JSON_Object* Configuration_GetPnpParametersForDevice(JSON_Object* device); diff --git a/PnpBridge/src/PnpBridge/DiscoveryManager.c b/PnpBridge/src/PnpBridge/DiscoveryManager.c index e860750..18728c8 100644 --- a/PnpBridge/src/PnpBridge/DiscoveryManager.c +++ b/PnpBridge/src/PnpBridge/DiscoveryManager.c @@ -106,63 +106,108 @@ PNPBRIDGE_RESULT DiscoveryManager_StarDiscoveryAdapter(PDISCOVERY_MANAGER discov return PNPBRIDGE_OK; } -PNPBRIDGE_RESULT DiscoveryAdapterManager_Start(PDISCOVERY_MANAGER discoveryManager, JSON_Value* config) { +const char* PnpBridge_DeviceChangeMessageformat = "{ \ + \"Identity\": \"pnpbridge-core\", \ + \"InterfaceId\": \"%s\", \ + \"Persistent\": \"true\", \ + \"MatchParameters\": %s \ + }"; + +PNPBRIDGE_RESULT DiscoveryAdapterManager_NotifyPersistentInterfaces(PDISCOVERY_MANAGER discoveryManager, JSON_Value* config) { JSON_Array *devices = Configuration_GetConfiguredDevices(config); - if (NULL == devices) { - return PNPBRIDGE_INVALID_ARGS; - } + for (int i = 0; i < (int)json_array_get_count(devices); i++) { + JSON_Object* device = json_array_get_object(devices, i); + const char* persistentString = json_object_get_string(device, PNP_CONFIG_PERSISTENT_NAME); + if (NULL != persistentString && stricmp(persistentString, "true") == 0) { + PNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload = { 0 }; + payload.ChangeType = PNPBRIDGE_INTERFACE_CHANGE_PERSIST; - for (int i = 0; i < DiscoveryAdapterCount; i++) { - PDISCOVERY_ADAPTER discoveryInterface = DISCOVERY_ADAPTER_MANIFEST[i]; - JSON_Object* deviceParams = NULL; + // Get the match filters and post a device change message + JSON_Object* matchParams = Configuration_GetMatchParametersForDevice(device); + const char* interfaceId = json_object_dotget_string(device, PNP_CONFIG_INTERFACE_ID_NAME); + if (NULL != interfaceId && NULL != matchParams) { + char msg[512] = { 0 }; + sprintf_s(msg, 512, PnpBridge_DeviceChangeMessageformat, interfaceId, json_serialize_to_string(json_object_get_wrapping_value(matchParams))); + + payload.Message = msg; + payload.MessageLength = (int)strlen(msg); - for (int j = 0; j < (int)json_array_get_count(devices); j++) { - JSON_Object *device = json_array_get_object(devices, j); - - // For this Identity check if there is any device - // TODO: Create an array of device - JSON_Object* params = Configuration_GetDiscoveryParametersForDevice(device); - if (NULL != params) { - const char* deviceFormatId = json_object_get_string(params, "Identity"); - if (strcmp(deviceFormatId, discoveryInterface->Identity) == 0) { - deviceParams = params; - break; - } + DiscoveryAdapterChangeHandler(&payload); } } - - JSON_Object* adapterParams = NULL; - adapterParams = Configuration_GetDiscoveryParameters(config, discoveryInterface->Identity); - - //PSTART_DISCOVERY_PARAMS threadContext; - - //// threadContext memory will be freed during cleanup. - //threadContext = malloc(sizeof(START_DISCOVERY_PARAMS)); - //if (NULL == threadContext) { - // return PNPBRIDGE_INSUFFICIENT_MEMORY; - //} - - //threadContext->adapterParams = adapterParams; - //threadContext->deviceParams = deviceParams; - //threadContext->discoveryInterface = discoveryInterface; - //threadContext->key = i; - //threadContext->discoveryManager = discoveryManager; - - //if (THREADAPI_OK != ThreadAPI_Create(&threadContext->workerThreadHandle, DiscoveryManager_StarDiscovery_Worker_Thread, threadContext)) { - // LogError("Failed to create PnpBridge_Worker_Thread \n"); - // threadContext->workerThreadHandle = NULL; - // return PNPBRIDGE_FAILED; - //} - int result = DiscoveryManager_StarDiscoveryAdapter(discoveryManager, discoveryInterface, deviceParams, adapterParams, i); - if (PNPBRIDGE_OK != result) { - return result; - } - - //singlylinkedlist_add(discoveryManager->startDiscoveryThreadHandles, threadContext); } - return PNPBRIDGE_OK; + return 0; +} + +PNPBRIDGE_RESULT DiscoveryAdapterManager_Start(PDISCOVERY_MANAGER discoveryManager, JSON_Value* config) { + JSON_Array *devices = Configuration_GetConfiguredDevices(config); + PNPBRIDGE_RESULT result = PNPBRIDGE_OK; + + TRY + { + if (NULL == devices) { + result = PNPBRIDGE_INVALID_ARGS; + LEAVE; + } + + for (int i = 0; i < DiscoveryAdapterCount; i++) { + PDISCOVERY_ADAPTER discoveryInterface = DISCOVERY_ADAPTER_MANIFEST[i]; + JSON_Object* deviceParams = NULL; + + for (int j = 0; j < (int)json_array_get_count(devices); j++) { + JSON_Object *device = json_array_get_object(devices, j); + + // For this Identity check if there is any device + // TODO: Create an array of device + JSON_Object* params = Configuration_GetDiscoveryParametersForDevice(device); + if (NULL != params) { + const char* discoveryIdentity = json_object_get_string(params, PNP_CONFIG_IDENTITY_NAME); + if (NULL != discoveryIdentity) { + if (stricmp(discoveryIdentity, discoveryInterface->Identity) == 0) { + deviceParams = params; + break; + } + } + } + } + + JSON_Object* adapterParams = NULL; + adapterParams = Configuration_GetDiscoveryParameters(config, discoveryInterface->Identity); + + //PSTART_DISCOVERY_PARAMS threadContext; + + //// threadContext memory will be freed during cleanup. + //threadContext = malloc(sizeof(START_DISCOVERY_PARAMS)); + //if (NULL == threadContext) { + // return PNPBRIDGE_INSUFFICIENT_MEMORY; + //} + + //threadContext->adapterParams = adapterParams; + //threadContext->deviceParams = deviceParams; + //threadContext->discoveryInterface = discoveryInterface; + //threadContext->key = i; + //threadContext->discoveryManager = discoveryManager; + + //if (THREADAPI_OK != ThreadAPI_Create(&threadContext->workerThreadHandle, DiscoveryManager_StarDiscovery_Worker_Thread, threadContext)) { + // LogError("Failed to create PnpBridge_Worker_Thread \n"); + // threadContext->workerThreadHandle = NULL; + // return PNPBRIDGE_FAILED; + //} + int result = DiscoveryManager_StarDiscoveryAdapter(discoveryManager, discoveryInterface, deviceParams, adapterParams, i); + if (PNPBRIDGE_OK != result) { + return result; + } + + //singlylinkedlist_add(discoveryManager->startDiscoveryThreadHandles, threadContext); + } + } + FINALLY + { + } + + return result; } void DiscoveryAdapterManager_Stop(PDISCOVERY_MANAGER discoveryManager) { diff --git a/PnpBridge/src/PnpBridge/DiscoveryManager.h b/PnpBridge/src/PnpBridge/DiscoveryManager.h index a560fe7..cef0d16 100644 --- a/PnpBridge/src/PnpBridge/DiscoveryManager.h +++ b/PnpBridge/src/PnpBridge/DiscoveryManager.h @@ -27,6 +27,8 @@ PNPBRIDGE_RESULT DiscoveryAdapterManager_Create(PDISCOVERY_MANAGER* discoveryMan */ PNPBRIDGE_RESULT DiscoveryAdapterManager_Start(PDISCOVERY_MANAGER discoveryManager, JSON_Value* config); +PNPBRIDGE_RESULT DiscoveryAdapterManager_NotifyPersistentInterfaces(PDISCOVERY_MANAGER discoveryManager, JSON_Value* config); + void DiscoveryAdapterManager_Stop(PDISCOVERY_MANAGER discoveryManager); #ifdef __cplusplus diff --git a/PnpBridge/src/PnpBridge/IotHubComms.c b/PnpBridge/src/PnpBridge/IotHubComms.c new file mode 100644 index 0000000..78d6ad3 --- /dev/null +++ b/PnpBridge/src/PnpBridge/IotHubComms.c @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +// DeviceAggregator.cpp : Defines the entry point for the console application. + +#include "PnpBridgeCommon.h" +#include "ConfigurationParser.h" +#include "DiscoveryManager.h" +#include "PnpAdapterInterface.h" +#include "PnpAdapterManager.h" + +#include "PnpBridgeh.h" + +// State of PnP registration process. We cannot proceed with PnP until we get into the state APP_PNP_REGISTRATION_SUCCEEDED. +typedef enum APP_PNP_REGISTRATION_STATUS_TAG +{ + APP_PNP_REGISTRATION_PENDING, + APP_PNP_REGISTRATION_SUCCEEDED, + APP_PNP_REGISTRATION_FAILED +} APP_PNP_REGISTRATION_STATUS; + +// appPnpInterfacesRegistered is invoked when the interfaces have been registered or failed. +void appPnpInterfacesRegistered(PNP_REPORTED_INTERFACES_STATUS pnpInterfaceStatus, void *userContextCallback) +{ + APP_PNP_REGISTRATION_STATUS* appPnpRegistrationStatus = (APP_PNP_REGISTRATION_STATUS*)userContextCallback; + *appPnpRegistrationStatus = (pnpInterfaceStatus == PNP_REPORTED_INTERFACES_OK) ? APP_PNP_REGISTRATION_SUCCEEDED : APP_PNP_REGISTRATION_FAILED; +} + +// Invokes PnP_DeviceClient_RegisterInterfacesAsync, which indicates to Azure IoT which PnP interfaces this device supports. +// The PnP Handle *is not valid* until this operation has completed (as indicated by the callback appPnpInterfacesRegistered being invoked). +// In this sample, we block indefinitely but production code should include a timeout. +int AppRegisterPnPInterfacesAndWait(PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PNP_INTERFACE_CLIENT_HANDLE* interfaces, int count) +{ + APP_PNP_REGISTRATION_STATUS appPnpRegistrationStatus = APP_PNP_REGISTRATION_PENDING; + PNPBRIDGE_RESULT result; + PNP_CLIENT_RESULT pnpResult; + + pnpResult = PnP_DeviceClient_RegisterInterfacesAsync(pnpDeviceClientHandle, interfaces, count, appPnpInterfacesRegistered, &appPnpRegistrationStatus); + if (PNP_CLIENT_OK != pnpResult) { + result = PNPBRIDGE_FAILED; + goto end; + } + + while (appPnpRegistrationStatus == APP_PNP_REGISTRATION_PENDING) { + ThreadAPI_Sleep(100); + } + + if (appPnpRegistrationStatus != APP_PNP_REGISTRATION_SUCCEEDED) { + LogError("PnP has failed to register.\n"); + result = __FAILURE__; + } + else { + result = 0; + } + +end: + + return result; +} + +// InitializeIotHubDeviceHandle initializes underlying IoTHub client, creates a device handle with the specified connection string, +// and sets some options on this handle prior to beginning. +IOTHUB_DEVICE_HANDLE InitializeIotHubDeviceHandle(const char* connectionString) +{ + IOTHUB_DEVICE_HANDLE deviceHandle = NULL; + IOTHUB_CLIENT_RESULT iothubClientResult; + bool traceOn = false; + bool urlEncodeOn = true; + + // TODO: PnP SDK should auto-set OPTION_AUTO_URL_ENCODE_DECODE for MQTT as its strictly required. Need way for IoTHub handle to communicate this back. + if (IoTHub_Init() != 0) + { + LogError("IoTHub_Init failed\n"); + } + else + { + // Get connection string from config + if ((deviceHandle = IoTHubDeviceClient_CreateFromConnectionString(connectionString, MQTT_Protocol)) == NULL) + { + LogError("Failed to create device handle\n"); + } + else if ((iothubClientResult = IoTHubDeviceClient_SetOption(deviceHandle, OPTION_LOG_TRACE, &traceOn)) != IOTHUB_CLIENT_OK) + { + LogError("Failed to set option %s, error=%d\n", OPTION_LOG_TRACE, iothubClientResult); + IoTHubDeviceClient_Destroy(deviceHandle); + deviceHandle = NULL; + } + else if ((iothubClientResult = IoTHubDeviceClient_SetOption(deviceHandle, OPTION_AUTO_URL_ENCODE_DECODE, &urlEncodeOn)) != IOTHUB_CLIENT_OK) + { + LogError("Failed to set option %s, error=%d\n", OPTION_AUTO_URL_ENCODE_DECODE, iothubClientResult); + IoTHubDeviceClient_Destroy(deviceHandle); + deviceHandle = NULL; + } + + if (deviceHandle == NULL) + { + IoTHub_Deinit(); + } + } + + return deviceHandle; +} \ No newline at end of file diff --git a/PnpBridge/src/PnpBridge/IotHubComms.h b/PnpBridge/src/PnpBridge/IotHubComms.h new file mode 100644 index 0000000..43d8b67 --- /dev/null +++ b/PnpBridge/src/PnpBridge/IotHubComms.h @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#pragma once + +#ifdef __cplusplus +extern "C" +{ +#endif + +IOTHUB_DEVICE_HANDLE InitializeIotHubDeviceHandle(const char* connectionString); + +int AppRegisterPnPInterfacesAndWait(PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PNP_INTERFACE_CLIENT_HANDLE* interfaces, int count); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/PnpBridge/src/PnpBridge/PnpAdapterInterface.h b/PnpBridge/src/PnpBridge/PnpAdapterInterface.h index 5ae03b7..6ca9829 100644 --- a/PnpBridge/src/PnpBridge/PnpAdapterInterface.h +++ b/PnpBridge/src/PnpBridge/PnpAdapterInterface.h @@ -9,14 +9,10 @@ extern "C" { #endif -typedef struct _PNPADAPTER_INTERFACE { - PNP_INTERFACE_CLIENT_HANDLE Interface; - void* Context; - int key; -} PNPADAPTER_INTERFACE, *PPNPADAPTER_INTERFACE; - +// Pnp adapter interface handle typedef void* PNPADAPTER_INTERFACE_HANDLE; - +typedef PNPADAPTER_INTERFACE_HANDLE* PPNPADAPTER_INTERFACE_HANDLE; +typedef void* PNPADAPTER_CONTEXT; /** * @brief PNPADAPTER_PNP_INTERFACE_INITIALIZE callback uses to initialize a pnp adapter. @@ -50,7 +46,23 @@ typedef int(*PNPADAPTER_PNP_INTERFACE_SHUTDOWN)(); * * @returns integer greater than zero on success and other values on failure. */ -typedef int(*PNPADAPTER_BIND_PNP_INTERFACE)(PNPADAPTER_INTERFACE_HANDLE pnpInterface, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload); +//typedef int(*PNPADAPTER_BIND_PNP_INTERFACE)(PNPADAPTER_INTERFACE_HANDLE pnpInterface, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload); + +typedef int(*PNPADAPTER_BIND_PNP_INTERFACE)(PNPADAPTER_CONTEXT adapterHandle, + PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, + PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload); + +// NOTES TO SELF: + +// +// Config update requires bridge tear down and restart +// + +// Discovered Device -> Bind -> CreatePnpInterfaces -> Create Pnp Interface client -> +// Create Pnp Adapter Interface -> Associate it with the adapter and store the device config pointer -> Get All interface for all adapters -> publish +// + +// *************** /** * @brief PNPADAPTER_RELEASE_PNP_INTERFACE uninitializes the pnp interface. @@ -61,9 +73,41 @@ typedef int(*PNPADAPTER_BIND_PNP_INTERFACE)(PNPADAPTER_INTERFACE_HANDLE pnpInter * * @returns integer greater than zero on success and other values on failure. */ -typedef int(*PNPADAPTER_RELEASE_PNP_INTERFACE)(PNPADAPTER_INTERFACE_HANDLE pnpInterface); +typedef int(*PNPADAPTER_INTERFACE_RELEASE)(PNPADAPTER_INTERFACE_HANDLE pnpInterface); +typedef int(*PNPADAPTER_DEVICE_ARRIVED)(PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload); + +/** + PnpAdapterInterface Methods +**/ + +// Pnp adapter interface creation parameters +typedef struct _PNPADPATER_INTERFACE_INIT_PARAMS { + PNPADAPTER_DEVICE_ARRIVED deviceArrived; + PNPADAPTER_INTERFACE_RELEASE releaseInterface; +} PNPADPATER_INTERFACE_INIT_PARAMS, *PPNPADPATER_INTERFACE_INIT_PARAMS; + +/** +* @brief PnpAdapter_CreatePnpInterface creates a PnP Bridge adapter interface + +* @param pnpAdapterInterface Handle to pnp adapter interface +* +* @returns Result indicating status of pnp adapter interface creation +*/ +int PnpAdapterInterface_Create(PNPADAPTER_CONTEXT adapterHandle, const char* interfaceName, + PNP_INTERFACE_CLIENT_HANDLE Interface, + PPNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface, + PPNPADPATER_INTERFACE_INIT_PARAMS params); + +/** +* @brief PnpAdapter_DestroyPnpInterface destroys a PnP Bridge adapter interface + +* @param pnpAdapterInterface Handle to pnp adapter interface +* +*/ +void PnpAdapterInterface_Destroy(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface); + /** * @brief PnpAdapter_GetPnpInterfaceClient gets the Azure iot pnp interface client handle @@ -71,23 +115,7 @@ typedef int(*PNPADAPTER_RELEASE_PNP_INTERFACE)(PNPADAPTER_INTERFACE_HANDLE pnpIn * * @returns Handle to Azure Pnp Interface client */ -PNP_INTERFACE_CLIENT_HANDLE PnpAdapter_GetPnpInterfaceClient(PNPADAPTER_INTERFACE_HANDLE pnpInterface); - -/** -* @brief PnpAdapter_SetPnpInterfaceClient seta the Azure iot pnp interface client handle -* -* @remarks This API is for private preview only. When PnpBridge calls CreatePnpInterface - callback on a pnp adapter, the adapter should create the Azure PnpInterfaceClient - using PnP_InterfaceClient_Create and then call PnpAdapter_SetPnpInterfaceClient with - the PnpInterfaceClient - -* @param pnpInterface Handle to pnp adapter interface -* -** @param pnpInterfaceClient Handle to Azure pnp interface client -* -* @returns VOID -*/ -void PnpAdapter_SetPnpInterfaceClient(PNPADAPTER_INTERFACE_HANDLE pnpInterface, PNP_INTERFACE_CLIENT_HANDLE pnpInterfaceClient); +PNP_INTERFACE_CLIENT_HANDLE PnpAdapterInterface_GetPnpInterfaceClient(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface); /** * @brief PnpAdapter_SetContext sets a context for pnp adapter interface handle @@ -98,7 +126,7 @@ void PnpAdapter_SetPnpInterfaceClient(PNPADAPTER_INTERFACE_HANDLE pnpInterface, * * @returns integer greater than zero on success and other values on failure. */ -int PnpAdapter_SetContext(PNPADAPTER_INTERFACE_HANDLE pnpInterface, void* context); +int PnpAdapterInterface_SetContext(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface, void* context); /** * @brief PnpAdapter_GetContext gets context set by pnp adapter. @@ -109,16 +137,23 @@ int PnpAdapter_SetContext(PNPADAPTER_INTERFACE_HANDLE pnpInterface, void* contex * * @returns void* context */ -void* PnpAdapter_GetContext(PNPADAPTER_INTERFACE_HANDLE pnpInterface); +void* PnpAdapterInterface_GetContext(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface); +/* + PnpAdapter Binding info +*/ typedef struct _PNP_ADAPTER { // Identity of the Pnp Adapter that will be used in the config // of a device under PnpParameters - const char* Identity; - PNPADAPTER_PNP_INTERFACE_INITIALIZE Initialize; - PNPADAPTER_BIND_PNP_INTERFACE CreatePnpInterface; - PNPADAPTER_RELEASE_PNP_INTERFACE ReleaseInterface; - PNPADAPTER_PNP_INTERFACE_SHUTDOWN Shutdown; + const char* identity; + + PNPADAPTER_PNP_INTERFACE_INITIALIZE initialize; + + PNPADAPTER_BIND_PNP_INTERFACE createPnpInterface; + + //PNPADAPTER_RELEASE_PNP_INTERFACE releaseInterface; + + PNPADAPTER_PNP_INTERFACE_SHUTDOWN shutdown; } PNP_ADAPTER, *PPNP_ADAPTER; #ifdef __cplusplus diff --git a/PnpBridge/src/PnpBridge/PnpAdapterManager.h b/PnpBridge/src/PnpBridge/PnpAdapterManager.h index cfef5f9..88f04c6 100644 --- a/PnpBridge/src/PnpBridge/PnpAdapterManager.h +++ b/PnpBridge/src/PnpBridge/PnpAdapterManager.h @@ -8,11 +8,40 @@ extern "C" { #endif +// Represents a PNPADPTER and its configuration in PnpAdapterManger +typedef struct _PNP_ADAPTER_TAG { + PPNP_ADAPTER adapter; + + // List of pnp interfaces created under this adapter + SINGLYLINKEDLIST_HANDLE pnpInterfaceList; + + // Lock to protect pnpInterfaceList modification + LOCK_HANDLE pnpInterfaceListLock; +} PNP_ADAPTER_TAG, *PPNP_ADAPTER_TAG; + +// Structure uses to share context between adapter manager and adapter interface +typedef struct _PNP_ADAPTER_CONTEXT_TAG { + PPNP_ADAPTER_TAG adapter; + JSON_Object* deviceConfig; +} PNP_ADAPTER_CONTEXT_TAG, *PPNP_ADAPTER_CONTEXT_TAG; + +// Structure used for an instance of Pnp Adapter Manager typedef struct _PNP_ADAPTER_MANAGER { - SINGLYLINKEDLIST_HANDLE AdapterList; - MAP_HANDLE PnpAdapterMap; + MAP_HANDLE pnpAdapterMap; + PPNP_ADAPTER_TAG* pnpAdapters; } PNP_ADAPTER_MANAGER, *PPNP_ADAPTER_MANAGER; +// Pnp adapter interface structure +typedef struct _PNPADAPTER_INTERFACE { + void* context; + int key; + bool persistent; + char* interfaceId; + PNP_INTERFACE_CLIENT_HANDLE pnpInterfaceClient; + PNPADPATER_INTERFACE_INIT_PARAMS params; + PNPADAPTER_CONTEXT adapterContext; + LIST_ITEM_HANDLE adapterEntry; +} PNPADAPTER_INTERFACE, *PPNPADAPTER_INTERFACE; /** * @brief PnpAdapterManager_Create creates the Azure Pnp Interface adapter manager. @@ -39,11 +68,17 @@ PNPBRIDGE_RESULT PnpAdapterManager_Create(PPNP_ADAPTER_MANAGER* adapter, JSON_Va */ void PnpAdapterManager_Release(PPNP_ADAPTER_MANAGER adapter); - PNPBRIDGE_RESULT PnpAdapterManager_SupportsIdentity(PPNP_ADAPTER_MANAGER adapter, JSON_Object* Message, bool* supported, int* key); -PNPBRIDGE_RESULT PnpAdapterManager_CreatePnpInterface(PPNP_ADAPTER_MANAGER adapter, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, int key, PNP_INTERFACE_CLIENT_HANDLE* InterfaceClient, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD DeviceChangePayload); +PNPBRIDGE_RESULT PnpAdapterManager_CreatePnpInterface(PPNP_ADAPTER_MANAGER adapter, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, int key, JSON_Object* deviceConfig, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD DeviceChangePayload); PNPBRIDGE_RESULT PnpAdapterManager_ReleasePnpInterface(PPNP_ADAPTER_MANAGER adapter, PNPADAPTER_INTERFACE_HANDLE Interface); +PNPBRIDGE_RESULT PnpAdapterManager_GetAllInterfaces(PPNP_ADAPTER_MANAGER adapterMgr, PNP_INTERFACE_CLIENT_HANDLE** interfaces, int* count); +bool PnpAdapterManager_IsInterfaceIdPublished(PPNP_ADAPTER_MANAGER adapterMgr, const char* interfaceId); +void PnpAdapterManager_ReleaseAdapter(PPNP_ADAPTER_TAG adapterTag); + +void PnpAdapterManager_AddInterface(PPNP_ADAPTER_TAG adapter, PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface); +void PnpAdapterManager_RemoveInterface(PPNP_ADAPTER_TAG adapter, PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/PnpBridge/src/PnpBridge/PnpAdapterManger.c b/PnpBridge/src/PnpBridge/PnpAdapterManger.c index 752bc1e..f585b2a 100644 --- a/PnpBridge/src/PnpBridge/PnpAdapterManger.c +++ b/PnpBridge/src/PnpBridge/PnpAdapterManger.c @@ -10,19 +10,19 @@ extern const int PnpAdapterCount; PNPBRIDGE_RESULT PnpAdapterManager_ValidatePnpAdapter(PPNP_ADAPTER pnpAdapter, MAP_HANDLE pnpAdapterMap) { bool containsKey = false; - if (NULL == pnpAdapter->Identity) { + if (NULL == pnpAdapter->identity) { LogError("PnpAdapter's Identity filed is not initialized"); return PNPBRIDGE_INVALID_ARGS; } - if (MAP_OK != Map_ContainsKey(pnpAdapterMap, pnpAdapter->Identity, &containsKey)) { + if (MAP_OK != Map_ContainsKey(pnpAdapterMap, pnpAdapter->identity, &containsKey)) { LogError("Map_ContainsKey failed"); return PNPBRIDGE_FAILED; } if (containsKey) { - LogError("Found duplicate pnp adapter identity %s", pnpAdapter->Identity); + LogError("Found duplicate pnp adapter identity %s", pnpAdapter->identity); return PNPBRIDGE_DUPLICATE_ENTRY; } - if (NULL == pnpAdapter->Initialize || NULL == pnpAdapter->Shutdown || NULL == pnpAdapter->CreatePnpInterface || NULL == pnpAdapter->ReleaseInterface) { + if (NULL == pnpAdapter->initialize || NULL == pnpAdapter->shutdown || NULL == pnpAdapter->createPnpInterface) { LogError("PnpAdapter's callbacks are not initialized"); return PNPBRIDGE_INVALID_ARGS; } @@ -30,6 +30,38 @@ PNPBRIDGE_RESULT PnpAdapterManager_ValidatePnpAdapter(PPNP_ADAPTER pnpAdapter, return PNPBRIDGE_OK; } +PNPBRIDGE_RESULT PnpAdapterManager_InitializeAdapter(PPNP_ADAPTER_TAG* adapterTag, PPNP_ADAPTER adapter) { + PNPBRIDGE_RESULT result = PNPBRIDGE_OK; + PPNP_ADAPTER_TAG adapterT = calloc(1, sizeof(PNP_ADAPTER_TAG)); + if (NULL == adapterT) { + + } + + adapterT->adapter = adapter; + adapterT->pnpInterfaceList = singlylinkedlist_create(); + adapterT->pnpInterfaceListLock = Lock_Init(); + + if (!PNPBRIDGE_SUCCESS(result)) { + PnpAdapterManager_ReleaseAdapter(adapterT); + } + + return result; +} + +void PnpAdapterManager_ReleaseAdapter(PPNP_ADAPTER_TAG adapterTag) { + if (NULL != adapterTag) { + if (NULL != adapterTag->pnpInterfaceList) { + singlylinkedlist_destroy(adapterTag->pnpInterfaceList); + } + + if (NULL != adapterTag->pnpInterfaceListLock) { + Lock_Deinit(adapterTag->pnpInterfaceListLock); + } + + free(adapterTag); + } +} + PNPBRIDGE_RESULT PnpAdapterManager_Create(PPNP_ADAPTER_MANAGER* adapterMgr, JSON_Value* config) { PNPBRIDGE_RESULT result = PNPBRIDGE_OK; PPNP_ADAPTER_MANAGER adapter = NULL; @@ -45,8 +77,15 @@ PNPBRIDGE_RESULT PnpAdapterManager_Create(PPNP_ADAPTER_MANAGER* adapterMgr, JSON goto exit; } - adapter->PnpAdapterMap = Map_Create(NULL); - if (NULL == adapter->PnpAdapterMap) { + adapter->pnpAdapterMap = Map_Create(NULL); + if (NULL == adapter->pnpAdapterMap) { + result = PNPBRIDGE_FAILED; + goto exit; + } + + // Create PNP_ADAPTER_HANDLE's + adapter->pnpAdapters = calloc(PnpAdapterCount, sizeof(PPNP_ADAPTER_TAG)); + if (NULL == adapter->pnpAdapters) { result = PNPBRIDGE_FAILED; goto exit; } @@ -54,36 +93,45 @@ PNPBRIDGE_RESULT PnpAdapterManager_Create(PPNP_ADAPTER_MANAGER* adapterMgr, JSON // Load a list of static modules and build an interface map for (int i = 0; i < PnpAdapterCount; i++) { PPNP_ADAPTER pnpAdapter = PNP_ADAPTER_MANIFEST[i]; + adapter->pnpAdapters[i] = calloc(1, sizeof(PNP_ADAPTER_TAG)); + adapter->pnpAdapters[i]->adapter = pnpAdapter; + adapter->pnpAdapters[i]->pnpInterfaceList = singlylinkedlist_create(); + adapter->pnpAdapters[i]->pnpInterfaceListLock = Lock_Init(); - if (NULL == pnpAdapter->Identity) { + if (NULL == pnpAdapter->identity) { LogError("Invalid Identity specified for a PnpAdapter"); continue; } // Validate Pnp Adapter Methods - result = PnpAdapterManager_ValidatePnpAdapter(pnpAdapter, adapter->PnpAdapterMap); + result = PnpAdapterManager_ValidatePnpAdapter(pnpAdapter, adapter->pnpAdapterMap); if (PNPBRIDGE_OK != result) { LogError("PnpAdapter structure is not initialized properly"); goto exit; } - JSON_Object* initParams = Configuration_GetPnpParameters(config, pnpAdapter->Identity); + JSON_Object* initParams = Configuration_GetPnpParameters(config, pnpAdapter->identity); const char* initParamstring = NULL; if (initParams != NULL) { initParamstring = json_serialize_to_string(json_object_get_wrapping_value(initParams)); } - result = pnpAdapter->Initialize(initParamstring); + result = pnpAdapter->initialize(initParamstring); if (PNPBRIDGE_OK != result) { LogError("Failed to initialze a PnpAdapter"); continue; } - Map_Add_Index(adapter->PnpAdapterMap, pnpAdapter->Identity, i); + Map_Add_Index(adapter->pnpAdapterMap, pnpAdapter->identity, i); } *adapterMgr = adapter; exit: + if (!PNPBRIDGE_SUCCESS(result)) { + if (NULL != adapter) { + PnpAdapterManager_Release(adapter); + } + } return result; } @@ -92,40 +140,47 @@ void PnpAdapterManager_Release(PPNP_ADAPTER_MANAGER adapter) { const char* const* values; size_t count; - // Call shutdown on all interfaces - if (Map_GetInternals(adapter->PnpAdapterMap, &keys, &values, &count) != MAP_OK) { - LogError("Map_GetInternals failed to get all pnp adapters"); - } - else - { - for (int i = 0; i < (int)count; i++) { - int index = values[i][0]; - PPNP_ADAPTER pnpAdapter = PNP_ADAPTER_MANIFEST[index]; - if (NULL != pnpAdapter->Shutdown) { - pnpAdapter->Shutdown(); + if (NULL != adapter->pnpAdapterMap) { + // Call shutdown on all interfaces + if (Map_GetInternals(adapter->pnpAdapterMap, &keys, &values, &count) != MAP_OK) { + LogError("Map_GetInternals failed to get all pnp adapters"); + } + else + { + for (int i = 0; i < (int)count; i++) { + int index = values[i][0]; + PPNP_ADAPTER pnpAdapter = PNP_ADAPTER_MANIFEST[index]; + if (NULL != pnpAdapter->shutdown) { + pnpAdapter->shutdown(); + } } } } - Map_Destroy(adapter->PnpAdapterMap); + if (NULL != adapter->pnpAdapters) { + free(adapter->pnpAdapters);; + } + + Map_Destroy(adapter->pnpAdapterMap); free(adapter); } PNPBRIDGE_RESULT PnpAdapterManager_SupportsIdentity(PPNP_ADAPTER_MANAGER adapter, JSON_Object* Message, bool* supported, int* key) { bool containsMessageKey = false; - JSON_Object* pnpParams = json_object_get_object(Message, "PnpParameters"); - char* getIdentity = (char*) json_object_get_string(pnpParams, "Identity"); + char* interfaceId = NULL; + JSON_Object* pnpParams = json_object_get_object(Message, PNP_CONFIG_NAME_PNP_PARAMETERS); + char* getIdentity = (char*) json_object_get_string(pnpParams, PNP_CONFIG_IDENTITY_NAME); MAP_RESULT mapResult; *supported = false; - mapResult = Map_ContainsKey(adapter->PnpAdapterMap, getIdentity, &containsMessageKey); + mapResult = Map_ContainsKey(adapter->pnpAdapterMap, getIdentity, &containsMessageKey); if (MAP_OK != mapResult || !containsMessageKey) { return PNPBRIDGE_FAILED; } // Get the interface ID - int index = Map_GetIndexValueFromKey(adapter->PnpAdapterMap, getIdentity); + int index = Map_GetIndexValueFromKey(adapter->pnpAdapterMap, getIdentity); *supported = true; *key = index; @@ -138,79 +193,117 @@ PNPBRIDGE_RESULT PnpAdapterManager_SupportsIdentity(PPNP_ADAPTER_MANAGER adapter method will take care of binding it to a module implementing PnP primitives */ -PNPBRIDGE_RESULT PnpAdapterManager_CreatePnpInterface(PPNP_ADAPTER_MANAGER adapter, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, int key, PNP_INTERFACE_CLIENT_HANDLE* InterfaceClient, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD DeviceChangePayload) { +PNPBRIDGE_RESULT PnpAdapterManager_CreatePnpInterface(PPNP_ADAPTER_MANAGER adapterMgr, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, + int key, JSON_Object* deviceConfig, + PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD DeviceChangePayload) +{ // Get the module using the key as index - PPNP_ADAPTER pnpAdapter = PNP_ADAPTER_MANIFEST[key]; + PPNP_ADAPTER_TAG pnpAdapter = adapterMgr->pnpAdapters[key]; + PNP_ADAPTER_CONTEXT_TAG context = { 0 }; - AZURE_UNREFERENCED_PARAMETER(adapter); - - PPNPADAPTER_INTERFACE pnpInterface = malloc(sizeof(PNPADAPTER_INTERFACE)); - - //pnpInterface->Interface = InterfaceClient; - pnpInterface->key = key; + context.adapter = pnpAdapter; + context.deviceConfig = deviceConfig; // Invoke interface binding method - int ret = pnpAdapter->CreatePnpInterface(pnpInterface, pnpDeviceClientHandle, DeviceChangePayload); + int ret = pnpAdapter->adapter->createPnpInterface(&context, pnpDeviceClientHandle, DeviceChangePayload); if (ret < 0) { return PNPBRIDGE_FAILED; } - *InterfaceClient = pnpInterface->Interface; - return PNPBRIDGE_OK; } +PNPBRIDGE_RESULT PnpAdapterManager_GetAllInterfaces(PPNP_ADAPTER_MANAGER adapterMgr, PNP_INTERFACE_CLIENT_HANDLE** interfaces , int* count) { + int n = 0; + + // Get the number of created interfaces + for (int i = 0; i < PnpAdapterCount; i++) { + PPNP_ADAPTER_TAG pnpAdapter = adapterMgr->pnpAdapters[i]; + + SINGLYLINKEDLIST_HANDLE pnpInterfaces = pnpAdapter->pnpInterfaceList; + LIST_ITEM_HANDLE handle = singlylinkedlist_get_head_item(pnpInterfaces); + while (NULL != handle) { + handle = singlylinkedlist_get_next_item(handle); + n++; + } + } + + // create an array of interface handles + PNP_INTERFACE_CLIENT_HANDLE* pnpClientHandles = NULL; + { + pnpClientHandles = calloc(n, sizeof(PNP_INTERFACE_CLIENT_HANDLE)); + int x = 0; + for (int i = 0; i < PnpAdapterCount; i++) { + PPNP_ADAPTER_TAG pnpAdapter = adapterMgr->pnpAdapters[i]; + + SINGLYLINKEDLIST_HANDLE pnpInterfaces = pnpAdapter->pnpInterfaceList; + LIST_ITEM_HANDLE handle = singlylinkedlist_get_head_item(pnpInterfaces); + while (NULL != handle) { + PPNPADAPTER_INTERFACE adapterInterface = (PNP_INTERFACE_CLIENT_HANDLE) singlylinkedlist_item_get_value(handle); + pnpClientHandles[x] = PnpAdapterInterface_GetPnpInterfaceClient(adapterInterface); + handle = singlylinkedlist_get_next_item(handle); + x++; + } + } + } + + *count = n; + *interfaces = pnpClientHandles; + + return 0; +} + +bool PnpAdapterManager_IsInterfaceIdPublished(PPNP_ADAPTER_MANAGER adapterMgr, const char* interfaceId) { + for (int i = 0; i < PnpAdapterCount; i++) { + PPNP_ADAPTER_TAG pnpAdapter = adapterMgr->pnpAdapters[i]; + + SINGLYLINKEDLIST_HANDLE pnpInterfaces = pnpAdapter->pnpInterfaceList; + LIST_ITEM_HANDLE handle = singlylinkedlist_get_head_item(pnpInterfaces); + while (NULL != handle) { + PPNPADAPTER_INTERFACE adapterInterface = (PNP_INTERFACE_CLIENT_HANDLE)singlylinkedlist_item_get_value(handle); + if (stricmp(adapterInterface->interfaceId, interfaceId)) { + return true; + } + handle = singlylinkedlist_get_next_item(handle); + } + } + + return false; +} + PNPBRIDGE_RESULT PnpAdapterManager_ReleasePnpInterface(PPNP_ADAPTER_MANAGER adapter, PNPADAPTER_INTERFACE_HANDLE interfaceClient) { if (NULL == interfaceClient) { return PNPBRIDGE_INVALID_ARGS; } - AZURE_UNREFERENCED_PARAMETER(adapter); - PPNPADAPTER_INTERFACE pnpInterface = (PPNPADAPTER_INTERFACE)interfaceClient; // Get the module index PPNP_ADAPTER pnpAdapter = PNP_ADAPTER_MANIFEST[pnpInterface->key]; - pnpAdapter->ReleaseInterface(interfaceClient); + //pnpAdapter->releaseInterface(interfaceClient); return PNPBRIDGE_OK; } -PNP_INTERFACE_CLIENT_HANDLE PnpAdapter_GetPnpInterfaceClient(PNPADAPTER_INTERFACE_HANDLE pnpInterfaceClient) { - if (pnpInterfaceClient == NULL) { - return NULL; - } +void PnpAdapterManager_AddInterface(PPNP_ADAPTER_TAG adapter, PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface) { + LIST_ITEM_HANDLE handle = NULL; + Lock(adapter->pnpInterfaceListLock); + handle = singlylinkedlist_add(adapter->pnpInterfaceList, pnpAdapterInterface); + Unlock(adapter->pnpInterfaceListLock); - PPNPADAPTER_INTERFACE interfaceClient = (PPNPADAPTER_INTERFACE)pnpInterfaceClient; - return interfaceClient->Interface; + if (NULL != handle) { + PPNPADAPTER_INTERFACE interface = (PPNPADAPTER_INTERFACE)pnpAdapterInterface; + interface->adapterEntry = handle; + } } -void PnpAdapter_SetPnpInterfaceClient(PNPADAPTER_INTERFACE_HANDLE pnpInterface, PNP_INTERFACE_CLIENT_HANDLE pnpInterfaceClient) { - if (pnpInterfaceClient == NULL) { - LogError("pnpInterface argument is NULL"); +void PnpAdapterManager_RemoveInterface(PPNP_ADAPTER_TAG adapter, PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface) { + PPNPADAPTER_INTERFACE interface = (PPNPADAPTER_INTERFACE)pnpAdapterInterface; + if (NULL == interface->adapterEntry) { return; } - PPNPADAPTER_INTERFACE interfaceClient = (PPNPADAPTER_INTERFACE)pnpInterface; - interfaceClient->Interface = pnpInterfaceClient; -} - -PNPBRIDGE_RESULT PnpAdapter_SetContext(PNPADAPTER_INTERFACE_HANDLE pnpInterfaceClient, void* Context) { - if (NULL == pnpInterfaceClient) { - return PNPBRIDGE_INVALID_ARGS; - } - - PPNPADAPTER_INTERFACE interfaceClient = (PPNPADAPTER_INTERFACE)pnpInterfaceClient; - interfaceClient->Context = Context; - - return PNPBRIDGE_OK; -} - -void* PnpAdapter_GetContext(PNPADAPTER_INTERFACE_HANDLE PnpInterfaceClient) { - if (NULL == PnpInterfaceClient) { - return NULL; - } - - PPNPADAPTER_INTERFACE pnpInterfaceClient = (PPNPADAPTER_INTERFACE)PnpInterfaceClient; - return pnpInterfaceClient->Context; + Lock(adapter->pnpInterfaceListLock); + singlylinkedlist_remove(adapter->pnpInterfaceList, interface->adapterEntry); + Unlock(adapter->pnpInterfaceListLock); } \ No newline at end of file diff --git a/PnpBridge/src/PnpBridge/PnpBridge.c b/PnpBridge/src/PnpBridge/PnpBridge.c index 567a019..9e01ef0 100644 --- a/PnpBridge/src/PnpBridge/PnpBridge.c +++ b/PnpBridge/src/PnpBridge/PnpBridge.c @@ -1,13 +1,12 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -// DeviceAggregator.cpp : Defines the entry point for the console application. - #include "PnpBridgeCommon.h" #include "ConfigurationParser.h" #include "DiscoveryManager.h" #include "PnpAdapterInterface.h" #include "PnpAdapterManager.h" +#include "IotHubComms.h" #include "PnpBridgeh.h" @@ -16,159 +15,112 @@ PPNP_BRIDGE g_PnpBridge = NULL; bool g_Shutdown = false; //////////////////////////////////////////////////////////////////////// -//const char* connectionString = "HostName=iot-pnp-hub1.azure-devices.net;DeviceId=win-gateway;SharedAccessKey=GfbYy7e2PikTf2qHyabvEDBaJB5S4T+H+b9TbLsXfns="; -//const char* connectionString = "HostName=saas-iothub-1529564b-8f58-4871-b721-fe9459308cb1.azure-devices.net;DeviceId=956da476-8b3c-41ce-b405-d2d32bcf5e79;SharedAccessKey=sQcfPeDCZGEJWPI3M3SyB8pD60TNdOw10oFKuv5FBio="; - typedef struct _PNPBRIDGE_INTERFACE_TAG { - PNP_INTERFACE_CLIENT_HANDLE Interface; char* InterfaceName; + PPNPADAPTER_INTERFACE pnpAdapterInterface; } PNPBRIDGE_INTERFACE_TAG, *PPNPBRIDGE_INTERFACE_TAG; -// InitializeIotHubDeviceHandle initializes underlying IoTHub client, creates a device handle with the specified connection string, -// and sets some options on this handle prior to beginning. -IOTHUB_DEVICE_HANDLE InitializeIotHubDeviceHandle(const char* connectionString) -{ - IOTHUB_DEVICE_HANDLE deviceHandle = NULL; - IOTHUB_CLIENT_RESULT iothubClientResult; - bool traceOn = true; - bool urlEncodeOn = true; - - // TODO: PnP SDK should auto-set OPTION_AUTO_URL_ENCODE_DECODE for MQTT as its strictly required. Need way for IoTHub handle to communicate this back. - if (IoTHub_Init() != 0) - { - LogError("IoTHub_Init failed\n"); - } - else - { - // Get connection string from config - if ((deviceHandle = IoTHubDeviceClient_CreateFromConnectionString(connectionString, MQTT_Protocol)) == NULL) - { - LogError("Failed to create device handle\n"); - } - else if ((iothubClientResult = IoTHubDeviceClient_SetOption(deviceHandle, OPTION_LOG_TRACE, &traceOn)) != IOTHUB_CLIENT_OK) - { - LogError("Failed to set option %s, error=%d\n", OPTION_LOG_TRACE, iothubClientResult); - IoTHubDeviceClient_Destroy(deviceHandle); - deviceHandle = NULL; - } - else if ((iothubClientResult = IoTHubDeviceClient_SetOption(deviceHandle, OPTION_AUTO_URL_ENCODE_DECODE, &urlEncodeOn)) != IOTHUB_CLIENT_OK) - { - LogError("Failed to set option %s, error=%d\n", OPTION_AUTO_URL_ENCODE_DECODE, iothubClientResult); - IoTHubDeviceClient_Destroy(deviceHandle); - deviceHandle = NULL; - } - - if (deviceHandle == NULL) - { - IoTHub_Deinit(); - } - } - - return deviceHandle; -} - -void PnpBridge_CoreCleanup() { - if (g_PnpBridge->publishedInterfaces) { - LIST_ITEM_HANDLE interfaceItem = singlylinkedlist_get_head_item(g_PnpBridge->publishedInterfaces); - while (interfaceItem != NULL) { - PPNPBRIDGE_INTERFACE_TAG interface = (PPNPBRIDGE_INTERFACE_TAG)singlylinkedlist_item_get_value(interfaceItem); - free(interface->Interface); - interfaceItem = singlylinkedlist_get_next_item(interfaceItem); - } - singlylinkedlist_destroy(g_PnpBridge->publishedInterfaces); - } - if (g_PnpBridge->dispatchLock) { - Lock_Deinit(g_PnpBridge->dispatchLock); - } -} - PNPBRIDGE_RESULT PnpBridge_Initialize(JSON_Value* config) { const char* connectionString; + PNPBRIDGE_RESULT result = PNPBRIDGE_OK; connectionString = Configuration_GetConnectionString(config); - if (NULL == connectionString) { - LogError("Connection string not specified in the config\n"); - return PNPBRIDGE_FAILED; - } - - g_PnpBridge = (PPNP_BRIDGE) calloc(1, sizeof(PNP_BRIDGE)); - - if (!g_PnpBridge) { - LogError("Failed to allocate memory for PnpBridge global"); - PnpBridge_CoreCleanup(); - return PNPBRIDGE_INSUFFICIENT_MEMORY; - } - - g_PnpBridge->configuration = config; - - g_PnpBridge->publishedInterfaces = singlylinkedlist_create(); - if (NULL == g_PnpBridge->publishedInterfaces) { - LogError("Failed to allocate memory publish interface list"); - PnpBridge_CoreCleanup(); - return PNPBRIDGE_INSUFFICIENT_MEMORY; - } - - g_PnpBridge->publishedInterfaceCount = 0; - - g_PnpBridge->dispatchLock = Lock_Init(); - if (NULL == g_PnpBridge->dispatchLock) { - LogError("Failed to init PnpBridge lock"); - PnpBridge_CoreCleanup(); - return PNPBRIDGE_INSUFFICIENT_MEMORY; - } - - g_Shutdown = false; - - // Connect to Iot Hub and create a PnP device client handle - if ((g_PnpBridge->deviceHandle = InitializeIotHubDeviceHandle(connectionString)) == NULL) + TRY { - LogError("Could not allocate IoTHub Device handle\n"); - PnpBridge_CoreCleanup(); - return PNPBRIDGE_FAILED; - } - else if ((g_PnpBridge->pnpDeviceClientHandle = PnP_DeviceClient_CreateFromDeviceHandle(g_PnpBridge->deviceHandle)) == NULL) - { - LogError("PnP_DeviceClient_CreateFromDeviceHandle failed\n"); - PnpBridge_CoreCleanup(); - return PNPBRIDGE_FAILED; - } + if (NULL == connectionString) { + LogError("Connection string not specified in the config\n"); + result = PNPBRIDGE_FAILED; + LEAVE; + } - return PNPBRIDGE_OK; + g_PnpBridge = (PPNP_BRIDGE)calloc(1, sizeof(PNP_BRIDGE)); + + if (NULL == g_PnpBridge) { + LogError("Failed to allocate memory for PnpBridge global"); + result = PNPBRIDGE_INSUFFICIENT_MEMORY; + LEAVE; + } + + g_PnpBridge->configuration = config; + + g_PnpBridge->dispatchLock = Lock_Init(); + if (NULL == g_PnpBridge->dispatchLock) { + LogError("Failed to init PnpBridge lock"); + result = PNPBRIDGE_INSUFFICIENT_MEMORY; + LEAVE; + } + + g_Shutdown = false; + + // Connect to Iot Hub and create a PnP device client handle + if ((g_PnpBridge->deviceHandle = InitializeIotHubDeviceHandle(connectionString)) == NULL) + { + LogError("Could not allocate IoTHub Device handle\n"); + result = PNPBRIDGE_FAILED; + LEAVE; + } + else if ((g_PnpBridge->pnpDeviceClientHandle = PnP_DeviceClient_CreateFromDeviceHandle(g_PnpBridge->deviceHandle)) == NULL) + { + LogError("PnP_DeviceClient_CreateFromDeviceHandle failed\n"); + result = PNPBRIDGE_FAILED; + LEAVE; + } + } + FINALLY + { + if (PNPBRIDGE_OK != result) { + PnpBridge_Release(g_PnpBridge); + g_PnpBridge = NULL; + } + } + + return result; } -void PnpBridge_Release() { +void PnpBridge_Release(PPNP_BRIDGE pnpBridge) { + if (NULL == pnpBridge) { + return; + } LogInfo("Cleaning DeviceAggregator resources"); - Lock(g_PnpBridge->dispatchLock); + if (pnpBridge->dispatchLock) { + Lock(g_PnpBridge->dispatchLock); + } // Stop Disovery Modules - if (g_PnpBridge->discoveryMgr) { - DiscoveryAdapterManager_Stop(g_PnpBridge->discoveryMgr); - g_PnpBridge->discoveryMgr = NULL; + if (pnpBridge->discoveryMgr) { + DiscoveryAdapterManager_Stop(pnpBridge->discoveryMgr); + pnpBridge->discoveryMgr = NULL; } // Stop Pnp Modules - if (g_PnpBridge->interfaceMgr) { - PnpAdapterManager_Release(g_PnpBridge->interfaceMgr); - g_PnpBridge->interfaceMgr = NULL; + if (pnpBridge->adapterMgr) { + PnpAdapterManager_Release(pnpBridge->adapterMgr); + pnpBridge->adapterMgr = NULL; } - Unlock(g_PnpBridge->dispatchLock); + if (pnpBridge->dispatchLock) { + Unlock(pnpBridge->dispatchLock); + Lock_Deinit(pnpBridge->dispatchLock); + } - PnpBridge_CoreCleanup(); - - if (g_PnpBridge) { - free(g_PnpBridge); + if (pnpBridge) { + free(pnpBridge); } } int PnpBridge_Worker_Thread(void* threadArgument) { - AZURE_UNREFERENCED_PARAMETER(threadArgument); PNPBRIDGE_RESULT result = PNPBRIDGE_OK; + // Publish persistent Pnp Interfaces + result = DiscoveryAdapterManager_NotifyPersistentInterfaces(g_PnpBridge->discoveryMgr, g_PnpBridge->configuration); + if (!PNPBRIDGE_SUCCESS(result)) { + goto exit; + } + // Start Device Discovery result = DiscoveryAdapterManager_Start(g_PnpBridge->discoveryMgr, g_PnpBridge->configuration); if (PNPBRIDGE_OK != result) { @@ -188,65 +140,6 @@ exit: return result; } -// State of PnP registration process. We cannot proceed with PnP until we get into the state APP_PNP_REGISTRATION_SUCCEEDED. -typedef enum APP_PNP_REGISTRATION_STATUS_TAG -{ - APP_PNP_REGISTRATION_PENDING, - APP_PNP_REGISTRATION_SUCCEEDED, - APP_PNP_REGISTRATION_FAILED -} APP_PNP_REGISTRATION_STATUS; - -// appPnpInterfacesRegistered is invoked when the interfaces have been registered or failed. -void appPnpInterfacesRegistered(PNP_REPORTED_INTERFACES_STATUS pnpInterfaceStatus, void *userContextCallback) -{ - APP_PNP_REGISTRATION_STATUS* appPnpRegistrationStatus = (APP_PNP_REGISTRATION_STATUS*)userContextCallback; - *appPnpRegistrationStatus = (pnpInterfaceStatus == PNP_REPORTED_INTERFACES_OK) ? APP_PNP_REGISTRATION_SUCCEEDED : APP_PNP_REGISTRATION_FAILED; -} - -// Invokes PnP_DeviceClient_RegisterInterfacesAsync, which indicates to Azure IoT which PnP interfaces this device supports. -// The PnP Handle *is not valid* until this operation has completed (as indicated by the callback appPnpInterfacesRegistered being invoked). -// In this sample, we block indefinitely but production code should include a timeout. -int AppRegisterPnPInterfacesAndWait(PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle) -{ - APP_PNP_REGISTRATION_STATUS appPnpRegistrationStatus = APP_PNP_REGISTRATION_PENDING; - PNPBRIDGE_RESULT result; - PNP_CLIENT_RESULT pnpResult; - PPNPBRIDGE_INTERFACE_TAG* interfaceTags = malloc(sizeof(PPNPBRIDGE_INTERFACE_TAG)*g_PnpBridge->publishedInterfaceCount); - PNP_INTERFACE_CLIENT_HANDLE* interfaceClients = malloc(sizeof(PNP_INTERFACE_CLIENT_HANDLE)*g_PnpBridge->publishedInterfaceCount); - LIST_ITEM_HANDLE interfaceItem = singlylinkedlist_get_head_item(g_PnpBridge->publishedInterfaces); - int i = 0; - - while (interfaceItem != NULL) { - PNP_INTERFACE_CLIENT_HANDLE interface = ((PPNPBRIDGE_INTERFACE_TAG) singlylinkedlist_item_get_value(interfaceItem))->Interface; - interfaceClients[i++] = interface; - interfaceItem = singlylinkedlist_get_next_item(interfaceItem); - } - - pnpResult = PnP_DeviceClient_RegisterInterfacesAsync(pnpDeviceClientHandle, interfaceClients, g_PnpBridge->publishedInterfaceCount, appPnpInterfacesRegistered, &appPnpRegistrationStatus); - if (PNP_CLIENT_OK != pnpResult) { - result = PNPBRIDGE_FAILED; - goto end; - } - - while (appPnpRegistrationStatus == APP_PNP_REGISTRATION_PENDING) { - ThreadAPI_Sleep(100); - } - - if (appPnpRegistrationStatus != APP_PNP_REGISTRATION_SUCCEEDED) { - LogError("PnP has failed to register.\n"); - result = __FAILURE__; - } - else { - result = 0; - } - -end: - free(interfaceClients); - free(interfaceTags); - - return result; -} - PNPBRIDGE_RESULT PnpBridge_ValidateDeviceChangePayload(PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD DeviceChangePayload) { if (NULL == DeviceChangePayload) { return PNPBRIDGE_INVALID_ARGS; @@ -260,10 +153,6 @@ PNPBRIDGE_RESULT PnpBridge_ValidateDeviceChangePayload(PPNPBRIDGE_DEVICE_CHANGE_ return PNPBRIDGE_INVALID_ARGS; } - //if (PNPBRIDGE_INTERFACE_CHANGE_INVALID == DeviceChangePayload->ChangeType) { - // return PNPBRIDGE_INVALID_ARGS; - //} - return PNPBRIDGE_OK; } @@ -290,20 +179,23 @@ PNPBRIDGE_RESULT PnpBridge_DeviceChangeCallback(PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD JSON_Object* jdevice; jmsg = json_parse_string(DeviceChangePayload->Message); + if (NULL == jmsg) { + goto end; + } + jobj = json_value_get_object(jmsg); if (Configuration_IsDeviceConfigured(g_PnpBridge->configuration, jobj, &jdevice) < 0) { LogInfo("Device is not configured. Dropping the change notification"); goto end; } - result = PnpAdapterManager_SupportsIdentity(g_PnpBridge->interfaceMgr, jdevice, &containsFilter, &key); + result = PnpAdapterManager_SupportsIdentity(g_PnpBridge->adapterMgr, jdevice, &containsFilter, &key); if (PNPBRIDGE_OK != result) { goto end; } if (containsFilter) { - // Create an Azure IoT PNP interface - PPNPBRIDGE_INTERFACE_TAG pInt = malloc(sizeof(PNPBRIDGE_INTERFACE_TAG)); + // Create an Pnp interface char* interfaceId = (char*) json_object_get_string(jobj, "InterfaceId"); if (interfaceId != NULL) { @@ -312,31 +204,27 @@ PNPBRIDGE_RESULT PnpBridge_DeviceChangeCallback(PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD strcpy_s(id, idSize, interfaceId); id[idSize - 1] = '\0'; - // check if interface is already published - //PPNPBRIDGE_INTERFACE_TAG* interfaceTags = malloc(sizeof(PPNPBRIDGE_INTERFACE_TAG)*g_PnpBridge->publishedInterfaceCount); - LIST_ITEM_HANDLE interfaceItem = singlylinkedlist_get_head_item(g_PnpBridge->publishedInterfaces); - while (interfaceItem != NULL) { - PPNPBRIDGE_INTERFACE_TAG interface = (PPNPBRIDGE_INTERFACE_TAG) singlylinkedlist_item_get_value(interfaceItem); - if (strcmp(interface->InterfaceName, id) == 0) { - LogError("PnP Interface has already been published. Dropping the change notification. \n"); - result = PNPBRIDGE_FAILED; - goto end; - } - interfaceItem = singlylinkedlist_get_next_item(interfaceItem); + if (PnpAdapterManager_IsInterfaceIdPublished(g_PnpBridge->adapterMgr, id)) { + LogError("PnP Interface has already been published. Dropping the change notification. \n"); + result = PNPBRIDGE_FAILED; + goto end; } - pInt->InterfaceName = id; - - result = PnpAdapterManager_CreatePnpInterface(g_PnpBridge->interfaceMgr, g_PnpBridge->pnpDeviceClientHandle, key, &pInt->Interface, DeviceChangePayload); + result = PnpAdapterManager_CreatePnpInterface(g_PnpBridge->adapterMgr, g_PnpBridge->pnpDeviceClientHandle, key, jdevice, DeviceChangePayload); if (PNPBRIDGE_OK != result) { goto end; } - g_PnpBridge->publishedInterfaceCount++; - singlylinkedlist_add(g_PnpBridge->publishedInterfaces, pInt); + // Query all the pnp interface clients and publish them + { + PNP_INTERFACE_CLIENT_HANDLE* interfaces = NULL; + int count = 0; + PnpAdapterManager_GetAllInterfaces(g_PnpBridge->adapterMgr, &interfaces, &count); - LogInfo("Publishing Azure Pnp Interface %s\n", interfaceId); - AppRegisterPnPInterfacesAndWait(g_PnpBridge->pnpDeviceClientHandle); + LogInfo("Publishing Azure Pnp Interface %s\n", interfaceId); + AppRegisterPnPInterfacesAndWait(g_PnpBridge->pnpDeviceClientHandle, interfaces, count); + free(interfaces); + } goto end; } @@ -375,7 +263,7 @@ PNPBRIDGE_RESULT PnpBridge_Main() { // Load all the adapters in interface manifest that implement Azure IoT PnP Interface // PnpBridge will call into corresponding adapter when a device is reported by // DiscoveryExtension - result = PnpAdapterManager_Create(&g_PnpBridge->interfaceMgr, g_PnpBridge->configuration); + result = PnpAdapterManager_Create(&g_PnpBridge->adapterMgr, g_PnpBridge->configuration); if (PNPBRIDGE_OK != result) { LogError("PnpAdapterManager_Create failed: %d\n", result); goto exit; @@ -399,7 +287,7 @@ PNPBRIDGE_RESULT PnpBridge_Main() { } exit: - PnpBridge_Release(); + PnpBridge_Release(g_PnpBridge); return result; } diff --git a/PnpBridge/src/PnpBridge/PnpBridge.h b/PnpBridge/src/PnpBridge/PnpBridge.h index 23ad19a..8534a2e 100644 --- a/PnpBridge/src/PnpBridge/PnpBridge.h +++ b/PnpBridge/src/PnpBridge/PnpBridge.h @@ -1,6 +1,14 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +/* + ___ ___ _ _ + | _ \_ _ _ __| _ )_ _(_)__| |__ _ ___ + | _/ ' \| '_ \ _ \ '_| / _` / _` / -_) + |_| |_||_| .__/___/_| |_\__,_\__, \___| + |_| |___/ +*/ + #pragma once #ifdef __cplusplus @@ -9,10 +17,12 @@ extern "C" #endif #include +#include typedef enum _PNPBRIDGE_INTERFACE_CHANGE_TYPE { PNPBRIDGE_INTERFACE_CHANGE_INVALID, PNPBRIDGE_INTERFACE_CHANGE_ARRIVAL, + PNPBRIDGE_INTERFACE_CHANGE_PERSIST, PNPBRIDGE_INTERFACE_CHANGE_REMOVAL } PNPBRIDGE_INTERFACE_CHANGE_TYPE; diff --git a/PnpBridge/src/PnpBridge/PnpBridge.log b/PnpBridge/src/PnpBridge/PnpBridge.log new file mode 100644 index 0000000..d1b4d6d --- /dev/null +++ b/PnpBridge/src/PnpBridge/PnpBridge.log @@ -0,0 +1 @@ +C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(775,5): error : The OutputPath property is not set for project 'PnpBridge.vcxproj'. Please check to make sure that you have specified a valid combination of Configuration and Platform for this project. Configuration='Debug' Platform='x64'. This error may also appear if some other project is trying to follow a project-to-project reference to this project, this project has been unloaded or is not included in the solution, and the referencing project does not build using the same or an equivalent Configuration or Platform. diff --git a/PnpBridge/src/PnpBridge/PnpBridge.vcxproj b/PnpBridge/src/PnpBridge/PnpBridge.vcxproj index fef6cf1..e9ff0ef 100644 --- a/PnpBridge/src/PnpBridge/PnpBridge.vcxproj +++ b/PnpBridge/src/PnpBridge/PnpBridge.vcxproj @@ -23,7 +23,7 @@ {8756FD40-34AF-4000-AAB9-C2A14E75B23B} Win32Proj PnpBridge - 10.0.17134.0 + 10.0.17763.0 @@ -155,9 +155,6 @@ ..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\$(Configuration)\parson.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\iothub_client\$(Configuration)\iothub_client.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\pnp_client\$(Configuration)\pnp_client.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\iothub_client\$(Configuration)\iothub_client_http_transport.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\iothub_client\$(Configuration)\iothub_client_amqp_transport.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\iothub_client\$(Configuration)\iothub_client_amqp_ws_transport.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\iothub_client\$(Configuration)\iothub_client_mqtt_transport.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\iothub_client\$(Configuration)\iothub_client_mqtt_ws_transport.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\umqtt\$(Configuration)\umqtt.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\$(Configuration)\parson.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\c-utility\$(Configuration)\aziotsharedutil.lib;crypt32.lib;winhttp.lib;crypt32.lib;winhttp.lib;ws2_32.lib;secur32.lib;advapi32.lib;ncrypt.lib;rpcrt4.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;Cfgmgr32.lib;mfplat.lib;mfsensorgroup.lib - - - @@ -167,8 +164,10 @@ + + @@ -193,6 +192,9 @@ + + + @@ -200,7 +202,6 @@ - true diff --git a/PnpBridge/src/PnpBridge/PnpBridge.vcxproj.filters b/PnpBridge/src/PnpBridge/PnpBridge.vcxproj.filters index fdc45da..a850761 100644 --- a/PnpBridge/src/PnpBridge/PnpBridge.vcxproj.filters +++ b/PnpBridge/src/PnpBridge/PnpBridge.vcxproj.filters @@ -13,27 +13,24 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - {3524bf36-1d0b-46dc-ada9-78d0803fe1ec} - - - {28fe5595-e94e-4bac-ac50-03299b219cd8} - {92a538f9-7056-4277-a567-906bc28ce6a8} - + + {2ed2ef04-8f74-4d43-87b5-1da519b4d2f3} + + + {3524bf36-1d0b-46dc-ada9-78d0803fe1ec} + + + {28fe5595-e94e-4bac-ac50-03299b219cd8} + + {83239274-3c8a-4c29-a27a-4d7aafc2f2e3} - + {611fd0c7-a77f-4116-bf8a-c41bded6d8a3} - - {05fcc339-7478-4508-9685-0279a2e32c46} - - - - @@ -55,34 +52,34 @@ Source Files\inc - Source Files\Adapters\CoreDeviceHealth + Source Files\adapters\CoreDeviceHealth Source Files\inc - Source Files\Adapters\CoreDeviceHealth + Source Files\adapters\CoreDeviceHealth - Source Files\Adapters\Camera + Source Files\adapters\Camera - Source Files\Adapters\Camera + Source Files\adapters\Camera - Source Files\Adapters\Camera + Source Files\adapters\Camera - Source Files\Adapters\Camera + Source Files\adapters\Camera - Source Files\Adapters\Camera + Source Files\adapters\Camera - Source Files\Adapters\Camera + Source Files\adapters\Camera - Source Files\Adapters\SerialPnp + Source Files\adapters\SerialPnp Source Files\inc @@ -91,10 +88,16 @@ Source Files\inc - Source Files\Adapters\Camera + Source Files\adapters\Camera - Source Files\Adapters\Camera + Source Files\adapters\Camera + + + Source Files\adapters + + + Source Files\inc @@ -108,7 +111,7 @@ Source Files - Source Files\Adapters\CoreDeviceHealth + Source Files\adapters\CoreDeviceHealth Source Files @@ -120,40 +123,46 @@ Source Files - Source Files\Adapters\CoreDeviceHealth + Source Files\adapters\CoreDeviceHealth - Source Files\Adapters\Camera + Source Files\adapters\Camera - Source Files\Adapters\Camera + Source Files\adapters\Camera - Source Files\Adapters\Camera + Source Files\adapters\Camera - Source Files\Adapters\Camera + Source Files\adapters\Camera - Source Files\Adapters\Camera + Source Files\adapters\Camera - Source Files\Adapters\SerialPnp + Source Files\adapters\SerialPnp - Source Files\Adapters + Source Files\adapters - Source Files\Adapters\Camera + Source Files\adapters\Camera - Source Files\Adapters\Camera + Source Files\adapters\Camera + + + Source Files\core + + + Source Files\core + + + Source Files - - Source Files\Adapters - \ No newline at end of file diff --git a/PnpBridge/src/PnpBridge/PnpBridgeCommon.h b/PnpBridge/src/PnpBridge/PnpBridgeCommon.h index 860d4a5..4a23578 100644 --- a/PnpBridge/src/PnpBridge/PnpBridgeCommon.h +++ b/PnpBridge/src/PnpBridge/PnpBridgeCommon.h @@ -39,9 +39,11 @@ extern "C" #include "parson.h" - -/** @brief Enumeration specifying the status of calls to various APIs in this module. -*/ +#define TRY +#define LEAVE goto __tryLabel; +#define FINALLY goto __tryLabel; __tryLabel: +#undef __try +#undef __finally #define PNPBRIDGE_RESULT_VALUES \ PNPBRIDGE_OK, \ @@ -53,6 +55,8 @@ extern "C" DEFINE_ENUM(PNPBRIDGE_RESULT, PNPBRIDGE_RESULT_VALUES); +#define PNPBRIDGE_SUCCESS(Result) (Result == PNPBRIDGE_OK) + #include "ConfigurationParser.h" MAP_RESULT Map_Add_Index(MAP_HANDLE handle, const char* key, int value); @@ -61,6 +65,17 @@ int Map_GetIndexValueFromKey(MAP_HANDLE handle, const char* key); #include +#define PNP_CONFIG_IDENTITY_NAME "Identity" +#define PNP_CONFIG_INTERFACE_ID_NAME "InterfaceId" +#define PNP_CONFIG_PERSISTENT_NAME "Persistent" +#define PNP_CONFIG_MATCH_FILTERS_NAME "MatchFilters" +#define PNP_CONFIG_MATCH_TYPE_NAME "MatchType" +#define PNP_CONFIG_NAME_MATCH_PARAMETERS "MatchParameters" +#define PNP_CONFIG_DISCOVERY_ADAPTER_NAME "DiscoveryAdapter" +#define PNP_CONFIG_NAME_PNP_PARAMETERS "PnpParameters" +#define PNP_CONFIG_NAME_PNP_ADAPTERS "PnpAdapters" +#define PNP_CONFIG_NAME_DISCOVERY_ADAPTERS "DiscoveryAdapters" + #ifdef __cplusplus } #endif diff --git a/PnpBridge/src/PnpBridge/PnpBridgeh.h b/PnpBridge/src/PnpBridge/PnpBridgeh.h index e91fa80..56f2acc 100644 --- a/PnpBridge/src/PnpBridge/PnpBridgeh.h +++ b/PnpBridge/src/PnpBridge/PnpBridgeh.h @@ -18,13 +18,7 @@ typedef struct _PNP_BRIDGE { PDISCOVERY_MANAGER discoveryMgr; // Manages loading all pnp adapter plugins and their lifetime - PPNP_ADAPTER_MANAGER interfaceMgr; - - // List of publised pnp interfaces - SINGLYLINKEDLIST_HANDLE publishedInterfaces; - - // Number of published pnp interfaces - int publishedInterfaceCount; + PPNP_ADAPTER_MANAGER adapterMgr; LOCK_HANDLE dispatchLock; @@ -33,6 +27,8 @@ typedef struct _PNP_BRIDGE { } PNP_BRIDGE, *PPNP_BRIDGE; +void PnpBridge_Release(PPNP_BRIDGE pnpBridge); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/PnpBridge/src/PnpBridge/SamplePnpInteface.c b/PnpBridge/src/PnpBridge/SamplePnpInteface.c deleted file mode 100644 index edf2e4f..0000000 --- a/PnpBridge/src/PnpBridge/SamplePnpInteface.c +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include - -#include -#include "PnPAdapterInterface.h" - diff --git a/PnpBridge/src/PnpBridge/config.json b/PnpBridge/src/PnpBridge/config.json index f52044e..b791063 100644 --- a/PnpBridge/src/PnpBridge/config.json +++ b/PnpBridge/src/PnpBridge/config.json @@ -18,6 +18,20 @@ "Identity": "core-device-health" } }, + { + "_comment": "DEVICE1 - RANDOM device", + "MatchFilters": { + "MatchType": "Exact", + "MatchParameters": { + "HardwareId": "USB\\VID_07DE&PID_11F3" + } + }, + "Persistent" : "true", + "InterfaceId": "http://windows.com/coredevicehealth/v1", + "PnpParameters": { + "Identity": "core-device-health" + } + }, { "_comment": "DEVICE2 - MCU sensor hub which reports Azure IoT Pnp interfaces", "MatchFilters": { diff --git a/PnpBridge/src/PnpBridge/core/PnpAdapterInterface.c b/PnpBridge/src/PnpBridge/core/PnpAdapterInterface.c new file mode 100644 index 0000000..412fc67 --- /dev/null +++ b/PnpBridge/src/PnpBridge/core/PnpAdapterInterface.c @@ -0,0 +1,114 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#include "PnpBridgeCommon.h" +#include "PnpAdapterInterface.h" +#include "PnpAdapterManager.h" + +int PnpAdapterInterface_Create(PNPADAPTER_CONTEXT adapterHandle, const char* interfaceId, + PNP_INTERFACE_CLIENT_HANDLE pnpInterface, + PPNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface, + PPNPADPATER_INTERFACE_INIT_PARAMS params) +{ + int result = 0; + PPNPADAPTER_INTERFACE interface = NULL; + + TRY + { + // validate params + if (NULL == params) { + return -1; + } + + if (NULL == params->releaseInterface || NULL == pnpInterface) { + return -1; + } + + // Create a pnp adapter interface + interface = calloc(1, sizeof(PNPADAPTER_INTERFACE)); + if (NULL == interface) { + LEAVE; + } + + interface->pnpInterfaceClient = pnpInterface; + interface->interfaceId = malloc(strlen(interfaceId) + 1); + if (NULL == interface->interfaceId) { + LEAVE; + } + + // Make a copy of interface id + strcpy_s(interface->interfaceId, strlen(interfaceId)+1, interfaceId); + + // Copy the params + memcpy(&interface->params, params, sizeof(interface->params)); + + PPNP_ADAPTER_CONTEXT_TAG adapterContext = adapterHandle; + + // Copy adapter context + interface->adapterContext = calloc(1, sizeof(PPNP_ADAPTER_CONTEXT_TAG)); + if (NULL == interface->adapterContext) { + LEAVE; + } + memcpy(&interface->adapterContext, adapterContext, sizeof(interface->adapterContext)); + + // Add this interface to the list of interfaces under the adapter context + PnpAdapterManager_AddInterface(adapterContext->adapter, interface); + + *pnpAdapterInterface = interface; + } + FINALLY + { + if (result < 0) { + PnpAdapterInterface_Destroy(interface); + } + } + + return result; +} + +void PnpAdapterInterface_Destroy(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface) { + if (NULL == pnpAdapterInterface) { + return; + } + + PPNPADAPTER_INTERFACE interface = (PPNPADAPTER_INTERFACE)pnpAdapterInterface; + if (NULL != interface->interfaceId) { + free(interface->interfaceId); + } + + if (NULL != interface->adapterContext) { + PPNP_ADAPTER_CONTEXT_TAG adapterContext = (PPNP_ADAPTER_CONTEXT_TAG)interface->adapterContext; + if (NULL != interface->adapterEntry) { + PnpAdapterManager_RemoveInterface(adapterContext->adapter, pnpAdapterInterface); + } + } +} + +PNP_INTERFACE_CLIENT_HANDLE PnpAdapterInterface_GetPnpInterfaceClient(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface) { + if (NULL == pnpAdapterInterface) { + return NULL; + } + + PPNPADAPTER_INTERFACE interfaceClient = (PPNPADAPTER_INTERFACE)pnpAdapterInterface; + return interfaceClient->pnpInterfaceClient; +} + +PNPBRIDGE_RESULT PnpAdapterInterface_SetContext(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface, void* context) { + if (NULL == pnpAdapterInterface) { + return PNPBRIDGE_INVALID_ARGS; + } + + PPNPADAPTER_INTERFACE interfaceClient = (PPNPADAPTER_INTERFACE)pnpAdapterInterface; + interfaceClient->context = context; + + return PNPBRIDGE_OK; +} + +void* PnpAdapterInterface_GetContext(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface) { + if (NULL == pnpAdapterInterface) { + return NULL; + } + + PPNPADAPTER_INTERFACE adapterInterface = (PPNPADAPTER_INTERFACE)pnpAdapterInterface; + return adapterInterface->context; +} \ No newline at end of file diff --git a/PnpBridge/src/PnpBridge/core/PnpBridgeMemory.c b/PnpBridge/src/PnpBridge/core/PnpBridgeMemory.c new file mode 100644 index 0000000..fb27ff1 --- /dev/null +++ b/PnpBridge/src/PnpBridge/core/PnpBridgeMemory.c @@ -0,0 +1,41 @@ +#include +#include "azure_c_shared_utility/refcount.h" +#include "core/PnpBridgeMemory.h" + +int PnpBridgeMemory_Create(PPNPBRIDGE_OBJECT_PARAMS params, int size, PNPBRIDGE_MEMORY* memory) { + if (NULL == params || NULL == params->destroyCallback) { + return -1; + } + + PPNPBRIDGE_MEMORY_TAG mem = calloc(1, sizeof(PNPBRIDGE_MEMORY_TAG) + size); + if (NULL == mem) { + return -1; + } + + INIT_REF_VAR(mem->count); + mem->size = size; + + *memory = (PNPBRIDGE_MEMORY*)mem; + + return 0; +} + +void PnpBridgeMemory_AddReference(PNPBRIDGE_MEMORY memory) { + PPNPBRIDGE_MEMORY_TAG mem = (PPNPBRIDGE_MEMORY_TAG)memory; + DEC_REF_VAR(mem->count); +} + +void PnpBridgeMemory_ReleaseReference(PNPBRIDGE_MEMORY memory) { + PPNPBRIDGE_MEMORY_TAG mem = (PPNPBRIDGE_MEMORY_TAG)memory; + if (DEC_RETURN_ZERO == DEC_REF_VAR(mem->count)) { + mem->params.destroyCallback(); + } +} + +void* PnpMemory_GetBuffer(PNPBRIDGE_MEMORY memory, int* size) { + PPNPBRIDGE_MEMORY_TAG mem = (PPNPBRIDGE_MEMORY_TAG)memory; + if (NULL != size) { + *size = mem->size; + } + return mem->memory; +} \ No newline at end of file diff --git a/PnpBridge/src/PnpBridge/core/PnpBridgeMemory.h b/PnpBridge/src/PnpBridge/core/PnpBridgeMemory.h new file mode 100644 index 0000000..cccae04 --- /dev/null +++ b/PnpBridge/src/PnpBridge/core/PnpBridgeMemory.h @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#ifndef PNPBRIDGE_OBJECT_H +#define PNPBRIDGE_OBJECT_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + typedef void* PNPBRIDGE_MEMORY; + + typedef int(*PNPBRIDGE_MEMORY_DESTROY) (); + + typedef struct _PNPBRIDGE_MEMORY_PARAMS { + PNPBRIDGE_MEMORY_DESTROY destroyCallback; + } PNPBRIDGE_MEMORY_PARAMS, *PPNPBRIDGE_OBJECT_PARAMS; + + typedef struct _PNPBRIDGE_MEMORY_TAG { + int count; + int size; + void* memory; + PNPBRIDGE_MEMORY_PARAMS params; + } PNPBRIDGE_MEMORY_TAG, *PPNPBRIDGE_MEMORY_TAG; + + int PnpBridgeMemory_Create(PPNPBRIDGE_OBJECT_PARAMS params, int size, PNPBRIDGE_MEMORY* memory); + + void PnpBridgeMemory_AddReference(PNPBRIDGE_MEMORY memory); + + void PnpBridgeMemory_ReleaseReference(PNPBRIDGE_MEMORY memory); + + void* PnpMemory_GetBuffer(PNPBRIDGE_MEMORY memory, int* size); + +#ifdef __cplusplus +} +#endif + +#endif /* PNPBRIDGE_OBJECT_H */ \ No newline at end of file diff --git a/PnpBridge/src/PnpBridge/targetver.h b/PnpBridge/src/PnpBridge/targetver.h deleted file mode 100644 index 87c0086..0000000 --- a/PnpBridge/src/PnpBridge/targetver.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -// Including SDKDDKVer.h defines the highest available Windows platform. - -// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and -// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. - -#include From 6bbe2379e55b3dfdb77d9cda03a5fe831bf78fc1 Mon Sep 17 00:00:00 2001 From: Ajay Barboza Date: Wed, 13 Feb 2019 12:30:40 -0800 Subject: [PATCH 4/7] config validation --- .../src/PnpBridge/Adapters/AdapterManifest.c | 6 +- PnpBridge/src/PnpBridge/ConfigurationParser.c | 69 ++++++++++++- PnpBridge/src/PnpBridge/ConfigurationParser.h | 2 + PnpBridge/src/PnpBridge/DiscoveryManager.c | 2 +- PnpBridge/src/PnpBridge/PnpAdapterManger.c | 1 + PnpBridge/src/PnpBridge/PnpBridge.c | 97 +++++++++++-------- PnpBridge/src/PnpBridge/PnpBridgeCommon.h | 4 +- 7 files changed, 130 insertions(+), 51 deletions(-) diff --git a/PnpBridge/src/PnpBridge/Adapters/AdapterManifest.c b/PnpBridge/src/PnpBridge/Adapters/AdapterManifest.c index 4a1b24e..b311d8d 100644 --- a/PnpBridge/src/PnpBridge/Adapters/AdapterManifest.c +++ b/PnpBridge/src/PnpBridge/Adapters/AdapterManifest.c @@ -10,8 +10,7 @@ extern DISCOVERY_ADAPTER WindowsPnpDeviceDiscovery; PDISCOVERY_ADAPTER DISCOVERY_ADAPTER_MANIFEST[] = { &CameraPnpAdapter, - &SerialPnpDiscovery, - &WindowsPnpDeviceDiscovery + &SerialPnpDiscovery }; const int DiscoveryAdapterCount = sizeof(DISCOVERY_ADAPTER_MANIFEST) / sizeof(PDISCOVERY_ADAPTER); @@ -22,8 +21,7 @@ extern PNP_ADAPTER SerialPnpInterface; PPNP_ADAPTER PNP_ADAPTER_MANIFEST[] = { &CameraPnpInterface, - &SerialPnpInterface, - &CoreDeviceHealthInterface + &SerialPnpInterface }; const int PnpAdapterCount = sizeof(PNP_ADAPTER_MANIFEST) / sizeof(PPNP_ADAPTER); diff --git a/PnpBridge/src/PnpBridge/ConfigurationParser.c b/PnpBridge/src/PnpBridge/ConfigurationParser.c index 2444d7a..b658847 100644 --- a/PnpBridge/src/PnpBridge/ConfigurationParser.c +++ b/PnpBridge/src/PnpBridge/ConfigurationParser.c @@ -16,6 +16,71 @@ PNPBRIDGE_RESULT PnpBridgeConfig_ReadConfigurationFromFile(const char *filename, return PNPBRIDGE_OK; } +PNPBRIDGE_RESULT PnpBridgeConfig_ValidateConfiguration(JSON_Value* config) { + PNPBRIDGE_RESULT result = PNPBRIDGE_OK; + + // Check for mandatory parameters + TRY + { + // Devices + { + JSON_Array* devices = Configuration_GetConfiguredDevices(config); + for (int i = 0; i < (int)json_array_get_count(devices); i++) { + JSON_Object *device = json_array_get_object(devices, i); + + // InterfaceId or SelfDescribing + { + const char* selfDescribing = json_object_dotget_string(device, PNP_CONFIG_NAME_SELF_DESCRIBING); + const char* interfaceId = json_object_dotget_string(device, PNP_CONFIG_NAME_INTERFACE_ID); + if (NULL == selfDescribing) { + if (NULL == interfaceId) { + LogError("A device is missing InterfaceId"); + } + } + } + + // PnpParameters + { + JSON_Object* pnpParams = Configuration_GetPnpParametersForDevice(device); + if (NULL == pnpParams) { + LogError("A device is missing PnpParameters"); + result = PNPBRIDGE_INVALID_ARGS; + LEAVE; + } + + // PnpParameters -> Idenitity + const char* identity = json_object_dotget_string(pnpParams, PNP_CONFIG_IDENTITY_NAME); + if (NULL == identity) { + LogError("PnpParameter is missing Adapter identity"); + result = PNPBRIDGE_INVALID_ARGS; + LEAVE; + } + } + + // DiscoveryParameters + { + JSON_Object* discParams = Configuration_GetDiscoveryParametersForDevice(device); + if (discParams) { + // DiscoveryParameters -> Idenitity + const char* identity = json_object_dotget_string(discParams, PNP_CONFIG_IDENTITY_NAME); + if (NULL == identity) { + LogError("DiscoveryParameters is missing Adapter identity"); + result = PNPBRIDGE_INVALID_ARGS; + LEAVE; + } + } + } + } + } + } + FINALLY + { + + } + + return result; +} + PNPBRIDGE_RESULT PnpBridgeConfig_ReadConfigurationFromString(const char *configString, JSON_Value** config) { if (NULL == configString || NULL == config) { return PNPBRIDGE_INVALID_ARGS; @@ -172,8 +237,8 @@ PNPBRIDGE_RESULT Configuration_IsDeviceConfigured(JSON_Value* config, JSON_Objec } } else { - const char* interfaceId = json_object_dotget_string(device, PNP_CONFIG_INTERFACE_ID_NAME); - json_object_set_string(Message, PNP_CONFIG_INTERFACE_ID_NAME, interfaceId); + const char* interfaceId = json_object_dotget_string(device, PNP_CONFIG_NAME_INTERFACE_ID); + json_object_set_string(Message, PNP_CONFIG_NAME_INTERFACE_ID, interfaceId); foundMatch = true; pnpAdapterIdentity = (char*) currPnpAdapterId; *Device = device; diff --git a/PnpBridge/src/PnpBridge/ConfigurationParser.h b/PnpBridge/src/PnpBridge/ConfigurationParser.h index 7b18108..c6e7eb3 100644 --- a/PnpBridge/src/PnpBridge/ConfigurationParser.h +++ b/PnpBridge/src/PnpBridge/ConfigurationParser.h @@ -42,6 +42,8 @@ PNPBRIDGE_RESULT Configuration_IsDeviceConfigured(JSON_Value* config, JSON_Objec const char* Configuration_GetConnectionString(JSON_Value* config); +PNPBRIDGE_RESULT PnpBridgeConfig_ValidateConfiguration(JSON_Value* config); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/PnpBridge/src/PnpBridge/DiscoveryManager.c b/PnpBridge/src/PnpBridge/DiscoveryManager.c index 18728c8..d581dcc 100644 --- a/PnpBridge/src/PnpBridge/DiscoveryManager.c +++ b/PnpBridge/src/PnpBridge/DiscoveryManager.c @@ -125,7 +125,7 @@ PNPBRIDGE_RESULT DiscoveryAdapterManager_NotifyPersistentInterfaces(PDISCOVERY_M // Get the match filters and post a device change message JSON_Object* matchParams = Configuration_GetMatchParametersForDevice(device); - const char* interfaceId = json_object_dotget_string(device, PNP_CONFIG_INTERFACE_ID_NAME); + const char* interfaceId = json_object_dotget_string(device, PNP_CONFIG_NAME_INTERFACE_ID); if (NULL != interfaceId && NULL != matchParams) { char msg[512] = { 0 }; sprintf_s(msg, 512, PnpBridge_DeviceChangeMessageformat, interfaceId, json_serialize_to_string(json_object_get_wrapping_value(matchParams))); diff --git a/PnpBridge/src/PnpBridge/PnpAdapterManger.c b/PnpBridge/src/PnpBridge/PnpAdapterManger.c index f585b2a..46e7ba6 100644 --- a/PnpBridge/src/PnpBridge/PnpAdapterManger.c +++ b/PnpBridge/src/PnpBridge/PnpAdapterManger.c @@ -176,6 +176,7 @@ PNPBRIDGE_RESULT PnpAdapterManager_SupportsIdentity(PPNP_ADAPTER_MANAGER adapter mapResult = Map_ContainsKey(adapter->pnpAdapterMap, getIdentity, &containsMessageKey); if (MAP_OK != mapResult || !containsMessageKey) { + LogError("PnpAdapter %s is not present in AdapterManifest", getIdentity); return PNPBRIDGE_FAILED; } diff --git a/PnpBridge/src/PnpBridge/PnpBridge.c b/PnpBridge/src/PnpBridge/PnpBridge.c index 9e01ef0..51a0a34 100644 --- a/PnpBridge/src/PnpBridge/PnpBridge.c +++ b/PnpBridge/src/PnpBridge/PnpBridge.c @@ -229,7 +229,7 @@ PNPBRIDGE_RESULT PnpBridge_DeviceChangeCallback(PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD goto end; } else { - LogError("Interface id not set for the device change callback\n"); + LogError("Dropping device change callback\n"); } } @@ -243,52 +243,63 @@ PNPBRIDGE_RESULT PnpBridge_Main() { PNPBRIDGE_RESULT result = PNPBRIDGE_OK; JSON_Value* config = NULL; - LogInfo("Starting Azure PnpBridge\n"); + TRY + { + LogInfo("Starting Azure PnpBridge\n"); - //#define CONFIG_FILE "c:\\data\\test\\dag\\config.json" - result = PnpBridgeConfig_ReadConfigurationFromFile("config.json", &config); - if (PNPBRIDGE_OK != result) { - LogError("Failed to parse configuration. Check if config file is present and ensure its formatted correctly.\n"); - goto exit; + // Read the config file from a file + result = PnpBridgeConfig_ReadConfigurationFromFile("config.json", &config); + if (PNPBRIDGE_OK != result) { + LogError("Failed to parse configuration. Check if config file is present and ensure its formatted correctly.\n"); + LEAVE; + } + + // Check if config file has mandatory parameters + result = PnpBridgeConfig_ValidateConfiguration(config); + if (PNPBRIDGE_OK != result) { + LogError("Config file is invalid\n"); + LEAVE; + } + + result = PnpBridge_Initialize(config); + if (PNPBRIDGE_OK != result) { + LogError("PnpBridge_Initialize failed: %d\n", result); + LEAVE; + } + + LogInfo("Connected to Azure IoT Hub\n"); + + // Load all the adapters in interface manifest that implement Azure IoT PnP Interface + // PnpBridge will call into corresponding adapter when a device is reported by + // DiscoveryExtension + result = PnpAdapterManager_Create(&g_PnpBridge->adapterMgr, g_PnpBridge->configuration); + if (PNPBRIDGE_OK != result) { + LogError("PnpAdapterManager_Create failed: %d\n", result); + LEAVE; + } + + // Load all the extensions that are capable of discovering devices + // and reporting back to PnpBridge + result = DiscoveryAdapterManager_Create(&g_PnpBridge->discoveryMgr); + if (PNPBRIDGE_OK != result) { + LogError("DiscoveryAdapterManager_Create failed: %d\n", result); + LEAVE; + } + + THREAD_HANDLE workerThreadHandle = NULL; + if (THREADAPI_OK != ThreadAPI_Create(&workerThreadHandle, PnpBridge_Worker_Thread, NULL)) { + LogError("Failed to create PnpBridge_Worker_Thread\n"); + workerThreadHandle = NULL; + } + else { + ThreadAPI_Join(workerThreadHandle, NULL); + } } - - result = PnpBridge_Initialize(config); - if (PNPBRIDGE_OK != result) { - LogError("PnpBridge_Initialize failed: %d\n", result); - goto exit; + FINALLY + { + PnpBridge_Release(g_PnpBridge); } - LogInfo("Connected to Azure IoT Hub\n"); - - // Load all the adapters in interface manifest that implement Azure IoT PnP Interface - // PnpBridge will call into corresponding adapter when a device is reported by - // DiscoveryExtension - result = PnpAdapterManager_Create(&g_PnpBridge->adapterMgr, g_PnpBridge->configuration); - if (PNPBRIDGE_OK != result) { - LogError("PnpAdapterManager_Create failed: %d\n", result); - goto exit; - } - - // Load all the extensions that are capable of discovering devices - // and reporting back to PnpBridge - result = DiscoveryAdapterManager_Create(&g_PnpBridge->discoveryMgr); - if (PNPBRIDGE_OK != result) { - LogError("DiscoveryAdapterManager_Create failed: %d\n", result); - goto exit; - } - - THREAD_HANDLE workerThreadHandle = NULL; - if (THREADAPI_OK != ThreadAPI_Create(&workerThreadHandle, PnpBridge_Worker_Thread, NULL)) { - LogError("Failed to create PnpBridge_Worker_Thread \n"); - workerThreadHandle = NULL; - } - else { - ThreadAPI_Join(workerThreadHandle, NULL); - } - -exit: - PnpBridge_Release(g_PnpBridge); - return result; } diff --git a/PnpBridge/src/PnpBridge/PnpBridgeCommon.h b/PnpBridge/src/PnpBridge/PnpBridgeCommon.h index 4a23578..dcd8842 100644 --- a/PnpBridge/src/PnpBridge/PnpBridgeCommon.h +++ b/PnpBridge/src/PnpBridge/PnpBridgeCommon.h @@ -66,15 +66,17 @@ int Map_GetIndexValueFromKey(MAP_HANDLE handle, const char* key); #include #define PNP_CONFIG_IDENTITY_NAME "Identity" -#define PNP_CONFIG_INTERFACE_ID_NAME "InterfaceId" +#define PNP_CONFIG_NAME_INTERFACE_ID "InterfaceId" #define PNP_CONFIG_PERSISTENT_NAME "Persistent" #define PNP_CONFIG_MATCH_FILTERS_NAME "MatchFilters" #define PNP_CONFIG_MATCH_TYPE_NAME "MatchType" #define PNP_CONFIG_NAME_MATCH_PARAMETERS "MatchParameters" #define PNP_CONFIG_DISCOVERY_ADAPTER_NAME "DiscoveryAdapter" #define PNP_CONFIG_NAME_PNP_PARAMETERS "PnpParameters" +#define PNP_CONFIG_NAME_DISCOVERY_PARAMETERS "DiscoveryParameters" #define PNP_CONFIG_NAME_PNP_ADAPTERS "PnpAdapters" #define PNP_CONFIG_NAME_DISCOVERY_ADAPTERS "DiscoveryAdapters" +#define PNP_CONFIG_NAME_SELF_DESCRIBING "SelfDescribing" #ifdef __cplusplus } From 0ef1f8e4e6b9ab43008640e5144e1f34f0fd3d31 Mon Sep 17 00:00:00 2001 From: Ajay Barboza Date: Wed, 13 Feb 2019 16:35:55 -0800 Subject: [PATCH 5/7] cmake cleanup --- PnpBridge/scripts/build.pnpbridge.cmd | 86 ++++++++++++++ PnpBridge/src/CMakeLists.txt | 3 +- .../CoreDeviceHealth/CoreDeviceHealth.c | 6 +- .../PnpBridge/Adapters/SerialPnp/SerialPnp.c | 1 + PnpBridge/src/PnpBridge/CMakeLists.txt | 51 +++++---- PnpBridge/src/PnpBridge/DiscoveryManager.c | 36 ++---- PnpBridge/src/PnpBridge/DiscoveryManager.h | 2 +- PnpBridge/src/PnpBridge/PnpAdapterInterface.h | 12 -- PnpBridge/src/PnpBridge/PnpAdapterManager.h | 9 +- PnpBridge/src/PnpBridge/PnpAdapterManger.c | 57 +++++----- PnpBridge/src/PnpBridge/PnpBridge.c | 4 +- PnpBridge/src/PnpBridge/PnpBridge.h | 37 ++++++ PnpBridge/src/PnpBridge/PnpBridge.vcxproj | 2 +- PnpBridge/src/PnpBridge/PnpBridgeCommon.h | 2 +- PnpBridge/src/PnpBridge/config.json | 2 +- .../src/PnpBridge/core/PnpBridgeMemory.h | 2 +- PnpBridge/src/tests/CMakeLists.txt | 3 + .../tests/pnp_adapter_manager/CMakeLists.txt | 4 + .../src/tests/pnp_adapter_manager/main.c | 11 ++ .../pnp_adapter_manager_ut.c | 105 ++++++++++++++++++ 20 files changed, 333 insertions(+), 102 deletions(-) create mode 100644 PnpBridge/scripts/build.pnpbridge.cmd create mode 100644 PnpBridge/src/tests/CMakeLists.txt create mode 100644 PnpBridge/src/tests/pnp_adapter_manager/CMakeLists.txt create mode 100644 PnpBridge/src/tests/pnp_adapter_manager/main.c create mode 100644 PnpBridge/src/tests/pnp_adapter_manager/pnp_adapter_manager_ut.c diff --git a/PnpBridge/scripts/build.pnpbridge.cmd b/PnpBridge/scripts/build.pnpbridge.cmd new file mode 100644 index 0000000..2c914cd --- /dev/null +++ b/PnpBridge/scripts/build.pnpbridge.cmd @@ -0,0 +1,86 @@ +@echo off + +goto START + +:Usage +echo Usage: build.prereq.cmd x86^|ARM^|x64 Debug^|Release [WindowsSDKVersion] +echo WinSDKVer............... Default is 10.0.14393.0, specify another version if necessary +echo [/?].................... Displays this usage string. +echo Example: +echo build.pnpbridge.cmd x64 Debug 10.0.17763.0 +endlocal +exit /b 1 + +:START +setlocal ENABLEDELAYEDEXPANSION + +if [%1] == [/?] goto Usage +if [%1] == [-?] goto Usage + +if [%1] == [] ( + set TARGETARCH=x64 +) else ( + set TARGETARCH=%1 +) + +if /I [%TARGETARCH%] == [x86] ( + set TARGETPLATFORM=Win32 +) else ( + set TARGETPLATFORM=%TARGETARCH% +) + +if [%2] == [] ( + set TARGETCONFIG=Debug +) else ( + set TARGETCONFIG=%2 +) + +if [%3] == [] ( + set TARGETPLATVER=10.0.17763.0 +) else ( + set TARGETPLATVER=%3 +) + +pushd %~dp0.. + +echo . +echo "Using CMAKE to set up Azure PnpBridge projects" +echo. + +set OUTPUTDIR=%TARGETPLATFORM%_%TARGETCONFIG% + +md %OUTPUTDIR% +pushd %OUTPUTDIR% +if /I [%TARGETARCH%] == [x86] ( +cmake -G "Visual Studio 15 2017" .. -Dskip_samples=ON .. +) + +if /I [%TARGETARCH%] == [arm] ( +cmake -G "Visual Studio 15 2017 ARM" .. -Duse_prov_client:BOOL=ON -Duse_tpm_simulator:BOOL=OFF -Dbuild_provisioning_service_client=ON -Duse_prov_client_core=ON -Dskip_samples=ON .. +) + +if /I [%TARGETARCH%] == [x64] ( +cmake -G "Visual Studio 15 2017 Win64" .. -Dskip_samples=ON .. +) +popd + + +echo . +echo "Building Azure SDK libraries" +echo . + +pushd %OUTPUTDIR% +msbuild %~dp0..\%OUTPUTDIR%\azure_iot_pnp_bridge.sln /p:Configuration=%TARGETCONFIG% /p:Platform=%TARGETPLATFORM% /p:TargetPlatformVersion=%TARGETPLATVER% +if errorlevel 1 goto BuildError + +popd + +goto Success + +:BuildError +popd +@echo Error building project... +exit /b 1 + +:Success + diff --git a/PnpBridge/src/CMakeLists.txt b/PnpBridge/src/CMakeLists.txt index babd373..aa58bee 100644 --- a/PnpBridge/src/CMakeLists.txt +++ b/PnpBridge/src/CMakeLists.txt @@ -1,3 +1,4 @@ cmake_minimum_required(VERSION 2.8.11) -add_subdirectory(PnpBridge) \ No newline at end of file +add_subdirectory(PnpBridge) +# add_subdirectory(tests) \ No newline at end of file diff --git a/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.c b/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.c index 1a04835..ae7bdca 100644 --- a/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.c +++ b/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.c @@ -100,9 +100,7 @@ int CoreDevice_CreatePnpInterface(PNPADAPTER_CONTEXT adapterHandle, PNP_DEVICE_C const char* interfaceId = json_object_get_string(args, "InterfaceId"); const char* hardwareId = json_object_get_string(args, "HardwareId"); const char* symbolicLink = json_object_get_string(args, "SymbolicLink"); - const char* persistent = json_object_get_string(args, "Persistent"); - - PNPADAPTER_INTERFACE_HANDLE Interface = NULL; + const char* publishMode = json_object_get_string(args, "PublishMode"); pnpInterfaceClient = PnP_InterfaceClient_Create(pnpDeviceClientHandle, interfaceId, NULL, NULL, NULL); if (NULL == pnpInterfaceClient) { @@ -121,7 +119,7 @@ int CoreDevice_CreatePnpInterface(PNPADAPTER_CONTEXT adapterHandle, PNP_DEVICE_C } } - if (NULL != persistent && stricmp(persistent, "true") == 0) { + if (NULL != publishMode && stricmp(publishMode, "true") == 0) { return 0; } diff --git a/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.c b/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.c index 84ae264..8158864 100644 --- a/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.c +++ b/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.c @@ -1246,6 +1246,7 @@ int SerialPnp_ReleasePnpInterface(PNPADAPTER_INTERFACE_HANDLE pnpInterface) { } int SerialPnp_Initialize(const char* adapterArgs) { + AZURE_UNREFERENCED_PARAMETER(adapterArgs); return 0; } diff --git a/PnpBridge/src/PnpBridge/CMakeLists.txt b/PnpBridge/src/PnpBridge/CMakeLists.txt index 2b910c8..51fae2c 100644 --- a/PnpBridge/src/PnpBridge/CMakeLists.txt +++ b/PnpBridge/src/PnpBridge/CMakeLists.txt @@ -15,43 +15,54 @@ endif() set(pnp_bridge_c_files ./ConfigurationParser.c ./DiscoveryManager.c + ./IotHubComms.c ./PnpAdapterManger.c ./PnpBridge.c + ./PnpBridgeService.c ./utility.c + ./Core/PnpAdapterInterface.c + ./Core/PnpBridgeMemory.c ./Adapters/AdapterManifest.c + ./Adapters/Camera/CameraIotPnpAPIs.cpp + ./Adapters/Camera/CameraCaptureEngineCallbacks.cpp + ./Adapters/Camera/CameraCaptureEngine.cpp + ./Adapters/Camera/CameraPnpDiscovery.cpp + ./Adapters/Camera/CameraIotPnpDevice.cpp + ./Adapters/Camera/JsonWrapper.cpp + ./Adapters/Camera/CameraStatConsumer.cpp + ./Adapters/CoreDeviceHealth/CoreDeviceHealth.c + ./Adapters/CoreDeviceHealth/WindowsPnPDeviceDiscovery.c + ./Adapters/SerialPnp/SerialPnp.c ) - # ./PnpBridgeService.c - # ./Adapters/SerialPnp/SerialPnp.c - # ./Adapters/Camera/CameraIotPnpAPIs.cpp - # ./Adapters/Camera/CameraPnpDiscovery.cpp - # ./Adapters/Camera/CameraStatConsumer.cpp - # ./Adapters/Camera/JsonWrapper.cpp - # ./Adapters/Camera/CameraIotPnpDevice.cpp - # ./Adapters/CoreDeviceHealth/CoreDeviceHealth.h - # ./Adapters/CoreDeviceHealth/WindowsPnpDeviceDiscovery.h - set(pnp_bridge_h_files - ./CmdAndPropHandler.h ./common.h ./ConfigurationParser.h ./DiscoveryAdapterInterface.h ./DiscoveryManager.h + ./IotHubComms.h ./PnpAdapterInterface.h ./PnpAdapterManager.h ./PnpBridge.h + ./PnpBridgeCommon.h ./PnpBridgeh.h + ./Core/PnpBridgeMemory.h + ./Adapters/PnpAdapterManifest.h + ./Adapters/DiscoveryAdapterManifest.h + ./Adapters/CmdAndPropHandler.h + ./Adapters/Camera/CameraCaptureEngine.h + ./Adapters/Camera/CameraCaptureEngineCallbacks.h + ./Adapters/Camera/CameraIotPnpAPIs.h + ./Adapters/Camera/CameraIotPnpDevice.h + ./Adapters/Camera/CameraPnpDiscovery.h + ./Adapters/Camera/CameraStatConsumer.h + ./Adapters/Camera/JsonWrapper.h + ./Adapters/Camera/pch.h + ./Adapters/CoreDeviceHealth/CoreDeviceHealth.h + ./Adapters/CoreDeviceHealth/WindowsPnpDeviceDiscovery.h + ./Adapters/SerialPnp/SerialPnp.h ) - # ./Adapters/Camera/CameraIotPnpAPIs.h - # ./Adapters/Camera/CameraIotPnpDevice.h - # ./Adapters/Camera/CameraPnpDiscovery.h - # ./Adapters/Camera/CameraStatConsumer.h - # ./Adapters/JsonWrapper.h - # ./Adapters/pch.h - # ./Adapters/CoreDeviceHealth/CoreDeviceHealth.c - # ./Adapters/CoreDeviceHealth/WindowsPnPDeviceDiscovery.c - set(pnp_bridge_libs) set(install_staticlibs diff --git a/PnpBridge/src/PnpBridge/DiscoveryManager.c b/PnpBridge/src/PnpBridge/DiscoveryManager.c index d581dcc..4139263 100644 --- a/PnpBridge/src/PnpBridge/DiscoveryManager.c +++ b/PnpBridge/src/PnpBridge/DiscoveryManager.c @@ -8,8 +8,6 @@ extern PDISCOVERY_ADAPTER DISCOVERY_ADAPTER_MANIFEST[]; extern const int DiscoveryAdapterCount; -DISCOVERY_ADAPTER discoveryInterface = { 0 }; - void DiscoveryAdapterChangeHandler(PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD DeviceChangePayload); PNPBRIDGE_RESULT DiscoveryManager_StarDiscoveryAdapter(PDISCOVERY_MANAGER discoveryManager, PDISCOVERY_ADAPTER discoveryInterface, JSON_Object* deviceParams, JSON_Object* adapterParams, int key); @@ -109,17 +107,18 @@ PNPBRIDGE_RESULT DiscoveryManager_StarDiscoveryAdapter(PDISCOVERY_MANAGER discov const char* PnpBridge_DeviceChangeMessageformat = "{ \ \"Identity\": \"pnpbridge-core\", \ \"InterfaceId\": \"%s\", \ - \"Persistent\": \"true\", \ + \"PublishMode\": \"true\", \ \"MatchParameters\": %s \ }"; -PNPBRIDGE_RESULT DiscoveryAdapterManager_NotifyPersistentInterfaces(PDISCOVERY_MANAGER discoveryManager, JSON_Value* config) { +PNPBRIDGE_RESULT DiscoveryAdapterManager_PublishAlwaysInterfaces(PDISCOVERY_MANAGER discoveryManager, JSON_Value* config) { + AZURE_UNREFERENCED_PARAMETER(discoveryManager); JSON_Array *devices = Configuration_GetConfiguredDevices(config); for (int i = 0; i < (int)json_array_get_count(devices); i++) { JSON_Object* device = json_array_get_object(devices, i); - const char* persistentString = json_object_get_string(device, PNP_CONFIG_PERSISTENT_NAME); - if (NULL != persistentString && stricmp(persistentString, "true") == 0) { + const char* publishModeString = json_object_get_string(device, PNP_CONFIG_NAME_PUBLISH_MODE); + if (NULL != publishModeString && stricmp(publishModeString, "always") == 0) { PNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload = { 0 }; payload.ChangeType = PNPBRIDGE_INTERFACE_CHANGE_PERSIST; @@ -176,31 +175,10 @@ PNPBRIDGE_RESULT DiscoveryAdapterManager_Start(PDISCOVERY_MANAGER discoveryManag JSON_Object* adapterParams = NULL; adapterParams = Configuration_GetDiscoveryParameters(config, discoveryInterface->Identity); - //PSTART_DISCOVERY_PARAMS threadContext; - - //// threadContext memory will be freed during cleanup. - //threadContext = malloc(sizeof(START_DISCOVERY_PARAMS)); - //if (NULL == threadContext) { - // return PNPBRIDGE_INSUFFICIENT_MEMORY; - //} - - //threadContext->adapterParams = adapterParams; - //threadContext->deviceParams = deviceParams; - //threadContext->discoveryInterface = discoveryInterface; - //threadContext->key = i; - //threadContext->discoveryManager = discoveryManager; - - //if (THREADAPI_OK != ThreadAPI_Create(&threadContext->workerThreadHandle, DiscoveryManager_StarDiscovery_Worker_Thread, threadContext)) { - // LogError("Failed to create PnpBridge_Worker_Thread \n"); - // threadContext->workerThreadHandle = NULL; - // return PNPBRIDGE_FAILED; - //} - int result = DiscoveryManager_StarDiscoveryAdapter(discoveryManager, discoveryInterface, deviceParams, adapterParams, i); + result = DiscoveryManager_StarDiscoveryAdapter(discoveryManager, discoveryInterface, deviceParams, adapterParams, i); if (PNPBRIDGE_OK != result) { - return result; + LEAVE; } - - //singlylinkedlist_add(discoveryManager->startDiscoveryThreadHandles, threadContext); } } FINALLY diff --git a/PnpBridge/src/PnpBridge/DiscoveryManager.h b/PnpBridge/src/PnpBridge/DiscoveryManager.h index cef0d16..62182ee 100644 --- a/PnpBridge/src/PnpBridge/DiscoveryManager.h +++ b/PnpBridge/src/PnpBridge/DiscoveryManager.h @@ -27,7 +27,7 @@ PNPBRIDGE_RESULT DiscoveryAdapterManager_Create(PDISCOVERY_MANAGER* discoveryMan */ PNPBRIDGE_RESULT DiscoveryAdapterManager_Start(PDISCOVERY_MANAGER discoveryManager, JSON_Value* config); -PNPBRIDGE_RESULT DiscoveryAdapterManager_NotifyPersistentInterfaces(PDISCOVERY_MANAGER discoveryManager, JSON_Value* config); +PNPBRIDGE_RESULT DiscoveryAdapterManager_PublishAlwaysInterfaces(PDISCOVERY_MANAGER discoveryManager, JSON_Value* config); void DiscoveryAdapterManager_Stop(PDISCOVERY_MANAGER discoveryManager); diff --git a/PnpBridge/src/PnpBridge/PnpAdapterInterface.h b/PnpBridge/src/PnpBridge/PnpAdapterInterface.h index 6ca9829..93fdf36 100644 --- a/PnpBridge/src/PnpBridge/PnpAdapterInterface.h +++ b/PnpBridge/src/PnpBridge/PnpAdapterInterface.h @@ -52,18 +52,6 @@ typedef int(*PNPADAPTER_BIND_PNP_INTERFACE)(PNPADAPTER_CONTEXT adapterHandle, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload); -// NOTES TO SELF: - -// -// Config update requires bridge tear down and restart -// - -// Discovered Device -> Bind -> CreatePnpInterfaces -> Create Pnp Interface client -> -// Create Pnp Adapter Interface -> Associate it with the adapter and store the device config pointer -> Get All interface for all adapters -> publish -// - -// *************** - /** * @brief PNPADAPTER_RELEASE_PNP_INTERFACE uninitializes the pnp interface. * diff --git a/PnpBridge/src/PnpBridge/PnpAdapterManager.h b/PnpBridge/src/PnpBridge/PnpAdapterManager.h index 88f04c6..85d69ef 100644 --- a/PnpBridge/src/PnpBridge/PnpAdapterManager.h +++ b/PnpBridge/src/PnpBridge/PnpAdapterManager.h @@ -31,11 +31,17 @@ typedef struct _PNP_ADAPTER_MANAGER { PPNP_ADAPTER_TAG* pnpAdapters; } PNP_ADAPTER_MANAGER, *PPNP_ADAPTER_MANAGER; +typedef enum { + PublishInvalid, + PublishAlways, + PublishOnDeviceFound +} PublishMode; + // Pnp adapter interface structure typedef struct _PNPADAPTER_INTERFACE { void* context; int key; - bool persistent; + PublishMode publishMode; char* interfaceId; PNP_INTERFACE_CLIENT_HANDLE pnpInterfaceClient; PNPADPATER_INTERFACE_INIT_PARAMS params; @@ -70,7 +76,6 @@ void PnpAdapterManager_Release(PPNP_ADAPTER_MANAGER adapter); PNPBRIDGE_RESULT PnpAdapterManager_SupportsIdentity(PPNP_ADAPTER_MANAGER adapter, JSON_Object* Message, bool* supported, int* key); PNPBRIDGE_RESULT PnpAdapterManager_CreatePnpInterface(PPNP_ADAPTER_MANAGER adapter, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, int key, JSON_Object* deviceConfig, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD DeviceChangePayload); -PNPBRIDGE_RESULT PnpAdapterManager_ReleasePnpInterface(PPNP_ADAPTER_MANAGER adapter, PNPADAPTER_INTERFACE_HANDLE Interface); PNPBRIDGE_RESULT PnpAdapterManager_GetAllInterfaces(PPNP_ADAPTER_MANAGER adapterMgr, PNP_INTERFACE_CLIENT_HANDLE** interfaces, int* count); bool PnpAdapterManager_IsInterfaceIdPublished(PPNP_ADAPTER_MANAGER adapterMgr, const char* interfaceId); diff --git a/PnpBridge/src/PnpBridge/PnpAdapterManger.c b/PnpBridge/src/PnpBridge/PnpAdapterManger.c index 46e7ba6..a146528 100644 --- a/PnpBridge/src/PnpBridge/PnpAdapterManger.c +++ b/PnpBridge/src/PnpBridge/PnpAdapterManger.c @@ -32,17 +32,30 @@ PNPBRIDGE_RESULT PnpAdapterManager_ValidatePnpAdapter(PPNP_ADAPTER pnpAdapter, PNPBRIDGE_RESULT PnpAdapterManager_InitializeAdapter(PPNP_ADAPTER_TAG* adapterTag, PPNP_ADAPTER adapter) { PNPBRIDGE_RESULT result = PNPBRIDGE_OK; - PPNP_ADAPTER_TAG adapterT = calloc(1, sizeof(PNP_ADAPTER_TAG)); - if (NULL == adapterT) { + PPNP_ADAPTER_TAG adapterT = NULL; + TRY + { + adapterT = calloc(1, sizeof(PNP_ADAPTER_TAG)); + if (NULL == adapterT) { + result = PNPBRIDGE_INSUFFICIENT_MEMORY; + LEAVE; + } + adapterT->adapter = adapter; + adapterT->pnpInterfaceList = singlylinkedlist_create(); + adapterT->pnpInterfaceListLock = Lock_Init(); + if (NULL == adapterT->pnpInterfaceListLock) { + result = PNPBRIDGE_INSUFFICIENT_MEMORY; + LEAVE; + } + + *adapterTag = adapterT; } - - adapterT->adapter = adapter; - adapterT->pnpInterfaceList = singlylinkedlist_create(); - adapterT->pnpInterfaceListLock = Lock_Init(); - - if (!PNPBRIDGE_SUCCESS(result)) { - PnpAdapterManager_ReleaseAdapter(adapterT); + FINALLY + { + if (!PNPBRIDGE_SUCCESS(result)) { + PnpAdapterManager_ReleaseAdapter(adapterT); + } } return result; @@ -93,10 +106,12 @@ PNPBRIDGE_RESULT PnpAdapterManager_Create(PPNP_ADAPTER_MANAGER* adapterMgr, JSON // Load a list of static modules and build an interface map for (int i = 0; i < PnpAdapterCount; i++) { PPNP_ADAPTER pnpAdapter = PNP_ADAPTER_MANIFEST[i]; - adapter->pnpAdapters[i] = calloc(1, sizeof(PNP_ADAPTER_TAG)); - adapter->pnpAdapters[i]->adapter = pnpAdapter; - adapter->pnpAdapters[i]->pnpInterfaceList = singlylinkedlist_create(); - adapter->pnpAdapters[i]->pnpInterfaceListLock = Lock_Init(); + + result = PnpAdapterManager_InitializeAdapter(&adapter->pnpAdapters[i], pnpAdapter); + if (!PNPBRIDGE_SUCCESS(result)) { + LogError("Failed to initialize PnpAdapter %s", pnpAdapter->identity); + continue; + } if (NULL == pnpAdapter->identity) { LogError("Invalid Identity specified for a PnpAdapter"); @@ -167,7 +182,7 @@ void PnpAdapterManager_Release(PPNP_ADAPTER_MANAGER adapter) { PNPBRIDGE_RESULT PnpAdapterManager_SupportsIdentity(PPNP_ADAPTER_MANAGER adapter, JSON_Object* Message, bool* supported, int* key) { bool containsMessageKey = false; - char* interfaceId = NULL; +// char* interfaceId = NULL; JSON_Object* pnpParams = json_object_get_object(Message, PNP_CONFIG_NAME_PNP_PARAMETERS); char* getIdentity = (char*) json_object_get_string(pnpParams, PNP_CONFIG_IDENTITY_NAME); MAP_RESULT mapResult; @@ -272,20 +287,6 @@ bool PnpAdapterManager_IsInterfaceIdPublished(PPNP_ADAPTER_MANAGER adapterMgr, c return false; } -PNPBRIDGE_RESULT PnpAdapterManager_ReleasePnpInterface(PPNP_ADAPTER_MANAGER adapter, PNPADAPTER_INTERFACE_HANDLE interfaceClient) { - if (NULL == interfaceClient) { - return PNPBRIDGE_INVALID_ARGS; - } - - PPNPADAPTER_INTERFACE pnpInterface = (PPNPADAPTER_INTERFACE)interfaceClient; - - // Get the module index - PPNP_ADAPTER pnpAdapter = PNP_ADAPTER_MANIFEST[pnpInterface->key]; - //pnpAdapter->releaseInterface(interfaceClient); - - return PNPBRIDGE_OK; -} - void PnpAdapterManager_AddInterface(PPNP_ADAPTER_TAG adapter, PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface) { LIST_ITEM_HANDLE handle = NULL; Lock(adapter->pnpInterfaceListLock); diff --git a/PnpBridge/src/PnpBridge/PnpBridge.c b/PnpBridge/src/PnpBridge/PnpBridge.c index 51a0a34..64b47ce 100644 --- a/PnpBridge/src/PnpBridge/PnpBridge.c +++ b/PnpBridge/src/PnpBridge/PnpBridge.c @@ -113,10 +113,12 @@ void PnpBridge_Release(PPNP_BRIDGE pnpBridge) { int PnpBridge_Worker_Thread(void* threadArgument) { + AZURE_UNREFERENCED_PARAMETER(threadArgument); + PNPBRIDGE_RESULT result = PNPBRIDGE_OK; // Publish persistent Pnp Interfaces - result = DiscoveryAdapterManager_NotifyPersistentInterfaces(g_PnpBridge->discoveryMgr, g_PnpBridge->configuration); + result = DiscoveryAdapterManager_PublishAlwaysInterfaces(g_PnpBridge->discoveryMgr, g_PnpBridge->configuration); if (!PNPBRIDGE_SUCCESS(result)) { goto exit; } diff --git a/PnpBridge/src/PnpBridge/PnpBridge.h b/PnpBridge/src/PnpBridge/PnpBridge.h index 8534a2e..cb02bb7 100644 --- a/PnpBridge/src/PnpBridge/PnpBridge.h +++ b/PnpBridge/src/PnpBridge/PnpBridge.h @@ -9,6 +9,43 @@ |_| |___/ */ +// TODO: REMOVE THE COMMENTS +// NOTES TO SELF: + +// +// Config update requires bridge tear down and restart +// + +// +// Discovered Device -> Bind -> CreatePnpInterfaces -> Create Pnp Interface client -> +// Create Pnp Adapter Interface -> Associate it with the adapter and store the device config pointer -> Get All interface for all adapters -> publish +// + +/* + +0. TEST FOR MEMORY LEAKS USING APPVERIFIER + +SerialPnp + 1. Closing serial handle + 2. Test publishing 2 interfaces (multiple) + 3. Test overlapped IO + +PnpBridge + 4. DPS connection & test + 5. FT to create a tear down in a loop *** MOCK the PNP CLIENT SDK + 6. Release PnpInterfaces.. + 7. Persistent device should get callback when device is discovered + +CoreDevice + 7. Enumerate devices + 8. Add properties based on original device schema + +CMAKE + 9. Clean up warnings to get a clean build + +*/ +// *************** + #pragma once #ifdef __cplusplus diff --git a/PnpBridge/src/PnpBridge/PnpBridge.vcxproj b/PnpBridge/src/PnpBridge/PnpBridge.vcxproj index e9ff0ef..e757827 100644 --- a/PnpBridge/src/PnpBridge/PnpBridge.vcxproj +++ b/PnpBridge/src/PnpBridge/PnpBridge.vcxproj @@ -23,7 +23,7 @@ {8756FD40-34AF-4000-AAB9-C2A14E75B23B} Win32Proj PnpBridge - 10.0.17763.0 + 10.0.17642.0 diff --git a/PnpBridge/src/PnpBridge/PnpBridgeCommon.h b/PnpBridge/src/PnpBridge/PnpBridgeCommon.h index dcd8842..95d04bf 100644 --- a/PnpBridge/src/PnpBridge/PnpBridgeCommon.h +++ b/PnpBridge/src/PnpBridge/PnpBridgeCommon.h @@ -67,7 +67,7 @@ int Map_GetIndexValueFromKey(MAP_HANDLE handle, const char* key); #define PNP_CONFIG_IDENTITY_NAME "Identity" #define PNP_CONFIG_NAME_INTERFACE_ID "InterfaceId" -#define PNP_CONFIG_PERSISTENT_NAME "Persistent" +#define PNP_CONFIG_NAME_PUBLISH_MODE "PublishMode" #define PNP_CONFIG_MATCH_FILTERS_NAME "MatchFilters" #define PNP_CONFIG_MATCH_TYPE_NAME "MatchType" #define PNP_CONFIG_NAME_MATCH_PARAMETERS "MatchParameters" diff --git a/PnpBridge/src/PnpBridge/config.json b/PnpBridge/src/PnpBridge/config.json index b791063..a9280a5 100644 --- a/PnpBridge/src/PnpBridge/config.json +++ b/PnpBridge/src/PnpBridge/config.json @@ -26,7 +26,7 @@ "HardwareId": "USB\\VID_07DE&PID_11F3" } }, - "Persistent" : "true", + "PublishMode" : "Always", "InterfaceId": "http://windows.com/coredevicehealth/v1", "PnpParameters": { "Identity": "core-device-health" diff --git a/PnpBridge/src/PnpBridge/core/PnpBridgeMemory.h b/PnpBridge/src/PnpBridge/core/PnpBridgeMemory.h index cccae04..a122507 100644 --- a/PnpBridge/src/PnpBridge/core/PnpBridgeMemory.h +++ b/PnpBridge/src/PnpBridge/core/PnpBridgeMemory.h @@ -18,7 +18,7 @@ extern "C" } PNPBRIDGE_MEMORY_PARAMS, *PPNPBRIDGE_OBJECT_PARAMS; typedef struct _PNPBRIDGE_MEMORY_TAG { - int count; + volatile long count; int size; void* memory; PNPBRIDGE_MEMORY_PARAMS params; diff --git a/PnpBridge/src/tests/CMakeLists.txt b/PnpBridge/src/tests/CMakeLists.txt new file mode 100644 index 0000000..5422b7b --- /dev/null +++ b/PnpBridge/src/tests/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.11) + +add_subdirectory(pnp_adapter_manager) \ No newline at end of file diff --git a/PnpBridge/src/tests/pnp_adapter_manager/CMakeLists.txt b/PnpBridge/src/tests/pnp_adapter_manager/CMakeLists.txt new file mode 100644 index 0000000..f38e84a --- /dev/null +++ b/PnpBridge/src/tests/pnp_adapter_manager/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 2.8.11) + +add_subdirectory(PnpBridge) +add_subdirectory(tests) \ No newline at end of file diff --git a/PnpBridge/src/tests/pnp_adapter_manager/main.c b/PnpBridge/src/tests/pnp_adapter_manager/main.c new file mode 100644 index 0000000..36b98aa --- /dev/null +++ b/PnpBridge/src/tests/pnp_adapter_manager/main.c @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#include "testrunnerswitcher.h" + +int main(void) +{ + size_t failedTestCount = 0; + RUN_TEST_SUITE(lock_thread_binding_stub_ut, failedTestCount); + return failedTestCount; +} \ No newline at end of file diff --git a/PnpBridge/src/tests/pnp_adapter_manager/pnp_adapter_manager_ut.c b/PnpBridge/src/tests/pnp_adapter_manager/pnp_adapter_manager_ut.c new file mode 100644 index 0000000..710171d --- /dev/null +++ b/PnpBridge/src/tests/pnp_adapter_manager/pnp_adapter_manager_ut.c @@ -0,0 +1,105 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#ifdef __cplusplus +#include +#include +#include +#else +#include +#include +#include +#endif + +#include "testrunnerswitcher.h" +#include "umock_c.h" + + +static const int PNP_TEST_MILLISECONDS = 0x1234; + +#include "internal/lock_thread_binding_stub.h" + +static void on_umock_c_error(UMOCK_C_ERROR_CODE error_code) +{ + char temp_str[256]; + (void)snprintf(temp_str, sizeof(temp_str), "umock_c reported error :%s", ENUM_TO_STRING(UMOCK_C_ERROR_CODE, error_code)); + ASSERT_FAIL(temp_str); +} +DEFINE_ENUM_STRINGS(UMOCK_C_ERROR_CODE, UMOCK_C_ERROR_CODE_VALUES) + +TEST_DEFINE_ENUM_TYPE(LOCK_RESULT, LOCK_RESULT_VALUES); +IMPLEMENT_UMOCK_C_ENUM_TYPE(LOCK_RESULT, LOCK_RESULT_VALUES); + +BEGIN_TEST_SUITE(lock_thread_binding_stub_ut) + +TEST_SUITE_INITIALIZE(suite_init) +{ + int result; + + result = umock_c_init(on_umock_c_error); + ASSERT_ARE_EQUAL(int, 0, result); + + REGISTER_UMOCK_ALIAS_TYPE(LOCK_HANDLE, void*); + REGISTER_UMOCK_ALIAS_TYPE(LOCK_RESULT, int); +} + +TEST_FUNCTION_INITIALIZE(TestMethodInit) +{ + umock_c_reset_all_calls(); +} + +TEST_FUNCTION_CLEANUP(TestMethodCleanup) +{ + ; +} + +TEST_FUNCTION(LockBinding_LockInit_Stub_ok) +{ + //act + LOCK_HANDLE h = LockBinding_LockInit_Stub(); + + //assert + ASSERT_IS_NOT_NULL(h); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); +} + +TEST_FUNCTION(LockBinding_Lock_Stub_ok) +{ + //act + LOCK_RESULT lockResult = LockBinding_Lock_Stub(NULL); + + //assert + ASSERT_ARE_EQUAL(LOCK_RESULT, lockResult, LOCK_OK); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); +} + +TEST_FUNCTION(LockBinding_Unlock_Stub_ok) +{ + //act + LOCK_RESULT lockResult = LockBinding_Unlock_Stub(NULL); + + //assert + ASSERT_ARE_EQUAL(LOCK_RESULT, lockResult, LOCK_OK); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); +} + +TEST_FUNCTION(LockBinding_LockDeinit_Stub_ok) +{ + //act + LOCK_RESULT lockResult = LockBinding_LockDeinit_Stub(NULL); + + //assert + ASSERT_ARE_EQUAL(LOCK_RESULT, lockResult, LOCK_OK); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); +} + +TEST_FUNCTION(ThreadBinding_ThreadSleep_Stub_ok) +{ + //act + ThreadBinding_ThreadSleep_Stub(PNP_TEST_MILLISECONDS); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); +} + +END_TEST_SUITE(lock_thread_binding_stub_ut) From ed271f86548273b11e6e2b532adce35bbc0b6e10 Mon Sep 17 00:00:00 2001 From: Ajay Barboza Date: Thu, 14 Feb 2019 09:56:32 -0800 Subject: [PATCH 6/7] cleanup --- .../src/PnpBridge/Adapters/AdapterManifest.c | 6 +- .../Adapters/Camera/CameraIotPnpAPIs.cpp | 17 +- .../Adapters/Camera/CameraPnpDiscovery.cpp | 6 +- .../PnpBridge/Adapters/Camera/JsonWrapper.cpp | 66 +++-- .../PnpBridge/Adapters/Camera/JsonWrapper.h | 3 +- .../CoreDeviceHealth/CoreDeviceHealth.c | 89 ++++--- .../CoreDeviceHealth/CoreDeviceHealth.h | 6 + .../WindowsPnPDeviceDiscovery.c | 25 +- .../PnpBridge/Adapters/SerialPnp/SerialPnp.c | 2 +- PnpBridge/src/PnpBridge/ConfigurationParser.c | 101 ++++---- PnpBridge/src/PnpBridge/PnpAdapterManager.h | 4 +- PnpBridge/src/PnpBridge/PnpAdapterManger.c | 72 ++++-- PnpBridge/src/PnpBridge/PnpBridge.c | 233 ++++++++++-------- PnpBridge/src/PnpBridge/PnpBridge.h | 5 +- PnpBridge/src/PnpBridge/PnpBridge.vcxproj | 2 +- PnpBridge/src/PnpBridge/PnpBridgeh.h | 2 + PnpBridge/src/PnpBridge/config.json | 34 +-- .../src/PnpBridge/core/PnpAdapterInterface.c | 31 +-- 18 files changed, 389 insertions(+), 315 deletions(-) diff --git a/PnpBridge/src/PnpBridge/Adapters/AdapterManifest.c b/PnpBridge/src/PnpBridge/Adapters/AdapterManifest.c index b311d8d..4a1b24e 100644 --- a/PnpBridge/src/PnpBridge/Adapters/AdapterManifest.c +++ b/PnpBridge/src/PnpBridge/Adapters/AdapterManifest.c @@ -10,7 +10,8 @@ extern DISCOVERY_ADAPTER WindowsPnpDeviceDiscovery; PDISCOVERY_ADAPTER DISCOVERY_ADAPTER_MANIFEST[] = { &CameraPnpAdapter, - &SerialPnpDiscovery + &SerialPnpDiscovery, + &WindowsPnpDeviceDiscovery }; const int DiscoveryAdapterCount = sizeof(DISCOVERY_ADAPTER_MANIFEST) / sizeof(PDISCOVERY_ADAPTER); @@ -21,7 +22,8 @@ extern PNP_ADAPTER SerialPnpInterface; PPNP_ADAPTER PNP_ADAPTER_MANIFEST[] = { &CameraPnpInterface, - &SerialPnpInterface + &SerialPnpInterface, + &CoreDeviceHealthInterface }; const int PnpAdapterCount = sizeof(PNP_ADAPTER_MANIFEST) / sizeof(PPNP_ADAPTER); diff --git a/PnpBridge/src/PnpBridge/Adapters/Camera/CameraIotPnpAPIs.cpp b/PnpBridge/src/PnpBridge/Adapters/Camera/CameraIotPnpAPIs.cpp index 1e343cc..4998e8f 100644 --- a/PnpBridge/src/PnpBridge/Adapters/Camera/CameraIotPnpAPIs.cpp +++ b/PnpBridge/src/PnpBridge/Adapters/Camera/CameraIotPnpAPIs.cpp @@ -13,7 +13,6 @@ PNP_ADAPTER CameraPnpInterface = { CameraPnpInterfaceBind, CameraPnpInterfaceShutdown }; -// CameraPnpInterfaceRelease, // Camera discovery API entry points. CameraPnpDiscovery* g_pPnpDiscovery = nullptr; @@ -87,9 +86,9 @@ CameraPnpInterfaceBind( JSON_Value* jmsg; JSON_Object* jobj; - PNPADAPTER_INTERFACE_HANDLE Interface = NULL; + PNPADAPTER_INTERFACE_HANDLE adapterInterface = nullptr; - if (nullptr == Interface || nullptr == payload || nullptr == payload->Context) + if (nullptr == payload || nullptr == payload->Context) { return E_INVALIDARG; } @@ -104,13 +103,17 @@ CameraPnpInterfaceBind( pnpInterfaceClient = PnP_InterfaceClient_Create(pnpDeviceClientHandle, interfaceId, nullptr, nullptr, nullptr); RETURN_HR_IF_NULL (E_UNEXPECTED, pnpInterfaceClient); - //PnpAdapter_SetPnpInterfaceClient(Interface, pnpInterfaceClient); + // Create PnpAdapter Interface + PNPADPATER_INTERFACE_INIT_PARAMS interfaceParams = { 0 }; + interfaceParams.releaseInterface = CameraPnpInterfaceRelease; + + RETURN_HR_IF (E_UNEXPECTED, 0 != PnpAdapterInterface_Create(adapterHandle, interfaceId, pnpInterfaceClient, &adapterInterface, &interfaceParams)) pIotPnp = std::make_unique(); - RETURN_IF_FAILED (pIotPnp->Initialize(PnpAdapterInterface_GetPnpInterfaceClient(Interface), nullptr /* cameraName.c_str() */)); + RETURN_IF_FAILED (pIotPnp->Initialize(PnpAdapterInterface_GetPnpInterfaceClient(adapterInterface), nullptr /* cameraName.c_str() */)); RETURN_IF_FAILED (pIotPnp->StartTelemetryWorker()); - RETURN_HR_IF (E_UNEXPECTED, 0 != PnpAdapterInterface_SetContext(Interface, (void*)pIotPnp.get())); + RETURN_HR_IF (E_UNEXPECTED, 0 != PnpAdapterInterface_SetContext(adapterInterface, (void*)pIotPnp.get())); // Our interface context now owns the object. pIotPnp.release(); @@ -138,6 +141,8 @@ CameraPnpInterfaceRelease( // object around. (void) PnpAdapterInterface_SetContext(Interface, nullptr); + PnpAdapterInterface_Destroy(Interface); + return S_OK; } diff --git a/PnpBridge/src/PnpBridge/Adapters/Camera/CameraPnpDiscovery.cpp b/PnpBridge/src/PnpBridge/Adapters/Camera/CameraPnpDiscovery.cpp index c94da4b..a1918a0 100644 --- a/PnpBridge/src/PnpBridge/Adapters/Camera/CameraPnpDiscovery.cpp +++ b/PnpBridge/src/PnpBridge/Adapters/Camera/CameraPnpDiscovery.cpp @@ -82,10 +82,13 @@ CameraPnpDiscovery::InitializePnpDiscovery( { PNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload = { }; std::unique_ptr pjson = std::make_unique(); + std::unique_ptr pmatchjson = std::make_unique(); RETURN_IF_FAILED (pjson->Initialize()); RETURN_IF_FAILED (pjson->AddFormatString("Identity", "camera-health-monitor")); - RETURN_IF_FAILED (pjson->AddFormatString("HardwareId", "UVC_Webcam_00")); + RETURN_IF_FAILED (pmatchjson->Initialize()); + RETURN_IF_FAILED (pmatchjson->AddFormatString("HardwareId", "UVC_Webcam_00")); + RETURN_IF_FAILED (pjson->AddObject("MatchParameters", pmatchjson->GetMessageW())); payload.Message = pjson->GetMessageW(); payload.MessageLength = static_cast(pjson->GetSize()); @@ -96,6 +99,7 @@ CameraPnpDiscovery::InitializePnpDiscovery( pfnCallback(&payload); // $$LEAKLEAK!!! + pmatchjson->Detach(); pjson->Detach(); } diff --git a/PnpBridge/src/PnpBridge/Adapters/Camera/JsonWrapper.cpp b/PnpBridge/src/PnpBridge/Adapters/Camera/JsonWrapper.cpp index 3744462..734c3f3 100644 --- a/PnpBridge/src/PnpBridge/Adapters/Camera/JsonWrapper.cpp +++ b/PnpBridge/src/PnpBridge/Adapters/Camera/JsonWrapper.cpp @@ -54,33 +54,33 @@ JsonWrapper::AddValueAsString( char sz[MAX_32BIT_DECIMAL_DIGIT] = { }; RETURN_HR_IF_NULL (E_INVALIDARG, m_object); - RETURN_HR_IF_NULL (E_INVALIDARG, name); +RETURN_HR_IF_NULL(E_INVALIDARG, name); - RETURN_IF_FAILED (StringCchPrintfA(sz, _countof(sz), "%u", val)); +RETURN_IF_FAILED(StringCchPrintfA(sz, _countof(sz), "%u", val)); - // json_object_set_string returns 0 on success and -1 on - // failure. Failure for this can be either via invalid - // arg (i.e., JSON_Object is invalid) or we ran out of - // memory. We'll assume, since this is only called by our - // object and the methods are protected, that the parameters - // are valid. So only failure would be E_OUTOFMEMORY. - RETURN_HR_IF (E_OUTOFMEMORY, JSONFailure == json_object_set_string(m_object, name, sz)); +// json_object_set_string returns 0 on success and -1 on +// failure. Failure for this can be either via invalid +// arg (i.e., JSON_Object is invalid) or we ran out of +// memory. We'll assume, since this is only called by our +// object and the methods are protected, that the parameters +// are valid. So only failure would be E_OUTOFMEMORY. +RETURN_HR_IF(E_OUTOFMEMORY, JSONFailure == json_object_set_string(m_object, name, sz)); - return S_OK; +return S_OK; } HRESULT JsonWrapper::AddValueAsString( _In_z_ LPCSTR name, _In_ LONGLONG val - ) +) { char sz[MAX_64BIT_DECIMAL_DIGIT] = { }; - RETURN_HR_IF_NULL (E_INVALIDARG, m_object); - RETURN_HR_IF_NULL (E_INVALIDARG, name); + RETURN_HR_IF_NULL(E_INVALIDARG, m_object); + RETURN_HR_IF_NULL(E_INVALIDARG, name); - RETURN_IF_FAILED (StringCchPrintfA(sz, _countof(sz), "%I64d", val)); + RETURN_IF_FAILED(StringCchPrintfA(sz, _countof(sz), "%I64d", val)); // json_object_set_string returns 0 on success and -1 on // failure. Failure for this can be either via invalid @@ -88,7 +88,7 @@ JsonWrapper::AddValueAsString( // memory. We'll assume, since this is only called by our // object and the methods are protected, that the parameters // are valid. So only failure would be E_OUTOFMEMORY. - RETURN_HR_IF (E_OUTOFMEMORY, JSONFailure == json_object_set_string(m_object, name, sz)); + RETURN_HR_IF(E_OUTOFMEMORY, JSONFailure == json_object_set_string(m_object, name, sz)); return S_OK; } @@ -97,13 +97,13 @@ HRESULT JsonWrapper::AddValueAsString( _In_z_ LPCSTR name, _In_ double val - ) +) { HRESULT hr = S_OK; char sz[MAX_64BIT_DECIMAL_DIGIT] = { }; - RETURN_HR_IF_NULL (E_INVALIDARG, m_object); - RETURN_HR_IF_NULL (E_INVALIDARG, name); + RETURN_HR_IF_NULL(E_INVALIDARG, m_object); + RETURN_HR_IF_NULL(E_INVALIDARG, name); hr = StringCchPrintfA(sz, _countof(sz), "%.3f", val); if (hr == S_OK || hr == STRSAFE_E_INSUFFICIENT_BUFFER) @@ -112,7 +112,7 @@ JsonWrapper::AddValueAsString( // we truncated the string, assume we're fine. hr = S_OK; } - RETURN_IF_FAILED (hr); + RETURN_IF_FAILED(hr); // json_object_set_string returns 0 on success and -1 on // failure. Failure for this can be either via invalid @@ -120,7 +120,7 @@ JsonWrapper::AddValueAsString( // memory. We'll assume, since this is only called by our // object and the methods are protected, that the parameters // are valid. So only failure would be E_OUTOFMEMORY. - RETURN_HR_IF (E_OUTOFMEMORY, JSONFailure == json_object_set_string(m_object, name, sz)); + RETURN_HR_IF(E_OUTOFMEMORY, JSONFailure == json_object_set_string(m_object, name, sz)); return S_OK; } @@ -129,14 +129,14 @@ HRESULT JsonWrapper::AddHresultAsString( _In_z_ LPCSTR name, _In_ HRESULT hr - ) +) { char sz[MAX_32BIT_HEX_DIGIT] = { }; - RETURN_HR_IF_NULL (E_INVALIDARG, m_object); - RETURN_HR_IF_NULL (E_INVALIDARG, name); + RETURN_HR_IF_NULL(E_INVALIDARG, m_object); + RETURN_HR_IF_NULL(E_INVALIDARG, name); - RETURN_IF_FAILED (StringCchPrintfA(sz, _countof(sz), "0x%08X", hr)); + RETURN_IF_FAILED(StringCchPrintfA(sz, _countof(sz), "0x%08X", hr)); // json_object_set_string returns 0 on success and -1 on // failure. Failure for this can be either via invalid @@ -144,7 +144,23 @@ JsonWrapper::AddHresultAsString( // memory. We'll assume, since this is only called by our // object and the methods are protected, that the parameters // are valid. So only failure would be E_OUTOFMEMORY. - RETURN_HR_IF (E_OUTOFMEMORY, JSONFailure == json_object_set_string(m_object, name, sz)); + RETURN_HR_IF(E_OUTOFMEMORY, JSONFailure == json_object_set_string(m_object, name, sz)); + + return S_OK; +} + +HRESULT +JsonWrapper::AddObject( + _In_z_ LPCSTR name, + _In_z_ LPCSTR object + ) +{ + RETURN_HR_IF_NULL(E_INVALIDARG, m_object); + RETURN_HR_IF_NULL(E_INVALIDARG, name); + RETURN_HR_IF_NULL(E_INVALIDARG, object); + + JSON_Value* value = json_parse_string(object); + RETURN_HR_IF(E_OUTOFMEMORY, JSONFailure == json_object_set_value(m_object, name, value)); return S_OK; } diff --git a/PnpBridge/src/PnpBridge/Adapters/Camera/JsonWrapper.h b/PnpBridge/src/PnpBridge/Adapters/Camera/JsonWrapper.h index 42d3cf6..3046459 100644 --- a/PnpBridge/src/PnpBridge/Adapters/Camera/JsonWrapper.h +++ b/PnpBridge/src/PnpBridge/Adapters/Camera/JsonWrapper.h @@ -19,8 +19,7 @@ public: HRESULT AddValueAsString(_In_z_ LPCSTR name, _In_ LONGLONG val); HRESULT AddValueAsString(_In_z_ LPCSTR name, _In_ double val); HRESULT AddHresultAsString(_In_z_ LPCSTR name, _In_ HRESULT hr); - HRESULT AddValue(_In_z_ LPCSTR name, _In_z_ LPCWSTR val); - HRESULT AddValue(_In_z_ LPCSTR name, _In_z_ LPCSTR val); + HRESULT AddObject(_In_z_ LPCSTR name, _In_z_ LPCSTR object); HRESULT AddFormatString(_In_z_ LPCSTR name, _In_z_ LPCSTR format, ...); size_t GetSize(); const char* GetMessage(); diff --git a/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.c b/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.c index ae7bdca..8f17581 100644 --- a/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.c +++ b/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.c @@ -17,14 +17,14 @@ #include "parson.h" -PNP_INTERFACE_CLIENT_HANDLE pnpinterfaceHandle = NULL; +#include "adapters/CoreDeviceHealth/CoreDeviceHealth.h" void WindowsPnpSendEventCallback(PNP_SEND_TELEMETRY_STATUS pnpSendEventStatus, void* userContextCallback) { LogInfo("WindowsPnpSendEventCallback called, result=%d, userContextCallback=%p", pnpSendEventStatus, userContextCallback); } -int Sample_SendEventAsync(char* eventName, char* data) +int Sample_SendEventAsync(PNP_INTERFACE_CLIENT_HANDLE pnpinterfaceHandle, char* eventName, char* data) { int result; PNP_CLIENT_RESULT pnpClientResult; @@ -49,9 +49,6 @@ int Sample_SendEventAsync(char* eventName, char* data) return result; } -volatile bool state = false; -SINGLYLINKEDLIST_HANDLE g_coreDeviceWatchers = NULL; - DWORD __stdcall CoreDevice_OnDeviceNotification( @@ -61,23 +58,23 @@ CoreDevice_OnDeviceNotification( _In_reads_bytes_(eventDataSize) PCM_NOTIFY_EVENT_DATA eventData, _In_ DWORD eventDataSize) { - char* deviceSymbolicLink = context; + PCORE_DEVICE_TAG device = context; char buff[512]; sprintf_s(buff, 512, "%S", eventData->u.DeviceInterface.SymbolicLink); if (action == CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL) { - if (state && strcmp(buff, deviceSymbolicLink) == 0) { - state = false; + if (device->state && strcmp(buff, device->symbolicLink) == 0) { + device->state = false; LogInfo("device removed %S", eventData->u.DeviceInterface.SymbolicLink); - Sample_SendEventAsync("DeviceStatus", "Disconnected"); + Sample_SendEventAsync(device->pnpinterfaceHandle, "DeviceStatus", "Disconnected"); } } else if (action == CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL) { - if (!state && strcmp(buff, deviceSymbolicLink) == 0) { - state = true; + if (!device->state && strcmp(buff, device->symbolicLink) == 0) { + device->state = true; LogInfo("device connected %S", eventData->u.DeviceInterface.SymbolicLink); - Sample_SendEventAsync("DeviceStatus", "Connected"); + Sample_SendEventAsync(device->pnpinterfaceHandle, "DeviceStatus", "Connected"); } } return 0; @@ -85,11 +82,20 @@ CoreDevice_OnDeviceNotification( int CoreDevice_ReleaseInterface(PNPADAPTER_INTERFACE_HANDLE pnpInterface) { + PCORE_DEVICE_TAG device = PnpAdapterInterface_GetContext(pnpInterface); + + if (NULL != device) { + if (NULL != device->hNotifyCtx) { + CM_Unregister_Notification(device->hNotifyCtx); + } + if (NULL != device->symbolicLink) { + free(device->symbolicLink); + } + free(device); + } return 0; } -HCMNOTIFICATION CoreDevice_hNotifyCtx = NULL; - int CoreDevice_CreatePnpInterface(PNPADAPTER_CONTEXT adapterHandle, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD param) { DWORD cmRet; CM_NOTIFY_FILTER cmFilter; @@ -97,14 +103,23 @@ int CoreDevice_CreatePnpInterface(PNPADAPTER_CONTEXT adapterHandle, PNP_DEVICE_C JSON_Value* jvalue = json_parse_string(param->Message); JSON_Object* jmsg = json_value_get_object(jvalue); JSON_Object* args = jmsg; + PCORE_DEVICE_TAG device = NULL; const char* interfaceId = json_object_get_string(args, "InterfaceId"); const char* hardwareId = json_object_get_string(args, "HardwareId"); const char* symbolicLink = json_object_get_string(args, "SymbolicLink"); const char* publishMode = json_object_get_string(args, "PublishMode"); + int result = 0; + + device = calloc(1, sizeof(CORE_DEVICE_TAG)); + if (NULL != device) { + result = -1; + goto end; + } pnpInterfaceClient = PnP_InterfaceClient_Create(pnpDeviceClientHandle, interfaceId, NULL, NULL, NULL); if (NULL == pnpInterfaceClient) { - return -1; + result = -1; + goto end; } // Create PnpAdapter Interface @@ -115,14 +130,20 @@ int CoreDevice_CreatePnpInterface(PNPADAPTER_CONTEXT adapterHandle, PNP_DEVICE_C int result = PnpAdapterInterface_Create(adapterHandle, interfaceId, pnpInterfaceClient, &pnpAdapterInterface, &interfaceParams); if (result < 0) { - return result; + goto end; } + PnpAdapterInterface_SetContext(pnpAdapterInterface, device); } - if (NULL != publishMode && stricmp(publishMode, "true") == 0) { - return 0; + // Don't bind the interface for publishMode always. There will be a device + // arrived notification from the discovery adapter. + if (NULL != publishMode && stricmp(publishMode, "always") == 0) { + goto end; } + device->symbolicLink = malloc(strlen(symbolicLink)+1); + strcpy_s(device->symbolicLink, strlen(symbolicLink) + 1, symbolicLink); + ZeroMemory(&cmFilter, sizeof(cmFilter)); cmFilter.cbSize = sizeof(cmFilter); cmFilter.Flags = 0; @@ -131,20 +152,29 @@ int CoreDevice_CreatePnpInterface(PNPADAPTER_CONTEXT adapterHandle, PNP_DEVICE_C cmRet = CM_Register_Notification( &cmFilter, - (void*)symbolicLink, + (void*)device, CoreDevice_OnDeviceNotification, - &CoreDevice_hNotifyCtx + &device->hNotifyCtx ); if (cmRet != CR_SUCCESS) { - return -1; + result = -1; + goto end; } - pnpinterfaceHandle = pnpInterfaceClient; - state = true; - - Sample_SendEventAsync("DeviceStatus", "Connected"); + device->pnpinterfaceHandle = pnpInterfaceClient; + device->state = true; + Sample_SendEventAsync(device->pnpinterfaceHandle, "DeviceStatus", "Connected"); +end: + if (result < 0) { + if (NULL != device) { + if (NULL != device->symbolicLink) { + free(device->symbolicLink); + } + free(device); + } + } return 0; } @@ -198,18 +228,10 @@ int SendDeviceDisconnectedEventAsync(PNP_INTERFACE_CLIENT_HANDLE pnpInterfaceCor } int CoreDevice_Initialize(const char* adapterArgs) { - g_coreDeviceWatchers = singlylinkedlist_create(); - if (NULL == g_coreDeviceWatchers) { - return -1; - } - return 0; } int CoreDevice_Shutdown() { - if (NULL != g_coreDeviceWatchers) { - singlylinkedlist_destroy(g_coreDeviceWatchers); - } return 0; } @@ -218,5 +240,4 @@ PNP_ADAPTER CoreDeviceHealthInterface = { .initialize = CoreDevice_Initialize, .shutdown = CoreDevice_Shutdown, .createPnpInterface = CoreDevice_CreatePnpInterface, - //.releaseInterface = CoreDevice_ReleaseInterface, }; \ No newline at end of file diff --git a/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.h b/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.h index 5b1adab..e66a159 100644 --- a/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.h +++ b/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.h @@ -8,6 +8,12 @@ extern "C" { #endif +typedef struct _CORE_DEVICE_TAG { + PNP_INTERFACE_CLIENT_HANDLE pnpinterfaceHandle; + HCMNOTIFICATION hNotifyCtx; + char* symbolicLink; + volatile bool state; +} CORE_DEVICE_TAG, *PCORE_DEVICE_TAG; #ifdef __cplusplus } diff --git a/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/WindowsPnPDeviceDiscovery.c b/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/WindowsPnPDeviceDiscovery.c index 951f78a..d506e63 100644 --- a/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/WindowsPnPDeviceDiscovery.c +++ b/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/WindowsPnPDeviceDiscovery.c @@ -52,8 +52,6 @@ OnDeviceNotification( LPWSTR SingleDeviceId; int msgLen = 512; STRING_HANDLE asJson; - // JSON_Value* json; - // JSON_Object* jsonObject; payload.ChangeType = PNPBRIDGE_INTERFACE_CHANGE_ARRIVAL; @@ -111,9 +109,6 @@ OnDeviceNotification( STRING_HANDLE asJson1 = STRING_new_JSON(msg1); sprintf_s(msg, msgLen, deviceChangeMessageformat, STRING_c_str(asJson), STRING_c_str(asJson1)); - // json = json_parse_string(msg); - // jsonObject = json_value_get_object(json); - payload.Message = msg; payload.Context = malloc(sizeof(eventData->u.DeviceInterface.ClassGuid)); @@ -131,21 +126,23 @@ int WindowsPnp_StartDiscovery(PNPBRIDGE_NOTIFY_DEVICE_CHANGE DeviceChangeCallbac DWORD cmRet; CM_NOTIFY_FILTER cmFilter; HCMNOTIFICATION hNotifyCtx = NULL; + JSON_Value* jmsg; + JSON_Object* jobj; g_deviceWatchers = singlylinkedlist_create(); if (NULL == g_deviceWatchers) { return -1; } - JSON_Value* jmsg; - JSON_Object* jobj; jmsg = json_parse_string(adapterArgs); jobj = json_value_get_object(jmsg); JSON_Array* interfaceClasses = json_object_dotget_array(jobj, "DeviceInterfaceClasses"); + DeviceChangeHandler = DeviceChangeCallback; + for (int j = 0; j < (int)json_array_get_count(interfaceClasses); j++) { + GUID guid = { 0 }; const char *interfaceClass = json_array_get_string(interfaceClasses, j); - GUID guid; if (UuidFromStringA((char *)interfaceClass, &guid) != RPC_S_OK) { return -1; } @@ -156,10 +153,10 @@ int WindowsPnp_StartDiscovery(PNPBRIDGE_NOTIFY_DEVICE_CHANGE DeviceChangeCallbac cmFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE; cmFilter.u.DeviceInterface.ClassGuid = guid; cmRet = CM_Register_Notification( - &cmFilter, // PCM_NOTIFY_FILTER pFilter, - NULL, // PVOID pContext, - (PCM_NOTIFY_CALLBACK)OnDeviceNotification, // PCM_NOTIFY_CALLBACK pCallback, - &hNotifyCtx // PHCMNOTIFICATION pNotifyContext + &cmFilter, + NULL, + (PCM_NOTIFY_CALLBACK)OnDeviceNotification, + &hNotifyCtx ); if (cmRet != CR_SUCCESS) { @@ -168,10 +165,6 @@ int WindowsPnp_StartDiscovery(PNPBRIDGE_NOTIFY_DEVICE_CHANGE DeviceChangeCallbac singlylinkedlist_add(g_deviceWatchers, hNotifyCtx); } - DeviceChangeHandler = DeviceChangeCallback; - - //EnumerateDevices() - return 0; } diff --git a/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.c b/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.c index 8158864..9cd3128 100644 --- a/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.c +++ b/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.c @@ -1246,7 +1246,7 @@ int SerialPnp_ReleasePnpInterface(PNPADAPTER_INTERFACE_HANDLE pnpInterface) { } int SerialPnp_Initialize(const char* adapterArgs) { - AZURE_UNREFERENCED_PARAMETER(adapterArgs); +// AZURE_UNREFERENCED_PARAMETER(adapterArgs); return 0; } diff --git a/PnpBridge/src/PnpBridge/ConfigurationParser.c b/PnpBridge/src/PnpBridge/ConfigurationParser.c index b658847..fd75465 100644 --- a/PnpBridge/src/PnpBridge/ConfigurationParser.c +++ b/PnpBridge/src/PnpBridge/ConfigurationParser.c @@ -37,6 +37,11 @@ PNPBRIDGE_RESULT PnpBridgeConfig_ValidateConfiguration(JSON_Value* config) { LogError("A device is missing InterfaceId"); } } + else { + if (NULL != interfaceId) { + LogError("A self describing device shouldn't have interface id"); + } + } } // PnpParameters @@ -176,79 +181,71 @@ PNPBRIDGE_RESULT Configuration_IsDeviceConfigured(JSON_Value* config, JSON_Objec JSON_Array *devices = Configuration_GetConfiguredDevices(config); JSON_Object* discMatchParams; char* pnpAdapterIdentity = NULL; - int res = -1; - bool foundMatch = false; + PNPBRIDGE_RESULT result = PNPBRIDGE_OK; -// const char* formatId = json_object_dotget_string(Message, "Identity"); - discMatchParams = json_object_get_object(Message, PNP_CONFIG_NAME_MATCH_PARAMETERS); + *Device = NULL; - // There needs to be only one match at the end. - for (int i = 0; i < (int)json_array_get_count(devices); i++) { - JSON_Object *device = json_array_get_object(devices, i); - JSON_Object* moduleParams = Configuration_GetPnpParametersForDevice(device); - if (NULL == moduleParams) { - continue; - } - -// const char* deviceFormatId = json_object_dotget_string(moduleParams, "Identity"); - if (true) { //strcmp(deviceFormatId, formatId) == 0) { - JSON_Object* matchCriteria = json_object_dotget_object(device, PNP_CONFIG_MATCH_FILTERS_NAME); - const char* matchType = json_object_get_string(matchCriteria, PNP_CONFIG_MATCH_TYPE_NAME); - const char* currPnpAdapterId = json_object_get_string(moduleParams, PNP_CONFIG_IDENTITY_NAME); - if (strcmp(matchType, "*") == 0) { - if (true == foundMatch) { - if (0 == stricmp(pnpAdapterIdentity, currPnpAdapterId)) { - LogError("Found multiple devices in the config that match the filter"); - res = -1; - goto end; - } - } - else { - foundMatch = true; - pnpAdapterIdentity = (char*) currPnpAdapterId; - res = 0; - *Device = device; - } + TRY + { + discMatchParams = json_object_get_object(Message, PNP_CONFIG_NAME_MATCH_PARAMETERS); + for (int i = 0; i < (int)json_array_get_count(devices); i++) { + JSON_Object* device = json_array_get_object(devices, i); + JSON_Object* pnpParams = Configuration_GetPnpParametersForDevice(device); + if (NULL == pnpParams) { continue; } + JSON_Object* matchCriteria = json_object_dotget_object(device, PNP_CONFIG_MATCH_FILTERS_NAME); + const char* matchType = json_object_get_string(matchCriteria, PNP_CONFIG_MATCH_TYPE_NAME); + const char* currPnpAdapterId = json_object_get_string(pnpParams, PNP_CONFIG_IDENTITY_NAME); + bool exactMatch = stricmp(matchType, "exact") == 0; + if (NULL == discMatchParams) { continue; } JSON_Object* matchParameters = json_object_dotget_object(matchCriteria, PNP_CONFIG_NAME_MATCH_PARAMETERS); const size_t matchParameterCount = json_object_get_count(matchParameters); + bool foundMatch = false; for (int j = 0; j < (int)matchParameterCount; j++) { const char* name = json_object_get_name(matchParameters, j); - const char* value = json_object_get_string(matchParameters, name); + const char* value1 = json_object_get_string(matchParameters, name); if (!json_object_dothas_value(discMatchParams, name)) { - res = -1; - goto end; + break; } const char* value2 = json_object_get_string(discMatchParams, name); - if (strstr(value2, value) != 0) { - if (true == foundMatch) { - if (0 == stricmp(pnpAdapterIdentity, currPnpAdapterId)) { - LogError("Found multiple devices in the config that match the filter"); - res = -1; - goto end; - } - } - else { - const char* interfaceId = json_object_dotget_string(device, PNP_CONFIG_NAME_INTERFACE_ID); - json_object_set_string(Message, PNP_CONFIG_NAME_INTERFACE_ID, interfaceId); - foundMatch = true; - pnpAdapterIdentity = (char*) currPnpAdapterId; - *Device = device; - res = 0; - } + bool match; + if (exactMatch) { + match = 0 != strstr(value2, value1); } + else { + match = 0 == stricmp(value2, value1); + } + if (false == match) { + foundMatch = false; + break; + } + else { + foundMatch = true; + } + } + + if (foundMatch) { + pnpAdapterIdentity = (char*)currPnpAdapterId; + *Device = device; + result = PNPBRIDGE_OK; + LEAVE; } } } + FINALLY + { + if (NULL == *Device) { + result = PNPBRIDGE_INVALID_ARGS; + } + } -end: - return res; + return result; } \ No newline at end of file diff --git a/PnpBridge/src/PnpBridge/PnpAdapterManager.h b/PnpBridge/src/PnpBridge/PnpAdapterManager.h index 85d69ef..f8c2661 100644 --- a/PnpBridge/src/PnpBridge/PnpAdapterManager.h +++ b/PnpBridge/src/PnpBridge/PnpAdapterManager.h @@ -38,7 +38,7 @@ typedef enum { } PublishMode; // Pnp adapter interface structure -typedef struct _PNPADAPTER_INTERFACE { +typedef struct _PNPADAPTER_INTERFACE_TAG { void* context; int key; PublishMode publishMode; @@ -47,7 +47,7 @@ typedef struct _PNPADAPTER_INTERFACE { PNPADPATER_INTERFACE_INIT_PARAMS params; PNPADAPTER_CONTEXT adapterContext; LIST_ITEM_HANDLE adapterEntry; -} PNPADAPTER_INTERFACE, *PPNPADAPTER_INTERFACE; +} PNPADAPTER_INTERFACE_TAG, *PPNPADAPTER_INTERFACE_TAG; /** * @brief PnpAdapterManager_Create creates the Azure Pnp Interface adapter manager. diff --git a/PnpBridge/src/PnpBridge/PnpAdapterManger.c b/PnpBridge/src/PnpBridge/PnpAdapterManger.c index a146528..da9ac51 100644 --- a/PnpBridge/src/PnpBridge/PnpAdapterManger.c +++ b/PnpBridge/src/PnpBridge/PnpAdapterManger.c @@ -42,8 +42,8 @@ PNPBRIDGE_RESULT PnpAdapterManager_InitializeAdapter(PPNP_ADAPTER_TAG* adapterTa } adapterT->adapter = adapter; - adapterT->pnpInterfaceList = singlylinkedlist_create(); adapterT->pnpInterfaceListLock = Lock_Init(); + adapterT->pnpInterfaceList = singlylinkedlist_create(); if (NULL == adapterT->pnpInterfaceListLock) { result = PNPBRIDGE_INSUFFICIENT_MEMORY; LEAVE; @@ -62,17 +62,32 @@ PNPBRIDGE_RESULT PnpAdapterManager_InitializeAdapter(PPNP_ADAPTER_TAG* adapterTa } void PnpAdapterManager_ReleaseAdapter(PPNP_ADAPTER_TAG adapterTag) { - if (NULL != adapterTag) { - if (NULL != adapterTag->pnpInterfaceList) { - singlylinkedlist_destroy(adapterTag->pnpInterfaceList); - } - - if (NULL != adapterTag->pnpInterfaceListLock) { - Lock_Deinit(adapterTag->pnpInterfaceListLock); - } - - free(adapterTag); + if (NULL == adapterTag) { + return; } + + if (NULL != adapterTag->pnpInterfaceList) { + SINGLYLINKEDLIST_HANDLE pnpInterfaces = adapterTag->pnpInterfaceList; + Lock(adapterTag->pnpInterfaceListLock); + LIST_ITEM_HANDLE handle = singlylinkedlist_get_head_item(pnpInterfaces); + while (NULL != handle) { + PPNPADAPTER_INTERFACE_TAG adapterInterface = (PPNPADAPTER_INTERFACE_TAG)singlylinkedlist_item_get_value(handle); + // Disconnect the adapter interface from the list. The cleanup of adapte interface + // will be done when destroy API is called + if (NULL != adapterInterface->adapterEntry) { + adapterInterface->adapterEntry = NULL; + } + adapterInterface->params.releaseInterface(adapterInterface); + + handle = singlylinkedlist_get_next_item(handle); + } + Unlock(adapterTag->pnpInterfaceListLock); + + singlylinkedlist_destroy(adapterTag->pnpInterfaceList); + Lock_Deinit(adapterTag->pnpInterfaceListLock); + } + + free(adapterTag); } PNPBRIDGE_RESULT PnpAdapterManager_Create(PPNP_ADAPTER_MANAGER* adapterMgr, JSON_Value* config) { @@ -164,16 +179,22 @@ void PnpAdapterManager_Release(PPNP_ADAPTER_MANAGER adapter) { { for (int i = 0; i < (int)count; i++) { int index = values[i][0]; - PPNP_ADAPTER pnpAdapter = PNP_ADAPTER_MANIFEST[index]; - if (NULL != pnpAdapter->shutdown) { - pnpAdapter->shutdown(); + PPNP_ADAPTER_TAG adapterT = adapter->pnpAdapters[index]; + if (NULL != adapterT) { + // Release all interfaces + PnpAdapterManager_ReleaseAdapter(adapterT); + + PPNP_ADAPTER adapter = PNP_ADAPTER_MANIFEST[index]; + if (NULL != adapter->shutdown) { + adapter->shutdown(); + } } } } } if (NULL != adapter->pnpAdapters) { - free(adapter->pnpAdapters);; + free(adapter->pnpAdapters); } Map_Destroy(adapter->pnpAdapterMap); @@ -182,7 +203,6 @@ void PnpAdapterManager_Release(PPNP_ADAPTER_MANAGER adapter) { PNPBRIDGE_RESULT PnpAdapterManager_SupportsIdentity(PPNP_ADAPTER_MANAGER adapter, JSON_Object* Message, bool* supported, int* key) { bool containsMessageKey = false; -// char* interfaceId = NULL; JSON_Object* pnpParams = json_object_get_object(Message, PNP_CONFIG_NAME_PNP_PARAMETERS); char* getIdentity = (char*) json_object_get_string(pnpParams, PNP_CONFIG_IDENTITY_NAME); MAP_RESULT mapResult; @@ -214,14 +234,14 @@ PNPBRIDGE_RESULT PnpAdapterManager_CreatePnpInterface(PPNP_ADAPTER_MANAGER adapt PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD DeviceChangePayload) { // Get the module using the key as index - PPNP_ADAPTER_TAG pnpAdapter = adapterMgr->pnpAdapters[key]; + PPNP_ADAPTER_TAG adapterT = adapterMgr->pnpAdapters[key]; PNP_ADAPTER_CONTEXT_TAG context = { 0 }; - context.adapter = pnpAdapter; + context.adapter = adapterT; context.deviceConfig = deviceConfig; // Invoke interface binding method - int ret = pnpAdapter->adapter->createPnpInterface(&context, pnpDeviceClientHandle, DeviceChangePayload); + int ret = adapterT->adapter->createPnpInterface(&context, pnpDeviceClientHandle, DeviceChangePayload); if (ret < 0) { return PNPBRIDGE_FAILED; } @@ -253,13 +273,15 @@ PNPBRIDGE_RESULT PnpAdapterManager_GetAllInterfaces(PPNP_ADAPTER_MANAGER adapter PPNP_ADAPTER_TAG pnpAdapter = adapterMgr->pnpAdapters[i]; SINGLYLINKEDLIST_HANDLE pnpInterfaces = pnpAdapter->pnpInterfaceList; + Lock(pnpAdapter->pnpInterfaceListLock); LIST_ITEM_HANDLE handle = singlylinkedlist_get_head_item(pnpInterfaces); while (NULL != handle) { - PPNPADAPTER_INTERFACE adapterInterface = (PNP_INTERFACE_CLIENT_HANDLE) singlylinkedlist_item_get_value(handle); + PPNPADAPTER_INTERFACE_TAG adapterInterface = (PNP_INTERFACE_CLIENT_HANDLE) singlylinkedlist_item_get_value(handle); pnpClientHandles[x] = PnpAdapterInterface_GetPnpInterfaceClient(adapterInterface); handle = singlylinkedlist_get_next_item(handle); x++; } + Unlock(pnpAdapter->pnpInterfaceListLock); } } @@ -274,14 +296,16 @@ bool PnpAdapterManager_IsInterfaceIdPublished(PPNP_ADAPTER_MANAGER adapterMgr, c PPNP_ADAPTER_TAG pnpAdapter = adapterMgr->pnpAdapters[i]; SINGLYLINKEDLIST_HANDLE pnpInterfaces = pnpAdapter->pnpInterfaceList; + Lock(pnpAdapter->pnpInterfaceListLock); LIST_ITEM_HANDLE handle = singlylinkedlist_get_head_item(pnpInterfaces); while (NULL != handle) { - PPNPADAPTER_INTERFACE adapterInterface = (PNP_INTERFACE_CLIENT_HANDLE)singlylinkedlist_item_get_value(handle); + PPNPADAPTER_INTERFACE_TAG adapterInterface = (PNP_INTERFACE_CLIENT_HANDLE)singlylinkedlist_item_get_value(handle); if (stricmp(adapterInterface->interfaceId, interfaceId)) { return true; } handle = singlylinkedlist_get_next_item(handle); } + Unlock(pnpAdapter->pnpInterfaceListLock); } return false; @@ -290,17 +314,19 @@ bool PnpAdapterManager_IsInterfaceIdPublished(PPNP_ADAPTER_MANAGER adapterMgr, c void PnpAdapterManager_AddInterface(PPNP_ADAPTER_TAG adapter, PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface) { LIST_ITEM_HANDLE handle = NULL; Lock(adapter->pnpInterfaceListLock); + handle = singlylinkedlist_add(adapter->pnpInterfaceList, pnpAdapterInterface); Unlock(adapter->pnpInterfaceListLock); if (NULL != handle) { - PPNPADAPTER_INTERFACE interface = (PPNPADAPTER_INTERFACE)pnpAdapterInterface; + PPNPADAPTER_INTERFACE_TAG interface = (PPNPADAPTER_INTERFACE_TAG)pnpAdapterInterface; interface->adapterEntry = handle; } + // Handle failure case when singlylinkedlist_add returns NULL } void PnpAdapterManager_RemoveInterface(PPNP_ADAPTER_TAG adapter, PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface) { - PPNPADAPTER_INTERFACE interface = (PPNPADAPTER_INTERFACE)pnpAdapterInterface; + PPNPADAPTER_INTERFACE_TAG interface = (PPNPADAPTER_INTERFACE_TAG)pnpAdapterInterface; if (NULL == interface->adapterEntry) { return; } diff --git a/PnpBridge/src/PnpBridge/PnpBridge.c b/PnpBridge/src/PnpBridge/PnpBridge.c index 64b47ce..e907851 100644 --- a/PnpBridge/src/PnpBridge/PnpBridge.c +++ b/PnpBridge/src/PnpBridge/PnpBridge.c @@ -10,19 +10,13 @@ #include "PnpBridgeh.h" -//////////////////////////// GLOBALS /////////////////////////////////// +// Global instance of PnpBridge PPNP_BRIDGE g_PnpBridge = NULL; -bool g_Shutdown = false; -//////////////////////////////////////////////////////////////////////// -typedef struct _PNPBRIDGE_INTERFACE_TAG { - char* InterfaceName; - PPNPADAPTER_INTERFACE pnpAdapterInterface; -} PNPBRIDGE_INTERFACE_TAG, *PPNPBRIDGE_INTERFACE_TAG; - -PNPBRIDGE_RESULT PnpBridge_Initialize(JSON_Value* config) { +PNPBRIDGE_RESULT PnpBridge_Initialize(PPNP_BRIDGE* pnpBridge, JSON_Value* config) { const char* connectionString; PNPBRIDGE_RESULT result = PNPBRIDGE_OK; + PPNP_BRIDGE pbridge = NULL; connectionString = Configuration_GetConnectionString(config); @@ -34,44 +28,46 @@ PNPBRIDGE_RESULT PnpBridge_Initialize(JSON_Value* config) { LEAVE; } - g_PnpBridge = (PPNP_BRIDGE)calloc(1, sizeof(PNP_BRIDGE)); + pbridge = (PPNP_BRIDGE)calloc(1, sizeof(PNP_BRIDGE)); - if (NULL == g_PnpBridge) { + if (NULL == pbridge) { LogError("Failed to allocate memory for PnpBridge global"); result = PNPBRIDGE_INSUFFICIENT_MEMORY; LEAVE; } - g_PnpBridge->configuration = config; + pbridge->configuration = config; - g_PnpBridge->dispatchLock = Lock_Init(); - if (NULL == g_PnpBridge->dispatchLock) { + pbridge->dispatchLock = Lock_Init(); + if (NULL == pbridge->dispatchLock) { LogError("Failed to init PnpBridge lock"); result = PNPBRIDGE_INSUFFICIENT_MEMORY; LEAVE; } - g_Shutdown = false; + pbridge->shutdown = false; // Connect to Iot Hub and create a PnP device client handle - if ((g_PnpBridge->deviceHandle = InitializeIotHubDeviceHandle(connectionString)) == NULL) + if ((pbridge->deviceHandle = InitializeIotHubDeviceHandle(connectionString)) == NULL) { LogError("Could not allocate IoTHub Device handle\n"); result = PNPBRIDGE_FAILED; LEAVE; } - else if ((g_PnpBridge->pnpDeviceClientHandle = PnP_DeviceClient_CreateFromDeviceHandle(g_PnpBridge->deviceHandle)) == NULL) + else if ((pbridge->pnpDeviceClientHandle = PnP_DeviceClient_CreateFromDeviceHandle(pbridge->deviceHandle)) == NULL) { LogError("PnP_DeviceClient_CreateFromDeviceHandle failed\n"); result = PNPBRIDGE_FAILED; LEAVE; } + + *pnpBridge = pbridge; } FINALLY { if (PNPBRIDGE_OK != result) { - PnpBridge_Release(g_PnpBridge); - g_PnpBridge = NULL; + PnpBridge_Release(pbridge); + *pnpBridge = NULL; } } @@ -86,7 +82,7 @@ void PnpBridge_Release(PPNP_BRIDGE pnpBridge) { LogInfo("Cleaning DeviceAggregator resources"); if (pnpBridge->dispatchLock) { - Lock(g_PnpBridge->dispatchLock); + Lock(pnpBridge->dispatchLock); } // Stop Disovery Modules @@ -115,16 +111,18 @@ int PnpBridge_Worker_Thread(void* threadArgument) { AZURE_UNREFERENCED_PARAMETER(threadArgument); + PPNP_BRIDGE pnpBridge = (PPNP_BRIDGE)threadArgument; + PNPBRIDGE_RESULT result = PNPBRIDGE_OK; // Publish persistent Pnp Interfaces - result = DiscoveryAdapterManager_PublishAlwaysInterfaces(g_PnpBridge->discoveryMgr, g_PnpBridge->configuration); + result = DiscoveryAdapterManager_PublishAlwaysInterfaces(pnpBridge->discoveryMgr, pnpBridge->configuration); if (!PNPBRIDGE_SUCCESS(result)) { goto exit; } // Start Device Discovery - result = DiscoveryAdapterManager_Start(g_PnpBridge->discoveryMgr, g_PnpBridge->configuration); + result = DiscoveryAdapterManager_Start(pnpBridge->discoveryMgr, pnpBridge->configuration); if (PNPBRIDGE_OK != result) { goto exit; } @@ -133,7 +131,7 @@ int PnpBridge_Worker_Thread(void* threadArgument) while (true) { ThreadAPI_Sleep(1 * 1000); - if (g_Shutdown) { + if (pnpBridge->shutdown) { goto exit; } } @@ -159,138 +157,161 @@ PNPBRIDGE_RESULT PnpBridge_ValidateDeviceChangePayload(PPNPBRIDGE_DEVICE_CHANGE_ } PNPBRIDGE_RESULT PnpBridge_DeviceChangeCallback(PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD DeviceChangePayload) { - PNPBRIDGE_RESULT result; + PPNP_BRIDGE pnpBridge = g_PnpBridge; + PNPBRIDGE_RESULT result = PNPBRIDGE_OK; bool containsFilter = false; int key = 0; + JSON_Value* jmsg = NULL; - Lock(g_PnpBridge->dispatchLock); + TRY + { + Lock(pnpBridge->dispatchLock); - if (g_Shutdown) { - LogInfo("PnpBridge is shutting down. Dropping the change notification"); - goto end; - } + if (pnpBridge->shutdown) { + LogInfo("PnpBridge is shutting down. Dropping the change notification"); + LEAVE; + } - result = PnpBridge_ValidateDeviceChangePayload(DeviceChangePayload); - if (PNPBRIDGE_OK != result) { - LogInfo("Change payload is invalid"); - goto end; - } + result = PnpBridge_ValidateDeviceChangePayload(DeviceChangePayload); + if (PNPBRIDGE_OK != result) { + LogInfo("Change payload is invalid"); + LEAVE; + } - JSON_Value* jmsg; - JSON_Object* jobj; - JSON_Object* jdevice; + JSON_Object* jobj; + JSON_Object* jdevice; - jmsg = json_parse_string(DeviceChangePayload->Message); - if (NULL == jmsg) { - goto end; - } + jmsg = json_parse_string(DeviceChangePayload->Message); + if (NULL == jmsg) { + LEAVE; + } - jobj = json_value_get_object(jmsg); - if (Configuration_IsDeviceConfigured(g_PnpBridge->configuration, jobj, &jdevice) < 0) { - LogInfo("Device is not configured. Dropping the change notification"); - goto end; - } + jobj = json_value_get_object(jmsg); + if (Configuration_IsDeviceConfigured(pnpBridge->configuration, jobj, &jdevice) < 0) { + LogInfo("Device is not configured. Dropping the change notification"); + LEAVE; + } - result = PnpAdapterManager_SupportsIdentity(g_PnpBridge->adapterMgr, jdevice, &containsFilter, &key); - if (PNPBRIDGE_OK != result) { - goto end; - } + result = PnpAdapterManager_SupportsIdentity(pnpBridge->adapterMgr, jdevice, &containsFilter, &key); + if (PNPBRIDGE_OK != result) { + LEAVE; + } + + if (!containsFilter) { + LogError("Dropping device change callback"); + result = PNPBRIDGE_INVALID_ARGS; + LEAVE; + } - if (containsFilter) { // Create an Pnp interface - char* interfaceId = (char*) json_object_get_string(jobj, "InterfaceId"); - - if (interfaceId != NULL) { - int idSize = (int) strlen(interfaceId) + 1; - char* id = malloc(idSize*sizeof(char)); - strcpy_s(id, idSize, interfaceId); - id[idSize - 1] = '\0'; - - if (PnpAdapterManager_IsInterfaceIdPublished(g_PnpBridge->adapterMgr, id)) { - LogError("PnP Interface has already been published. Dropping the change notification. \n"); - result = PNPBRIDGE_FAILED; - goto end; + char* interfaceId = NULL; + char* selfDescribing = (char*)json_object_get_string(jdevice, PNP_CONFIG_NAME_SELF_DESCRIBING);; + if (NULL != selfDescribing && 0 == stricmp(selfDescribing, "true")) { + interfaceId = (char*)json_object_get_string(jobj, "InterfaceId"); + if (NULL == interfaceId) { + LogError("Interface id is missing for self descrbing device"); + result = PNPBRIDGE_INVALID_ARGS; + LEAVE; } - - result = PnpAdapterManager_CreatePnpInterface(g_PnpBridge->adapterMgr, g_PnpBridge->pnpDeviceClientHandle, key, jdevice, DeviceChangePayload); - if (PNPBRIDGE_OK != result) { - goto end; - } - - // Query all the pnp interface clients and publish them - { - PNP_INTERFACE_CLIENT_HANDLE* interfaces = NULL; - int count = 0; - PnpAdapterManager_GetAllInterfaces(g_PnpBridge->adapterMgr, &interfaces, &count); - - LogInfo("Publishing Azure Pnp Interface %s\n", interfaceId); - AppRegisterPnPInterfacesAndWait(g_PnpBridge->pnpDeviceClientHandle, interfaces, count); - free(interfaces); - } - - goto end; } else { - LogError("Dropping device change callback\n"); + interfaceId = (char*)json_object_get_string(jdevice, "InterfaceId"); + if (NULL == interfaceId) { + LogError("Interface Id is missing in config for the device"); + result = PNPBRIDGE_INVALID_ARGS; + LEAVE; + } + + // Add interfaceId to the message + json_object_set_string(jobj, PNP_CONFIG_NAME_INTERFACE_ID, interfaceId); + } + + if (PnpAdapterManager_IsInterfaceIdPublished(pnpBridge->adapterMgr, interfaceId)) { + LogError("PnP Interface has already been published. Dropping the change notification. \n"); + result = PNPBRIDGE_FAILED; + LEAVE; + } + + result = PnpAdapterManager_CreatePnpInterface(pnpBridge->adapterMgr, pnpBridge->pnpDeviceClientHandle, key, jdevice, DeviceChangePayload); + if (!PNPBRIDGE_SUCCESS(result)) { + LEAVE; + } + + // Query all the pnp interface clients and publish them + { + PNP_INTERFACE_CLIENT_HANDLE* interfaces = NULL; + int count = 0; + PnpAdapterManager_GetAllInterfaces(pnpBridge->adapterMgr, &interfaces, &count); + + LogInfo("Publishing Azure Pnp Interface %s", interfaceId); + AppRegisterPnPInterfacesAndWait(pnpBridge->pnpDeviceClientHandle, interfaces, count); + free(interfaces); + } + } + FINALLY + { + Unlock(pnpBridge->dispatchLock); + if (NULL != jmsg) { + json_value_free(jmsg); } } -end: - Unlock(g_PnpBridge->dispatchLock); - return PNPBRIDGE_OK; } PNPBRIDGE_RESULT PnpBridge_Main() { PNPBRIDGE_RESULT result = PNPBRIDGE_OK; JSON_Value* config = NULL; + PPNP_BRIDGE pnpBridge = NULL; TRY { - LogInfo("Starting Azure PnpBridge\n"); + LogInfo("Starting Azure PnpBridge"); // Read the config file from a file result = PnpBridgeConfig_ReadConfigurationFromFile("config.json", &config); if (PNPBRIDGE_OK != result) { - LogError("Failed to parse configuration. Check if config file is present and ensure its formatted correctly.\n"); + LogError("Failed to parse configuration. Check if config file is present and ensure its formatted correctly"); LEAVE; } // Check if config file has mandatory parameters result = PnpBridgeConfig_ValidateConfiguration(config); if (PNPBRIDGE_OK != result) { - LogError("Config file is invalid\n"); + LogError("Config file is invalid"); LEAVE; } - result = PnpBridge_Initialize(config); + result = PnpBridge_Initialize(&pnpBridge, config); if (PNPBRIDGE_OK != result) { - LogError("PnpBridge_Initialize failed: %d\n", result); + LogError("PnpBridge_Initialize failed: %d", result); LEAVE; } - LogInfo("Connected to Azure IoT Hub\n"); + g_PnpBridge = pnpBridge; + + LogInfo("Connected to Azure IoT Hub"); // Load all the adapters in interface manifest that implement Azure IoT PnP Interface // PnpBridge will call into corresponding adapter when a device is reported by // DiscoveryExtension - result = PnpAdapterManager_Create(&g_PnpBridge->adapterMgr, g_PnpBridge->configuration); + result = PnpAdapterManager_Create(&pnpBridge->adapterMgr, pnpBridge->configuration); if (PNPBRIDGE_OK != result) { - LogError("PnpAdapterManager_Create failed: %d\n", result); + LogError("PnpAdapterManager_Create failed: %d", result); LEAVE; } // Load all the extensions that are capable of discovering devices // and reporting back to PnpBridge - result = DiscoveryAdapterManager_Create(&g_PnpBridge->discoveryMgr); + result = DiscoveryAdapterManager_Create(&pnpBridge->discoveryMgr); if (PNPBRIDGE_OK != result) { - LogError("DiscoveryAdapterManager_Create failed: %d\n", result); + LogError("DiscoveryAdapterManager_Create failed: %d", result); LEAVE; } THREAD_HANDLE workerThreadHandle = NULL; - if (THREADAPI_OK != ThreadAPI_Create(&workerThreadHandle, PnpBridge_Worker_Thread, NULL)) { - LogError("Failed to create PnpBridge_Worker_Thread\n"); + if (THREADAPI_OK != ThreadAPI_Create(&workerThreadHandle, PnpBridge_Worker_Thread, pnpBridge)) { + LogError("Failed to create PnpBridge_Worker_Thread"); workerThreadHandle = NULL; } else { @@ -299,16 +320,22 @@ PNPBRIDGE_RESULT PnpBridge_Main() { } FINALLY { - PnpBridge_Release(g_PnpBridge); + g_PnpBridge = NULL; + + PnpBridge_Release(pnpBridge); + + if (NULL != config) { + json_value_free(config); + } } return result; } -void PnpBridge_Stop() { - Lock(g_PnpBridge->dispatchLock); - g_Shutdown = true; - Unlock(g_PnpBridge->dispatchLock); +void PnpBridge_Stop(PPNP_BRIDGE pnpBridge) { + Lock(pnpBridge->dispatchLock); + pnpBridge->shutdown = true; + Unlock(pnpBridge->dispatchLock); } #include @@ -319,7 +346,7 @@ BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) { // Handle the CTRL-C signal. case CTRL_C_EVENT: - PnpBridge_Stop(); + PnpBridge_Stop(g_PnpBridge); return TRUE; default: diff --git a/PnpBridge/src/PnpBridge/PnpBridge.h b/PnpBridge/src/PnpBridge/PnpBridge.h index cb02bb7..cb2fd73 100644 --- a/PnpBridge/src/PnpBridge/PnpBridge.h +++ b/PnpBridge/src/PnpBridge/PnpBridge.h @@ -32,9 +32,11 @@ SerialPnp PnpBridge 4. DPS connection & test + 5. FT to create a tear down in a loop *** MOCK the PNP CLIENT SDK - 6. Release PnpInterfaces.. + 6. Release PnpInterfaces.. - DONE 7. Persistent device should get callback when device is discovered + 7.1 Use event to notify PnpBridgeWorker thread exit CoreDevice 7. Enumerate devices @@ -42,6 +44,7 @@ CoreDevice CMAKE 9. Clean up warnings to get a clean build + 10. Creating VS filters: https://stackoverflow.com/questions/33808087/cmake-how-to-create-visual-studio-filters */ // *************** diff --git a/PnpBridge/src/PnpBridge/PnpBridge.vcxproj b/PnpBridge/src/PnpBridge/PnpBridge.vcxproj index e757827..e9ff0ef 100644 --- a/PnpBridge/src/PnpBridge/PnpBridge.vcxproj +++ b/PnpBridge/src/PnpBridge/PnpBridge.vcxproj @@ -23,7 +23,7 @@ {8756FD40-34AF-4000-AAB9-C2A14E75B23B} Win32Proj PnpBridge - 10.0.17642.0 + 10.0.17763.0 diff --git a/PnpBridge/src/PnpBridge/PnpBridgeh.h b/PnpBridge/src/PnpBridge/PnpBridgeh.h index 56f2acc..d9a70af 100644 --- a/PnpBridge/src/PnpBridge/PnpBridgeh.h +++ b/PnpBridge/src/PnpBridge/PnpBridgeh.h @@ -25,6 +25,8 @@ typedef struct _PNP_BRIDGE { // PnpBridge config document JSON_Value* configuration; + bool shutdown; + } PNP_BRIDGE, *PPNP_BRIDGE; void PnpBridge_Release(PPNP_BRIDGE pnpBridge); diff --git a/PnpBridge/src/PnpBridge/config.json b/PnpBridge/src/PnpBridge/config.json index a9280a5..263413f 100644 --- a/PnpBridge/src/PnpBridge/config.json +++ b/PnpBridge/src/PnpBridge/config.json @@ -13,30 +13,17 @@ "HardwareId": "USB\\VID_06CB&PID_00B3" } }, - "InterfaceId": "http://windows.com/coredevicehealth/v1", + "InterfaceId": "http://windows.com/coredevicehealth/1.0.0", "PnpParameters": { "Identity": "core-device-health" } }, - { - "_comment": "DEVICE1 - RANDOM device", - "MatchFilters": { - "MatchType": "Exact", - "MatchParameters": { - "HardwareId": "USB\\VID_07DE&PID_11F3" - } - }, - "PublishMode" : "Always", - "InterfaceId": "http://windows.com/coredevicehealth/v1", - "PnpParameters": { - "Identity": "core-device-health" - } - }, { "_comment": "DEVICE2 - MCU sensor hub which reports Azure IoT Pnp interfaces", "MatchFilters": { - "MatchType": "*" + "MatchType": "Exact" }, + "SelfDescribing": "true", "PnpParameters": { "Identity": "serial-pnp-interface" }, @@ -72,21 +59,6 @@ "DeviceInterfaceClasses": [ "A5DCBF10-6530-11D2-901F-00C04FB951ED" ] - }, - { - "Identity": "camera-health-monitor", - "_comment1": "USB Device class", - "DeviceInterfaceClasses": [ - "A5DCBF10-6530-11D2-901F-00C04FB951ED" - ] - } - ] - }, - "PnpAdapters": { - "EnabledAdapters": { - }, - "Parameters": [ - { } ] } diff --git a/PnpBridge/src/PnpBridge/core/PnpAdapterInterface.c b/PnpBridge/src/PnpBridge/core/PnpAdapterInterface.c index 412fc67..fa13956 100644 --- a/PnpBridge/src/PnpBridge/core/PnpAdapterInterface.c +++ b/PnpBridge/src/PnpBridge/core/PnpAdapterInterface.c @@ -11,28 +11,28 @@ int PnpAdapterInterface_Create(PNPADAPTER_CONTEXT adapterHandle, const char* int PPNPADPATER_INTERFACE_INIT_PARAMS params) { int result = 0; - PPNPADAPTER_INTERFACE interface = NULL; + PPNPADAPTER_INTERFACE_TAG interface = NULL; + PPNP_ADAPTER_CONTEXT_TAG adapterContext = adapterHandle; TRY { // validate params - if (NULL == params) { - return -1; - } - - if (NULL == params->releaseInterface || NULL == pnpInterface) { - return -1; + if (NULL == params || NULL == params->releaseInterface || NULL == pnpInterface) { + result = -1; + LEAVE; } // Create a pnp adapter interface - interface = calloc(1, sizeof(PNPADAPTER_INTERFACE)); + interface = calloc(1, sizeof(PNPADAPTER_INTERFACE_TAG)); if (NULL == interface) { + result = -1; LEAVE; } interface->pnpInterfaceClient = pnpInterface; interface->interfaceId = malloc(strlen(interfaceId) + 1); if (NULL == interface->interfaceId) { + result = -1; LEAVE; } @@ -42,14 +42,13 @@ int PnpAdapterInterface_Create(PNPADAPTER_CONTEXT adapterHandle, const char* int // Copy the params memcpy(&interface->params, params, sizeof(interface->params)); - PPNP_ADAPTER_CONTEXT_TAG adapterContext = adapterHandle; - // Copy adapter context interface->adapterContext = calloc(1, sizeof(PPNP_ADAPTER_CONTEXT_TAG)); if (NULL == interface->adapterContext) { + result = -1; LEAVE; } - memcpy(&interface->adapterContext, adapterContext, sizeof(interface->adapterContext)); + memcpy(interface->adapterContext, adapterContext, sizeof(interface->adapterContext)); // Add this interface to the list of interfaces under the adapter context PnpAdapterManager_AddInterface(adapterContext->adapter, interface); @@ -59,6 +58,7 @@ int PnpAdapterInterface_Create(PNPADAPTER_CONTEXT adapterHandle, const char* int FINALLY { if (result < 0) { + /* PnpAdapterManager_RemoveInterface(adapterContext->adapter, pnpAdapterInterface);*/ PnpAdapterInterface_Destroy(interface); } } @@ -71,7 +71,7 @@ void PnpAdapterInterface_Destroy(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface return; } - PPNPADAPTER_INTERFACE interface = (PPNPADAPTER_INTERFACE)pnpAdapterInterface; + PPNPADAPTER_INTERFACE_TAG interface = (PPNPADAPTER_INTERFACE_TAG)pnpAdapterInterface; if (NULL != interface->interfaceId) { free(interface->interfaceId); } @@ -81,6 +81,7 @@ void PnpAdapterInterface_Destroy(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface if (NULL != interface->adapterEntry) { PnpAdapterManager_RemoveInterface(adapterContext->adapter, pnpAdapterInterface); } + free(interface->adapterContext); } } @@ -89,7 +90,7 @@ PNP_INTERFACE_CLIENT_HANDLE PnpAdapterInterface_GetPnpInterfaceClient(PNPADAPTER return NULL; } - PPNPADAPTER_INTERFACE interfaceClient = (PPNPADAPTER_INTERFACE)pnpAdapterInterface; + PPNPADAPTER_INTERFACE_TAG interfaceClient = (PPNPADAPTER_INTERFACE_TAG)pnpAdapterInterface; return interfaceClient->pnpInterfaceClient; } @@ -98,7 +99,7 @@ PNPBRIDGE_RESULT PnpAdapterInterface_SetContext(PNPADAPTER_INTERFACE_HANDLE pnpA return PNPBRIDGE_INVALID_ARGS; } - PPNPADAPTER_INTERFACE interfaceClient = (PPNPADAPTER_INTERFACE)pnpAdapterInterface; + PPNPADAPTER_INTERFACE_TAG interfaceClient = (PPNPADAPTER_INTERFACE_TAG)pnpAdapterInterface; interfaceClient->context = context; return PNPBRIDGE_OK; @@ -109,6 +110,6 @@ void* PnpAdapterInterface_GetContext(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInter return NULL; } - PPNPADAPTER_INTERFACE adapterInterface = (PPNPADAPTER_INTERFACE)pnpAdapterInterface; + PPNPADAPTER_INTERFACE_TAG adapterInterface = (PPNPADAPTER_INTERFACE_TAG)pnpAdapterInterface; return adapterInterface->context; } \ No newline at end of file From a41beedb9a0ed74a27fcaaa2642e589f01152c52 Mon Sep 17 00:00:00 2001 From: Ajay Barboza Date: Thu, 14 Feb 2019 12:11:27 -0800 Subject: [PATCH 7/7] cmake build success --- PnpBridge/CMakeLists.txt | 2 +- PnpBridge/src/CMakeLists.txt | 3 +- .../Adapters/Camera/CameraCaptureEngine.cpp | 2 +- .../Adapters/Camera/CameraIotPnpAPIs.cpp | 1 + .../PnpBridge/Adapters/CmdAndPropHandler.h | 20 +- .../CoreDeviceHealth/CoreDeviceHealth.c | 8 +- .../WindowsPnPDeviceDiscovery.c | 18 +- .../PnpBridge/Adapters/SerialPnp/SerialPnp.c | 1700 ++++++++--------- PnpBridge/src/PnpBridge/CMakeLists.txt | 6 +- PnpBridge/src/PnpBridge/PnpAdapterManger.c | 16 +- PnpBridge/src/PnpBridge/PnpBridge.vcxproj | 1 - PnpBridge/src/PnpBridge/PnpBridgeService.c | 4 - PnpBridge/src/tests/CMakeLists.txt | 3 - .../tests/pnp_adapter_manager/CMakeLists.txt | 4 - .../src/tests/pnp_adapter_manager/main.c | 11 - .../pnp_adapter_manager_ut.c | 105 - 16 files changed, 895 insertions(+), 1009 deletions(-) delete mode 100644 PnpBridge/src/PnpBridge/PnpBridgeService.c delete mode 100644 PnpBridge/src/tests/CMakeLists.txt delete mode 100644 PnpBridge/src/tests/pnp_adapter_manager/CMakeLists.txt delete mode 100644 PnpBridge/src/tests/pnp_adapter_manager/main.c delete mode 100644 PnpBridge/src/tests/pnp_adapter_manager/pnp_adapter_manager_ut.c diff --git a/PnpBridge/CMakeLists.txt b/PnpBridge/CMakeLists.txt index 1d1f8ec..e661ea3 100644 --- a/PnpBridge/CMakeLists.txt +++ b/PnpBridge/CMakeLists.txt @@ -25,7 +25,7 @@ if (MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /wd4232") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4 /wd4232") # Make warning as error - add_definitions(/WX) + # add_definitions(/WX) else() # Make warning as error set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") diff --git a/PnpBridge/src/CMakeLists.txt b/PnpBridge/src/CMakeLists.txt index aa58bee..babd373 100644 --- a/PnpBridge/src/CMakeLists.txt +++ b/PnpBridge/src/CMakeLists.txt @@ -1,4 +1,3 @@ cmake_minimum_required(VERSION 2.8.11) -add_subdirectory(PnpBridge) -# add_subdirectory(tests) \ No newline at end of file +add_subdirectory(PnpBridge) \ No newline at end of file diff --git a/PnpBridge/src/PnpBridge/Adapters/Camera/CameraCaptureEngine.cpp b/PnpBridge/src/PnpBridge/Adapters/Camera/CameraCaptureEngine.cpp index 376b4a2..11aefed 100644 --- a/PnpBridge/src/PnpBridge/Adapters/Camera/CameraCaptureEngine.cpp +++ b/PnpBridge/src/PnpBridge/Adapters/Camera/CameraCaptureEngine.cpp @@ -228,7 +228,7 @@ CameraCaptureEngine::GetDefaultCamera( } pwzInterfaceList = std::make_unique(cchInterfaceList); - cr = CM_Get_Device_Interface_List((GUID*)&guidCategory, nullptr, pwzInterfaceList.get(), cchInterfaceList, CM_GET_DEVICE_INTERFACE_LIST_PRESENT); + cr = CM_Get_Device_Interface_ListW((GUID*)&guidCategory, nullptr, pwzInterfaceList.get(), cchInterfaceList, CM_GET_DEVICE_INTERFACE_LIST_PRESENT); if (cr != CR_SUCCESS) { pwzInterfaceList = nullptr; diff --git a/PnpBridge/src/PnpBridge/Adapters/Camera/CameraIotPnpAPIs.cpp b/PnpBridge/src/PnpBridge/Adapters/Camera/CameraIotPnpAPIs.cpp index 4998e8f..cc1978b 100644 --- a/PnpBridge/src/PnpBridge/Adapters/Camera/CameraIotPnpAPIs.cpp +++ b/PnpBridge/src/PnpBridge/Adapters/Camera/CameraIotPnpAPIs.cpp @@ -61,6 +61,7 @@ CameraPnpInterfaceInitialize( _In_ const char* adapterArgs ) { + UNREFERENCED_PARAMETER(adapterArgs); return S_OK; } diff --git a/PnpBridge/src/PnpBridge/Adapters/CmdAndPropHandler.h b/PnpBridge/src/PnpBridge/Adapters/CmdAndPropHandler.h index 337898d..a72e023 100644 --- a/PnpBridge/src/PnpBridge/Adapters/CmdAndPropHandler.h +++ b/PnpBridge/src/PnpBridge/Adapters/CmdAndPropHandler.h @@ -1,9 +1,7 @@ #define CONC(A, B) CONC_(A, B) #define CONC_(A, B) A##B -static void SerialPnp_PropertyUpdateHandler(const char* propertyName, unsigned const char* propertyInitial, size_t propertyInitialLen, unsigned const char* propertyDataUpdated, size_t propertyDataUpdatedLen, int desiredVersion, void* userContextCallback); - -#define PROP_HANDLER(index) void CONC(SerialPnp_PropertyUpdateHandler, CONC(CMD_PROP_HANDLER_ADAPTER_NAME, index))(unsigned const char* propertyInitial, \ +#define PROP_HANDLER(index) void CONC(PnpBridge_PropertyUpdateHandler, CONC(CMD_PROP_HANDLER_ADAPTER_NAME, index))(unsigned const char* propertyInitial, \ size_t propertyInitialLen, unsigned const char* propertyDataUpdated, size_t propertyDataUpdatedLen, int desiredVersion, void* userContextCallback) \ {PROP_HANDLER_ADAPTER_METHOD(index, propertyInitial, propertyInitialLen, propertyDataUpdated, propertyDataUpdatedLen, \ desiredVersion, userContextCallback);}; @@ -29,9 +27,13 @@ PROP_HANDLER(17); PROP_HANDLER(18); PROP_HANDLER(19); -#define PROP_HANDLER_METHOD(index) &CONC(SerialPnp_PropertyUpdateHandler, CONC(CMD_PROP_HANDLER_ADAPTER_NAME, index)) +#define PROP_HANDLER_METHOD(index) &CONC(PnpBridge_PropertyUpdateHandler, CONC(CMD_PROP_HANDLER_ADAPTER_NAME, index)) -void* PredefinedPropertyHandlerTables[] = { + +typedef void(*PropertyHandlersFunction)(unsigned const char* propertyInitial, + size_t propertyInitialLen, unsigned const char* propertyDataUpdated, size_t propertyDataUpdatedLen, int desiredVersion, void* userContextCallback); + +PropertyHandlersFunction PredefinedPropertyHandlerTables[] = { PROP_HANDLER_METHOD(0), PROP_HANDLER_METHOD(1), PROP_HANDLER_METHOD(2), @@ -54,7 +56,7 @@ void* PredefinedPropertyHandlerTables[] = { PROP_HANDLER_METHOD(19) }; -#define CMD_HANDLER(index) void CONC(SerialPnp_CommandUpdateHandler, CONC(CMD_PROP_HANDLER_ADAPTER_NAME, index))( \ +#define CMD_HANDLER(index) void CONC(PnpBridge_CommandUpdateHandler, CONC(CMD_PROP_HANDLER_ADAPTER_NAME, index))( \ const PNP_CLIENT_COMMAND_REQUEST* pnpClientCommandContext, PNP_CLIENT_COMMAND_RESPONSE* pnpClientCommandResponseContext, void* userContextCallback) \ {CMD_HANDLER_ADAPTER_METHOD(index, pnpClientCommandContext, pnpClientCommandResponseContext, userContextCallback);}; @@ -79,9 +81,11 @@ CMD_HANDLER(17); CMD_HANDLER(18); CMD_HANDLER(19); -#define CMD_HANDLER_METHOD(index) &CONC(SerialPnp_CommandUpdateHandler, CONC(CMD_PROP_HANDLER_ADAPTER_NAME, index)) +#define CMD_HANDLER_METHOD(index) &CONC(PnpBridge_CommandUpdateHandler, CONC(CMD_PROP_HANDLER_ADAPTER_NAME, index)) -void* PredefinedCommandHandlerTables[] = { +typedef void(*CommandHandlersFunction)(const PNP_CLIENT_COMMAND_REQUEST* pnpClientCommandContext, PNP_CLIENT_COMMAND_RESPONSE* pnpClientCommandResponseContext, void* userContextCallback); + +CommandHandlersFunction PredefinedCommandHandlerTables[] = { CMD_HANDLER_METHOD(0), CMD_HANDLER_METHOD(1), CMD_HANDLER_METHOD(2), diff --git a/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.c b/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.c index 8f17581..f3a02a4 100644 --- a/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.c +++ b/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/CoreDeviceHealth.c @@ -60,6 +60,9 @@ CoreDevice_OnDeviceNotification( { PCORE_DEVICE_TAG device = context; + UNREFERENCED_PARAMETER(hNotify); + UNREFERENCED_PARAMETER(eventDataSize); + char buff[512]; sprintf_s(buff, 512, "%S", eventData->u.DeviceInterface.SymbolicLink); @@ -105,7 +108,7 @@ int CoreDevice_CreatePnpInterface(PNPADAPTER_CONTEXT adapterHandle, PNP_DEVICE_C JSON_Object* args = jmsg; PCORE_DEVICE_TAG device = NULL; const char* interfaceId = json_object_get_string(args, "InterfaceId"); - const char* hardwareId = json_object_get_string(args, "HardwareId"); + //const char* hardwareId = json_object_get_string(args, "HardwareId"); const char* symbolicLink = json_object_get_string(args, "SymbolicLink"); const char* publishMode = json_object_get_string(args, "PublishMode"); int result = 0; @@ -128,7 +131,7 @@ int CoreDevice_CreatePnpInterface(PNPADAPTER_CONTEXT adapterHandle, PNP_DEVICE_C interfaceParams.releaseInterface = CoreDevice_ReleaseInterface; PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface; - int result = PnpAdapterInterface_Create(adapterHandle, interfaceId, pnpInterfaceClient, &pnpAdapterInterface, &interfaceParams); + result = PnpAdapterInterface_Create(adapterHandle, interfaceId, pnpInterfaceClient, &pnpAdapterInterface, &interfaceParams); if (result < 0) { goto end; } @@ -228,6 +231,7 @@ int SendDeviceDisconnectedEventAsync(PNP_INTERFACE_CLIENT_HANDLE pnpInterfaceCor } int CoreDevice_Initialize(const char* adapterArgs) { + UNREFERENCED_PARAMETER(adapterArgs); return 0; } diff --git a/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/WindowsPnPDeviceDiscovery.c b/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/WindowsPnPDeviceDiscovery.c index d506e63..125cab9 100644 --- a/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/WindowsPnPDeviceDiscovery.c +++ b/PnpBridge/src/PnpBridge/Adapters/CoreDeviceHealth/WindowsPnPDeviceDiscovery.c @@ -35,6 +35,9 @@ OnDeviceNotification( _In_reads_bytes_(eventDataSize) PCM_NOTIFY_EVENT_DATA eventData, _In_ DWORD eventDataSize) { + UNREFERENCED_PARAMETER(hNotify); + UNREFERENCED_PARAMETER(eventDataSize); + UNREFERENCED_PARAMETER(context); if (action == CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL) { if (DeviceChangeHandler != NULL) { @@ -57,7 +60,7 @@ OnDeviceNotification( // Find the hardware Id DevPropSize = MAX_DEVICE_ID_LEN * sizeof(WCHAR); - status = CM_Get_Device_Interface_Property( + status = CM_Get_Device_Interface_PropertyW( eventData->u.DeviceInterface.SymbolicLink, &DEVPKEY_Device_InstanceId, &DevPropType, @@ -66,19 +69,19 @@ OnDeviceNotification( 0); if (status != CR_SUCCESS) { - return -1; + return 1; } - status = CM_Locate_DevNode( + status = CM_Locate_DevNodeW( &Devinst, deviceInstance, CM_LOCATE_DEVNODE_NORMAL); if (status != CR_SUCCESS) { - return -1; + return 1; } - status = CM_Get_DevNode_Property( + status = CM_Get_DevNode_PropertyW( Devinst, &DEVPKEY_Device_HardwareIds, &PropType, @@ -119,6 +122,7 @@ OnDeviceNotification( STRING_delete(asJson); } } + return 0; } @@ -129,6 +133,8 @@ int WindowsPnp_StartDiscovery(PNPBRIDGE_NOTIFY_DEVICE_CHANGE DeviceChangeCallbac JSON_Value* jmsg; JSON_Object* jobj; + UNREFERENCED_PARAMETER(deviceArgs); + g_deviceWatchers = singlylinkedlist_create(); if (NULL == g_deviceWatchers) { return -1; @@ -143,7 +149,7 @@ int WindowsPnp_StartDiscovery(PNPBRIDGE_NOTIFY_DEVICE_CHANGE DeviceChangeCallbac for (int j = 0; j < (int)json_array_get_count(interfaceClasses); j++) { GUID guid = { 0 }; const char *interfaceClass = json_array_get_string(interfaceClasses, j); - if (UuidFromStringA((char *)interfaceClass, &guid) != RPC_S_OK) { + if (UuidFromStringA((RPC_CSTR)interfaceClass, &guid) != RPC_S_OK) { return -1; } diff --git a/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.c b/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.c index 9cd3128..2db81c5 100644 --- a/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.c +++ b/PnpBridge/src/PnpBridge/Adapters/SerialPnp/SerialPnp.c @@ -23,13 +23,13 @@ // Temporary redirection for property and command handling since PnP C SDK property change // callback doesn't provide the command name. void SerialPnp_PropertyUpdateHandlerRedirect(int index, unsigned const char* propertyInitial, - size_t propertyInitialLen, unsigned const char* propertyDataUpdated, - size_t propertyDataUpdatedLen, int desiredVersion, void* userContextCallback); + size_t propertyInitialLen, unsigned const char* propertyDataUpdated, + size_t propertyDataUpdatedLen, int desiredVersion, void* userContextCallback); void SerialPnp_CommandUpdateHandlerRedirect(int index, - const PNP_CLIENT_COMMAND_REQUEST* pnpClientCommandContext, - PNP_CLIENT_COMMAND_RESPONSE* pnpClientCommandResponseContext, - void* userContextCallback); + const PNP_CLIENT_COMMAND_REQUEST* pnpClientCommandContext, + PNP_CLIENT_COMMAND_RESPONSE* pnpClientCommandResponseContext, + void* userContextCallback); #define CMD_PROP_HANDLER_ADAPTER_NAME SerialPnp #define PROP_HANDLER_ADAPTER_METHOD SerialPnp_PropertyUpdateHandlerRedirect @@ -40,487 +40,486 @@ void SerialPnp_CommandUpdateHandlerRedirect(int index, int SerialPnp_UartReceiver(void* context) { - BYTE msgBuffer[2048]; - PBYTE p = msgBuffer; - UINT16 SizeToRead = 0; - int result = 0; - PSERIAL_DEVICE_CONTEXT deviceContext = (PSERIAL_DEVICE_CONTEXT)context; + int result = 0; + PSERIAL_DEVICE_CONTEXT deviceContext = (PSERIAL_DEVICE_CONTEXT)context; - while (result >= 0) { - byte* desc = NULL; - DWORD length; + while (result >= 0) { + byte* desc = NULL; + DWORD length; - SerialPnp_RxPacket(deviceContext, &desc, &length, 0x00); - SerialPnp_UnsolicitedPacket(deviceContext, desc, length); + SerialPnp_RxPacket(deviceContext, &desc, &length, 0x00); + SerialPnp_UnsolicitedPacket(deviceContext, desc, length); - if (desc != NULL) { - free(desc); - } - } + if (desc != NULL) { + free(desc); + } + } - return 0; + return 0; } void SerialPnp_TxPacket(PSERIAL_DEVICE_CONTEXT serialDevice, byte* OutPacket, int Length) { - int txLength = 1 + Length; - // First iterate through and find out our new length - for (int i = 0; i < Length; i++) - { - if ((OutPacket[i] == 0x5A) || (OutPacket[i] == 0xEF)) - { - txLength++; - } - } + int txLength = 1 + Length; + // First iterate through and find out our new length + for (int i = 0; i < Length; i++) + { + if ((OutPacket[i] == 0x5A) || (OutPacket[i] == 0xEF)) + { + txLength++; + } + } - // Now construct outgoing buffer - byte* SerialPnp_TxPacket = malloc(sizeof(byte) *txLength); + // Now construct outgoing buffer + byte* SerialPnp_TxPacket = malloc(sizeof(byte) *txLength); - txLength = 1; - SerialPnp_TxPacket[0] = 0x5A; // Start of frame - for (int i = 0; i < Length; i++) - { - // Escape these bytes where necessary - if ((OutPacket[i] == 0x5A) || (OutPacket[i] == 0xEF)) - { - SerialPnp_TxPacket[txLength++] = 0xEF; - SerialPnp_TxPacket[txLength++] = (byte)(OutPacket[i] - 1); - } - else - { - SerialPnp_TxPacket[txLength++] = OutPacket[i]; - } - } + txLength = 1; + SerialPnp_TxPacket[0] = 0x5A; // Start of frame + for (int i = 0; i < Length; i++) + { + // Escape these bytes where necessary + if ((OutPacket[i] == 0x5A) || (OutPacket[i] == 0xEF)) + { + SerialPnp_TxPacket[txLength++] = 0xEF; + SerialPnp_TxPacket[txLength++] = (byte)(OutPacket[i] - 1); + } + else + { + SerialPnp_TxPacket[txLength++] = OutPacket[i]; + } + } - DWORD write_size = 0; - if (!WriteFile(serialDevice->hSerial, SerialPnp_TxPacket, txLength, &write_size, NULL)) - { - LogError("write failed"); - } + DWORD write_size = 0; + if (!WriteFile(serialDevice->hSerial, SerialPnp_TxPacket, txLength, &write_size, NULL)) + { + LogError("write failed"); + } - free(SerialPnp_TxPacket); + free(SerialPnp_TxPacket); } const EventDefinition* SerialPnp_LookupEvent(SINGLYLINKEDLIST_HANDLE interfaceDefinitions, char* EventName, int InterfaceId) { - const InterfaceDefinition* interfaceDef; - LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(interfaceDefinitions); + const InterfaceDefinition* interfaceDef; + LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(interfaceDefinitions); - for (int i = 0; i < InterfaceId - 1; i++) - { - interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); - } - interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); + for (int i = 0; i < InterfaceId - 1; i++) + { + interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); + } + interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); - SINGLYLINKEDLIST_HANDLE events = interfaceDef->Events; - LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(events); - const EventDefinition* ev; - while (eventDef != NULL) { - ev = singlylinkedlist_item_get_value(eventDef); - if (strcmp(ev->defintion.Name, EventName) == 0) { - return ev; - } - eventDef = singlylinkedlist_get_next_item(eventDef); - } + SINGLYLINKEDLIST_HANDLE events = interfaceDef->Events; + LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(events); + const EventDefinition* ev; + while (eventDef != NULL) { + ev = singlylinkedlist_item_get_value(eventDef); + if (strcmp(ev->defintion.Name, EventName) == 0) { + return ev; + } + eventDef = singlylinkedlist_get_next_item(eventDef); + } - return NULL; + return NULL; } -byte* SerialPnp_StringSchemaToBinary(Schema Schema, byte* data, int* length) +byte* SerialPnp_StringSchemaToBinary(Schema Schema, byte* buffer, int* length) { - byte* bd = NULL; + byte* bd = NULL; + char* data = (char*) buffer; - if ((Schema == Float) || (Schema == Int)) - { - bd = malloc(sizeof(byte) * 4); - *length = 4; + if ((Schema == Float) || (Schema == Int)) + { + bd = malloc(sizeof(byte) * 4); + *length = 4; - if (Schema == Float) - { - float x = 0; - x = (float)atof(data); - memcpy(bd, &x, sizeof(float)); - } - else if (Schema == Int) - { - int x; - x = atoi(data); - memcpy(bd, &x, sizeof(int)); - } - } - else if (Schema == Boolean) - { - bd = malloc(sizeof(byte) * 1); - *length = 1; - if (stricmp(data, "true")) { - bd[0] = 1; - } - else if (stricmp(data, "false")) { - bd[0] = 1; - } - else { - free(bd); - *length = 0; - bd = NULL; - } - } + if (Schema == Float) + { + float x = 0; + x = (float)atof(data); + memcpy(bd, &x, sizeof(float)); + } + else if (Schema == Int) + { + int x; + x = atoi(data); + memcpy(bd, &x, sizeof(int)); + } + } + else if (Schema == Boolean) + { + bd = malloc(sizeof(byte) * 1); + *length = 1; + if (stricmp(data, "true")) { + bd[0] = 1; + } + else if (stricmp(data, "false")) { + bd[0] = 1; + } + else { + free(bd); + *length = 0; + bd = NULL; + } + } - return bd; + return bd; } char* SerialPnp_BinarySchemaToString(Schema Schema, byte* Data, byte length) { - char* rxstrdata = malloc(256); + char* rxstrdata = malloc(256); - if ((Schema == Float) && (length == 4)) - { - float *fa = malloc(sizeof(float)); - memcpy(fa, Data, 4); - sprintf_s(rxstrdata, 256, "%.6f", *fa); - } - else if (((Schema == Int) && (length == 4))) - { - int *fa = malloc(sizeof(int)); - memcpy(fa, Data, 4); - sprintf_s(rxstrdata, 256, "%d", *fa); - } + if ((Schema == Float) && (length == 4)) + { + float *fa = malloc(sizeof(float)); + memcpy(fa, Data, 4); + sprintf_s(rxstrdata, 256, "%.6f", *fa); + } + else if (((Schema == Int) && (length == 4))) + { + int *fa = malloc(sizeof(int)); + memcpy(fa, Data, 4); + sprintf_s(rxstrdata, 256, "%d", *fa); + } - return rxstrdata; + return rxstrdata; } void SerialPnp_UnsolicitedPacket(PSERIAL_DEVICE_CONTEXT device, byte* packet, DWORD length) { - // Got an event - if (packet[2] == 0x0A) { - byte rxNameLength = packet[5]; - byte rxInterfaceId = packet[4]; - DWORD rxDataSize = length - rxNameLength - 6; + // Got an event + if (packet[2] == 0x0A) { + byte rxNameLength = packet[5]; + byte rxInterfaceId = packet[4]; + DWORD rxDataSize = length - rxNameLength - 6; - //string event_name = Encoding.UTF8.GetString(packet, 6, rxNameLength); - char* event_name = malloc(sizeof(char)*(rxNameLength + 1)); - memcpy(event_name, packet + 6, rxNameLength); - event_name[rxNameLength] = '\0'; + //string event_name = Encoding.UTF8.GetString(packet, 6, rxNameLength); + char* event_name = malloc(sizeof(char)*(rxNameLength + 1)); + memcpy(event_name, packet + 6, rxNameLength); + event_name[rxNameLength] = '\0'; - const EventDefinition* ev = SerialPnp_LookupEvent(device->InterfaceDefinitions, event_name, rxInterfaceId); + const EventDefinition* ev = SerialPnp_LookupEvent(device->InterfaceDefinitions, event_name, rxInterfaceId); - byte* rxData = malloc(sizeof(byte)*rxDataSize); - memcpy(rxData, packet + 6 + rxNameLength, rxDataSize); + byte* rxData = malloc(sizeof(byte)*rxDataSize); + memcpy(rxData, packet + 6 + rxNameLength, rxDataSize); - char* rxstrdata = SerialPnp_BinarySchemaToString(ev->DataSchema, rxData, (byte)rxDataSize); - LogInfo("%s: %s", ev->defintion.Name, rxstrdata); + char* rxstrdata = SerialPnp_BinarySchemaToString(ev->DataSchema, rxData, (byte)rxDataSize); + LogInfo("%s: %s", ev->defintion.Name, rxstrdata); - SerialPnp_SendEventAsync(PnpAdapterInterface_GetPnpInterfaceClient(device->pnpAdapterInterface), ev->defintion.Name, rxstrdata); + SerialPnp_SendEventAsync(PnpAdapterInterface_GetPnpInterfaceClient(device->pnpAdapterInterface), ev->defintion.Name, rxstrdata); - free(event_name); - free(rxData); - } - // Got a command update - else if (packet[2] == 0x08) - { - // TODO - } - else if (packet[2] == 0x08) { + free(event_name); + free(rxData); + } + // Got a command update + else if (packet[2] == 0x08) + { + // TODO + } + else if (packet[2] == 0x08) { - } + } } const PropertyDefinition* SerialPnp_LookupProperty(SINGLYLINKEDLIST_HANDLE interfaceDefinitions, const char* propertyName, int InterfaceId) { - LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(interfaceDefinitions); - const InterfaceDefinition* interfaceDef; + LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(interfaceDefinitions); + const InterfaceDefinition* interfaceDef; - for (int i = 0; i < InterfaceId - 1; i++) - { - interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); - } - interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); + for (int i = 0; i < InterfaceId - 1; i++) + { + interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); + } + interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); - SINGLYLINKEDLIST_HANDLE property = interfaceDef->Properties; - LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(property); - const PropertyDefinition* ev; - while (eventDef != NULL) { - ev = singlylinkedlist_item_get_value(eventDef); - if (strcmp(ev->defintion.Name, propertyName) == 0) { - return ev; - } - eventDef = singlylinkedlist_get_next_item(eventDef); - } + SINGLYLINKEDLIST_HANDLE property = interfaceDef->Properties; + LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(property); + const PropertyDefinition* ev; + while (eventDef != NULL) { + ev = singlylinkedlist_item_get_value(eventDef); + if (strcmp(ev->defintion.Name, propertyName) == 0) { + return ev; + } + eventDef = singlylinkedlist_get_next_item(eventDef); + } - return NULL; + return NULL; } const CommandDefinition* SerialPnp_LookupCommand(SINGLYLINKEDLIST_HANDLE interfaceDefinitions, const char* commandName, int InterfaceId) { - LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(interfaceDefinitions); - const InterfaceDefinition* interfaceDef; + LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(interfaceDefinitions); + const InterfaceDefinition* interfaceDef; - for (int i = 0; i < InterfaceId - 1; i++) - { - interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); - } - interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); + for (int i = 0; i < InterfaceId - 1; i++) + { + interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); + } + interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); - SINGLYLINKEDLIST_HANDLE command = interfaceDef->Commands; - LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(command); - const CommandDefinition* ev; - while (eventDef != NULL) { - ev = singlylinkedlist_item_get_value(eventDef); - if (strcmp(ev->defintion.Name, commandName) == 0) { - return ev; - } - eventDef = singlylinkedlist_get_next_item(eventDef); - } + SINGLYLINKEDLIST_HANDLE command = interfaceDef->Commands; + LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(command); + const CommandDefinition* ev; + while (eventDef != NULL) { + ev = singlylinkedlist_item_get_value(eventDef); + if (strcmp(ev->defintion.Name, commandName) == 0) { + return ev; + } + eventDef = singlylinkedlist_get_next_item(eventDef); + } - return NULL; + return NULL; } -int SerialPnp_PropertyHandler(PSERIAL_DEVICE_CONTEXT serialDevice, const char* property, char* input) +int SerialPnp_PropertyHandler(PSERIAL_DEVICE_CONTEXT serialDevice, const char* property, char* data) { - const PropertyDefinition* prop = SerialPnp_LookupProperty(serialDevice->InterfaceDefinitions, property, 0); + const PropertyDefinition* prop = SerialPnp_LookupProperty(serialDevice->InterfaceDefinitions, property, 0); + byte* input = (byte*)data; - if (prop == NULL) - { - return -1; - } + if (prop == NULL) { + return -1; + } - // otherwise serialize data - int length = 0; - byte* inputPayload = SerialPnp_StringSchemaToBinary(prop->DataSchema, input, &length); + // otherwise serialize data + int length = 0; + byte* inputPayload = SerialPnp_StringSchemaToBinary(prop->DataSchema, input, &length); - int nameLength = (int)strlen(property); - int txlength = 6 + nameLength + length; - byte* txPacket = malloc(txlength); + int nameLength = (int)strlen(property); + int txlength = 6 + nameLength + length; + byte* txPacket = malloc(txlength); - txPacket[0] = (byte)(txlength & 0xFF); - txPacket[1] = (byte)(txlength >> 8); - txPacket[2] = 0x07; // command request - // [3] is reserved - txPacket[4] = (byte)0; - txPacket[5] = (byte)nameLength; + txPacket[0] = (byte)(txlength & 0xFF); + txPacket[1] = (byte)(txlength >> 8); + txPacket[2] = 0x07; // command request + // [3] is reserved + txPacket[4] = (byte)0; + txPacket[5] = (byte)nameLength; - memcpy(txPacket + 6, property, nameLength); - if (inputPayload != NULL) { - memcpy(txPacket + 6 + nameLength, inputPayload, length); - } + memcpy(txPacket + 6, property, nameLength); + if (inputPayload != NULL) { + memcpy(txPacket + 6 + nameLength, inputPayload, length); + } - LogInfo("Setting property %s to %s", property, input); + LogInfo("Setting property %s to %s", property, input); - SerialPnp_TxPacket(serialDevice, txPacket, txlength); + SerialPnp_TxPacket(serialDevice, txPacket, txlength); - //ThreadAPI_Sleep(2000); + //ThreadAPI_Sleep(2000); - if (inputPayload != NULL) { - free(inputPayload); - } + if (inputPayload != NULL) { + free(inputPayload); + } - free(txPacket); + free(txPacket); - return 0; + return 0; } -int SerialPnp_CommandHandler(PSERIAL_DEVICE_CONTEXT serialDevice, const char* command, char* input, char** response) +int SerialPnp_CommandHandler(PSERIAL_DEVICE_CONTEXT serialDevice, const char* command, char* data, char** response) { - const CommandDefinition* cmd = SerialPnp_LookupCommand(serialDevice->InterfaceDefinitions, command, 0); + const CommandDefinition* cmd = SerialPnp_LookupCommand(serialDevice->InterfaceDefinitions, command, 0); + byte* input = (byte*)data; - if (cmd == NULL) - { - return -1; - } + if (cmd == NULL) + { + return -1; + } - // otherwise serialize data - int length = 0; - byte* inputPayload = SerialPnp_StringSchemaToBinary(cmd->RequestSchema, input, &length); + // otherwise serialize data + int length = 0; + byte* inputPayload = SerialPnp_StringSchemaToBinary(cmd->RequestSchema, input, &length); - int nameLength = (int)strlen(command); - int txlength = 6 + nameLength + length; - byte* txPacket = malloc(txlength); + int nameLength = (int)strlen(command); + int txlength = 6 + nameLength + length; + byte* txPacket = malloc(txlength); - txPacket[0] = (byte)(txlength & 0xFF); - txPacket[1] = (byte)(txlength >> 8); - txPacket[2] = 0x05; // command request - // [3] is reserved - txPacket[4] = (byte)0; - txPacket[5] = (byte)nameLength; + txPacket[0] = (byte)(txlength & 0xFF); + txPacket[1] = (byte)(txlength >> 8); + txPacket[2] = 0x05; // command request + // [3] is reserved + txPacket[4] = (byte)0; + txPacket[5] = (byte)nameLength; - memcpy(txPacket + 6, command, nameLength); - if (inputPayload != NULL) { - memcpy(txPacket + 6 + nameLength, inputPayload, length); - } + memcpy(txPacket + 6, command, nameLength); + if (inputPayload != NULL) { + memcpy(txPacket + 6 + nameLength, inputPayload, length); + } - LogInfo("Invoking command %s to %s", command, input); + LogInfo("Invoking command %s to %s", command, input); - SerialPnp_TxPacket(serialDevice, txPacket, txlength); + SerialPnp_TxPacket(serialDevice, txPacket, txlength); - byte* responsePacket; - SerialPnp_RxPacket(serialDevice, &responsePacket, &length, 0x02); + byte* responsePacket; + SerialPnp_RxPacket(serialDevice, &responsePacket, (DWORD*)&length, 0x02); - char* stval = SerialPnp_BinarySchemaToString(cmd->ResponseSchema, responsePacket, length); - *response = responsePacket; + char* stval = SerialPnp_BinarySchemaToString(cmd->ResponseSchema, responsePacket, (byte)length); + *response = stval; - if (inputPayload != NULL) { - free(inputPayload); - } + if (inputPayload != NULL) { + free(inputPayload); + } - free(txPacket); + free(txPacket); - return 0; + return 0; } void SerialPnp_ParseDescriptor(SINGLYLINKEDLIST_HANDLE interfaceDefinitions, byte* descriptor, DWORD length) { - int c = 4; + int c = 4; - byte version = descriptor[c++]; - byte display_name_length = descriptor[c++]; + byte version = descriptor[c++]; + byte display_name_length = descriptor[c++]; - char display_name[128]; - memcpy(display_name, descriptor + c, display_name_length); - display_name[display_name_length] = '\0'; + char display_name[128]; + memcpy(display_name, descriptor + c, display_name_length); + display_name[display_name_length] = '\0'; - LogInfo("Device Version : %d", version); - LogInfo("Device Name : %s", display_name); + LogInfo("Device Version : %d", version); + LogInfo("Device Name : %s", display_name); - c += display_name_length; + c += display_name_length; - while (c < (int)length) - { - if (descriptor[c++] == 0x05) - { - // inline interface - InterfaceDefinition* indef = calloc(1, sizeof(InterfaceDefinition)); - indef->Events = singlylinkedlist_create(); - indef->Properties = singlylinkedlist_create(); - indef->Commands = singlylinkedlist_create(); + while (c < (int)length) + { + if (descriptor[c++] == 0x05) + { + // inline interface + InterfaceDefinition* indef = calloc(1, sizeof(InterfaceDefinition)); + indef->Events = singlylinkedlist_create(); + indef->Properties = singlylinkedlist_create(); + indef->Commands = singlylinkedlist_create(); - // parse ID5 - UINT16 interface_id_length = descriptor[c] | (descriptor[c + 1] << 8); - c += 2; + // parse ID5 + UINT16 interface_id_length = descriptor[c] | (descriptor[c + 1] << 8); + c += 2; - char* interface_id = malloc(sizeof(char)*(interface_id_length + 1)); - memcpy(interface_id, descriptor + c, interface_id_length); - interface_id[interface_id_length] = '\0'; - LogInfo("Interface ID : %s", interface_id); - c += interface_id_length; + char* interface_id = malloc(sizeof(char)*(interface_id_length + 1)); + memcpy(interface_id, descriptor + c, interface_id_length); + interface_id[interface_id_length] = '\0'; + LogInfo("Interface ID : %s", interface_id); + c += interface_id_length; - indef->Id = interface_id; + indef->Id = interface_id; - // now process the different types - while (c < (int)length) - { - if (descriptor[c] > 0x03) break; // not in a type of nested entry anymore + // now process the different types + while (c < (int)length) + { + if (descriptor[c] > 0x03) break; // not in a type of nested entry anymore - FieldDefinition fielddef = { 0 }; + FieldDefinition fielddef = { 0 }; - // extract common field properties - byte ptype = descriptor[c++]; + // extract common field properties + byte ptype = descriptor[c++]; - byte pname_length = descriptor[c++]; - char* pname = malloc(sizeof(char)*(pname_length + 1)); - memcpy(pname, descriptor + c, pname_length); - pname[pname_length] = '\0'; - c += pname_length; + byte pname_length = descriptor[c++]; + char* pname = malloc(sizeof(char)*(pname_length + 1)); + memcpy(pname, descriptor + c, pname_length); + pname[pname_length] = '\0'; + c += pname_length; - byte pdisplay_name_length = descriptor[c++]; - char* pdisplay_name = malloc(sizeof(char)*(pdisplay_name_length + 1)); - memcpy(pdisplay_name, descriptor + c, pdisplay_name_length); - pdisplay_name[pdisplay_name_length] = '\0'; - c += pdisplay_name_length; + byte pdisplay_name_length = descriptor[c++]; + char* pdisplay_name = malloc(sizeof(char)*(pdisplay_name_length + 1)); + memcpy(pdisplay_name, descriptor + c, pdisplay_name_length); + pdisplay_name[pdisplay_name_length] = '\0'; + c += pdisplay_name_length; - byte pdescription_length = descriptor[c++]; - char* pdescription = malloc(sizeof(char)*(pdescription_length + 1)); - memcpy(pdescription, descriptor + c, pdescription_length); - pdescription[pdescription_length] = '\0'; - c += pdescription_length; + byte pdescription_length = descriptor[c++]; + char* pdescription = malloc(sizeof(char)*(pdescription_length + 1)); + memcpy(pdescription, descriptor + c, pdescription_length); + pdescription[pdescription_length] = '\0'; + c += pdescription_length; - LogInfo("\tProperty type : %d", ptype); - LogInfo("\tName : %s", pname); - LogInfo("\tDisplay Name : %s", pdisplay_name); - LogInfo("\tDescription : %s", pdescription); + LogInfo("\tProperty type : %d", ptype); + LogInfo("\tName : %s", pname); + LogInfo("\tDisplay Name : %s", pdisplay_name); + LogInfo("\tDescription : %s", pdescription); - fielddef.Name = pname; - fielddef.DisplayName = pdisplay_name; - fielddef.Description = pdescription; + fielddef.Name = pname; + fielddef.DisplayName = pdisplay_name; + fielddef.Description = pdescription; - if (ptype == 0x01) // command - { - CommandDefinition* tfdef = calloc(1, sizeof(CommandDefinition)); - tfdef->defintion = fielddef; + if (ptype == 0x01) // command + { + CommandDefinition* tfdef = calloc(1, sizeof(CommandDefinition)); + tfdef->defintion = fielddef; - UINT16 prequest_schema = (UINT16)(descriptor[c] | (descriptor[c + 1] << 8)); - c += 2; - UINT16 presponse_schema = (UINT16)(descriptor[c] | (descriptor[c + 1] << 8)); - c += 2; + UINT16 prequest_schema = (UINT16)(descriptor[c] | (descriptor[c + 1] << 8)); + c += 2; + UINT16 presponse_schema = (UINT16)(descriptor[c] | (descriptor[c + 1] << 8)); + c += 2; - tfdef->RequestSchema = prequest_schema; - tfdef->ResponseSchema = presponse_schema; + tfdef->RequestSchema = prequest_schema; + tfdef->ResponseSchema = presponse_schema; - singlylinkedlist_add(indef->Commands, tfdef); - } - else if (ptype == 0x02) // command - { - PropertyDefinition* tfdef = calloc(1, sizeof(PropertyDefinition)); - tfdef->defintion = fielddef; + singlylinkedlist_add(indef->Commands, tfdef); + } + else if (ptype == 0x02) // command + { + PropertyDefinition* tfdef = calloc(1, sizeof(PropertyDefinition)); + tfdef->defintion = fielddef; - byte punit_length = descriptor[c++]; - char* punit = malloc(sizeof(char)*(punit_length + 1)); - memcpy(punit, descriptor + c, punit_length); - punit[punit_length] = '\0'; - c += punit_length; + byte punit_length = descriptor[c++]; + char* punit = malloc(sizeof(char)*(punit_length + 1)); + memcpy(punit, descriptor + c, punit_length); + punit[punit_length] = '\0'; + c += punit_length; - LogInfo("\tUnit : %s", punit); + LogInfo("\tUnit : %s", punit); - UINT16 schema = descriptor[c] | (descriptor[c + 1] << 8); - c += 2; - tfdef->DataSchema = schema; + UINT16 schema = descriptor[c] | (descriptor[c + 1] << 8); + c += 2; + tfdef->DataSchema = schema; - byte flags = descriptor[c++]; + byte flags = descriptor[c++]; - bool prequired = (flags & (1 << 1)) != 0; - bool pwriteable = (flags & (1 << 0)) != 0; + bool prequired = (flags & (1 << 1)) != 0; + bool pwriteable = (flags & (1 << 0)) != 0; - tfdef->Units = punit; - tfdef->Required = prequired; - tfdef->Writeable = pwriteable; + tfdef->Units = punit; + tfdef->Required = prequired; + tfdef->Writeable = pwriteable; - singlylinkedlist_add(indef->Properties, tfdef); - } - else if (ptype == 0x03) // event - { - EventDefinition* tfdef = calloc(1, sizeof(EventDefinition)); - tfdef->defintion = fielddef; + singlylinkedlist_add(indef->Properties, tfdef); + } + else if (ptype == 0x03) // event + { + EventDefinition* tfdef = calloc(1, sizeof(EventDefinition)); + tfdef->defintion = fielddef; - byte punit_length = descriptor[c++]; - char* punit = malloc(sizeof(char)*(punit_length + 1)); - memcpy(punit, descriptor + c, punit_length); - punit[punit_length] = '\0'; - c += punit_length; + byte punit_length = descriptor[c++]; + char* punit = malloc(sizeof(char)*(punit_length + 1)); + memcpy(punit, descriptor + c, punit_length); + punit[punit_length] = '\0'; + c += punit_length; - LogInfo("\tUnit : %s", punit); + LogInfo("\tUnit : %s", punit); - UINT16 schema = (UINT16)(descriptor[c] | (descriptor[c + 1] << 8)); - c += 2; - tfdef->DataSchema = schema; + UINT16 schema = (UINT16)(descriptor[c] | (descriptor[c + 1] << 8)); + c += 2; + tfdef->DataSchema = schema; - tfdef->Units = punit; + tfdef->Units = punit; - singlylinkedlist_add(indef->Events, tfdef); - } - } + singlylinkedlist_add(indef->Events, tfdef); + } + } - singlylinkedlist_add(interfaceDefinitions, indef); - } - else - { - LogError("Unsupported descriptor\n"); - } - } + singlylinkedlist_add(interfaceDefinitions, indef); + } + else + { + LogError("Unsupported descriptor\n"); + } + } } typedef struct _SERIAL_DEVICE { - char* InterfaceName; + char* InterfaceName; } SERIAL_DEVICE, *PSERIAL_DEVICE; SINGLYLINKEDLIST_HANDLE SerialDeviceList = NULL; @@ -528,45 +527,45 @@ int SerialDeviceCount = 0; int SerialPnp_FindSerialDevices() { - CONFIGRET cmResult = CR_SUCCESS; - char* deviceInterfaceList; - ULONG bufferSize = 0; + CONFIGRET cmResult = CR_SUCCESS; + char* deviceInterfaceList; + ULONG bufferSize = 0; - SerialDeviceList = singlylinkedlist_create(); + SerialDeviceList = singlylinkedlist_create(); - cmResult = CM_Get_Device_Interface_List_Size( - &bufferSize, - (LPGUID)&GUID_DEVINTERFACE_COMPORT, - NULL, - CM_GET_DEVICE_INTERFACE_LIST_PRESENT); - if (CR_SUCCESS != cmResult) { - return -1; - } + cmResult = CM_Get_Device_Interface_List_Size( + &bufferSize, + (LPGUID)&GUID_DEVINTERFACE_COMPORT, + NULL, + CM_GET_DEVICE_INTERFACE_LIST_PRESENT); + if (CR_SUCCESS != cmResult) { + return -1; + } - deviceInterfaceList = malloc(bufferSize * sizeof(char)); + deviceInterfaceList = malloc(bufferSize * sizeof(char)); - cmResult = CM_Get_Device_Interface_ListA( - (LPGUID)&GUID_DEVINTERFACE_COMPORT, - NULL, - deviceInterfaceList, - bufferSize, - CM_GET_DEVICE_INTERFACE_LIST_PRESENT); - if (CR_SUCCESS != cmResult) { - return -1; - } + cmResult = CM_Get_Device_Interface_ListA( + (LPGUID)&GUID_DEVINTERFACE_COMPORT, + NULL, + deviceInterfaceList, + bufferSize, + CM_GET_DEVICE_INTERFACE_LIST_PRESENT); + if (CR_SUCCESS != cmResult) { + return -1; + } - for (PCHAR currentDeviceInterface = deviceInterfaceList; - *currentDeviceInterface != '\0'; - currentDeviceInterface += strlen(currentDeviceInterface) + 1) - { - PSERIAL_DEVICE serialDevs = malloc(sizeof(SERIAL_DEVICE)); - serialDevs->InterfaceName = malloc((strlen(currentDeviceInterface) + 1) * sizeof(char)); - strcpy_s(serialDevs->InterfaceName, strlen(currentDeviceInterface) + 1, currentDeviceInterface); - singlylinkedlist_add(SerialDeviceList, serialDevs); - SerialDeviceCount++; - } + for (PCHAR currentDeviceInterface = deviceInterfaceList; + *currentDeviceInterface != '\0'; + currentDeviceInterface += strlen(currentDeviceInterface) + 1) + { + PSERIAL_DEVICE serialDevs = malloc(sizeof(SERIAL_DEVICE)); + serialDevs->InterfaceName = malloc((strlen(currentDeviceInterface) + 1) * sizeof(char)); + strcpy_s(serialDevs->InterfaceName, strlen(currentDeviceInterface) + 1, currentDeviceInterface); + singlylinkedlist_add(SerialDeviceList, serialDevs); + SerialDeviceCount++; + } - return 0; + return 0; } const char* serialDeviceChangeMessageformat = "{ \ @@ -574,440 +573,441 @@ const char* serialDeviceChangeMessageformat = "{ \ }"; int SerialPnp_OpenDeviceWorker(void* context) { - byte* desc; - DWORD length; - PNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload = { 0 }; - PSERIAL_DEVICE_CONTEXT deviceContext = context; + byte* desc; + DWORD length; + PNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload = { 0 }; + PSERIAL_DEVICE_CONTEXT deviceContext = context; - SerialPnp_ResetDevice(deviceContext); - SerialPnp_DeviceDescriptorRequest(deviceContext, &desc, &length); + SerialPnp_ResetDevice(deviceContext); + SerialPnp_DeviceDescriptorRequest(deviceContext, &desc, &length); - SerialPnp_ParseDescriptor(deviceContext->InterfaceDefinitions, desc, length); + SerialPnp_ParseDescriptor(deviceContext->InterfaceDefinitions, desc, length); - STRING_HANDLE asJson = STRING_new_JSON(serialDeviceChangeMessageformat); - JSON_Value* json = json_parse_string(serialDeviceChangeMessageformat); - JSON_Object* jsonObject = json_value_get_object(json); + JSON_Value* json = json_parse_string(serialDeviceChangeMessageformat); + JSON_Object* jsonObject = json_value_get_object(json); - LIST_ITEM_HANDLE interfaceItem = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions); - while (interfaceItem != NULL) { - const InterfaceDefinition* def = (const InterfaceDefinition*)singlylinkedlist_item_get_value(interfaceItem); - json_object_set_string(jsonObject, "InterfaceId", def->Id); - payload.Message = json_serialize_to_string(json_object_get_wrapping_value(jsonObject)); - payload.MessageLength = (int)json_serialization_size(json_object_get_wrapping_value(jsonObject)); - payload.Context = deviceContext; - deviceContext->SerialDeviceChangeCallback(&payload); - interfaceItem = singlylinkedlist_get_next_item(interfaceItem); - } + LIST_ITEM_HANDLE interfaceItem = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions); + while (interfaceItem != NULL) { + const InterfaceDefinition* def = (const InterfaceDefinition*)singlylinkedlist_item_get_value(interfaceItem); + json_object_set_string(jsonObject, "InterfaceId", def->Id); + payload.Message = json_serialize_to_string(json_object_get_wrapping_value(jsonObject)); + payload.MessageLength = (int)json_serialization_size(json_object_get_wrapping_value(jsonObject)); + payload.Context = deviceContext; + deviceContext->SerialDeviceChangeCallback(&payload); + interfaceItem = singlylinkedlist_get_next_item(interfaceItem); + } - SerialPnp_UartReceiver(deviceContext); + SerialPnp_UartReceiver(deviceContext); - return 0; + return 0; } int SerialPnp_OpenDevice(const char* port, DWORD baudRate, PNPBRIDGE_NOTIFY_DEVICE_CHANGE DeviceChangeCallback) { - BOOL status = FALSE; - HANDLE hSerial = CreateFileA(port, - GENERIC_READ | GENERIC_WRITE, - 0, // must be opened with exclusive-access - 0, //NULL, no security attributes - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - 0); + HANDLE hSerial = CreateFileA(port, + GENERIC_READ | GENERIC_WRITE, + 0, // must be opened with exclusive-access + 0, //NULL, no security attributes + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + 0); - if (hSerial == INVALID_HANDLE_VALUE) { - // Handle the error - int error = GetLastError(); - LogError("Failed to open com port %s, %x", port, error); - if (error == ERROR_FILE_NOT_FOUND) { - return -1; - } + if (hSerial == INVALID_HANDLE_VALUE) { + // Handle the error + int error = GetLastError(); + LogError("Failed to open com port %s, %x", port, error); + if (error == ERROR_FILE_NOT_FOUND) { + return -1; + } - return -1; - } + return -1; + } - DCB dcbSerialParams = { 0 }; - dcbSerialParams.DCBlength = sizeof(dcbSerialParams); - if (!GetCommState(hSerial, &dcbSerialParams)) { - return -1; - } - dcbSerialParams.BaudRate = baudRate; - dcbSerialParams.ByteSize = 8; - dcbSerialParams.StopBits = ONESTOPBIT; - dcbSerialParams.Parity = NOPARITY; - if (!SetCommState(hSerial, &dcbSerialParams)) { - //error setting serial port state - return -1; - } + DCB dcbSerialParams = { 0 }; + dcbSerialParams.DCBlength = sizeof(dcbSerialParams); + if (!GetCommState(hSerial, &dcbSerialParams)) { + return -1; + } + dcbSerialParams.BaudRate = baudRate; + dcbSerialParams.ByteSize = 8; + dcbSerialParams.StopBits = ONESTOPBIT; + dcbSerialParams.Parity = NOPARITY; + if (!SetCommState(hSerial, &dcbSerialParams)) { + //error setting serial port state + return -1; + } - PSERIAL_DEVICE_CONTEXT deviceContext = malloc(sizeof(SERIAL_DEVICE_CONTEXT)); - deviceContext->hSerial = hSerial; - deviceContext->pnpAdapterInterface = NULL; - deviceContext->SerialDeviceChangeCallback = DeviceChangeCallback; - deviceContext->InterfaceDefinitions = singlylinkedlist_create(); + PSERIAL_DEVICE_CONTEXT deviceContext = malloc(sizeof(SERIAL_DEVICE_CONTEXT)); + deviceContext->hSerial = hSerial; + deviceContext->pnpAdapterInterface = NULL; + deviceContext->SerialDeviceChangeCallback = DeviceChangeCallback; + deviceContext->InterfaceDefinitions = singlylinkedlist_create(); - //deviceContext->osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + //deviceContext->osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - // TODO error handling - // https://docs.microsoft.com/en-us/previous-versions/ff802693(v=msdn.10) + // TODO error handling + // https://docs.microsoft.com/en-us/previous-versions/ff802693(v=msdn.10) - if (ThreadAPI_Create(&deviceContext->SerialDeviceWorker, SerialPnp_OpenDeviceWorker, deviceContext) != THREADAPI_OK) { - LogError("ThreadAPI_Create failed"); - } + if (ThreadAPI_Create(&deviceContext->SerialDeviceWorker, SerialPnp_OpenDeviceWorker, deviceContext) != THREADAPI_OK) { + LogError("ThreadAPI_Create failed"); + } - return 0; + return 0; } void SerialPnp_RxPacket(PSERIAL_DEVICE_CONTEXT serialDevice, byte** receivedPacket, DWORD* length, char packetType) { - BYTE inb = 0; - DWORD dwRead = 0; - *receivedPacket = NULL; - *length = 0; + BYTE inb = 0; + DWORD dwRead = 0; + *receivedPacket = NULL; + *length = 0; - while (ReadFile(serialDevice->hSerial, &inb, 1, &dwRead, NULL)) { - // Check for a start of packet byte - if (inb == 0x5A) - { - serialDevice->RxBufferIndex = 0; - serialDevice->RxEscaped = false; - continue; - } + while (ReadFile(serialDevice->hSerial, &inb, 1, &dwRead, NULL)) { + // Check for a start of packet byte + if (inb == 0x5A) + { + serialDevice->RxBufferIndex = 0; + serialDevice->RxEscaped = false; + continue; + } - // Check for an escape byte - if (inb == 0xEF) - { - serialDevice->RxEscaped = true; - continue; - } + // Check for an escape byte + if (inb == 0xEF) + { + serialDevice->RxEscaped = true; + continue; + } - // If last byte was an escape byte, increment current byte by 1 - if (serialDevice->RxEscaped) - { - inb++; - serialDevice->RxEscaped = false; - } + // If last byte was an escape byte, increment current byte by 1 + if (serialDevice->RxEscaped) + { + inb++; + serialDevice->RxEscaped = false; + } - serialDevice->RxBuffer[serialDevice->RxBufferIndex++] = (byte)inb; + serialDevice->RxBuffer[serialDevice->RxBufferIndex++] = (byte)inb; - if (serialDevice->RxBufferIndex >= 4096) - { - LogError("Filled Rx buffer. Protocol is bad."); - break; - } + if (serialDevice->RxBufferIndex >= 4096) + { + LogError("Filled Rx buffer. Protocol is bad."); + break; + } - // Minimum packet length is 4, so once we are >= 4 begin checking - // the receieve buffer length against the length field. - if (serialDevice->RxBufferIndex >= 4) - { - int PacketLength = (int)((serialDevice->RxBuffer[0]) | (serialDevice->RxBuffer[1] << 8)); // LSB first, L-endian + // Minimum packet length is 4, so once we are >= 4 begin checking + // the receieve buffer length against the length field. + if (serialDevice->RxBufferIndex >= 4) + { + int PacketLength = (int)((serialDevice->RxBuffer[0]) | (serialDevice->RxBuffer[1] << 8)); // LSB first, L-endian - if (serialDevice->RxBufferIndex == PacketLength && (packetType == 0x00 || packetType == serialDevice->RxBuffer[2])) - { - *receivedPacket = malloc(serialDevice->RxBufferIndex * sizeof(byte)); - *length = serialDevice->RxBufferIndex; - memcpy(*receivedPacket, serialDevice->RxBuffer, serialDevice->RxBufferIndex); - serialDevice->RxBufferIndex = 0; // This should be reset anyway - // Deliver the newly receieved packet - //Console.Out.Write("\n"); - break; - } - } - } + if (((int)serialDevice->RxBufferIndex == PacketLength) && (packetType == 0x00 || packetType == serialDevice->RxBuffer[2])) + { + *receivedPacket = malloc(serialDevice->RxBufferIndex * sizeof(byte)); + *length = serialDevice->RxBufferIndex; + memcpy(*receivedPacket, serialDevice->RxBuffer, serialDevice->RxBufferIndex); + serialDevice->RxBufferIndex = 0; // This should be reset anyway + // Deliver the newly receieved packet + //Console.Out.Write("\n"); + break; + } + } + } } void SerialPnp_ResetDevice(PSERIAL_DEVICE_CONTEXT serialDevice) { - // Prepare packet - byte* resetPacket = calloc(4, sizeof(byte)); // packet header - byte* responsePacket = NULL; - resetPacket[0] = 4; // length 4 - resetPacket[1] = 0; - resetPacket[2] = 0x01; // type reset + // Prepare packet + byte* resetPacket = calloc(4, sizeof(byte)); // packet header + byte* responsePacket = NULL; + resetPacket[0] = 4; // length 4 + resetPacket[1] = 0; + resetPacket[2] = 0x01; // type reset - ThreadAPI_Sleep(2000); + ThreadAPI_Sleep(2000); - // Send the new packet - SerialPnp_TxPacket(serialDevice, resetPacket, 4); + // Send the new packet + SerialPnp_TxPacket(serialDevice, resetPacket, 4); - ThreadAPI_Sleep(2000); + ThreadAPI_Sleep(2000); - DWORD length; - SerialPnp_RxPacket(serialDevice, &responsePacket, &length, 0x02); + DWORD length; + SerialPnp_RxPacket(serialDevice, &responsePacket, &length, 0x02); - if (responsePacket == NULL) { - LogError("received NULL for response packet"); - return; - } + if (responsePacket == NULL) { + LogError("received NULL for response packet"); + return; + } - if (responsePacket[2] != 0x02) - { - LogError("Bad reset response"); - } + if (responsePacket[2] != 0x02) + { + LogError("Bad reset response"); + } - LogInfo("Receieved reset response"); + LogInfo("Receieved reset response"); } void SerialPnp_DeviceDescriptorRequest(PSERIAL_DEVICE_CONTEXT serialDevice, byte** desc, DWORD* length) { - // Prepare packet - byte txPacket[4] = { 0 }; // packet header - txPacket[0] = 4; // length 4 - txPacket[1] = 0; - txPacket[2] = 0x03; // type descriptor request + // Prepare packet + byte txPacket[4] = { 0 }; // packet header + txPacket[0] = 4; // length 4 + txPacket[1] = 0; + txPacket[2] = 0x03; // type descriptor request - // Get ready to receieve a reset response + // Get ready to receieve a reset response - // Send the new packets - SerialPnp_TxPacket(serialDevice, txPacket, 4); - LogInfo("Sent descriptor request"); + // Send the new packets + SerialPnp_TxPacket(serialDevice, txPacket, 4); + LogInfo("Sent descriptor request"); - SerialPnp_RxPacket(serialDevice, desc, length, 0x04); + SerialPnp_RxPacket(serialDevice, desc, length, 0x04); - if ((*desc)[2] != 0x04) - { - LogError("Bad descriptor response"); - return; - } + if ((*desc)[2] != 0x04) + { + LogError("Bad descriptor response"); + return; + } - LogInfo("Receieved descriptor response, of length %d", *length); + LogInfo("Receieved descriptor response, of length %d", *length); } int SerialPnp_StartDiscovery(PNPBRIDGE_NOTIFY_DEVICE_CHANGE DeviceChangeCallback, const char* deviceArgs, const char* adapterArgs) { - if (deviceArgs == NULL) { - return -1; - } + if (deviceArgs == NULL) { + return -1; + } - const char* port = NULL; - const char* useComDevInterfaceStr; - const char* baudRateParam; - bool useComDeviceInterface = false; - JSON_Value* jvalue = json_parse_string(deviceArgs); - JSON_Object* args = json_value_get_object(jvalue); + UNREFERENCED_PARAMETER(adapterArgs); - useComDevInterfaceStr = (const char*)json_object_dotget_string(args, "UseComDeviceInterface"); - if ((NULL != useComDevInterfaceStr) && (0 == stricmp(useComDevInterfaceStr, "true"))) { - useComDeviceInterface = true; - } + const char* port = NULL; + const char* useComDevInterfaceStr; + const char* baudRateParam; + bool useComDeviceInterface = false; + JSON_Value* jvalue = json_parse_string(deviceArgs); + JSON_Object* args = json_value_get_object(jvalue); - if (!useComDeviceInterface) { - port = (const char*)json_object_dotget_string(args, "ComPort"); - if (NULL == port) { - LogError("ComPort parameter is missing in configuration"); - return -1; - } - } + useComDevInterfaceStr = (const char*)json_object_dotget_string(args, "UseComDeviceInterface"); + if ((NULL != useComDevInterfaceStr) && (0 == stricmp(useComDevInterfaceStr, "true"))) { + useComDeviceInterface = true; + } - JSON_Object* SerialDeviceInterfaceInfo = args; + if (!useComDeviceInterface) { + port = (const char*)json_object_dotget_string(args, "ComPort"); + if (NULL == port) { + LogError("ComPort parameter is missing in configuration"); + return -1; + } + } - baudRateParam = (const char*)json_object_dotget_string(args, "BaudRate"); - if (NULL == baudRateParam) { - LogError("BaudRate parameter is missing in configuration"); - return -1; - } + baudRateParam = (const char*)json_object_dotget_string(args, "BaudRate"); + if (NULL == baudRateParam) { + LogError("BaudRate parameter is missing in configuration"); + return -1; + } - PSERIAL_DEVICE seriaDevice = NULL; - DWORD baudRate = atoi(baudRateParam); - if (useComDeviceInterface) { - if (SerialPnp_FindSerialDevices() < 0) { - LogError("Failed to get com port %s", port); - } + PSERIAL_DEVICE seriaDevice = NULL; + DWORD baudRate = atoi(baudRateParam); + if (useComDeviceInterface) { + if (SerialPnp_FindSerialDevices() < 0) { + LogError("Failed to get com port %s", port); + } - LIST_ITEM_HANDLE item = singlylinkedlist_get_head_item(SerialDeviceList); - if (item == NULL) { - LogError("No serial device was found %s", port); - return -1; - } + LIST_ITEM_HANDLE item = singlylinkedlist_get_head_item(SerialDeviceList); + if (item == NULL) { + LogError("No serial device was found %s", port); + return -1; + } - seriaDevice = (PSERIAL_DEVICE)singlylinkedlist_item_get_value(item); - } + seriaDevice = (PSERIAL_DEVICE)singlylinkedlist_item_get_value(item); + } - LogInfo("Opening com port %s", useComDeviceInterface ? seriaDevice->InterfaceName : port); + LogInfo("Opening com port %s", useComDeviceInterface ? seriaDevice->InterfaceName : port); - SerialPnp_OpenDevice(useComDeviceInterface ? seriaDevice->InterfaceName : port, baudRate, DeviceChangeCallback); - return 0; + SerialPnp_OpenDevice(useComDeviceInterface ? seriaDevice->InterfaceName : port, baudRate, DeviceChangeCallback); + return 0; } int SerialPnp_StopDiscovery() { - return 0; + return 0; } void SerialPnp_SendEventCallback(PNP_SEND_TELEMETRY_STATUS pnpSendEventStatus, void* userContextCallback) { - LogInfo("SerialDataSendEventCallback called, result=%d, userContextCallback=%p", pnpSendEventStatus, userContextCallback); + LogInfo("SerialDataSendEventCallback called, result=%d, userContextCallback=%p", pnpSendEventStatus, userContextCallback); } int SerialPnp_SendEventAsync(PNP_INTERFACE_CLIENT_HANDLE pnpInterface, char* eventName, char* data) { - int result; - PNP_CLIENT_RESULT pnpClientResult; + int result; + PNP_CLIENT_RESULT pnpClientResult; - if (pnpInterface == NULL) { - return 0; - } + if (pnpInterface == NULL) { + return 0; + } - if ((pnpClientResult = PnP_InterfaceClient_SendTelemetryAsync(pnpInterface, eventName, (const unsigned char*)data, strlen(data), SerialPnp_SendEventCallback, NULL)) != PNP_CLIENT_OK) - { - LogError("PnP_InterfaceClient_SendEventAsync failed, result=%d\n", pnpClientResult); - result = __FAILURE__; - } - else - { - result = 0; - } + if ((pnpClientResult = PnP_InterfaceClient_SendTelemetryAsync(pnpInterface, eventName, (const unsigned char*)data, strlen(data), SerialPnp_SendEventCallback, NULL)) != PNP_CLIENT_OK) + { + LogError("PnP_InterfaceClient_SendEventAsync failed, result=%d\n", pnpClientResult); + result = __FAILURE__; + } + else + { + result = 0; + } - return result; + return result; } static void SerialPnp_PropertyUpdateHandler(const char* propertyName, unsigned const char* propertyInitial, size_t propertyInitialLen, unsigned const char* propertyDataUpdated, size_t propertyDataUpdatedLen, int desiredVersion, void* userContextCallback) { - PNP_CLIENT_RESULT pnpClientResult; - PNP_CLIENT_READWRITE_PROPERTY_RESPONSE propertyResponse; - PSERIAL_DEVICE_CONTEXT deviceContext; + PNP_CLIENT_RESULT pnpClientResult; + PNP_CLIENT_READWRITE_PROPERTY_RESPONSE propertyResponse; + PSERIAL_DEVICE_CONTEXT deviceContext; - LogInfo("Processed property. propertyUpdated = %.*s", (int)propertyDataUpdatedLen, propertyDataUpdated); + UNREFERENCED_PARAMETER(propertyInitial); + UNREFERENCED_PARAMETER(propertyInitialLen); - deviceContext = (PSERIAL_DEVICE_CONTEXT)userContextCallback; + LogInfo("Processed property. propertyUpdated = %.*s", (int)propertyDataUpdatedLen, propertyDataUpdated); - SerialPnp_PropertyHandler(deviceContext, propertyName, (char*)propertyDataUpdated); + deviceContext = (PSERIAL_DEVICE_CONTEXT)userContextCallback; - // TODO: Send the correct response code below - propertyResponse.version = 1; - propertyResponse.propertyData = propertyDataUpdated; - propertyResponse.propertyDataLen = propertyDataUpdatedLen; - propertyResponse.responseVersion = desiredVersion; - propertyResponse.statusCode = 200; - propertyResponse.statusDescription = "Property Updated Successfully"; + SerialPnp_PropertyHandler(deviceContext, propertyName, (char*)propertyDataUpdated); - pnpClientResult = PnP_InterfaceClient_ReportReadWritePropertyStatusAsync(deviceContext->pnpAdapterInterface, propertyName, &propertyResponse, NULL, NULL); + // TODO: Send the correct response code below + propertyResponse.version = 1; + propertyResponse.propertyData = propertyDataUpdated; + propertyResponse.propertyDataLen = propertyDataUpdatedLen; + propertyResponse.responseVersion = desiredVersion; + propertyResponse.statusCode = 200; + propertyResponse.statusDescription = "Property Updated Successfully"; + + pnpClientResult = PnP_InterfaceClient_ReportReadWritePropertyStatusAsync(deviceContext->pnpAdapterInterface, propertyName, &propertyResponse, NULL, NULL); } // PnPSampleEnvironmentalSensor_SetCommandResponse is a helper that fills out a PNP_CLIENT_COMMAND_RESPONSE static void SerialPnp_SetCommandResponse(PNP_CLIENT_COMMAND_RESPONSE* pnpClientCommandResponseContext, const char* responseData, int status) { - size_t responseLen = strlen(responseData); - memset(pnpClientCommandResponseContext, 0, sizeof(*pnpClientCommandResponseContext)); - pnpClientCommandResponseContext->version = PNP_CLIENT_COMMAND_RESPONSE_VERSION_1; + size_t responseLen = strlen(responseData); + memset(pnpClientCommandResponseContext, 0, sizeof(*pnpClientCommandResponseContext)); + pnpClientCommandResponseContext->version = PNP_CLIENT_COMMAND_RESPONSE_VERSION_1; - // Allocate a copy of the response data to return to the invoker. The PnP layer that invoked PnPSampleEnvironmentalSensor_Blink - // takes responsibility for freeing this data. - if ((pnpClientCommandResponseContext->responseData = malloc(responseLen + 1)) == NULL) - { - LogError("ENVIRONMENTAL_SENSOR_INTERFACE: Unable to allocate response data"); - pnpClientCommandResponseContext->status = 500; - } - else - { - pnpClientCommandResponseContext->responseData = (unsigned char*)responseData; - //strcpy_s((char*)pnpClientCommandResponseContext->responseData, responseData); - pnpClientCommandResponseContext->responseDataLen = responseLen; - pnpClientCommandResponseContext->status = status; - } + // Allocate a copy of the response data to return to the invoker. The PnP layer that invoked PnPSampleEnvironmentalSensor_Blink + // takes responsibility for freeing this data. + if ((pnpClientCommandResponseContext->responseData = malloc(responseLen + 1)) == NULL) + { + LogError("ENVIRONMENTAL_SENSOR_INTERFACE: Unable to allocate response data"); + pnpClientCommandResponseContext->status = 500; + } + else + { + pnpClientCommandResponseContext->responseData = (unsigned char*)responseData; + //strcpy_s((char*)pnpClientCommandResponseContext->responseData, responseData); + pnpClientCommandResponseContext->responseDataLen = responseLen; + pnpClientCommandResponseContext->status = status; + } } void SerialPnp_CommandUpdateHandler(const char* commandName, const PNP_CLIENT_COMMAND_REQUEST* pnpClientCommandContext, PNP_CLIENT_COMMAND_RESPONSE* pnpClientCommandResponseContext, void* userContextCallback) { - PSERIAL_DEVICE_CONTEXT deviceContext; + PSERIAL_DEVICE_CONTEXT deviceContext; - // LogInfo("Processed command frequency property updated. propertyUpdated = %.*s", (int)propertyDataUpdatedLen, propertyDataUpdated); + // LogInfo("Processed command frequency property updated. propertyUpdated = %.*s", (int)propertyDataUpdatedLen, propertyDataUpdated); - deviceContext = (PSERIAL_DEVICE_CONTEXT)userContextCallback; + deviceContext = (PSERIAL_DEVICE_CONTEXT)userContextCallback; - char* response; - SerialPnp_CommandHandler(deviceContext, commandName, (char*)pnpClientCommandContext->requestData, &response); - SerialPnp_SetCommandResponse(pnpClientCommandResponseContext, response, 200); + char* response; + SerialPnp_CommandHandler(deviceContext, commandName, (char*)pnpClientCommandContext->requestData, &response); + SerialPnp_SetCommandResponse(pnpClientCommandResponseContext, response, 200); } void SerialPnp_PropertyUpdateHandlerRedirect(int index, unsigned const char* propertyInitial, - size_t propertyInitialLen, unsigned const char* propertyDataUpdated, - size_t propertyDataUpdatedLen, int desiredVersion, void* userContextCallback) + size_t propertyInitialLen, unsigned const char* propertyDataUpdated, + size_t propertyDataUpdatedLen, int desiredVersion, void* userContextCallback) { - PSERIAL_DEVICE_CONTEXT deviceContext = userContextCallback; - LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions); - const InterfaceDefinition* interfaceDef; + PSERIAL_DEVICE_CONTEXT deviceContext = userContextCallback; + LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions); + const InterfaceDefinition* interfaceDef; - for (int i = 0; i < 0 - 1; i++) - { - interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); - } - interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); + for (int i = 0; i < 0 - 1; i++) + { + interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); + } + interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); - SINGLYLINKEDLIST_HANDLE property = interfaceDef->Properties; - LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(property); - const PropertyDefinition* ev = NULL; - eventDef = singlylinkedlist_get_head_item(property); - for (int i = 0; i < index + 1; i++) { - ev = singlylinkedlist_item_get_value(eventDef); - eventDef = singlylinkedlist_get_next_item(eventDef); - } - if (NULL != ev) { - SerialPnp_PropertyUpdateHandler(ev->defintion.Name, propertyInitial, propertyInitialLen, propertyDataUpdated, propertyDataUpdatedLen, - desiredVersion, userContextCallback); - } + SINGLYLINKEDLIST_HANDLE property = interfaceDef->Properties; + LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(property); + const PropertyDefinition* ev = NULL; + eventDef = singlylinkedlist_get_head_item(property); + for (int i = 0; i < index + 1; i++) { + ev = singlylinkedlist_item_get_value(eventDef); + eventDef = singlylinkedlist_get_next_item(eventDef); + } + if (NULL != ev) { + SerialPnp_PropertyUpdateHandler(ev->defintion.Name, propertyInitial, propertyInitialLen, propertyDataUpdated, propertyDataUpdatedLen, + desiredVersion, userContextCallback); + } } void SerialPnp_CommandUpdateHandlerRedirect(int index, - const PNP_CLIENT_COMMAND_REQUEST* pnpClientCommandContext, - PNP_CLIENT_COMMAND_RESPONSE* pnpClientCommandResponseContext, - void* userContextCallback) + const PNP_CLIENT_COMMAND_REQUEST* pnpClientCommandContext, + PNP_CLIENT_COMMAND_RESPONSE* pnpClientCommandResponseContext, + void* userContextCallback) { - PSERIAL_DEVICE_CONTEXT deviceContext = userContextCallback; - LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions); - const InterfaceDefinition* interfaceDef; + PSERIAL_DEVICE_CONTEXT deviceContext = userContextCallback; + LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions); + const InterfaceDefinition* interfaceDef; - for (int i = 0; i < 0 - 1; i++) - { - interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); - } - interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); + for (int i = 0; i < 0 - 1; i++) + { + interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); + } + interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); - SINGLYLINKEDLIST_HANDLE command = interfaceDef->Commands; - LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(command); - const CommandDefinition* ev = NULL; - eventDef = singlylinkedlist_get_head_item(command); - for (int i = 0; i < index + 1; i++) { - ev = singlylinkedlist_item_get_value(eventDef); - eventDef = singlylinkedlist_get_next_item(eventDef); - } - if (NULL != ev) { - SerialPnp_CommandUpdateHandler(ev->defintion.Name, pnpClientCommandContext, pnpClientCommandResponseContext, userContextCallback); - } + SINGLYLINKEDLIST_HANDLE command = interfaceDef->Commands; + LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(command); + const CommandDefinition* ev = NULL; + eventDef = singlylinkedlist_get_head_item(command); + for (int i = 0; i < index + 1; i++) { + ev = singlylinkedlist_item_get_value(eventDef); + eventDef = singlylinkedlist_get_next_item(eventDef); + } + if (NULL != ev) { + SerialPnp_CommandUpdateHandler(ev->defintion.Name, pnpClientCommandContext, pnpClientCommandResponseContext, userContextCallback); + } } const InterfaceDefinition* SerialPnp_GetInterface(PSERIAL_DEVICE_CONTEXT deviceContext, const char* interfaceId) { - LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions); - while (interfaceDefHandle != NULL) { - const InterfaceDefinition* interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); - if (stricmp(interfaceDef->Id, interfaceId) == 0) { - return interfaceDef; - } - interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); - } - return NULL; + LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions); + while (interfaceDefHandle != NULL) { + const InterfaceDefinition* interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); + if (stricmp(interfaceDef->Id, interfaceId) == 0) { + return interfaceDef; + } + interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle); + } + return NULL; } int SerialPnp_GetListCount(SINGLYLINKEDLIST_HANDLE list) { - if (NULL == list) { - return 0; - } + if (NULL == list) { + return 0; + } - LIST_ITEM_HANDLE item = singlylinkedlist_get_head_item(list); - int count = 0; - while (NULL != item) { - count++; - item = singlylinkedlist_get_next_item(item); - } - return count; + LIST_ITEM_HANDLE item = singlylinkedlist_get_head_item(list); + int count = 0; + while (NULL != item) { + count++; + item = singlylinkedlist_get_next_item(item); + } + return count; } int SerialPnp_CreatePnpInterface(PNPADAPTER_CONTEXT adapterHandle, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD args) { - PSERIAL_DEVICE_CONTEXT deviceContext = (PSERIAL_DEVICE_CONTEXT)args->Context; - JSON_Value* jvalue = json_parse_string(args->Message); - JSON_Object* jmsg = json_value_get_object(jvalue); + PSERIAL_DEVICE_CONTEXT deviceContext = (PSERIAL_DEVICE_CONTEXT)args->Context; + JSON_Value* jvalue = json_parse_string(args->Message); + JSON_Object* jmsg = json_value_get_object(jvalue); - const char* interfaceId = json_object_get_string(jmsg, "InterfaceId"); - int result = 0; + const char* interfaceId = json_object_get_string(jmsg, "InterfaceId"); + int result = 0; // Create an Azure Pnp interface for each interface in the SerialPnp descriptor LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions); @@ -1024,90 +1024,90 @@ int SerialPnp_CreatePnpInterface(PNPADAPTER_CONTEXT adapterHandle, PNP_DEVICE_CL PNP_CLIENT_COMMAND_CALLBACK_TABLE serialCommandTable = { 0 }; const InterfaceDefinition* interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle); - // Construct property table - { - SINGLYLINKEDLIST_HANDLE property = interfaceDef->Properties; - propertyCount = SerialPnp_GetListCount(interfaceDef->Properties); + // Construct property table + { + SINGLYLINKEDLIST_HANDLE property = interfaceDef->Properties; + propertyCount = SerialPnp_GetListCount(interfaceDef->Properties); - if (propertyCount > 0) { - LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(property); - const PropertyDefinition* ev; + if (propertyCount > 0) { + LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(property); + const PropertyDefinition* ev; - propertyNames = malloc(sizeof(char*)*propertyCount); - if (NULL == propertyNames) { - result = -1; - goto exit; - } + propertyNames = malloc(sizeof(char*)*propertyCount); + if (NULL == propertyNames) { + result = -1; + goto exit; + } - propertyUpdateTable = malloc(sizeof(PNP_READWRITE_PROPERTY_UPDATE_CALLBACK*)*propertyCount); - if (NULL == propertyUpdateTable) { - result = -1; - goto exit; - } + propertyUpdateTable = malloc(sizeof(PNP_READWRITE_PROPERTY_UPDATE_CALLBACK*)*propertyCount); + if (NULL == propertyUpdateTable) { + result = -1; + goto exit; + } - eventDef = singlylinkedlist_get_head_item(property); - int x = 0; - while (eventDef != NULL) { - ev = singlylinkedlist_item_get_value(eventDef); - propertyNames[x] = ev->defintion.Name; - propertyUpdateTable[x] = PredefinedPropertyHandlerTables[x]; - x++; - eventDef = singlylinkedlist_get_next_item(eventDef); - } + eventDef = singlylinkedlist_get_head_item(property); + int x = 0; + while (eventDef != NULL) { + ev = singlylinkedlist_item_get_value(eventDef); + propertyNames[x] = ev->defintion.Name; + propertyUpdateTable[x] = PredefinedPropertyHandlerTables[x]; + x++; + eventDef = singlylinkedlist_get_next_item(eventDef); + } - serialPropertyTable.numCallbacks = propertyCount; - serialPropertyTable.propertyNames = propertyNames; - serialPropertyTable.callbacks = propertyUpdateTable; - serialPropertyTable.version = 1; - } - } + serialPropertyTable.numCallbacks = propertyCount; + serialPropertyTable.propertyNames = propertyNames; + serialPropertyTable.callbacks = propertyUpdateTable; + serialPropertyTable.version = 1; + } + } - // Construct command table - { - SINGLYLINKEDLIST_HANDLE command = interfaceDef->Commands; - int commandCount = SerialPnp_GetListCount(command); + // Construct command table + { + SINGLYLINKEDLIST_HANDLE command = interfaceDef->Commands; + commandCount = SerialPnp_GetListCount(command); - if (commandCount > 0) { - LIST_ITEM_HANDLE cmdDef; - int x = 0; - const CommandDefinition* cv; + if (commandCount > 0) { + LIST_ITEM_HANDLE cmdDef; + int x = 0; + const CommandDefinition* cv; - commandNames = malloc(sizeof(char*)*commandCount); - if (NULL == commandNames) { - result = -1; - goto exit; - } + commandNames = malloc(sizeof(char*)*commandCount); + if (NULL == commandNames) { + result = -1; + goto exit; + } - commandUpdateTable = malloc(sizeof(PNP_COMMAND_EXECUTE_CALLBACK*)*commandCount); - if (NULL == commandUpdateTable) { - result = -1; - goto exit; - } + commandUpdateTable = malloc(sizeof(PNP_COMMAND_EXECUTE_CALLBACK*)*commandCount); + if (NULL == commandUpdateTable) { + result = -1; + goto exit; + } - cmdDef = singlylinkedlist_get_head_item(command); - while (cmdDef != NULL) { - cv = singlylinkedlist_item_get_value(cmdDef); - commandNames[x] = cv->defintion.Name; - commandUpdateTable[x] = PredefinedCommandHandlerTables[x]; - x++; - cmdDef = singlylinkedlist_get_next_item(cmdDef); - } + cmdDef = singlylinkedlist_get_head_item(command); + while (cmdDef != NULL) { + cv = singlylinkedlist_item_get_value(cmdDef); + commandNames[x] = cv->defintion.Name; + commandUpdateTable[x] = PredefinedCommandHandlerTables[x]; + x++; + cmdDef = singlylinkedlist_get_next_item(cmdDef); + } - serialCommandTable.numCommandCallbacks = commandCount; - serialCommandTable.commandNames = commandNames; - serialCommandTable.commandCallbacks = commandUpdateTable; - serialCommandTable.version = 1; - } - } + serialCommandTable.numCommandCallbacks = commandCount; + serialCommandTable.commandNames = commandNames; + serialCommandTable.commandCallbacks = commandUpdateTable; + serialCommandTable.version = 1; + } + } - pnpInterfaceClient = PnP_InterfaceClient_Create(pnpDeviceClientHandle, interfaceId, + pnpInterfaceClient = PnP_InterfaceClient_Create(pnpDeviceClientHandle, interfaceId, propertyCount > 0 ? &serialPropertyTable : NULL, commandCount > 0 ? &serialCommandTable : NULL, deviceContext); - if (NULL == pnpInterfaceClient) { - result = -1; - goto exit; - } + if (NULL == pnpInterfaceClient) { + result = -1; + goto exit; + } // Create PnpAdapter Interface { @@ -1143,126 +1143,126 @@ int SerialPnp_CreatePnpInterface(PNPADAPTER_CONTEXT adapterHandle, PNP_DEVICE_CL exit: - // Cleanup incase of failure + // Cleanup incase of failure if (result < 0) { // Destroy PnpInterfaceClient //if (NULL != pnpInterfaceClient) { - // PnP_InterfaceClient_Destroy(pnpInterfaceClient); + // PnP_InterfaceClient_Destroy(pnpInterfaceClient); //} } - return 0; + return 0; } void SerialPnp_FreeFieldDefinition(FieldDefinition* fdef) { - if (NULL != fdef->Description) { - free(fdef->Description); - } + if (NULL != fdef->Description) { + free(fdef->Description); + } - if (NULL != fdef->DisplayName) { - free(fdef->DisplayName); - } + if (NULL != fdef->DisplayName) { + free(fdef->DisplayName); + } - if (NULL != fdef->Name) { - free(fdef->Name); - } + if (NULL != fdef->Name) { + free(fdef->Name); + } } void SerialPnp_FreeEventDefinition(SINGLYLINKEDLIST_HANDLE events) { - if (NULL == events) { - return; - } + if (NULL == events) { + return; + } - LIST_ITEM_HANDLE eventItem = singlylinkedlist_get_head_item(events); - while (NULL != eventItem) { - EventDefinition* e = (EventDefinition*)singlylinkedlist_item_get_value(eventItem); - SerialPnp_FreeFieldDefinition(&e->defintion); - if (NULL != e->Units) { - free(e->Units); - } - free(e); - eventItem = singlylinkedlist_get_next_item(eventItem); - } + LIST_ITEM_HANDLE eventItem = singlylinkedlist_get_head_item(events); + while (NULL != eventItem) { + EventDefinition* e = (EventDefinition*)singlylinkedlist_item_get_value(eventItem); + SerialPnp_FreeFieldDefinition(&e->defintion); + if (NULL != e->Units) { + free(e->Units); + } + free(e); + eventItem = singlylinkedlist_get_next_item(eventItem); + } } void SerialPnp_FreeCommandDefinition(SINGLYLINKEDLIST_HANDLE cmds) { - if (NULL == cmds) { - return; - } + if (NULL == cmds) { + return; + } - LIST_ITEM_HANDLE cmdItem = singlylinkedlist_get_head_item(cmds); - while (NULL != cmdItem) { - CommandDefinition* c = (CommandDefinition*)singlylinkedlist_item_get_value(cmdItem); - free(c); - cmdItem = singlylinkedlist_get_next_item(cmdItem); - } + LIST_ITEM_HANDLE cmdItem = singlylinkedlist_get_head_item(cmds); + while (NULL != cmdItem) { + CommandDefinition* c = (CommandDefinition*)singlylinkedlist_item_get_value(cmdItem); + free(c); + cmdItem = singlylinkedlist_get_next_item(cmdItem); + } } void SerialPnp_FreePropertiesDefinition(SINGLYLINKEDLIST_HANDLE props) { - if (NULL == props) { - return; - } + if (NULL == props) { + return; + } - LIST_ITEM_HANDLE propItem = singlylinkedlist_get_head_item(props); - while (NULL != propItem) { - PropertyDefinition* p = (PropertyDefinition*)singlylinkedlist_item_get_value(propItem); - SerialPnp_FreeFieldDefinition(&p->defintion); - if (NULL != p->Units) { - free(p->Units); - } - free(p); - propItem = singlylinkedlist_get_next_item(propItem); - } + LIST_ITEM_HANDLE propItem = singlylinkedlist_get_head_item(props); + while (NULL != propItem) { + PropertyDefinition* p = (PropertyDefinition*)singlylinkedlist_item_get_value(propItem); + SerialPnp_FreeFieldDefinition(&p->defintion); + if (NULL != p->Units) { + free(p->Units); + } + free(p); + propItem = singlylinkedlist_get_next_item(propItem); + } } int SerialPnp_ReleasePnpInterface(PNPADAPTER_INTERFACE_HANDLE pnpInterface) { - PSERIAL_DEVICE_CONTEXT deviceContext = PnpAdapterInterface_GetContext(pnpInterface); + PSERIAL_DEVICE_CONTEXT deviceContext = PnpAdapterInterface_GetContext(pnpInterface); - if (NULL == deviceContext) { - return 0; - } + if (NULL == deviceContext) { + return 0; + } - if (NULL != deviceContext->hSerial) { - CloseHandle(deviceContext->hSerial); - } + if (NULL != deviceContext->hSerial) { + CloseHandle(deviceContext->hSerial); + } - if (deviceContext->InterfaceDefinitions) { - LIST_ITEM_HANDLE interfaceItem = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions); - while (interfaceItem != NULL) { - InterfaceDefinition* def = (InterfaceDefinition*)singlylinkedlist_item_get_value(interfaceItem); - SerialPnp_FreeEventDefinition(def->Events); - SerialPnp_FreeCommandDefinition(def->Commands); - SerialPnp_FreePropertiesDefinition(def->Properties); + if (deviceContext->InterfaceDefinitions) { + LIST_ITEM_HANDLE interfaceItem = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions); + while (interfaceItem != NULL) { + InterfaceDefinition* def = (InterfaceDefinition*)singlylinkedlist_item_get_value(interfaceItem); + SerialPnp_FreeEventDefinition(def->Events); + SerialPnp_FreeCommandDefinition(def->Commands); + SerialPnp_FreePropertiesDefinition(def->Properties); - free(def); - interfaceItem = singlylinkedlist_get_next_item(interfaceItem); - } - singlylinkedlist_destroy(deviceContext->InterfaceDefinitions); - } + free(def); + interfaceItem = singlylinkedlist_get_next_item(interfaceItem); + } + singlylinkedlist_destroy(deviceContext->InterfaceDefinitions); + } - free(deviceContext); + free(deviceContext); - return 0; + return 0; } int SerialPnp_Initialize(const char* adapterArgs) { -// AZURE_UNREFERENCED_PARAMETER(adapterArgs); - return 0; + UNREFERENCED_PARAMETER(adapterArgs); + return 0; } int SerialPnp_Shutdown() { - return 0; + return 0; } DISCOVERY_ADAPTER SerialPnpDiscovery = { - .Identity = "serial-pnp-discovery", - .StartDiscovery = SerialPnp_StartDiscovery, - .StopDiscovery = SerialPnp_StopDiscovery + .Identity = "serial-pnp-discovery", + .StartDiscovery = SerialPnp_StartDiscovery, + .StopDiscovery = SerialPnp_StopDiscovery }; PNP_ADAPTER SerialPnpInterface = { - .identity = "serial-pnp-interface", - .initialize = SerialPnp_Initialize, - .shutdown = SerialPnp_Shutdown, - .createPnpInterface = SerialPnp_CreatePnpInterface + .identity = "serial-pnp-interface", + .initialize = SerialPnp_Initialize, + .shutdown = SerialPnp_Shutdown, + .createPnpInterface = SerialPnp_CreatePnpInterface }; diff --git a/PnpBridge/src/PnpBridge/CMakeLists.txt b/PnpBridge/src/PnpBridge/CMakeLists.txt index 51fae2c..067d612 100644 --- a/PnpBridge/src/PnpBridge/CMakeLists.txt +++ b/PnpBridge/src/PnpBridge/CMakeLists.txt @@ -18,7 +18,6 @@ set(pnp_bridge_c_files ./IotHubComms.c ./PnpAdapterManger.c ./PnpBridge.c - ./PnpBridgeService.c ./utility.c ./Core/PnpAdapterInterface.c ./Core/PnpBridgeMemory.c @@ -63,6 +62,8 @@ set(pnp_bridge_h_files ./Adapters/SerialPnp/SerialPnp.h ) +add_definitions("-D_UNICODE") + set(pnp_bridge_libs) set(install_staticlibs @@ -95,8 +96,7 @@ add_executable(${PROJECT_NAME} ${pnp_bridge_h_files} ) -target_link_libraries(${PROJECT_NAME} ${pnp_bridge_libs}) -target_link_libraries(${PROJECT_NAME} iothub_client parson pnp_client iothub_client_http_transport iothub_client_amqp_transport iothub_client_amqp_ws_transport iothub_client_mqtt_transport iothub_client_mqtt_ws_transport umqtt aziotsharedutil) +target_link_libraries(${PROJECT_NAME} ${pnp_bridge_libs} iothub_client parson pnp_client iothub_client_http_transport iothub_client_amqp_transport iothub_client_amqp_ws_transport iothub_client_mqtt_transport iothub_client_mqtt_ws_transport umqtt aziotsharedutil cfgmgr32 mfplat mfsensorgroup) set(pnp_bridge_libs ${PROJECT_NAME} diff --git a/PnpBridge/src/PnpBridge/PnpAdapterManger.c b/PnpBridge/src/PnpBridge/PnpAdapterManger.c index da9ac51..dd2c7cc 100644 --- a/PnpBridge/src/PnpBridge/PnpAdapterManger.c +++ b/PnpBridge/src/PnpBridge/PnpAdapterManger.c @@ -165,21 +165,21 @@ exit: return result; } -void PnpAdapterManager_Release(PPNP_ADAPTER_MANAGER adapter) { +void PnpAdapterManager_Release(PPNP_ADAPTER_MANAGER adapterMgr) { const char* const* keys; const char* const* values; size_t count; - if (NULL != adapter->pnpAdapterMap) { + if (NULL != adapterMgr->pnpAdapterMap) { // Call shutdown on all interfaces - if (Map_GetInternals(adapter->pnpAdapterMap, &keys, &values, &count) != MAP_OK) { + if (Map_GetInternals(adapterMgr->pnpAdapterMap, &keys, &values, &count) != MAP_OK) { LogError("Map_GetInternals failed to get all pnp adapters"); } else { for (int i = 0; i < (int)count; i++) { int index = values[i][0]; - PPNP_ADAPTER_TAG adapterT = adapter->pnpAdapters[index]; + PPNP_ADAPTER_TAG adapterT = adapterMgr->pnpAdapters[index]; if (NULL != adapterT) { // Release all interfaces PnpAdapterManager_ReleaseAdapter(adapterT); @@ -193,12 +193,12 @@ void PnpAdapterManager_Release(PPNP_ADAPTER_MANAGER adapter) { } } - if (NULL != adapter->pnpAdapters) { - free(adapter->pnpAdapters); + if (NULL != adapterMgr->pnpAdapters) { + free(adapterMgr->pnpAdapters); } - Map_Destroy(adapter->pnpAdapterMap); - free(adapter); + Map_Destroy(adapterMgr->pnpAdapterMap); + free(adapterMgr); } PNPBRIDGE_RESULT PnpAdapterManager_SupportsIdentity(PPNP_ADAPTER_MANAGER adapter, JSON_Object* Message, bool* supported, int* key) { diff --git a/PnpBridge/src/PnpBridge/PnpBridge.vcxproj b/PnpBridge/src/PnpBridge/PnpBridge.vcxproj index e9ff0ef..c073598 100644 --- a/PnpBridge/src/PnpBridge/PnpBridge.vcxproj +++ b/PnpBridge/src/PnpBridge/PnpBridge.vcxproj @@ -198,7 +198,6 @@ - diff --git a/PnpBridge/src/PnpBridge/PnpBridgeService.c b/PnpBridge/src/PnpBridge/PnpBridgeService.c deleted file mode 100644 index c420c11..0000000 --- a/PnpBridge/src/PnpBridge/PnpBridgeService.c +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -// Placeholder for code to make PnpBridge a NT service \ No newline at end of file diff --git a/PnpBridge/src/tests/CMakeLists.txt b/PnpBridge/src/tests/CMakeLists.txt deleted file mode 100644 index 5422b7b..0000000 --- a/PnpBridge/src/tests/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -cmake_minimum_required(VERSION 2.8.11) - -add_subdirectory(pnp_adapter_manager) \ No newline at end of file diff --git a/PnpBridge/src/tests/pnp_adapter_manager/CMakeLists.txt b/PnpBridge/src/tests/pnp_adapter_manager/CMakeLists.txt deleted file mode 100644 index f38e84a..0000000 --- a/PnpBridge/src/tests/pnp_adapter_manager/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -cmake_minimum_required(VERSION 2.8.11) - -add_subdirectory(PnpBridge) -add_subdirectory(tests) \ No newline at end of file diff --git a/PnpBridge/src/tests/pnp_adapter_manager/main.c b/PnpBridge/src/tests/pnp_adapter_manager/main.c deleted file mode 100644 index 36b98aa..0000000 --- a/PnpBridge/src/tests/pnp_adapter_manager/main.c +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -#include "testrunnerswitcher.h" - -int main(void) -{ - size_t failedTestCount = 0; - RUN_TEST_SUITE(lock_thread_binding_stub_ut, failedTestCount); - return failedTestCount; -} \ No newline at end of file diff --git a/PnpBridge/src/tests/pnp_adapter_manager/pnp_adapter_manager_ut.c b/PnpBridge/src/tests/pnp_adapter_manager/pnp_adapter_manager_ut.c deleted file mode 100644 index 710171d..0000000 --- a/PnpBridge/src/tests/pnp_adapter_manager/pnp_adapter_manager_ut.c +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -#ifdef __cplusplus -#include -#include -#include -#else -#include -#include -#include -#endif - -#include "testrunnerswitcher.h" -#include "umock_c.h" - - -static const int PNP_TEST_MILLISECONDS = 0x1234; - -#include "internal/lock_thread_binding_stub.h" - -static void on_umock_c_error(UMOCK_C_ERROR_CODE error_code) -{ - char temp_str[256]; - (void)snprintf(temp_str, sizeof(temp_str), "umock_c reported error :%s", ENUM_TO_STRING(UMOCK_C_ERROR_CODE, error_code)); - ASSERT_FAIL(temp_str); -} -DEFINE_ENUM_STRINGS(UMOCK_C_ERROR_CODE, UMOCK_C_ERROR_CODE_VALUES) - -TEST_DEFINE_ENUM_TYPE(LOCK_RESULT, LOCK_RESULT_VALUES); -IMPLEMENT_UMOCK_C_ENUM_TYPE(LOCK_RESULT, LOCK_RESULT_VALUES); - -BEGIN_TEST_SUITE(lock_thread_binding_stub_ut) - -TEST_SUITE_INITIALIZE(suite_init) -{ - int result; - - result = umock_c_init(on_umock_c_error); - ASSERT_ARE_EQUAL(int, 0, result); - - REGISTER_UMOCK_ALIAS_TYPE(LOCK_HANDLE, void*); - REGISTER_UMOCK_ALIAS_TYPE(LOCK_RESULT, int); -} - -TEST_FUNCTION_INITIALIZE(TestMethodInit) -{ - umock_c_reset_all_calls(); -} - -TEST_FUNCTION_CLEANUP(TestMethodCleanup) -{ - ; -} - -TEST_FUNCTION(LockBinding_LockInit_Stub_ok) -{ - //act - LOCK_HANDLE h = LockBinding_LockInit_Stub(); - - //assert - ASSERT_IS_NOT_NULL(h); - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); -} - -TEST_FUNCTION(LockBinding_Lock_Stub_ok) -{ - //act - LOCK_RESULT lockResult = LockBinding_Lock_Stub(NULL); - - //assert - ASSERT_ARE_EQUAL(LOCK_RESULT, lockResult, LOCK_OK); - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); -} - -TEST_FUNCTION(LockBinding_Unlock_Stub_ok) -{ - //act - LOCK_RESULT lockResult = LockBinding_Unlock_Stub(NULL); - - //assert - ASSERT_ARE_EQUAL(LOCK_RESULT, lockResult, LOCK_OK); - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); -} - -TEST_FUNCTION(LockBinding_LockDeinit_Stub_ok) -{ - //act - LOCK_RESULT lockResult = LockBinding_LockDeinit_Stub(NULL); - - //assert - ASSERT_ARE_EQUAL(LOCK_RESULT, lockResult, LOCK_OK); - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); -} - -TEST_FUNCTION(ThreadBinding_ThreadSleep_Stub_ok) -{ - //act - ThreadBinding_ThreadSleep_Stub(PNP_TEST_MILLISECONDS); - - //assert - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); -} - -END_TEST_SUITE(lock_thread_binding_stub_ut)