From eabda8907f9dc007374b9854ac0a6856f206f4cb Mon Sep 17 00:00:00 2001 From: Sebastian Sumpf Date: Tue, 8 Jun 2021 18:34:53 +0200 Subject: [PATCH] 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 --- repos/dde_linux/src/drivers/usb_host/raw.cc | 34 ++++++++++++++++++--- repos/os/include/usb_session/usb_session.h | 2 +- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/repos/dde_linux/src/drivers/usb_host/raw.cc b/repos/dde_linux/src/drivers/usb_host/raw.cc index ada2140118..b2153c2f1e 100644 --- a/repos/dde_linux/src/drivers/usb_host/raw.cc +++ b/repos/dde_linux/src/drivers/usb_host/raw.cc @@ -21,6 +21,7 @@ #include #include #include +#include #include "raw.h" #include #include @@ -103,6 +104,11 @@ class Device : public List::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::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::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::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::Element case Packet_descriptor::RELEASE_IF: _release_interface(p); break; + + case Packet_descriptor::FLUSH_TRANSFERS: + _flush_endpoint(p); + break; } _ack_packet(p); diff --git a/repos/os/include/usb_session/usb_session.h b/repos/os/include/usb_session/usb_session.h index c987abbd6e..723bd21506 100644 --- a/repos/os/include/usb_session/usb_session.h +++ b/repos/os/include/usb_session/usb_session.h @@ -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 */