From ee341139c064f03b3060d67413083ef16b281d3d Mon Sep 17 00:00:00 2001 From: David Rebbe Date: Sat, 23 Nov 2024 17:57:14 -0500 Subject: [PATCH] first commit, open and close work. --- CMakeLists.txt | 38 +++- api/icsneo/icsneo.cpp | 168 ++++++++++++++++++ api/icsneo/version.rc.template | 51 ++++++ examples/CMakeLists.txt | 21 ++- examples/c/simple/CMakeLists.txt | 6 +- examples/c/simple/src/main.c | 61 +++++++ .../interactive/CMakeLists.txt | 0 .../{c => c_legacy}/interactive/README.md | 0 .../{c => c_legacy}/interactive/src/main.c | 0 .../{c => c_legacy}/legacy/CMakeLists.txt | 0 examples/{c => c_legacy}/legacy/README.md | 0 .../legacy/deviceSettings/main.c | 0 examples/{c => c_legacy}/legacy/lin/main.c | 0 examples/c_legacy/simple/CMakeLists.txt | 5 + examples/{c => c_legacy}/simple/README.md | 0 examples/{c => c_legacy}/simple/lin/main.c | 0 include/icsneo/icsneo.h | 124 +++++++++++++ 17 files changed, 461 insertions(+), 13 deletions(-) create mode 100644 api/icsneo/icsneo.cpp create mode 100644 api/icsneo/version.rc.template create mode 100644 examples/c/simple/src/main.c rename examples/{c => c_legacy}/interactive/CMakeLists.txt (100%) rename examples/{c => c_legacy}/interactive/README.md (100%) rename examples/{c => c_legacy}/interactive/src/main.c (100%) rename examples/{c => c_legacy}/legacy/CMakeLists.txt (100%) rename examples/{c => c_legacy}/legacy/README.md (100%) rename examples/{c => c_legacy}/legacy/deviceSettings/main.c (100%) rename examples/{c => c_legacy}/legacy/lin/main.c (100%) create mode 100644 examples/c_legacy/simple/CMakeLists.txt rename examples/{c => c_legacy}/simple/README.md (100%) rename examples/{c => c_legacy}/simple/lin/main.c (100%) create mode 100644 include/icsneo/icsneo.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f4351c..97ae3ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,10 @@ option(LIBICSNEO_BUILD_UNIT_TESTS "Build unit tests." OFF) option(LIBICSNEO_BUILD_SYSTEM_TESTS "Build system tests." OFF) option(LIBICSNEO_BUILD_DOCS "Build documentation. Don't use in Visual Studio." OFF) option(LIBICSNEO_BUILD_EXAMPLES "Build examples." ON) -option(LIBICSNEO_BUILD_ICSNEOC "Build dynamic C library" ON) -option(LIBICSNEO_BUILD_ICSNEOC_STATIC "Build static C library" ON) +option(LIBICSNEO_BUILD_ICSNEO "Build dynamic C library" ON) +option(LIBICSNEO_BUILD_ICSNEO_STATIC "Build static C library" ON) +option(LIBICSNEO_BUILD_ICSNEOC "Build dynamic C legacy library" ON) +option(LIBICSNEO_BUILD_ICSNEOC_STATIC "Build static C legacy library" ON) option(LIBICSNEO_BUILD_ICSNEOLEGACY "Build icsnVC40 compatibility library" ON) option(LIBICSNEO_BUILD_ICSNEOLEGACY_STATIC "Build static icsnVC40 compatibility library" ON) set(LIBICSNEO_NPCAP_INCLUDE_DIR "" CACHE STRING "Npcap include directory; set to build with Npcap") @@ -332,6 +334,7 @@ endif() configure_file(api/icsneocpp/buildinfo.h.template ${CMAKE_CURRENT_BINARY_DIR}/generated/buildinfo.h) configure_file(api/icsneoc/version.rc.template ${CMAKE_CURRENT_BINARY_DIR}/generated/icsneoc/version.rc) +configure_file(api/icsneo/version.rc.template ${CMAKE_CURRENT_BINARY_DIR}/generated/icsneo/version.rc) foreach(EXTINC ${LIBICSNEO_EXTENSION_INCLUDES}) message("Including " ${EXTINC}) @@ -432,6 +435,37 @@ if(LIBICSNEO_ENABLE_RAW_ETHERNET) endif(WIN32) endif(LIBICSNEO_ENABLE_RAW_ETHERNET) +if(LIBICSNEO_BUILD_ICSNEO) + add_library(icsneo SHARED api/icsneo/icsneo.cpp ${CMAKE_CURRENT_BINARY_DIR}/generated/icsneo/version.rc) + + target_include_directories(icsneo + PUBLIC + $ + $ + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/include + ) + target_link_libraries(icsneo PRIVATE icsneocpp) + target_compile_definitions(icsneo PRIVATE ICSNEO_EXPORTS) + target_compile_features(icsneo PRIVATE cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums) +endif() + +if(LIBICSNEO_BUILD_ICSNEO_STATIC) + add_library(icsneo-static STATIC api/icsneo/icsneo.cpp) + target_include_directories(icsneo-static + PUBLIC + $ + $ + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/include + ) + target_link_libraries(icsneo-static PUBLIC icsneocpp) + target_compile_features(icsneo-static PUBLIC cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums) + target_compile_definitions(icsneo PRIVATE ICSNEO_EXPORTS) + target_compile_definitions(icsneo-static PUBLIC ICSNEOC_BUILD_STATIC) +endif() + + if(LIBICSNEO_BUILD_ICSNEOC) add_library(icsneoc SHARED api/icsneoc/icsneoc.cpp ${CMAKE_CURRENT_BINARY_DIR}/generated/icsneoc/version.rc) target_include_directories(icsneoc diff --git a/api/icsneo/icsneo.cpp b/api/icsneo/icsneo.cpp new file mode 100644 index 0000000..9fb18f2 --- /dev/null +++ b/api/icsneo/icsneo.cpp @@ -0,0 +1,168 @@ +#include +#include +#include "icsneo/device/devicefinder.h" + +#include +#include +#include + +using namespace icsneo; + +typedef struct icsneo_device_t { + std::shared_ptr device; + + icsneo_open_options_t options; +} icsneo_device_t; + + +static std::deque> g_devices; + +ICSNEO_API icsneo_error_t icsneo_find(icsneo_device_t** devices, uint32_t* devices_count, void* reserved) { + if (!devices || !devices_count) { + return icsneo_error_invalid_parameters; + } + // Find devices + auto found_devices = DeviceFinder::FindAll(); + // Remove all devices that have been closed or are no longer connected + for (auto it = g_devices.begin(); it != g_devices.end();) { + if (!it->get()->device) { + it = g_devices.erase(it); + } else { + ++it; + } + } + // Add new devices + for (auto& found_device : found_devices) { + if (std::none_of(g_devices.begin(), g_devices.end(), + [&](const auto& device) { + return device->device == found_device; + })) { + auto device = std::make_shared(); + device->device = found_device; + device->options = icsneo_open_options_go_online | icsneo_open_options_enable_message_polling | icsneo_open_options_sync_rtc | icsneo_open_options_enable_auto_update; + g_devices.push_back(device); + } + } + // Determine how many we can return to the caller + auto min_size = std::minmax(static_cast(found_devices.size()), *devices_count).first; + *devices_count = min_size; + + // Return the devices to the caller + for (uint32_t i = 0; i < min_size; i++) { + devices[i] = g_devices[i].get(); + } + // Winner winner chicken dinner + return icsneo_error_success; +} + +ICSNEO_API icsneo_error_t icsneo_device_is_valid(icsneo_device_t* device) { + if (!device) { + return icsneo_error_invalid_parameters; + } + + return !device->device ? icsneo_error_invalid_parameters : icsneo_error_success; +} + +ICSNEO_API icsneo_error_t icsneo_get_open_options(icsneo_device_t* device, icsneo_open_options_t* options) { + if (!device || !options) { + return icsneo_error_invalid_parameters; + } + *options = device->options; + + return icsneo_error_success; +} + +ICSNEO_API icsneo_error_t icsneo_set_open_options(icsneo_device_t* device, icsneo_open_options_t options) { + if (!device) { + return icsneo_error_invalid_parameters; + } + + device->options = options; + + return icsneo_error_success; +} + +ICSNEO_API icsneo_error_t icsneo_open(icsneo_device_t* device) { + if (!device || !device->device) { + return icsneo_error_invalid_parameters; + } + // Open the device + auto dev = device->device; + // Nothing to do if we are already open + if (dev->isOpen()) { + return icsneo_error_success; + } + // TODO: OpenFlags and OpenStatusHandler + // Open the device + if (!dev->open()) { + return icsneo_error_open_failed; + } + // Go online + if ((device->options & icsneo_open_options_go_online) == icsneo_open_options_go_online && !dev->goOnline()) { + dev->close(); + return icsneo_error_open_gonline_failed; + } + // Enable message polling + if ((device->options & icsneo_open_options_enable_message_polling) == icsneo_open_options_enable_message_polling && !dev->enableMessagePolling()) { + dev->close(); + return icsneo_error_open_message_polling_failed; + } + // Sync RTC + if ((device->options & icsneo_open_options_sync_rtc) == icsneo_open_options_sync_rtc && !dev->setRTC(std::chrono::system_clock::now())) { + dev->close(); + return icsneo_error_open_sync_rtc_failed; + } + return icsneo_error_success; +} + +ICSNEO_API icsneo_error_t icsneo_close(icsneo_device_t* device) { + if (!device || !device->device) { + return icsneo_error_invalid_parameters; + } + auto dev = device->device; + if (!dev->isOpen()) { + return icsneo_error_success; + } + dev->close(); + return icsneo_error_success; +} + + +ICSNEO_API icsneo_error_t icsneo_device_describe(icsneo_device_t* device, const char* value, uint32_t* value_length) { + if (!device || !device->device) { + return icsneo_error_invalid_parameters; + } + auto dev = device->device; + // Get and set the length + auto min_length = std::minmax(static_cast(dev->describe().length()), *value_length).first; + *value_length = min_length; + // Copy the string into value + strncpy(const_cast(value), dev->describe().c_str(), min_length); + + return icsneo_error_success; +} + +ICSNEO_API icsneo_error_t icsneo_device_type(icsneo_device_t* device, uint64_t* value) { + if (!device || !device->device) { + return icsneo_error_invalid_parameters; + } + auto dev = device->device; + // TODO: We should expose these types + *value = static_cast(dev->getType()); + + return icsneo_error_success; +} + +ICSNEO_API icsneo_error_t icsneo_device_serial(icsneo_device_t* device, const char* value, uint32_t* value_length) { + if (!device || !device->device) { + return icsneo_error_invalid_parameters; + } + auto dev = device->device; + // Get and set the length + auto min_length = std::minmax(static_cast(dev->getSerial().length()), *value_length).first; + *value_length = min_length; + // Copy the string into value + strncpy(const_cast(value), dev->getSerial().c_str(), min_length); + + return icsneo_error_success; +} diff --git a/api/icsneo/version.rc.template b/api/icsneo/version.rc.template new file mode 100644 index 0000000..409bbed --- /dev/null +++ b/api/icsneo/version.rc.template @@ -0,0 +1,51 @@ +#define VER_FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@ +#define VER_FILEVERSION_STR "v@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@@BUILD_METADATA_PLUS@ @BUILD_GIT_INFO@" + +#define VER_PRODUCTVERSION VER_FILEVERSION +#define VER_PRODUCTVERSION_STR VER_FILEVERSION_STR + +#ifndef DEBUG +#define VER_DEBUG 0 +#else +#define VER_DEBUG VS_FF_DEBUG +#endif + +#include + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILEVERSION +PRODUCTVERSION VER_PRODUCTVERSION +FILEFLAGSMASK (VS_FF_DEBUG) +FILEFLAGS (VER_DEBUG) +FILEOS VOS__WINDOWS32 +FILETYPE VFT_DLL +FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", "Intrepid Control Systems, Inc." + VALUE "FileDescription", "Intrepid Control Systems Open Device Communication C API" + VALUE "FileVersion", VER_FILEVERSION_STR + VALUE "InternalName", "icsneo.dll" + VALUE "LegalCopyright", "Intrepid Control Systems, Inc. (C) 2018-2024" + VALUE "OriginalFilename", "icsneo.dll" + VALUE "ProductName", "libicsneo" + VALUE "ProductVersion", VER_PRODUCTVERSION_STR + END + END + + BLOCK "VarFileInfo" + BEGIN + /* The following line should only be modified for localized versions. */ + /* It consists of any number of WORD,WORD pairs, with each pair */ + /* describing a language,codepage combination supported by the file. */ + /* */ + /* For example, a file might have values "0x409,1252" indicating that it */ + /* supports English language (0x409) in the Windows ANSI codepage (1252). */ + + VALUE "Translation", 0x409, 1252 + + END +END \ No newline at end of file diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 6379bdb..800349c 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,6 +1,7 @@ -option(LIBICSNEO_BUILD_C_INTERACTIVE_EXAMPLE "Build the command-line interactive C example." ON) option(LIBICSNEO_BUILD_C_SIMPLE_EXAMPLE "Build the command-line simple C example." ON) -option(LIBICSNEO_BUILD_C_LEGACY_EXAMPLE "Build the command-line simple C example." ON) +option(LIBICSNEO_BUILD_C_LEGACY_INTERACTIVE_EXAMPLE "Build the command-line interactive C example." ON) +option(LIBICSNEO_BUILD_C_LEGACY_SIMPLE_EXAMPLE "Build the command-line simple C example." ON) +option(LIBICSNEO_BUILD_C_LEGACY_LEGACY_EXAMPLE "Build the command-line simple C example." ON) option(LIBICSNEO_BUILD_CPP_SIMPLE_EXAMPLE "Build the simple C++ example." ON) option(LIBICSNEO_BUILD_CPP_INTERACTIVE_EXAMPLE "Build the command-line interactive C++ example." ON) option(LIBICSNEO_BUILD_CPP_A2B_EXAMPLE "Build the A2B example." ON) @@ -15,16 +16,20 @@ option(LIBICSNEO_BUILD_CPP_APP_ERROR_EXAMPLE "Build the app error example." ON) # option(LIBICSNEO_BUILD_CSHARP_INTERACTIVE_EXAMPLE "Build the command-line interactive C# example." OFF) # option(LIBICSNEO_BUILD_JAVA_INTERACTIVE_EXAMPLE "Build the command-line interactive Java example." OFF) -if(LIBICSNEO_BUILD_C_INTERACTIVE_EXAMPLE) - add_subdirectory(c/interactive) -endif() - if(LIBICSNEO_BUILD_C_SIMPLE_EXAMPLE) add_subdirectory(c/simple) endif() -if(LIBICSNEO_BUILD_C_LEGACY_EXAMPLE) - add_subdirectory(c/legacy) +if(LIBICSNEO_BUILD_C_LEGACY_INTERACTIVE_EXAMPLE) + add_subdirectory(c_legacy/interactive) +endif() + +if(LIBICSNEO_BUILD_C_LEGACY_SIMPLE_EXAMPLE) + add_subdirectory(c_legacy/simple) +endif() + +if(LIBICSNEO_BUILD_C_LEGACY_LEGACY_EXAMPLE) + add_subdirectory(c_legacy/legacy) endif() if(LIBICSNEO_BUILD_CPP_SIMPLE_EXAMPLE) diff --git a/examples/c/simple/CMakeLists.txt b/examples/c/simple/CMakeLists.txt index faf526a..36ed1b5 100644 --- a/examples/c/simple/CMakeLists.txt +++ b/examples/c/simple/CMakeLists.txt @@ -1,5 +1,5 @@ -add_executable(libicsneoc-simple-lin-example lin/main.c) +add_executable(libicsneo-simple-example src/main.c) if(UNIX) - target_link_libraries(libicsneoc-simple-lin-example ${CMAKE_DL_LIBS}) + target_link_libraries(libicsneo-simple-example ${CMAKE_DL_LIBS}) endif() -target_link_libraries(libicsneoc-simple-lin-example icsneoc) \ No newline at end of file +target_link_libraries(libicsneo-simple-example icsneo) \ No newline at end of file diff --git a/examples/c/simple/src/main.c b/examples/c/simple/src/main.c new file mode 100644 index 0000000..0a11cae --- /dev/null +++ b/examples/c/simple/src/main.c @@ -0,0 +1,61 @@ +#include + +#include + + +int main(int argc, char* argv[]) { + (void)argc; + (void)argv; + + icsneo_device_t* devices[255] = {0}; + uint32_t devices_count = 255; + + if (icsneo_find(devices, &devices_count, NULL) != icsneo_error_success) { + printf("Failed to find devices\n"); + return 1; + }; + + printf("Found %u devices\n", devices_count); + + for (uint32_t i = 0; i < devices_count; i++) { + icsneo_device_t* device = devices[i]; + + const char description[255] = {0}; + uint32_t description_length = 255; + icsneo_error_t res = icsneo_device_describe(device, description, &description_length); + if (res != icsneo_error_success) { + printf("Failed to get device description %d\n", res); + return 1; + }; + + icsneo_open_options_t options = icsneo_open_options_none; + res = icsneo_get_open_options(device, &options); + if (res != icsneo_error_success) { + printf("Failed to get open options %d\n", res); + return 1; + } + // Disable Syncing RTC + options &= ~icsneo_open_options_sync_rtc; + res = icsneo_set_open_options(device, options); + if (res != icsneo_error_success) { + printf("Failed to set open options %d\n", res); + return 1; + } + + printf("Opening device: %s...\n", description); + res = icsneo_open(device); + if (res != icsneo_error_success) { + printf("Failed to open device %d\n", res); + return 1; + }; + + printf("Closing device: %s...\n", description); + res = icsneo_close(device); + if (res != icsneo_error_success) { + printf("Failed to close device %d\n", res); + return 1; + }; + } + + return 0; +} diff --git a/examples/c/interactive/CMakeLists.txt b/examples/c_legacy/interactive/CMakeLists.txt similarity index 100% rename from examples/c/interactive/CMakeLists.txt rename to examples/c_legacy/interactive/CMakeLists.txt diff --git a/examples/c/interactive/README.md b/examples/c_legacy/interactive/README.md similarity index 100% rename from examples/c/interactive/README.md rename to examples/c_legacy/interactive/README.md diff --git a/examples/c/interactive/src/main.c b/examples/c_legacy/interactive/src/main.c similarity index 100% rename from examples/c/interactive/src/main.c rename to examples/c_legacy/interactive/src/main.c diff --git a/examples/c/legacy/CMakeLists.txt b/examples/c_legacy/legacy/CMakeLists.txt similarity index 100% rename from examples/c/legacy/CMakeLists.txt rename to examples/c_legacy/legacy/CMakeLists.txt diff --git a/examples/c/legacy/README.md b/examples/c_legacy/legacy/README.md similarity index 100% rename from examples/c/legacy/README.md rename to examples/c_legacy/legacy/README.md diff --git a/examples/c/legacy/deviceSettings/main.c b/examples/c_legacy/legacy/deviceSettings/main.c similarity index 100% rename from examples/c/legacy/deviceSettings/main.c rename to examples/c_legacy/legacy/deviceSettings/main.c diff --git a/examples/c/legacy/lin/main.c b/examples/c_legacy/legacy/lin/main.c similarity index 100% rename from examples/c/legacy/lin/main.c rename to examples/c_legacy/legacy/lin/main.c diff --git a/examples/c_legacy/simple/CMakeLists.txt b/examples/c_legacy/simple/CMakeLists.txt new file mode 100644 index 0000000..faf526a --- /dev/null +++ b/examples/c_legacy/simple/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(libicsneoc-simple-lin-example lin/main.c) +if(UNIX) + target_link_libraries(libicsneoc-simple-lin-example ${CMAKE_DL_LIBS}) +endif() +target_link_libraries(libicsneoc-simple-lin-example icsneoc) \ No newline at end of file diff --git a/examples/c/simple/README.md b/examples/c_legacy/simple/README.md similarity index 100% rename from examples/c/simple/README.md rename to examples/c_legacy/simple/README.md diff --git a/examples/c/simple/lin/main.c b/examples/c_legacy/simple/lin/main.c similarity index 100% rename from examples/c/simple/lin/main.c rename to examples/c_legacy/simple/lin/main.c diff --git a/include/icsneo/icsneo.h b/include/icsneo/icsneo.h new file mode 100644 index 0000000..fb9dee5 --- /dev/null +++ b/include/icsneo/icsneo.h @@ -0,0 +1,124 @@ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_WIN32) || defined(_WIN64) + // Microsoft + #define EXPORT __declspec(dllexport) + #define IMPORT __declspec(dllimport) +#elif defined(__GNUC__) + // GCC + #define EXPORT __attribute__((visibility("default"))) + #define IMPORT +#else + // do nothing and hope for the best? + #define EXPORT + #define IMPORT + #pragma warning Unknown dynamic link import/export semantics. +#endif + +#ifdef ICSNEO_EXPORTS +#define ICSNEO_API EXPORT +#else +#define ICSNEO_API IMPORT +#endif + +/** @brief icsneo_device_t opaque struct definition + * + * This object represents a single device found on the system. + * + * @see icsneo_find_devices + */ +typedef struct icsneo_device_t icsneo_device_t; + +typedef enum _icsneo_error_t { + icsneo_error_success, + icsneo_error_invalid_parameters, + icsneo_error_open_failed, + icsneo_error_open_gonline_failed, + icsneo_error_open_message_polling_failed, + icsneo_error_open_sync_rtc_failed, +} _icsneo_error_t; + +typedef uint32_t icsneo_error_t; + +typedef enum _icsneo_open_options_t { + icsneo_open_options_none = 0x0, + icsneo_open_options_go_online = 0x1, + icsneo_open_options_enable_message_polling = 0x2, + icsneo_open_options_sync_rtc = 0x4, + icsneo_open_options_enable_auto_update = 0x8, + icsneo_open_options_force_update = 0x10, +} _icsneo_open_options_t; + +typedef uint32_t icsneo_open_options_t; + +/** @brief Find all hardware attached to the system. + * + * @param[out] icsneo_device_t array of devices to be filled with found devices. Last element will be NULL. + * @param[in,out] uint32_t* devices_count Size of the devices array. Modified with the number of devices found. + * @param[in] void* reserved Reserved for future use. Currently unused and must be set to NULL. + * + * @return icsneo_error_t icsneo_error_success if successful, icsneo_error_failure otherwise. +*/ +ICSNEO_API icsneo_error_t icsneo_find(icsneo_device_t** devices, uint32_t* devices_count, void* reserved); + +/** @brief Check to make sure a device is valid. + * + * @param[in] icsneo_device_t device The device to check. + * + * @return icsneo_error_t icsneo_error_success if successful, icsneo_error_invalid_parameters otherwise. +*/ +ICSNEO_API icsneo_error_t icsneo_device_is_valid(icsneo_device_t* device); + +/** @brief Get the open options for a device + * + * @param[in] icsneo_device_t device The device to set options for. + * @param[in] icsneo_open_options_t options Options to set for the device. + * + * @return icsneo_error_t icsneo_error_success if successful, icsneo_error_invalid_parameters otherwise. +*/ +ICSNEO_API icsneo_error_t icsneo_get_open_options(icsneo_device_t* device, icsneo_open_options_t* options); + +/** @brief Set the open options for a device + * + * @param[in] icsneo_device_t device The device to set options for. + * @param[in] icsneo_open_options_t options Options to set for the device. + * + * @return icsneo_error_t icsneo_error_success if successful, icsneo_error_invalid_parameters otherwise. +*/ +ICSNEO_API icsneo_error_t icsneo_set_open_options(icsneo_device_t* device, icsneo_open_options_t options); + +/** @brief Open a connection to a device. + * + * After a successful call to this function, icsneo_close() must be called to close the device. + * + * @param[in] icsneo_device_t device The device to open. + * @param[out] icsneo_handle_t* handle Pointer to a handle to the opened device. Will be NULL on failure. + * + * @return icsneo_error_t icsneo_error_success if successful, icsneo_error_failure otherwise. + * + * @see icsneo_close + */ +ICSNEO_API icsneo_error_t icsneo_open(icsneo_device_t* device); + +/** @brief Close a connection to a previously opened device. + * + * After a successful call to icsneo_open(), this function must be called to close the device. + * An already closed device will still succeed. + * + * @param[in] icsneo_device_t device The device to close. + * + * @return icsneo_error_t icsneo_error_success if successful, icsneo_error_failure otherwise. + */ +ICSNEO_API icsneo_error_t icsneo_close(icsneo_device_t* device); + +ICSNEO_API icsneo_error_t icsneo_device_describe(icsneo_device_t* device, const char* value, uint32_t* value_length); +ICSNEO_API icsneo_error_t icsneo_device_type(icsneo_device_t* device, uint64_t* value); +ICSNEO_API icsneo_error_t icsneo_device_serial(icsneo_device_t* device, const char* value, uint32_t* value_length); + +#ifdef __cplusplus +} +#endif \ No newline at end of file