1// SPDX-License-Identifier: GPL-3.0-or-later
2#include "units/device.hpp"
3
4#include "ServiceManager.hpp"
5#include "common/ConfigurationManager.hpp"
6
7using namespace std::string_literals;
8
9RegisterUnit(device, Device);
10
11Device::Device(const std::string &id, toml::table &table, std::shared_ptr<const Template> template_, const ArgumentMap &args)
12 : Unit(id, table, template_, args), //
13 driver_exec(PopArg(table, key: "driver")), //
14 driver_args(GetArrayArg(table, key: "driver_args"))
15{
16 toml::table root;
17 root.emplace(key: "description", args: description + " - Device Driver (auto-generated)");
18 {
19 toml::table options;
20 toml::array exec{ driver_exec };
21 for (const auto &arg : driver_args)
22 exec.push_back(val: arg);
23 options.emplace(key: "exec", args&: exec);
24 root.emplace(key: "options", args&: options);
25 }
26 {
27 toml::table service;
28 service.emplace(key: "state-change", args: "notify"s);
29 root.emplace(key: "service", args&: service);
30 }
31
32 // Create a service unit for the device driver
33 const auto driverId = replace_all(str: this->id, matcher: ".device", replacement: ".driver");
34 driver = Create(id: driverId, data: root);
35 ConfigurationManager->AddUnit(unit: driver);
36}
37
38bool Device::Start()
39{
40 status.Starting(msg: "plugged");
41 const auto worker = [this]
42 {
43 bool ok = ServiceManager->StartUnit(id: driver->id);
44 if (ok)
45 {
46 status.Started(msg: "working");
47 ServiceManager->OnUnitStarted(unit: this);
48 }
49 else
50 {
51 status.Failed(msg: "driver failed");
52 }
53 };
54
55 std::thread(worker).detach();
56 status.Started(msg: "starting driver");
57 return true;
58}
59
60bool Device::Stop()
61{
62 status.Stopping();
63 if (driver->GetStatus().active)
64 {
65 if (!driver->Stop())
66 {
67 std::cerr << "Failed to stop device driver service: " << driver->GetDescription() << std::endl;
68 status.Failed(msg: "driver service failed to stop");
69 return false;
70 }
71 }
72
73 status.Inactive();
74 ServiceManager->OnUnitStopped(unit: this);
75 return true;
76}
77
78void Device::onPrint(std::ostream &os) const
79{
80 os << " driver: " << driver_exec << std::endl;
81 os << " driver_args: ";
82 for (const auto &arg : driver_args)
83 os << arg << " ";
84 os << std::endl;
85}
86