first commit, open and close work.

David Rebbe 2024-11-23 17:57:14 -05:00
parent dbe19a5616
commit ee341139c0
17 changed files with 461 additions and 13 deletions

View File

@ -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
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:>
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
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:>
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

View File

@ -0,0 +1,168 @@
#include <icsneo/icsneo.h>
#include <icsneo/device/device.h>
#include "icsneo/device/devicefinder.h"
#include <string>
#include <deque>
#include <algorithm>
using namespace icsneo;
typedef struct icsneo_device_t {
std::shared_ptr<Device> device;
icsneo_open_options_t options;
} icsneo_device_t;
static std::deque<std::shared_ptr<icsneo_device_t>> 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<icsneo_device_t>();
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<uint32_t>(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<uint32_t>(dev->describe().length()), *value_length).first;
*value_length = min_length;
// Copy the string into value
strncpy(const_cast<char *>(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<uint64_t>(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<uint32_t>(dev->getSerial().length()), *value_length).first;
*value_length = min_length;
// Copy the string into value
strncpy(const_cast<char *>(value), dev->getSerial().c_str(), min_length);
return icsneo_error_success;
}

View File

@ -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 <windows.h>
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

View File

@ -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)

View File

@ -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)
target_link_libraries(libicsneo-simple-example icsneo)

View File

@ -0,0 +1,61 @@
#include <icsneo/icsneo.h>
#include <stdio.h>
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;
}

View File

@ -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)

View File

@ -0,0 +1,124 @@
#include <stdint.h>
#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