169 lines
5.5 KiB
C++
169 lines
5.5 KiB
C++
#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, icsneo_devicetype_t* value) {
|
|
if (!device || !device->device) {
|
|
return icsneo_error_invalid_parameters;
|
|
}
|
|
auto dev = device->device;
|
|
// TODO: We should expose these types
|
|
*value = dev->getType().getDeviceType();
|
|
|
|
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;
|
|
}
|