blob: f77b215ba1ca30850a02129c4f85adec58eb0f61 [file] [log] [blame] [edit]
#pragma once
#include <libudev.h>
#include <boost/asio/io_service.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <atomic>
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
namespace usbdevice
{
struct UsbInterface
{
std::string rootHubPath;
std::string port;
std::string vendorId;
std::string productId;
std::string manufacturer;
std::string product;
std::string name;
std::string configuration;
std::string interfacePath;
std::string interfaceString;
std::string interfaceNum;
std::string interfaceClass;
std::string interfaceSubclass;
std::string interfaceProtocol;
};
using AddCallback =
std::function<void(usbdevice::UsbInterface& usbInf, void* context)>;
using RemoveCallback =
std::function<void(std::string_view infPath, void* context)>;
namespace Udev
{
struct UdevDeleter
{
void operator()(udev* ptr) const
{
udev_unref(ptr);
}
};
struct EnumerateDeleter
{
void operator()(udev_enumerate* ptr) const
{
udev_enumerate_unref(ptr);
}
};
struct DeviceDeleter
{
void operator()(udev_device* ptr) const
{
udev_device_unref(ptr);
}
};
struct MonitorDeleter
{
void operator()(udev_monitor* ptr) const
{
udev_monitor_unref(ptr);
}
};
using UdevUniquePtr = std::unique_ptr<udev, UdevDeleter>;
using EnumerateUniquePtr = std::unique_ptr<udev_enumerate, EnumerateDeleter>;
using DeviceUniquePtr = std::unique_ptr<udev_device, DeviceDeleter>;
using MonitorUniquePtr = std::unique_ptr<udev_monitor, MonitorDeleter>;
} // namespace Udev
class UsbMonitor
{
public:
UsbMonitor() = delete;
UsbMonitor(const UsbMonitor&) = delete;
UsbMonitor& operator=(const UsbMonitor&) = delete;
~UsbMonitor();
/**
* @brief Creates a new UsbMonitor instance.
*
* @param io The boost::asio::io_context to use for asynchronous operations.
* @return A unique_ptr to a new UsbMonitor instance, or nullptr if creation
* fails.
*/
static std::unique_ptr<UsbMonitor> create(boost::asio::io_context& io);
/**
* @brief Get a list of currently connected USB interfaces.
*
* @return A vector of UsbInterface objects.
*/
std::vector<UsbInterface> getEndpoints();
/**
* @brief Starts monitoring for USB device add/remove events.
*
* @param onAdd Callback function to be invoked when a USB device is added.
* @param onRemove Callback function to be invoked when a USB device is
* removed.
* @param context User-defined context to be passed to the callbacks.
* @return 0 on success, or a negative error code on failure.
*/
int monitor(AddCallback onAdd, RemoveCallback onRemove, void* context);
private:
/** @brief Constructor for UsbMonitor.
*
* @param udevContext Unique pointer to the udev context.
* @param udevMonitor Unique pointer to the udev monitor.
* @param io The boost::asio::io_context to use.
*/
explicit UsbMonitor(Udev::UdevUniquePtr udevContext,
Udev::MonitorUniquePtr udevMonitor,
boost::asio::io_context& io);
/**
* @brief Processes a udev_device representing a USB interface and extracts
* relevant information into a UsbInterface struct.
*
* @param usbInf A pointer to the udev_device representing the USB
* interface.
* @param infPath The syspath of the USB interface.
* @return An optional UsbInterface object if processing is successful,
* otherwise std::nullopt.
*/
std::optional<UsbInterface> processUsbInf(udev_device* usbInf,
std::string_view infPath);
/**
* @brief Handles incoming udev events.
*
* This function is called asynchronously when a udev event occurs. It
* processes the event, determines if it's an add or remove event for a USB
* interface, and invokes the appropriate callback.
*
* @param ec The boost::system::error_code indicating the success or failure
* of the asynchronous wait operation.
*/
void handleUdevEvent(const boost::system::error_code& ec);
Udev::UdevUniquePtr udevCtx;
Udev::MonitorUniquePtr udevMonitor;
boost::asio::posix::stream_descriptor udevDescriptor;
AddCallback onAddCallback;
RemoveCallback onRemoveCallback;
void* cbContext;
};
} // namespace usbdevice