82 using Device_factory_type = FACTORY;
83 using Client_type =
typename Device_factory_type::Client_type;
84 using Device_type =
typename Device_factory_type::Device_type;
85 using Scheduler_type = SCHEDULER;
87 using Ds_vector = std::vector<L4::Cap<L4Re::Dataspace>>;
89 using Pairing_callback = std::function<void(Device_type *)>;
97 std::string device_id;
105 bool enable_trusted_ds_validation;
107 std::shared_ptr<Ds_vector const> trusted_dataspaces;
110 Pairing_callback pairing_cb;
112 Pending_client() =
default;
115 bool ro,
bool enable_trusted_ds_validation,
116 std::shared_ptr<Ds_vector const> trusted_dataspaces,
118 : device_id(dev), gate(g), num_ds(ds), readonly(ro),
119 enable_trusted_ds_validation(enable_trusted_ds_validation),
120 trusted_dataspaces(trusted_dataspaces), pairing_cb(cb)
128 : _shutdown_state(Shutdown_type::Running),
129 _device(cxx::move(dev)),
134 {
return _interface ? _interface->obj_cap() :
L4::Cap<void>(); }
136 void start_disk_scan(Errand::Callback
const &callback)
138 _device->start_device_scan(
141 scan_disk_partitions(callback, 0);
150 for (
auto *sub : _subs)
151 sub->unregister_interfaces(registry);
156 if (_shutdown_state != Shutdown_type::Running)
165 for (
auto *sub : _subs)
170 int ret = sub->create_interface_for(c, registry);
176 if (!match_hid(c->device_id))
182 auto clt = Device_factory_type::create_client(_device, c->num_ds,
185 clt->add_trusted_dataspaces(c->trusted_dataspaces);
186 if (c->enable_trusted_ds_validation)
187 clt->enable_trusted_ds_validation();
189 if (c->gate.is_valid())
191 if (!clt->register_obj(registry, c->gate).is_valid())
196 c->gate = L4::cap_reinterpret_cast<L4::Rcv_endpoint>(
197 clt->register_obj(registry));
198 if (!c->gate.is_valid())
202 _mgr->_scheduler->add_client(clt.get());
203 _interface.reset(clt.release());
207 c->pairing_cb(_device.get());
215 if (_interface->obj_cap() && !_interface->obj_cap().validate().label())
216 remove_client(registry);
222 for (
auto *sub : _subs)
223 sub->check_clients(registry);
227 void shutdown_event(Shutdown_type type)
230 _shutdown_state = type;
231 for (
auto const &sub: _subs)
232 sub->shutdown_event(type);
234 _interface->shutdown_event(type);
249 template <
typename T = Device_factory_type>
250 auto scan_disk_partitions(Errand::Callback
const &callback,
int)
253 auto reader = cxx::make_ref_obj<Partition_reader<Device_type>>(_device.get());
265 if (reader->get_partition(i, &info) < 0)
268 auto conn = cxx::make_ref_obj<Connection>(
270 Device_factory_type::create_partition(_device, i, info));
271 _subs.push_front(std::move(conn));
279 Errand::schedule([reader](){}, 0);
290 template <
typename T = Device_factory_type>
291 void scan_disk_partitions(Errand::Callback
const &callback,
long)
302 _interface->shutdown_event(Shutdown_type::Client_gone);
304 if (_interface->busy())
306 Dbg::trace().printf(
"Deferring dead client removal.\n");
313 Errand::schedule([
this, registry]() { remove_client(registry); },
318 _interface->unregister_obj(registry);
319 _mgr->_scheduler->remove_client(_interface.get());
323 bool contains_device(std::string
const &name)
const
328 for (
auto *sub : _subs)
329 if (sub->contains_device(name))
335 bool match_hid(std::string
const &name)
const
336 {
return _device->match_hid(
cxx::String(name.c_str(), name.length())); }
340 Shutdown_type _shutdown_state;
344 cxx::unique_ptr<Client_type> _interface;
353 : _registry(registry)
355 _scheduler = cxx::make_unique<Scheduler_type>(registry);
360 for (
auto *c : _connpts)
361 c->unregister_interfaces(_registry);
365 int partno,
int num_ds,
bool readonly =
false,
366 Pairing_callback cb =
nullptr,
367 bool enable_trusted_ds_validation =
false,
368 std::shared_ptr<Ds_vector const> trusted_dataspaces
376 Err().printf(
"Invalid partition number 0.\n");
384 snprintf(_buf,
sizeof(_buf),
"%s:%d", device, partno);
390 _pending_clients.emplace_back(client, buf, num_ds, readonly,
391 enable_trusted_ds_validation,
392 trusted_dataspaces, cb);
397 int create_dynamic_client(std::string
const &device,
int partno,
int num_ds,
399 Pairing_callback cb =
nullptr,
400 bool enable_trusted_ds_validation =
false,
401 std::shared_ptr<Ds_vector const> trusted_dataspaces
409 clt.readonly = readonly;
411 clt.device_id = device;
415 clt.trusted_dataspaces = trusted_dataspaces;
417 clt.enable_trusted_ds_validation = enable_trusted_ds_validation;
421 clt.device_id +=
':';
422 clt.device_id += std::to_string(partno);
425 for (
auto *c : _connpts)
427 int ret = c->create_interface_for(&clt, _registry);
448 for (
auto *c : _connpts)
449 c->check_clients(_registry);
454 auto conn = cxx::make_ref_obj<Connection>(
this, std::move(device));
456 conn->start_disk_scan(
459 _connpts.push_front(conn);
460 connect_static_clients(conn.get());
471 for (
auto const &con : _connpts)
472 con->shutdown_event(type);
476 void connect_static_clients(Connection *con)
478 for (
auto &c : _pending_clients)
480 Dbg::trace().printf(
"Checking existing client %s\n", c.device_id.c_str());
481 if (!c.gate.is_valid())
484 int ret = con->create_interface_for(&c, _registry);
505 std::vector<Pending_client> _pending_clients;
507 cxx::unique_ptr<Scheduler_type> _scheduler;