2025-01-08 06:26:36 -04:00
|
|
|
#include <iostream>
|
|
|
|
|
#include <stdexcept>
|
|
|
|
|
#include <optional>
|
2025-01-08 13:43:44 -04:00
|
|
|
#include <filesystem>
|
2025-01-08 06:26:36 -04:00
|
|
|
#include <senseApis/senseApiManager.h>
|
2025-01-08 11:49:28 -04:00
|
|
|
#include <senseApis/senseApiLib.h>
|
2025-01-08 13:43:44 -04:00
|
|
|
#include <opts.h>
|
2025-09-10 11:37:35 -04:00
|
|
|
#include <asynchronousBridge.h>
|
2025-09-10 18:12:08 -04:00
|
|
|
#include <asynchronousContinuation.h>
|
2025-09-10 11:37:35 -04:00
|
|
|
#include <asynchronousLoop.h>
|
2025-01-08 13:43:44 -04:00
|
|
|
#include <user/senseApiDesc.h>
|
2025-01-12 14:31:33 -04:00
|
|
|
#include <deviceManager/deviceManager.h>
|
2025-01-08 13:43:44 -04:00
|
|
|
|
|
|
|
|
namespace fs = std::filesystem;
|
2025-01-08 06:26:36 -04:00
|
|
|
|
2025-07-22 06:48:04 -04:00
|
|
|
namespace smo {
|
2025-01-08 11:49:28 -04:00
|
|
|
namespace sense_api {
|
2025-01-08 06:26:36 -04:00
|
|
|
|
2025-01-14 14:11:40 -04:00
|
|
|
/**
|
|
|
|
|
* @brief Searches for a library in predefined locations
|
|
|
|
|
* @param libraryPath The name or path of the library to find
|
|
|
|
|
* @return Optional containing the full path if found in search paths, nullopt
|
|
|
|
|
* if not
|
|
|
|
|
*
|
|
|
|
|
* Searches for the library in the following locations in order:
|
|
|
|
|
* 1. Custom path specified by --sense-api-lib-path option (if provided)
|
|
|
|
|
* 2. Current working directory
|
|
|
|
|
* 3. Directory containing the executable
|
|
|
|
|
*
|
|
|
|
|
* If the library is not found in any of these locations, returns nullopt and
|
|
|
|
|
* falls back to system default library search paths (LD_LIBRARY_PATH, etc.)
|
|
|
|
|
*/
|
2025-07-24 02:12:31 -04:00
|
|
|
static std::optional<std::string> searchForLibInSmoSearchPaths(
|
2025-01-08 13:43:44 -04:00
|
|
|
const std::string& libraryPath)
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::string> searchPaths = {
|
|
|
|
|
fs::current_path().string(),
|
|
|
|
|
fs::path("/proc/self/exe").parent_path().string()
|
|
|
|
|
};
|
|
|
|
|
|
2025-07-23 00:12:50 -04:00
|
|
|
const auto& options = OptionParser::getOptions();
|
|
|
|
|
if (!options.senseApiLibPath.empty())
|
2025-01-08 15:08:23 -04:00
|
|
|
{
|
2025-07-23 00:12:50 -04:00
|
|
|
// Insert all sense API library paths at the beginning of search paths
|
2025-01-08 15:08:23 -04:00
|
|
|
searchPaths.insert(
|
2025-07-23 00:12:50 -04:00
|
|
|
searchPaths.begin(),
|
|
|
|
|
options.senseApiLibPath.begin(),
|
|
|
|
|
options.senseApiLibPath.end());
|
2025-01-08 15:08:23 -04:00
|
|
|
}
|
|
|
|
|
|
2025-01-08 13:43:44 -04:00
|
|
|
for (const auto& path : searchPaths)
|
|
|
|
|
{
|
|
|
|
|
fs::path fullPath = fs::path(path) / libraryPath;
|
|
|
|
|
if (fs::exists(fullPath))
|
|
|
|
|
{
|
|
|
|
|
return fullPath.string();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::cerr << std::string(__func__) + ": library '"
|
|
|
|
|
+ libraryPath + "' isn't in search bespoke search paths: ";
|
2025-01-13 21:57:11 -04:00
|
|
|
for (const auto& path : searchPaths) {
|
2025-01-08 13:43:44 -04:00
|
|
|
std::cerr << path << " ";
|
|
|
|
|
}
|
|
|
|
|
std::cerr << std::endl;
|
2025-01-13 21:57:11 -04:00
|
|
|
std::cerr << "Trying to load " + libraryPath + " from system default "
|
|
|
|
|
"search paths\n";
|
2025-01-08 13:43:44 -04:00
|
|
|
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-09 12:02:40 -04:00
|
|
|
/* Local static function to wrap ComponentThread::getSelf for SmoCallbacks */
|
|
|
|
|
static std::shared_ptr<ComponentThread> ComponentThread_getSelf()
|
|
|
|
|
{
|
|
|
|
|
return ComponentThread::getSelf();
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-24 06:00:35 -04:00
|
|
|
/* Hooks to be provided to senseApiLibs, enabling them to call into Salmanoff
|
|
|
|
|
* code.
|
|
|
|
|
*/
|
2025-09-04 17:45:11 -04:00
|
|
|
static SmoCallbacks smoCallbacks =
|
2025-07-24 06:00:35 -04:00
|
|
|
{
|
2025-09-09 12:02:40 -04:00
|
|
|
.searchForLibInSmoSearchPaths = searchForLibInSmoSearchPaths,
|
|
|
|
|
.ComponentThread_getSelf = ComponentThread_getSelf
|
2025-07-24 06:00:35 -04:00
|
|
|
};
|
|
|
|
|
|
2025-09-04 17:35:49 -04:00
|
|
|
/* Static file-scope threading model object for senseApi libraries */
|
|
|
|
|
static SmoThreadingModelDesc smoThreadingModelDesc = {
|
|
|
|
|
.componentThread = nullptr
|
|
|
|
|
};
|
|
|
|
|
|
2025-07-24 02:12:31 -04:00
|
|
|
std::optional<std::string> SenseApiManager::searchForLibInSmoSearchPaths(
|
|
|
|
|
const std::string& libraryPath)
|
|
|
|
|
{
|
|
|
|
|
return ::smo::sense_api::searchForLibInSmoSearchPaths(libraryPath);
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-04 17:35:49 -04:00
|
|
|
SenseApiLib& SenseApiManager::loadSenseApiLib(
|
|
|
|
|
const std::string& libraryPath,
|
2025-09-12 16:09:26 -04:00
|
|
|
const std::shared_ptr<ComponentThread>& componentThread
|
2025-09-04 17:35:49 -04:00
|
|
|
)
|
2025-01-08 06:26:36 -04:00
|
|
|
{
|
2025-07-24 02:12:31 -04:00
|
|
|
std::optional<std::string> fullPath = searchForLibInSmoSearchPaths(
|
|
|
|
|
libraryPath);
|
2025-01-09 06:03:43 -04:00
|
|
|
std::string resolvedPath = fullPath.value_or(libraryPath);
|
2025-01-08 06:26:36 -04:00
|
|
|
|
|
|
|
|
// Clear any existing error
|
|
|
|
|
dlerror();
|
2025-01-12 09:44:08 -04:00
|
|
|
auto dlopen_handle = std::unique_ptr<void, SenseApiLib::DlCloser>(
|
2025-01-09 06:03:43 -04:00
|
|
|
dlopen(resolvedPath.c_str(), RTLD_LAZY));
|
|
|
|
|
if (!dlopen_handle && fullPath.has_value())
|
2025-01-08 13:43:44 -04:00
|
|
|
{
|
|
|
|
|
// Fallback to using the supplied libraryPath
|
|
|
|
|
dlerror();
|
2025-01-09 06:03:43 -04:00
|
|
|
dlopen_handle.reset(dlopen(libraryPath.c_str(), RTLD_LAZY));
|
2025-01-08 13:43:44 -04:00
|
|
|
}
|
|
|
|
|
|
2025-01-09 06:03:43 -04:00
|
|
|
if (!dlopen_handle)
|
2025-01-08 06:26:36 -04:00
|
|
|
{
|
2025-01-08 15:08:51 -04:00
|
|
|
const char *dlerr = dlerror();
|
|
|
|
|
|
|
|
|
|
std::string error = (dlerr
|
|
|
|
|
? dlerr
|
|
|
|
|
: "Unknown error while opening shlib");
|
2025-01-08 06:26:36 -04:00
|
|
|
throw std::runtime_error(
|
2025-01-08 15:08:51 -04:00
|
|
|
std::string(__func__) + ": Cannot load library '"
|
2025-01-08 06:26:36 -04:00
|
|
|
+ libraryPath + "': "
|
|
|
|
|
+ error);
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-08 13:43:44 -04:00
|
|
|
// Initialize getSenseApiDescriptor
|
2025-07-22 06:48:04 -04:00
|
|
|
auto func = reinterpret_cast<SMO_GET_SENSE_API_DESC_FN_TYPEDEF *>(
|
|
|
|
|
dlsym(dlopen_handle.get(), SMO_GET_SENSE_API_DESC_FN_NAME_STR));
|
2025-01-08 13:43:44 -04:00
|
|
|
if (!func)
|
|
|
|
|
{
|
|
|
|
|
throw std::runtime_error(
|
2025-01-08 15:09:18 -04:00
|
|
|
std::string(__func__) + ": dlsym('"
|
2025-07-22 06:48:04 -04:00
|
|
|
SMO_GET_SENSE_API_DESC_FN_NAME_STR "') failed for library '"
|
2025-01-09 06:03:43 -04:00
|
|
|
+ libraryPath + "'");
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-04 17:35:49 -04:00
|
|
|
// Check if the static threading model obj is null and initialize if needed
|
|
|
|
|
if (!smoThreadingModelDesc.componentThread) {
|
|
|
|
|
smoThreadingModelDesc.componentThread = componentThread;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const SenseApiDesc &libApiDesc = func(
|
2025-09-04 17:45:11 -04:00
|
|
|
smoCallbacks, smoThreadingModelDesc);
|
2025-09-04 17:35:49 -04:00
|
|
|
|
|
|
|
|
auto lib = std::make_shared<SenseApiLib>(
|
2025-01-09 06:03:43 -04:00
|
|
|
libraryPath, dlopen_handle.release(), func);
|
|
|
|
|
lib->setSenseApiDesc(libApiDesc);
|
2025-08-29 13:19:33 -04:00
|
|
|
senseApiLibs.push_back(lib);
|
2025-01-08 06:26:36 -04:00
|
|
|
return *senseApiLibs.back();
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-29 13:19:33 -04:00
|
|
|
std::optional<std::shared_ptr<SenseApiLib>>
|
2025-01-08 11:49:28 -04:00
|
|
|
SenseApiManager::getSenseApiLib(const std::string& libraryPath)
|
2025-01-08 06:26:36 -04:00
|
|
|
{
|
|
|
|
|
auto it = std::find_if(senseApiLibs.begin(), senseApiLibs.end(),
|
2025-08-29 13:19:33 -04:00
|
|
|
[&libPath = libraryPath](const std::shared_ptr<SenseApiLib>& lib) {
|
2025-01-08 06:26:36 -04:00
|
|
|
return lib->libraryPath == libPath;
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
2025-08-29 13:19:33 -04:00
|
|
|
if (it != senseApiLibs.end()) { return *it; }
|
2025-01-08 06:26:36 -04:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-29 13:19:33 -04:00
|
|
|
std::optional<std::shared_ptr<SenseApiLib>>
|
2025-01-12 14:31:33 -04:00
|
|
|
SenseApiManager::getSenseApiLibByApiName(const std::string& apiName)
|
|
|
|
|
{
|
|
|
|
|
auto it = std::find_if(senseApiLibs.begin(), senseApiLibs.end(),
|
2025-08-29 13:19:33 -04:00
|
|
|
[&apiName](const std::shared_ptr<SenseApiLib>& lib) {
|
2025-01-13 11:53:38 -04:00
|
|
|
return lib->senseApiDesc.name == apiName;
|
2025-01-12 14:31:33 -04:00
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
2025-08-29 13:19:33 -04:00
|
|
|
if (it != senseApiLibs.end()) { return *it; }
|
2025-01-12 14:31:33 -04:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-08 06:26:36 -04:00
|
|
|
void SenseApiManager::unloadSenseApiLib(const std::string& libraryPath)
|
|
|
|
|
{
|
|
|
|
|
auto it = std::find_if(senseApiLibs.begin(), senseApiLibs.end(),
|
2025-08-29 13:19:33 -04:00
|
|
|
[&lpath = libraryPath](const std::shared_ptr<SenseApiLib>& lib) {
|
2025-01-08 06:26:36 -04:00
|
|
|
return lib->libraryPath == lpath;
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (it != senseApiLibs.end())
|
|
|
|
|
{
|
|
|
|
|
senseApiLibs.erase(it);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::cerr << std::string(__func__) + ": Library not found: "
|
|
|
|
|
<< libraryPath << '\n';
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-12 09:44:49 -04:00
|
|
|
void SenseApiManager::unloadAllSenseApiLibs(void)
|
|
|
|
|
{
|
|
|
|
|
senseApiLibs.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-04 17:35:49 -04:00
|
|
|
void SenseApiManager::loadAllSenseApiLibsFromOptions(
|
2025-09-12 16:09:26 -04:00
|
|
|
const std::shared_ptr<ComponentThread>& componentThread
|
2025-09-04 17:35:49 -04:00
|
|
|
)
|
2025-01-08 15:06:31 -04:00
|
|
|
{
|
|
|
|
|
const auto& options = OptionParser::getOptions();
|
|
|
|
|
for (const auto& libPath : options.senseApiLibs) {
|
2025-09-04 17:35:49 -04:00
|
|
|
loadSenseApiLib(libPath, componentThread);
|
2025-01-08 15:06:31 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-11 06:40:43 -04:00
|
|
|
std::string SenseApiManager::stringifyLibs() const
|
|
|
|
|
{
|
|
|
|
|
std::string result;
|
|
|
|
|
for (const auto& lib : senseApiLibs) {
|
|
|
|
|
result += lib->stringify() + "\n";
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-12 09:44:49 -04:00
|
|
|
void SenseApiManager::initializeSenseApiLib(SenseApiLib& lib)
|
|
|
|
|
{
|
2025-01-13 21:57:11 -04:00
|
|
|
if (!lib.senseApiDesc.sal_mgmt_libOps.initializeInd)
|
2025-01-12 09:44:49 -04:00
|
|
|
{
|
|
|
|
|
throw std::runtime_error(
|
|
|
|
|
std::string(__func__) + ": initializeInd() is NULL for library '"
|
|
|
|
|
+ lib.libraryPath + "'");
|
|
|
|
|
}
|
2025-01-13 21:57:11 -04:00
|
|
|
lib.senseApiDesc.sal_mgmt_libOps.initializeInd();
|
2025-01-12 09:44:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SenseApiManager::finalizeSenseApiLib(SenseApiLib& lib)
|
|
|
|
|
{
|
2025-01-13 21:57:11 -04:00
|
|
|
if (!lib.senseApiDesc.sal_mgmt_libOps.finalizeInd)
|
2025-01-12 09:44:49 -04:00
|
|
|
{
|
|
|
|
|
throw std::runtime_error(
|
|
|
|
|
std::string(__func__) + ": finalizeInd() is NULL for library '"
|
|
|
|
|
+ lib.libraryPath + "'");
|
|
|
|
|
}
|
2025-01-13 21:57:11 -04:00
|
|
|
lib.senseApiDesc.sal_mgmt_libOps.finalizeInd();
|
2025-01-12 09:44:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SenseApiManager::initializeAllSenseApiLibs(void)
|
|
|
|
|
{
|
|
|
|
|
for (auto& lib : senseApiLibs) {
|
|
|
|
|
initializeSenseApiLib(*lib);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SenseApiManager::finalizeAllSenseApiLibs(void)
|
|
|
|
|
{
|
|
|
|
|
for (auto& lib : senseApiLibs) {
|
|
|
|
|
finalizeSenseApiLib(*lib);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-10 06:51:55 -04:00
|
|
|
void SenseApiManager::attachSenseDeviceReq(
|
|
|
|
|
const std::shared_ptr<device::DeviceAttachmentSpec>& spec,
|
|
|
|
|
attachSenseDeviceReqCbFn cb
|
2025-08-29 09:50:26 -04:00
|
|
|
)
|
2025-01-12 14:31:33 -04:00
|
|
|
{
|
2025-09-10 06:51:55 -04:00
|
|
|
/** FIXME:
|
|
|
|
|
* We should acquire a spinlock here to ensure that the device isn't added
|
|
|
|
|
* in the interim while the async op executes.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
auto libOpt = getSenseApiLibByApiName(spec->api);
|
2025-01-12 14:31:33 -04:00
|
|
|
if (!libOpt)
|
|
|
|
|
{
|
|
|
|
|
throw std::runtime_error(
|
|
|
|
|
std::string(__func__) + ": No library found for API '"
|
2025-08-29 09:50:26 -04:00
|
|
|
+ spec->api + "'");
|
2025-01-12 14:31:33 -04:00
|
|
|
}
|
2025-08-29 13:19:33 -04:00
|
|
|
auto& lib = *libOpt.value();
|
2025-01-13 21:57:11 -04:00
|
|
|
if (!lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq)
|
2025-01-12 14:31:33 -04:00
|
|
|
{
|
|
|
|
|
throw std::runtime_error(
|
|
|
|
|
std::string(__func__) + ": attachDeviceReq() is NULL for library '"
|
|
|
|
|
+ lib.libraryPath + "'");
|
|
|
|
|
}
|
2025-09-10 06:51:55 -04:00
|
|
|
lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq(spec, cb);
|
2025-01-12 14:31:33 -04:00
|
|
|
}
|
|
|
|
|
|
2025-09-10 06:51:55 -04:00
|
|
|
void SenseApiManager::detachSenseDeviceReq(
|
|
|
|
|
const std::shared_ptr<device::DeviceAttachmentSpec>& spec,
|
|
|
|
|
detachSenseDeviceReqCbFn cb
|
2025-08-29 09:50:26 -04:00
|
|
|
)
|
2025-01-12 14:31:33 -04:00
|
|
|
{
|
2025-09-10 06:51:55 -04:00
|
|
|
/** FIXME:
|
|
|
|
|
* We should acquire a spinlock here to ensure that the device isn't removed
|
|
|
|
|
* in the interim while the async op executes.
|
|
|
|
|
*/
|
|
|
|
|
|
2025-08-29 09:50:26 -04:00
|
|
|
auto libOpt = getSenseApiLibByApiName(spec->api);
|
2025-01-12 14:31:33 -04:00
|
|
|
if (!libOpt)
|
|
|
|
|
{
|
|
|
|
|
throw std::runtime_error(
|
|
|
|
|
std::string(__func__) + ": No library found for API '"
|
2025-08-29 09:50:26 -04:00
|
|
|
+ spec->api + "'");
|
2025-01-12 14:31:33 -04:00
|
|
|
}
|
2025-08-29 13:19:33 -04:00
|
|
|
auto& lib = *libOpt.value();
|
2025-01-13 21:57:11 -04:00
|
|
|
if (!lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq)
|
2025-01-12 14:31:33 -04:00
|
|
|
{
|
|
|
|
|
throw std::runtime_error(
|
|
|
|
|
std::string(__func__) + ": detachDeviceReq() is NULL for library '"
|
|
|
|
|
+ lib.libraryPath + "'");
|
|
|
|
|
}
|
2025-09-10 06:51:55 -04:00
|
|
|
lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq(spec, cb);
|
2025-01-12 14:31:33 -04:00
|
|
|
}
|
|
|
|
|
|
2025-09-10 18:12:08 -04:00
|
|
|
class SenseApiManager::AttachAllSenseDevicesFromSpecsReq
|
|
|
|
|
: public AsynchronousContinuation<attachAllSenseDevicesFromSpecsReqCbFn>
|
2025-01-12 14:31:33 -04:00
|
|
|
{
|
2025-09-10 18:12:08 -04:00
|
|
|
public:
|
|
|
|
|
AttachAllSenseDevicesFromSpecsReq(
|
|
|
|
|
const unsigned int totalNSpecs,
|
|
|
|
|
attachAllSenseDevicesFromSpecsReqCbFn cb)
|
|
|
|
|
: AsynchronousContinuation(std::move(cb)),
|
|
|
|
|
loop(totalNSpecs)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
// Callback methods for the attachment sequence
|
|
|
|
|
void attachAllSenseDevicesFromSpecsReq1(
|
|
|
|
|
std::shared_ptr<AttachAllSenseDevicesFromSpecsReq> context,
|
|
|
|
|
bool success, std::shared_ptr<device::DeviceAttachmentSpec> spec
|
|
|
|
|
)
|
2025-09-10 06:51:55 -04:00
|
|
|
{
|
2025-09-10 18:12:08 -04:00
|
|
|
if (!success)
|
|
|
|
|
{
|
|
|
|
|
std::cerr << __func__ << ": Failed to attach device: "
|
|
|
|
|
<< spec->deviceIdentifier << "\n";
|
|
|
|
|
}
|
2025-09-10 11:37:35 -04:00
|
|
|
|
2025-09-10 18:12:08 -04:00
|
|
|
if (!context->loop.incrementSuccessOrFailureAndTestForCompletionDueTo(
|
|
|
|
|
success))
|
|
|
|
|
{
|
|
|
|
|
return;
|
2025-09-10 06:51:55 -04:00
|
|
|
}
|
|
|
|
|
|
2025-09-10 18:12:08 -04:00
|
|
|
if (OptionParser::getOptions().verbose)
|
|
|
|
|
{
|
|
|
|
|
std::cout << __func__ << ": " << context->loop.nSucceeded.load()
|
|
|
|
|
<< " devices attached, "
|
|
|
|
|
<< context->loop.nFailed.load() << " devices failed\n";
|
|
|
|
|
}
|
2025-09-10 06:51:55 -04:00
|
|
|
|
2025-09-10 18:12:08 -04:00
|
|
|
context->originalCbFn(context->loop);
|
2025-09-10 06:51:55 -04:00
|
|
|
}
|
|
|
|
|
|
2025-09-12 16:09:26 -04:00
|
|
|
void callOriginalCallback()
|
|
|
|
|
{
|
|
|
|
|
originalCbFn(loop);
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-10 18:12:08 -04:00
|
|
|
public:
|
|
|
|
|
AsynchronousLoop loop;
|
|
|
|
|
};
|
2025-01-12 14:31:33 -04:00
|
|
|
|
2025-09-10 18:12:08 -04:00
|
|
|
void SenseApiManager::attachAllSenseDevicesFromSpecsReq(
|
|
|
|
|
attachAllSenseDevicesFromSpecsReqCbFn cb
|
|
|
|
|
)
|
2025-01-12 14:31:33 -04:00
|
|
|
{
|
2025-09-10 18:12:08 -04:00
|
|
|
// Create the attachment request object to hold state and callbacks
|
|
|
|
|
auto request = std::make_shared<AttachAllSenseDevicesFromSpecsReq>(
|
|
|
|
|
device::DeviceManager::deviceAttachmentSpecs.size(), std::move(cb));
|
2025-09-10 11:37:35 -04:00
|
|
|
|
2025-09-11 20:08:35 -04:00
|
|
|
if (request->loop.nTotalIsZero())
|
|
|
|
|
{
|
2025-09-12 16:09:26 -04:00
|
|
|
request->callOriginalCallback();
|
2025-09-11 20:08:35 -04:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-10 06:51:55 -04:00
|
|
|
for (const auto& spec : device::DeviceManager::deviceAttachmentSpecs)
|
|
|
|
|
{
|
|
|
|
|
try {
|
2025-09-10 18:12:08 -04:00
|
|
|
attachSenseDeviceReq(
|
|
|
|
|
spec,
|
|
|
|
|
std::bind(
|
|
|
|
|
&AttachAllSenseDevicesFromSpecsReq::attachAllSenseDevicesFromSpecsReq1,
|
|
|
|
|
request.get(), request,
|
|
|
|
|
std::placeholders::_1, std::placeholders::_2));
|
2025-09-10 06:51:55 -04:00
|
|
|
} catch (const std::exception& e) {
|
|
|
|
|
std::cerr << __func__ << ": Exception: " << e.what() << "\n";
|
2025-09-10 18:12:08 -04:00
|
|
|
if (request->loop.incrementSuccessOrFailureAndTestForCompletionDueTo(false))
|
2025-09-12 16:09:26 -04:00
|
|
|
{ request->callOriginalCallback(); }
|
2025-09-10 06:51:55 -04:00
|
|
|
}
|
|
|
|
|
}
|
2025-09-10 18:12:08 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SenseApiManager::DetachAllSenseDevicesReq
|
|
|
|
|
: public AttachAllSenseDevicesFromSpecsReq
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
using AttachAllSenseDevicesFromSpecsReq::AttachAllSenseDevicesFromSpecsReq;
|
2025-09-10 06:51:55 -04:00
|
|
|
|
2025-09-10 18:12:08 -04:00
|
|
|
void detachAllSenseDevicesReq1(
|
|
|
|
|
std::shared_ptr<DetachAllSenseDevicesReq> context,
|
|
|
|
|
bool success, std::shared_ptr<device::DeviceAttachmentSpec> spec
|
|
|
|
|
)
|
2025-09-10 06:51:55 -04:00
|
|
|
{
|
2025-09-10 18:12:08 -04:00
|
|
|
if (!success)
|
|
|
|
|
{
|
|
|
|
|
std::cerr << __func__ << ": Failed to detach device: "
|
|
|
|
|
<< spec->deviceIdentifier << "\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!context->loop.incrementSuccessOrFailureAndTestForCompletionDueTo(
|
|
|
|
|
success))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (OptionParser::getOptions().verbose)
|
|
|
|
|
{
|
|
|
|
|
std::cout << __func__ << ": " << context->loop.nSucceeded.load()
|
|
|
|
|
<< " devices detached, "
|
|
|
|
|
<< context->loop.nFailed.load() << " devices failed\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
context->originalCbFn(context->loop);
|
2025-09-10 06:51:55 -04:00
|
|
|
}
|
2025-09-12 16:09:26 -04:00
|
|
|
|
|
|
|
|
void callOriginalCallback()
|
|
|
|
|
{
|
|
|
|
|
originalCbFn(loop);
|
|
|
|
|
}
|
2025-09-10 18:12:08 -04:00
|
|
|
};
|
2025-09-10 06:51:55 -04:00
|
|
|
|
2025-09-10 18:12:08 -04:00
|
|
|
void SenseApiManager::detachAllSenseDevicesReq(
|
|
|
|
|
detachAllSenseDevicesReqCbFn cb
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
auto request = std::make_shared<DetachAllSenseDevicesReq>(
|
|
|
|
|
device::DeviceManager::deviceAttachmentSpecs.size(), std::move(cb));
|
|
|
|
|
|
2025-09-11 20:08:35 -04:00
|
|
|
if (request->loop.nTotalIsZero())
|
|
|
|
|
{
|
2025-09-12 16:09:26 -04:00
|
|
|
request->callOriginalCallback();
|
2025-09-11 20:08:35 -04:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-10 18:12:08 -04:00
|
|
|
for (const auto& spec : device::DeviceManager::deviceAttachmentSpecs)
|
2025-09-10 06:51:55 -04:00
|
|
|
{
|
2025-09-10 18:12:08 -04:00
|
|
|
try {
|
|
|
|
|
detachSenseDeviceReq(
|
|
|
|
|
spec,
|
|
|
|
|
std::bind(
|
|
|
|
|
&DetachAllSenseDevicesReq::detachAllSenseDevicesReq1,
|
|
|
|
|
request.get(), request,
|
|
|
|
|
std::placeholders::_1, std::placeholders::_2));
|
|
|
|
|
} catch (const std::exception& e) {
|
|
|
|
|
std::cerr << __func__ << ": Exception: " << e.what() << "\n";
|
2025-09-15 08:25:49 -04:00
|
|
|
if (request->loop
|
|
|
|
|
.incrementSuccessOrFailureAndTestForCompletionDueTo(false))
|
2025-09-12 16:09:26 -04:00
|
|
|
{
|
|
|
|
|
request->callOriginalCallback();
|
|
|
|
|
}
|
2025-09-10 18:12:08 -04:00
|
|
|
}
|
2025-09-10 06:51:55 -04:00
|
|
|
}
|
2025-01-12 14:31:33 -04:00
|
|
|
}
|
|
|
|
|
|
2025-01-08 11:49:28 -04:00
|
|
|
} // namespace sense_api
|
2025-07-22 06:48:04 -04:00
|
|
|
} // namespace smo
|