blob: b96a3dbed6c86a65c5871c66a4dd7bb6c8b518a4 [file] [log] [blame] [edit]
#include "usb_monitor.hpp"
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <stdplus/print.hpp>
#include <atomic>
#include <chrono>
#include <csignal>
#include <iostream>
#include <map>
#include <sstream>
#include <string_view>
#include <thread>
#define SERVICE_NAME "xyz.openbmc_project.UsbDevices"
#define OBJECT_PATH "/xyz/openbmc_project/usbdevices"
struct DbusContext
{
sdbusplus::asio::object_server& objectServer;
std::map<std::string, std::shared_ptr<sdbusplus::asio::dbus_interface>>&
dIfaceMap;
};
void addUsbInfToDbus(
usbdevice::UsbInterface& usbInfInfo,
sdbusplus::asio::object_server& objectServer,
std::map<std::string, std::shared_ptr<sdbusplus::asio::dbus_interface>>&
dIfaceMap)
{
sdbusplus::message::object_path objPath(
std::string(OBJECT_PATH) + "/" + usbInfInfo.name);
std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
objectServer.add_interface(objPath, SERVICE_NAME);
iface->register_property("RootHubPath", usbInfInfo.rootHubPath,
sdbusplus::asio::PropertyPermission::readOnly);
iface->register_property("Product", usbInfInfo.product,
sdbusplus::asio::PropertyPermission::readOnly);
iface->register_property("VID", usbInfInfo.vendorId,
sdbusplus::asio::PropertyPermission::readOnly);
iface->register_property("PID", usbInfInfo.productId,
sdbusplus::asio::PropertyPermission::readOnly);
iface->register_property("UsbPort", usbInfInfo.port,
sdbusplus::asio::PropertyPermission::readOnly);
iface->register_property("Configuration", usbInfInfo.configuration,
sdbusplus::asio::PropertyPermission::readOnly);
iface->register_property("InterfaceString", usbInfInfo.interfaceString,
sdbusplus::asio::PropertyPermission::readOnly);
iface->register_property("InterfaceNum", usbInfInfo.interfaceNum,
sdbusplus::asio::PropertyPermission::readOnly);
iface->register_property("InterfaceClass", usbInfInfo.interfaceClass,
sdbusplus::asio::PropertyPermission::readOnly);
iface->register_property("InterfaceSubclass", usbInfInfo.interfaceSubclass,
sdbusplus::asio::PropertyPermission::readOnly);
iface->register_property("InterfaceProtocol", usbInfInfo.interfaceProtocol,
sdbusplus::asio::PropertyPermission::readOnly);
iface->initialize();
dIfaceMap.emplace(usbInfInfo.interfacePath, std::move(iface));
stdplus::println(stdout, "Added USB interface {}",
usbInfInfo.interfacePath);
}
void removeUsbIfaceFromDbus(
std::string_view infPath, sdbusplus::asio::object_server& objectServer,
std::map<std::string, std::shared_ptr<sdbusplus::asio::dbus_interface>>&
dIfaceMap)
{
auto it = dIfaceMap.find(infPath.data());
if (it == dIfaceMap.end())
{
stdplus::println(stderr, "Removed interface {} not found under Dbus",
infPath);
return;
}
std::shared_ptr<sdbusplus::asio::dbus_interface> iface = it->second;
objectServer.remove_interface(iface);
dIfaceMap.erase(it);
stdplus::println(stdout, "Removed USB interface: {}", infPath);
}
void onUsbAdd(usbdevice::UsbInterface& usbInf, void* context)
{
if (context == nullptr)
{
return;
}
DbusContext* dbCtx = static_cast<DbusContext*>(context);
addUsbInfToDbus(usbInf, dbCtx->objectServer, dbCtx->dIfaceMap);
}
void onUsbRemove(std::string_view infPath, void* context)
{
if (context == nullptr)
{
return;
}
DbusContext* dbCtx = static_cast<DbusContext*>(context);
removeUsbIfaceFromDbus(infPath, dbCtx->objectServer, dbCtx->dIfaceMap);
}
int main()
{
boost::asio::io_context io;
auto conn = std::make_shared<sdbusplus::asio::connection>(io);
conn->request_name(SERVICE_NAME);
auto objectServer =
sdbusplus::asio::object_server(conn, /*skipManager=*/true);
objectServer.add_manager(OBJECT_PATH);
auto monitor = usbdevice::UsbMonitor::create(io);
if (!monitor)
{
return -1;
}
stdplus::println(stdout, "Enumerating devices ---");
std::vector<usbdevice::UsbInterface> usbInterfaces =
monitor->getEndpoints();
if (usbInterfaces.empty())
{
std::cout << "No existing USB interfaces found.\n";
}
std::map<std::string, std::shared_ptr<sdbusplus::asio::dbus_interface>>
dIfaceMap;
for (auto inf : usbInterfaces)
{
addUsbInfToDbus(inf, objectServer, dIfaceMap);
}
DbusContext context = {objectServer, dIfaceMap};
int ret = monitor->monitor(onUsbAdd, onUsbRemove, &context);
if (ret != 0)
{
stdplus::println(stderr, "Failed to start USB monitor: {}", ret);
return -1;
}
stdplus::println(stdout, "Monitoring started");
io.run();
return 0;
}