17f9d41ddSJagpal Singh Gill #include "usb_port.hpp"
27f9d41ddSJagpal Singh Gill
37f9d41ddSJagpal Singh Gill #include "common/entity_manager_interface.hpp"
47f9d41ddSJagpal Singh Gill #include "port_factory.hpp"
57f9d41ddSJagpal Singh Gill
67f9d41ddSJagpal Singh Gill #include <fcntl.h>
77f9d41ddSJagpal Singh Gill
87f9d41ddSJagpal Singh Gill #include <phosphor-logging/lg2.hpp>
97f9d41ddSJagpal Singh Gill #include <xyz/openbmc_project/Configuration/USBPort/client.hpp>
107f9d41ddSJagpal Singh Gill
117f9d41ddSJagpal Singh Gill #include <filesystem>
127f9d41ddSJagpal Singh Gill #include <format>
137f9d41ddSJagpal Singh Gill #include <optional>
147f9d41ddSJagpal Singh Gill #include <regex>
157f9d41ddSJagpal Singh Gill
167f9d41ddSJagpal Singh Gill namespace phosphor::modbus::rtu::port
177f9d41ddSJagpal Singh Gill {
187f9d41ddSJagpal Singh Gill
197f9d41ddSJagpal Singh Gill PHOSPHOR_LOG2_USING;
207f9d41ddSJagpal Singh Gill
217f9d41ddSJagpal Singh Gill using USBPortConfigIntf =
227f9d41ddSJagpal Singh Gill sdbusplus::client::xyz::openbmc_project::configuration::USBPort<>;
237f9d41ddSJagpal Singh Gill
247f9d41ddSJagpal Singh Gill namespace config
257f9d41ddSJagpal Singh Gill {
267f9d41ddSJagpal Singh Gill
277f9d41ddSJagpal Singh Gill struct USBPortConfig : public PortFactoryConfig
287f9d41ddSJagpal Singh Gill {
297f9d41ddSJagpal Singh Gill std::string address = "unknown";
307f9d41ddSJagpal Singh Gill uint16_t port = 0;
317f9d41ddSJagpal Singh Gill uint16_t interface = 0;
32*b62e3dfeSJagpal Singh Gill
33*b62e3dfeSJagpal Singh Gill virtual ~USBPortConfig() = default;
347f9d41ddSJagpal Singh Gill };
357f9d41ddSJagpal Singh Gill
367f9d41ddSJagpal Singh Gill } // namespace config
377f9d41ddSJagpal Singh Gill
getDevicePath(const config::PortFactoryConfig & inConfig)38*b62e3dfeSJagpal Singh Gill static auto getDevicePath(const config::PortFactoryConfig& inConfig)
39*b62e3dfeSJagpal Singh Gill -> std::string
407f9d41ddSJagpal Singh Gill {
417f9d41ddSJagpal Singh Gill namespace fs = std::filesystem;
427f9d41ddSJagpal Singh Gill auto config = static_cast<const config::USBPortConfig&>(inConfig);
43*b62e3dfeSJagpal Singh Gill
447f9d41ddSJagpal Singh Gill std::regex pattern(
457f9d41ddSJagpal Singh Gill std::format("platform-{}\\.usb-usb.*{}-port{}", config.address,
467f9d41ddSJagpal Singh Gill config.interface, config.port));
477f9d41ddSJagpal Singh Gill fs::path searchDir = "/dev/serial/by-path/";
487f9d41ddSJagpal Singh Gill
497f9d41ddSJagpal Singh Gill for (const auto& entry : fs::recursive_directory_iterator(searchDir))
507f9d41ddSJagpal Singh Gill {
517f9d41ddSJagpal Singh Gill if (entry.is_symlink())
527f9d41ddSJagpal Singh Gill {
537f9d41ddSJagpal Singh Gill auto filePath = entry.path();
547f9d41ddSJagpal Singh Gill if (std::regex_search(filePath.filename().string(), pattern))
557f9d41ddSJagpal Singh Gill {
567f9d41ddSJagpal Singh Gill return ("/dev/" +
577f9d41ddSJagpal Singh Gill fs::read_symlink(filePath).filename().string());
587f9d41ddSJagpal Singh Gill }
597f9d41ddSJagpal Singh Gill }
607f9d41ddSJagpal Singh Gill }
617f9d41ddSJagpal Singh Gill
627f9d41ddSJagpal Singh Gill throw std::runtime_error("Failed to get device path");
637f9d41ddSJagpal Singh Gill }
647f9d41ddSJagpal Singh Gill
USBPort(sdbusplus::async::context & ctx,const config::PortFactoryConfig & config)657f9d41ddSJagpal Singh Gill USBPort::USBPort(sdbusplus::async::context& ctx,
66*b62e3dfeSJagpal Singh Gill const config::PortFactoryConfig& config) :
677f9d41ddSJagpal Singh Gill BasePort(ctx, config, getDevicePath(config))
687f9d41ddSJagpal Singh Gill {
697f9d41ddSJagpal Singh Gill info("USB port {NAME} created successfully", "NAME", config.name);
707f9d41ddSJagpal Singh Gill }
717f9d41ddSJagpal Singh Gill
getConfig(sdbusplus::async::context & ctx,const sdbusplus::message::object_path & objectPath)727f9d41ddSJagpal Singh Gill auto USBPort::getConfig(sdbusplus::async::context& ctx,
737f9d41ddSJagpal Singh Gill const sdbusplus::message::object_path& objectPath)
74*b62e3dfeSJagpal Singh Gill -> sdbusplus::async::task<std::unique_ptr<config::PortFactoryConfig>>
757f9d41ddSJagpal Singh Gill {
76*b62e3dfeSJagpal Singh Gill auto config = std::make_unique<config::USBPortConfig>();
77*b62e3dfeSJagpal Singh Gill if (!config)
78*b62e3dfeSJagpal Singh Gill {
79*b62e3dfeSJagpal Singh Gill co_return std::nullptr_t();
80*b62e3dfeSJagpal Singh Gill }
817f9d41ddSJagpal Singh Gill
827f9d41ddSJagpal Singh Gill auto properties =
837f9d41ddSJagpal Singh Gill co_await USBPortConfigIntf(ctx)
847f9d41ddSJagpal Singh Gill .service(entity_manager::EntityManagerInterface::serviceName)
857f9d41ddSJagpal Singh Gill .path(objectPath.str)
867f9d41ddSJagpal Singh Gill .properties();
877f9d41ddSJagpal Singh Gill
88*b62e3dfeSJagpal Singh Gill auto res = updateBaseConfig(*config, properties);
897f9d41ddSJagpal Singh Gill if (!res)
907f9d41ddSJagpal Singh Gill {
91*b62e3dfeSJagpal Singh Gill co_return std::nullptr_t();
927f9d41ddSJagpal Singh Gill }
937f9d41ddSJagpal Singh Gill
94*b62e3dfeSJagpal Singh Gill config->address = properties.device_address;
95*b62e3dfeSJagpal Singh Gill config->port = properties.port;
96*b62e3dfeSJagpal Singh Gill config->interface = properties.device_interface;
97*b62e3dfeSJagpal Singh Gill config->portType = config::PortType::usb;
987f9d41ddSJagpal Singh Gill
997f9d41ddSJagpal Singh Gill debug(
1007f9d41ddSJagpal Singh Gill "USB port config: {NAME} {PORT_TYPE} {PORT_MODE} {ADDRESS} {PORT} {INTERFACE} {BAUD_RATE} {RTS_DELAY}",
101*b62e3dfeSJagpal Singh Gill "NAME", config->name, "PORT_TYPE", config->portType, "PORT_MODE",
102*b62e3dfeSJagpal Singh Gill config->portMode, "ADDRESS", config->address, "PORT", config->port,
103*b62e3dfeSJagpal Singh Gill "INTERFACE", config->interface, "BAUD_RATE", config->baudRate,
104*b62e3dfeSJagpal Singh Gill "RTS_DELAY", config->rtsDelay);
105*b62e3dfeSJagpal Singh Gill
1067f9d41ddSJagpal Singh Gill co_return config;
1077f9d41ddSJagpal Singh Gill }
1087f9d41ddSJagpal Singh Gill
1097f9d41ddSJagpal Singh Gill } // namespace phosphor::modbus::rtu::port
110