| #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 |