mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 08:25:38 +00:00
usb: add asynchronous interface release
This became necessary, since URBs may still be pending upon interface release. Fixes #2466
This commit is contained in:
parent
132748a783
commit
5adda2d934
@ -39,6 +39,7 @@ namespace Usb {
|
|||||||
class Session_component;
|
class Session_component;
|
||||||
class Root;
|
class Root;
|
||||||
class Worker;
|
class Worker;
|
||||||
|
class Cleaner;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -517,6 +518,51 @@ class Usb::Worker
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct Interface : List<Interface>::Element
|
||||||
|
{
|
||||||
|
usb_interface *iface;
|
||||||
|
|
||||||
|
Interface(usb_interface *iface) : iface(iface) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronous USB-interface release
|
||||||
|
*/
|
||||||
|
class Usb::Cleaner : List<Interface>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
static void _run(void *c)
|
||||||
|
{
|
||||||
|
Cleaner *cleaner = (Cleaner *)c;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
cleaner->_task.block_and_schedule();
|
||||||
|
|
||||||
|
while (Interface *interface = cleaner->first()) {
|
||||||
|
usb_driver_release_interface(&raw_intf_driver, interface->iface);
|
||||||
|
cleaner->remove(interface);
|
||||||
|
destroy(Lx::Malloc::mem(), interface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Lx::Task _task { _run, this, "raw_cleaner", Lx::Task::PRIORITY_2,
|
||||||
|
Lx::scheduler() };
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void schedule_release(usb_interface *iface)
|
||||||
|
{
|
||||||
|
Interface *interface = new(Lx::Malloc::mem()) Interface(iface);
|
||||||
|
insert(interface);
|
||||||
|
_task.unblock();
|
||||||
|
Lx::scheduler().schedule();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*****************
|
/*****************
|
||||||
** USB session **
|
** USB session **
|
||||||
*****************/
|
*****************/
|
||||||
@ -537,6 +583,7 @@ class Usb::Session_component : public Session_rpc_object,
|
|||||||
Io_signal_handler<Session_component> _ready_ack;
|
Io_signal_handler<Session_component> _ready_ack;
|
||||||
Worker _worker;
|
Worker _worker;
|
||||||
Ram_dataspace_capability _tx_ds;
|
Ram_dataspace_capability _tx_ds;
|
||||||
|
Usb::Cleaner &_cleaner;
|
||||||
|
|
||||||
|
|
||||||
void _signal_state_change()
|
void _signal_state_change()
|
||||||
@ -562,13 +609,12 @@ class Usb::Session_component : public Session_rpc_object,
|
|||||||
Genode::Entrypoint &ep,
|
Genode::Entrypoint &ep,
|
||||||
Genode::Region_map &rm,
|
Genode::Region_map &rm,
|
||||||
unsigned long vendor, unsigned long product,
|
unsigned long vendor, unsigned long product,
|
||||||
long bus, long dev)
|
long bus, long dev, Usb::Cleaner &cleaner)
|
||||||
: Session_rpc_object(tx_ds, ep.rpc_ep(), rm),
|
: Session_rpc_object(tx_ds, ep.rpc_ep(), rm),
|
||||||
_ep(ep),
|
_ep(ep), _vendor(vendor), _product(product), _bus(bus), _dev(dev),
|
||||||
_vendor(vendor), _product(product), _bus(bus), _dev(dev),
|
|
||||||
_packet_avail(ep, *this, &Session_component::_receive),
|
_packet_avail(ep, *this, &Session_component::_receive),
|
||||||
_ready_ack(ep, *this, &Session_component::_receive),
|
_ready_ack(ep, *this, &Session_component::_receive),
|
||||||
_worker(sink()), _tx_ds(tx_ds)
|
_worker(sink()), _tx_ds(tx_ds), _cleaner(cleaner)
|
||||||
{
|
{
|
||||||
Device *device;
|
Device *device;
|
||||||
if (bus && dev)
|
if (bus && dev)
|
||||||
@ -623,7 +669,7 @@ class Usb::Session_component : public Session_rpc_object,
|
|||||||
if (!iface)
|
if (!iface)
|
||||||
throw Interface_not_found();
|
throw Interface_not_found();
|
||||||
|
|
||||||
usb_driver_release_interface(&raw_intf_driver, iface);
|
_cleaner.schedule_release(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
void config_descriptor(Device_descriptor *device_descr,
|
void config_descriptor(Device_descriptor *device_descr,
|
||||||
@ -639,7 +685,6 @@ class Usb::Session_component : public Session_rpc_object,
|
|||||||
else
|
else
|
||||||
Genode::memset(config_descr, 0, sizeof(usb_config_descriptor));
|
Genode::memset(config_descr, 0, sizeof(usb_config_descriptor));
|
||||||
|
|
||||||
device_descr->bus = _device->udev->bus->busnum;
|
|
||||||
device_descr->num = _device->udev->devnum;
|
device_descr->num = _device->udev->devnum;
|
||||||
device_descr->speed = _device->udev->speed;
|
device_descr->speed = _device->udev->speed;
|
||||||
}
|
}
|
||||||
@ -774,6 +819,8 @@ class Usb::Root : public Genode::Root_component<Session_component>
|
|||||||
Genode::Reporter _device_list_reporter {
|
Genode::Reporter _device_list_reporter {
|
||||||
_env, "devices", "devices", 512*1024 };
|
_env, "devices", "devices", 512*1024 };
|
||||||
|
|
||||||
|
Usb::Cleaner _cleaner;
|
||||||
|
|
||||||
void _handle_config()
|
void _handle_config()
|
||||||
{
|
{
|
||||||
Lx_kit::env().config_rom().update();
|
Lx_kit::env().config_rom().update();
|
||||||
@ -832,7 +879,7 @@ class Usb::Root : public Genode::Root_component<Session_component>
|
|||||||
|
|
||||||
Ram_dataspace_capability tx_ds = _env.ram().alloc(tx_buf_size);
|
Ram_dataspace_capability tx_ds = _env.ram().alloc(tx_buf_size);
|
||||||
Session_component *session = new (md_alloc())
|
Session_component *session = new (md_alloc())
|
||||||
Session_component(tx_ds, _env.ep(), _env.rm(), vendor, product, bus, dev);
|
Session_component(tx_ds, _env.ep(), _env.rm(), vendor, product, bus, dev, _cleaner);
|
||||||
::Session::list()->insert(session);
|
::Session::list()->insert(session);
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user