xref: /openbmc/phosphor-modbus/rtu/port/usb_port.cpp (revision b62e3dfe5505fdb8c2ab96156b62e3bfb878b7a6)
1 #include "usb_port.hpp"
2 
3 #include "common/entity_manager_interface.hpp"
4 #include "port_factory.hpp"
5 
6 #include <fcntl.h>
7 
8 #include <phosphor-logging/lg2.hpp>
9 #include <xyz/openbmc_project/Configuration/USBPort/client.hpp>
10 
11 #include <filesystem>
12 #include <format>
13 #include <optional>
14 #include <regex>
15 
16 namespace phosphor::modbus::rtu::port
17 {
18 
19 PHOSPHOR_LOG2_USING;
20 
21 using USBPortConfigIntf =
22     sdbusplus::client::xyz::openbmc_project::configuration::USBPort<>;
23 
24 namespace config
25 {
26 
27 struct USBPortConfig : public PortFactoryConfig
28 {
29     std::string address = "unknown";
30     uint16_t port = 0;
31     uint16_t interface = 0;
32 
33     virtual ~USBPortConfig() = default;
34 };
35 
36 } // namespace config
37 
getDevicePath(const config::PortFactoryConfig & inConfig)38 static auto getDevicePath(const config::PortFactoryConfig& inConfig)
39     -> std::string
40 {
41     namespace fs = std::filesystem;
42     auto config = static_cast<const config::USBPortConfig&>(inConfig);
43 
44     std::regex pattern(
45         std::format("platform-{}\\.usb-usb.*{}-port{}", config.address,
46                     config.interface, config.port));
47     fs::path searchDir = "/dev/serial/by-path/";
48 
49     for (const auto& entry : fs::recursive_directory_iterator(searchDir))
50     {
51         if (entry.is_symlink())
52         {
53             auto filePath = entry.path();
54             if (std::regex_search(filePath.filename().string(), pattern))
55             {
56                 return ("/dev/" +
57                         fs::read_symlink(filePath).filename().string());
58             }
59         }
60     }
61 
62     throw std::runtime_error("Failed to get device path");
63 }
64 
USBPort(sdbusplus::async::context & ctx,const config::PortFactoryConfig & config)65 USBPort::USBPort(sdbusplus::async::context& ctx,
66                  const config::PortFactoryConfig& config) :
67     BasePort(ctx, config, getDevicePath(config))
68 {
69     info("USB port {NAME} created successfully", "NAME", config.name);
70 }
71 
getConfig(sdbusplus::async::context & ctx,const sdbusplus::message::object_path & objectPath)72 auto USBPort::getConfig(sdbusplus::async::context& ctx,
73                         const sdbusplus::message::object_path& objectPath)
74     -> sdbusplus::async::task<std::unique_ptr<config::PortFactoryConfig>>
75 {
76     auto config = std::make_unique<config::USBPortConfig>();
77     if (!config)
78     {
79         co_return std::nullptr_t();
80     }
81 
82     auto properties =
83         co_await USBPortConfigIntf(ctx)
84             .service(entity_manager::EntityManagerInterface::serviceName)
85             .path(objectPath.str)
86             .properties();
87 
88     auto res = updateBaseConfig(*config, properties);
89     if (!res)
90     {
91         co_return std::nullptr_t();
92     }
93 
94     config->address = properties.device_address;
95     config->port = properties.port;
96     config->interface = properties.device_interface;
97     config->portType = config::PortType::usb;
98 
99     debug(
100         "USB port config: {NAME} {PORT_TYPE} {PORT_MODE} {ADDRESS} {PORT} {INTERFACE} {BAUD_RATE} {RTS_DELAY}",
101         "NAME", config->name, "PORT_TYPE", config->portType, "PORT_MODE",
102         config->portMode, "ADDRESS", config->address, "PORT", config->port,
103         "INTERFACE", config->interface, "BAUD_RATE", config->baudRate,
104         "RTS_DELAY", config->rtsDelay);
105 
106     co_return config;
107 }
108 
109 } // namespace phosphor::modbus::rtu::port
110