78 using Device_factory_type = FACTORY;
79 using Client_type =
typename Device_factory_type::Client_type;
80 using Device_type =
typename Device_factory_type::Device_type;
82 using Ds_vector = std::vector<L4::Cap<L4Re::Dataspace>>;
84 using Pairing_callback = std::function<void(Device_type *)>;
92 std::string device_id;
100 bool enable_trusted_ds_validation;
102 std::shared_ptr<Ds_vector const> trusted_dataspaces;
105 Pairing_callback pairing_cb;
107 Pending_client() =
default;
110 bool ro,
bool enable_trusted_ds_validation,
111 std::shared_ptr<Ds_vector const> trusted_dataspaces,
113 : device_id(dev), gate(g), num_ds(ds), readonly(ro),
114 enable_trusted_ds_validation(enable_trusted_ds_validation),
115 trusted_dataspaces(trusted_dataspaces), pairing_cb(cb)
123 : _shutdown_state(Shutdown_type::Running),
124 _device(cxx::move(dev))
128 {
return _interface ? _interface->obj_cap() :
L4::Cap<void>(); }
130 void start_disk_scan(Errand::Callback
const &callback)
132 _device->start_device_scan(
135 scan_disk_partitions(callback, 0);
144 for (
auto *sub : _subs)
145 sub->unregister_interfaces(registry);
150 if (_shutdown_state != Shutdown_type::Running)
159 for (
auto *sub : _subs)
164 int ret = sub->create_interface_for(c, registry);
170 if (!match_hid(c->device_id))
176 auto clt = Device_factory_type::create_client(_device, c->num_ds,
179 clt->add_trusted_dataspaces(c->trusted_dataspaces);
180 if (c->enable_trusted_ds_validation)
181 clt->enable_trusted_ds_validation();
183 if (c->gate.is_valid())
185 if (!clt->register_obj(registry, c->gate).is_valid())
190 c->gate = L4::cap_reinterpret_cast<L4::Rcv_endpoint>(
191 clt->register_obj(registry));
192 if (!c->gate.is_valid())
196 _interface.reset(clt.release());
200 c->pairing_cb(_device.get());
208 if (_interface->obj_cap() && !_interface->obj_cap().validate().label())
209 remove_client(registry);
215 for (
auto *sub : _subs)
216 sub->check_clients(registry);
220 void shutdown_event(Shutdown_type type)
223 _shutdown_state = type;
224 for (
auto const &sub: _subs)
225 sub->shutdown_event(type);
227 _interface->shutdown_event(type);
242 template <
typename T = Device_factory_type>
243 auto scan_disk_partitions(Errand::Callback
const &callback,
int)
246 auto reader = cxx::make_ref_obj<Partition_reader<Device_type>>(_device.get());
258 if (reader->get_partition(i, &info) < 0)
261 auto conn = cxx::make_ref_obj<Connection>(
262 Device_factory_type::create_partition(_device, i, info));
263 _subs.push_front(std::move(conn));
271 Errand::schedule([reader](){}, 0);
282 template <
typename T = Device_factory_type>
283 void scan_disk_partitions(Errand::Callback
const &callback,
long)
294 _interface->shutdown_event(Shutdown_type::Client_gone);
296 if (_interface->busy())
298 Dbg::trace().printf(
"Deferring dead client removal.\n");
305 Errand::schedule([
this, registry]() { remove_client(registry); },
310 _interface->unregister_obj(registry);
314 bool contains_device(std::string
const &name)
const
319 for (
auto *sub : _subs)
320 if (sub->contains_device(name))
326 bool match_hid(std::string
const &name)
const
327 {
return _device->match_hid(
cxx::String(name.c_str(), name.length())); }
330 Shutdown_type _shutdown_state;
334 cxx::unique_ptr<Client_type> _interface;
341 : _registry(registry)
346 for (
auto *c : _connpts)
347 c->unregister_interfaces(_registry);
351 int partno,
int num_ds,
bool readonly =
false,
352 Pairing_callback cb =
nullptr,
353 bool enable_trusted_ds_validation =
false,
354 std::shared_ptr<Ds_vector const> trusted_dataspaces
362 Err().printf(
"Invalid partition number 0.\n");
370 snprintf(_buf,
sizeof(_buf),
"%s:%d", device, partno);
376 _pending_clients.emplace_back(client, buf, num_ds, readonly,
377 enable_trusted_ds_validation,
378 trusted_dataspaces, cb);
383 int create_dynamic_client(std::string
const &device,
int partno,
int num_ds,
385 Pairing_callback cb =
nullptr,
386 bool enable_trusted_ds_validation =
false,
387 std::shared_ptr<Ds_vector const> trusted_dataspaces
395 clt.readonly = readonly;
397 clt.device_id = device;
401 clt.trusted_dataspaces = trusted_dataspaces;
403 clt.enable_trusted_ds_validation = enable_trusted_ds_validation;
407 clt.device_id +=
':';
408 clt.device_id += std::to_string(partno);
411 for (
auto *c : _connpts)
413 int ret = c->create_interface_for(&clt, _registry);
434 for (
auto *c : _connpts)
435 c->check_clients(_registry);
440 auto conn = cxx::make_ref_obj<Connection>(std::move(device));
442 conn->start_disk_scan(
445 _connpts.push_front(conn);
446 connect_static_clients(conn.get());
457 for (
auto const &con : _connpts)
458 con->shutdown_event(type);
462 void connect_static_clients(Connection *con)
464 for (
auto &c : _pending_clients)
466 Dbg::trace().printf(
"Checking existing client %s\n", c.device_id.c_str());
467 if (!c.gate.is_valid())
470 int ret = con->create_interface_for(&c, _registry);
491 std::vector<Pending_client> _pending_clients;