genode_c_api usb: always return valid capability

Instead of returning an invalid capability whenever an interface is
requested that does not exist, create a disconnected interface component.
It is also possible that a client requests an interface that got removed
at the same time. When an invalid capability gets returned, a client
can stumble about invoking it.
Moreover, this commit marks either invalid interface or device components
as disconnected objects to optimize their handling.

Ref genodelabs/genode#5021
This commit is contained in:
Stefan Kalkowski 2024-04-16 15:58:11 +02:00 committed by Christian Helmuth
parent fe144a6c5f
commit 1bdff41544

View File

@ -427,6 +427,11 @@ class Interface_component
size_t buf_size, size_t buf_size,
Signal_context_capability sigh_cap, Signal_context_capability sigh_cap,
uint8_t iface_idx); uint8_t iface_idx);
Interface_component(Env &env,
Reg_list<Interface_component> &registry,
Session_component &session,
size_t buf_size,
Signal_context_capability sigh_cap);
bool handle_response(genode_usb_request_handle_t request_id, bool handle_response(genode_usb_request_handle_t request_id,
genode_usb_request_ret_t return_value, genode_usb_request_ret_t return_value,
@ -467,6 +472,12 @@ class Device_component
bool const controls, bool const controls,
genode_usb_device::Label const &device, genode_usb_device::Label const &device,
Signal_context_capability sigh_cap); Signal_context_capability sigh_cap);
Device_component(Env &env,
Heap &heap,
Reg_list<Device_component> &registry,
Session_component &session,
bool const controls,
Signal_context_capability sigh_cap);
~Device_component(); ~Device_component();
bool request(genode_usb_req_callback_t const callback, bool request(genode_usb_req_callback_t const callback,
@ -864,6 +875,19 @@ Interface_component::Interface_component(Env &env,
} }
Interface_component::Interface_component(Env &env,
Reg_list<Interface_component> &registry,
Session_component &session,
size_t buf_size,
Signal_context_capability sigh_cap)
:
Base(env, session, registry, buf_size, *this, sigh_cap),
_iface_idx(0xff)
{
disconnect();
}
void void
Device_component::_handle_request(Constructible<Packet_descriptor> &cpd, Device_component::_handle_request(Constructible<Packet_descriptor> &cpd,
genode_buffer_t payload, genode_buffer_t payload,
@ -910,12 +934,11 @@ Interface_capability Device_component::acquire_interface(uint8_t index,
size_t buf_size) size_t buf_size)
{ {
if (!_session.matches(_device_label, index)) if (!_session.matches(_device_label, index))
return Interface_capability(); return (new (_heap) Interface_component(_env, _interfaces, _session,
buf_size, _sigh_cap))->session_cap();
Interface_component * ic = new (_heap) return (new (_heap)
Interface_component(_env, _interfaces, _session, _device_label, Interface_component(_env, _interfaces, _session, _device_label,
buf_size, _sigh_cap, index); buf_size, _sigh_cap, index))->session_cap();
return ic->session_cap();
} }
@ -1035,6 +1058,20 @@ Device_component::Device_component(Env &env,
_sigh_cap(sigh_cap) {} _sigh_cap(sigh_cap) {}
Device_component::Device_component(Env &env,
Heap &heap,
Reg_list<Device_component> &registry,
Session_component &session,
bool const controls,
Signal_context_capability sigh_cap)
:
Device_component(env, heap, registry, session, controls,
"INVALID_DEVICE", sigh_cap)
{
disconnect();
}
Device_component::~Device_component() Device_component::~Device_component()
{ {
_interfaces.for_each([&] (Interface_component & ic) { _interfaces.for_each([&] (Interface_component & ic) {
@ -1316,7 +1353,10 @@ Device_capability Session_component::acquire_device(Device_name const &name)
_root.report(); _root.report();
}); });
if (!found) _acquire("INVALID_DEVICE", false); if (!found)
cap = (new (_heap)
Device_component(_env, _heap, _device_sessions, *this,
false, _sigh_cap))->session_cap();
return cap; return cap;
} }