usb_host: add support to flush EP transfers

This causes all pending transfers of a EP to be canceled and in turn to
be acked by the raw session.

issue #4196
This commit is contained in:
Sebastian Sumpf 2021-06-08 18:34:53 +02:00 committed by Christian Helmuth
parent 4aa99fd1a9
commit eabda8907f
2 changed files with 30 additions and 6 deletions

View File

@ -21,6 +21,7 @@
#include <lx_emul.h>
#include <lx_emul/extern_c_begin.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include "raw.h"
#include <lx_emul/extern_c_end.h>
#include <signal.h>
@ -103,6 +104,11 @@ class Device : public List<Device>::Element
});
}
usb_host_endpoint *_host_ep(uint8_t ep)
{
return ep & USB_DIR_IN ? _udev.ep_in[ep & 0xf] : _udev.ep_out[ep & 0xf];
}
/**
* Retrieve string descriptor at index given in packet
*/
@ -359,8 +365,7 @@ class Device : public List<Device>::Element
if (p.transfer.polling_interval == Usb::Packet_descriptor::DEFAULT_POLLING_INTERVAL) {
usb_host_endpoint *ep = read ? _udev.ep_in[p.transfer.ep & 0x0f]
: _udev.ep_out[p.transfer.ep & 0x0f];
usb_host_endpoint *ep = _host_ep(p.transfer.ep);
if (!ep) {
error("could not get ep: ", p.transfer.ep);
@ -415,16 +420,14 @@ class Device : public List<Device>::Element
bool _isoc(Packet_descriptor &p, bool read)
{
unsigned pipe;
usb_host_endpoint *ep;
usb_host_endpoint *ep = _host_ep(p.transfer.ep);
void *buf = dma_malloc(p.size());
if (read) {
pipe = usb_rcvisocpipe(&_udev, p.transfer.ep);
ep = _udev.ep_in[p.transfer.ep & 0x0f];
}
else {
pipe = usb_sndisocpipe(&_udev, p.transfer.ep);
ep = _udev.ep_out[p.transfer.ep & 0x0f];
Genode::memcpy(buf, _sink->packet_content(p), p.size());
}
@ -535,6 +538,23 @@ class Device : public List<Device>::Element
p.succeded = true;
}
/**
* Flush all pending URBs for endpoint
*/
void _flush_endpoint(Packet_descriptor &p)
{
usb_host_endpoint *ep = _host_ep(p.number);
if (!ep) {
error("could net get ep: ", p.number);
p.error = Usb::Packet_descriptor::INTERFACE_OR_ENDPOINT_ERROR;
return;
}
usb_hcd_flush_endpoint(&_udev, ep);
p.succeded = true;
}
/**
* Dispatch incoming packet types
*/
@ -597,6 +617,10 @@ class Device : public List<Device>::Element
case Packet_descriptor::RELEASE_IF:
_release_interface(p);
break;
case Packet_descriptor::FLUSH_TRANSFERS:
_flush_endpoint(p);
break;
}
_ack_packet(p);

View File

@ -33,7 +33,7 @@ namespace Usb {
*/
struct Usb::Packet_descriptor : Genode::Packet_descriptor
{
enum Type { STRING, CTRL, BULK, IRQ, ISOC, ALT_SETTING, CONFIG, RELEASE_IF };
enum Type { STRING, CTRL, BULK, IRQ, ISOC, ALT_SETTING, CONFIG, RELEASE_IF, FLUSH_TRANSFERS };
enum Iso { MAX_PACKETS = 32 };
/* use the polling interval stated in the endpoint descriptor */