Skip to content

Commit

Permalink
genode_c_api: support to handle empty usb session
Browse files Browse the repository at this point in the history
Adds a function to the USB part of the Genode's C API, to enable
usb_host drivers to acknowledge USB request in client's packet buffer
although they are not assigned to an USB device. The requests are
marked with a "no device" error.

This commit fixes a regression originally solved in genodelabs#4149

Ref genodelabs#4416
  • Loading branch information
skalk committed Feb 17, 2022
1 parent dfbb5b3 commit 2eddad9
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 1 deletion.
2 changes: 2 additions & 0 deletions repos/os/include/genode_c_api/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ void genode_usb_ack_request(genode_usb_session_handle_t session_handle,

void genode_usb_notify_peers(void);

void genode_usb_handle_empty_sessions(void);

#ifdef __cplusplus
}
#endif
Expand Down
51 changes: 50 additions & 1 deletion repos/os/src/lib/genode_c_api/usb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ class genode_usb_session : public Usb::Session_rpc_object
*/
void notify();

/*
* Acknowledge all remaining requests in the packet stream
*/
void flush_packet_stream();


/***************************
** USB session interface **
Expand Down Expand Up @@ -228,6 +233,11 @@ class Root : public Root_component<genode_usb_session>
*/
template <typename FUNC>
void session(genode_usb_session_handle_t id, FUNC const & fn);

/*
* Acknowledge requests from sessions without device
*/
void handle_empty_sessions();
};


Expand All @@ -248,6 +258,22 @@ void genode_usb_session::notify()
}


void genode_usb_session::flush_packet_stream()
{
/* ack packets in flight */
for (unsigned idx = 0; idx < MAX_PACKETS_IN_FLY; idx++) {
if (!packets[idx].constructed())
continue;
_ack(Usb::Packet_descriptor::NO_DEVICE_ERROR, *packets[idx]);
packets[idx].destruct();
}

/* ack all packets in request stream */
while (sink()->packet_avail() && sink()->ack_slots_free())
_ack(Usb::Packet_descriptor::NO_DEVICE_ERROR, sink()->get_packet());
}


bool genode_usb_session::plugged()
{
genode_usb_bus_num_t bus;
Expand Down Expand Up @@ -634,8 +660,10 @@ void ::Root::discontinue_device(genode_usb_bus_num_t bus,
_devices[idx]->dev != dev)
continue;

if (_devices[idx]->usb_session)
if (_devices[idx]->usb_session) {
_devices[idx]->usb_session->notify();
_devices[idx]->usb_session->flush_packet_stream();
}

_devices[idx].destruct();
_report();
Expand Down Expand Up @@ -682,6 +710,18 @@ bool ::Root::device_associated(genode_usb_session * session,
}


void ::Root::handle_empty_sessions()
{
_for_each_session([&] (genode_usb_session & s) {
bool associated = false;
_for_each_device([&] (Device & d) {
if (d.usb_session == &s) associated = true; });
if (!associated)
s.flush_packet_stream();
});
}


::Root::Root(Env & env, Allocator & alloc, Signal_context_capability cap)
:
Root_component<genode_usb_session>(env.ep(), alloc),
Expand Down Expand Up @@ -766,3 +806,12 @@ extern "C" void genode_usb_ack_request(genode_usb_session_handle_t session_id,


extern "C" void genode_usb_notify_peers() { }


extern "C" void genode_usb_handle_empty_sessions()
{
if (!_usb_root)
return;

_usb_root->handle_empty_sessions();
}
1 change: 1 addition & 0 deletions repos/pc/src/drivers/usb_host/pc/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,7 @@ static int usb_poll_sessions(void * data)
usb_for_each_dev(&work_done, poll_usb_device);
if (work_done)
continue;
genode_usb_handle_empty_sessions();
lx_emul_task_schedule(true);
}

Expand Down

0 comments on commit 2eddad9

Please sign in to comment.