usb_host: Move task to device in USB session

A Lx::Task is now associated to a USB device not the session any more.
This implies that a task lives as long as the device making it possible
to gracefully handle outstanding requests (i.e., synchronous) in case
the session has been closed.

issue #4149
This commit is contained in:
Sebastian Sumpf 2021-05-09 05:04:04 +02:00 committed by Christian Helmuth
parent a0517686ca
commit 9543161827

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
* Copyright (C) 2014-2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
@ -38,200 +38,69 @@ constexpr bool verbose_raw = false;
namespace Usb {
class Session_component;
class Root;
class Worker;
class Cleaner;
}
/**
* Keep track of all registered USB devices (via raw driver)
*/
struct Device : List<Device>::Element
class Device : public List<Device>::Element
{
usb_device *udev;
using Tx = Usb::Session_rpc_object::Tx;
using Packet_descriptor = Usb::Packet_descriptor;
static List<Device> *list()
{
static List<Device> _l;
return &_l;
}
static Device * device_by_product(uint16_t vendor, uint16_t product)
{
for (Device *d = list()->first(); d; d = d->next()) {
if (d->udev->descriptor.idVendor == vendor && d->udev->descriptor.idProduct == product)
return d;
}
return nullptr;
}
static Device * device_by_bus(long bus, long dev)
{
for (Device *d = list()->first(); d; d = d->next()) {
if (d->udev->bus->busnum == bus && d->udev->devnum == dev)
return d;
}
return nullptr;
}
static Device * device_by_class(long class_value, Session_label label)
{
for (Device *d = list()->first(); d; d = d->next()) {
if (class_value == d->device_class_value() && label == d->label())
return d;
}
return nullptr;
}
static void report_device_list();
Device(usb_device *udev) : udev(udev)
{
list()->insert(this);
report_device_list();
}
~Device()
{
list()->remove(this);
report_device_list();
}
usb_interface *interface(unsigned index)
{
if (!udev || !udev->actconfig)
return nullptr;
if (index >= udev->actconfig->desc.bNumInterfaces)
return nullptr;
usb_interface *iface = udev->actconfig->interface[index];
return iface;
}
template <typename FN>
void _with_interface(unsigned index, FN const &fn)
{
if (!udev || !udev->actconfig)
return;
if (index >= udev->actconfig->desc.bNumInterfaces)
return;
usb_interface * const interface_ptr = udev->actconfig->interface[index];
if (!interface_ptr)
return;
fn(*interface_ptr);
}
template <typename FN>
void _for_each_interface(FN const &fn)
{
if (!udev || !udev->actconfig)
return;
for (unsigned i = 0; i < udev->actconfig->desc.bNumInterfaces; i++)
_with_interface(i, fn);
}
/**
* Return pseudo device class of USB device
*
* The returned value expresses the type of USB device. If the device
* has at least one HID interface, the value is USB_CLASS_HID. Otherwise,
* the class of the first interface is interpreted at type the device.
*
* Note this classification of USB devices is meant as an interim solution
* only to assist the implementation of access-control policies.
*/
unsigned device_class_value()
{
unsigned result = 0;
_with_interface(0, [&] (usb_interface &interface) {
if (interface.cur_altsetting)
result = interface.cur_altsetting->desc.bInterfaceClass; });
_for_each_interface([&] (usb_interface &interface) {
if (interface.cur_altsetting)
if (interface.cur_altsetting->desc.bInterfaceClass == USB_CLASS_HID)
result = USB_CLASS_HID; });
return result;
}
void report(Xml_generator &xml)
{
if (!udev || !udev->actconfig)
return;
using namespace Genode;
using Value = String<64>;
xml.attribute("label", label());
xml.attribute("vendor_id", Value(Hex(udev->descriptor.idVendor)));
xml.attribute("product_id", Value(Hex(udev->descriptor.idProduct)));
xml.attribute("bus", Value(Hex(udev->bus->busnum)));
xml.attribute("dev", Value(Hex(udev->devnum)));
xml.attribute("class", Value(Hex(device_class_value())));
_for_each_interface([&] (usb_interface &interface) {
if (!interface.cur_altsetting)
return;
xml.node("interface", [&] () {
uint8_t const class_value =
interface.cur_altsetting->desc.bInterfaceClass;
xml.attribute("class", Value(Hex(class_value)));
});
});
}
usb_host_endpoint *endpoint(usb_interface *iface, unsigned alt_setting,
unsigned endpoint_num)
{
return &iface->altsetting[alt_setting].endpoint[endpoint_num];
}
Session_label label()
{
if (!udev || !udev->bus)
return Session_label("usb-unknown");
return Session_label("usb-", udev->bus->busnum, "-", udev->devnum);
}
};
/**
* Handle packet stream request, this way the entrypoint always returns to it's
* server loop
*/
class Usb::Worker : public Genode::Weak_object<Usb::Worker>
{
private:
completion _packet_avail;
usb_device &_udev;
Lx::Task _task { _run, this, "device_worker",
Lx::Task::PRIORITY_2,
Lx::scheduler() };
completion _packet_avail;
Tx::Sink *_sink { nullptr };
Session::Tx::Sink *_sink;
Device *_device = nullptr;
Signal_context_capability _sigh_ready;
Lx::Task *_task = nullptr;
unsigned _p_in_flight = 0;
bool _device_ready = false;
unsigned _p_in_flight { 0 };
void _ack_packet(Packet_descriptor &p)
template<typename FN>
void _with_packet_stream(FN const &fn)
{
_sink->acknowledge_packet(p);
_p_in_flight--;
if (_sink == nullptr) return;
fn(*_sink);
}
template <typename FN>
void _with_interface(unsigned index, FN const &fn)
{
if (!_udev.actconfig)
return;
if (index >= _udev.actconfig->desc.bNumInterfaces)
return;
usb_interface * const interface_ptr = _udev.actconfig->interface[index];
if (!interface_ptr)
return;
fn(*interface_ptr);
}
template <typename FN>
void _for_each_interface(FN const &fn)
{
if (!_udev.actconfig)
return;
for (unsigned i = 0; i < _udev.actconfig->desc.bNumInterfaces; i++)
_with_interface(i, fn);
}
void _ack_packet(Packet_descriptor p)
{
_with_packet_stream([&](Tx::Sink &sink) {
sink.acknowledge_packet(p);
_p_in_flight--;
});
}
/**
@ -242,7 +111,7 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
char *buffer = _sink->packet_content(p);
int length;
if ((length = usb_string(_device->udev, p.string.index, buffer, p.size())) < 0) {
if ((length = usb_string(&_udev, p.string.index, buffer, p.size())) < 0) {
warning("Could not read string descriptor index: ", (unsigned)p.string.index);
p.string.length = 0;
} else {
@ -259,13 +128,16 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
{
void *buf = kmalloc(4096, GFP_NOIO);
int err = usb_control_msg(_device->udev, usb_rcvctrlpipe(_device->udev, 0),
int err = usb_control_msg(&_udev, usb_rcvctrlpipe(&_udev, 0),
p.control.request, p.control.request_type,
p.control.value, p.control.index, buf,
p.size(), p.control.timeout);
if (err > 0 && p.size())
Genode::memcpy(_sink->packet_content(p), buf, err);
if (err > 0 && p.size()) {
_with_packet_stream([&](Tx::Sink &sink) {
Genode::memcpy(sink.packet_content(p), buf, err);
});
}
kfree(buf);
@ -302,7 +174,7 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
if (p.size())
Genode::memcpy(buf, _sink->packet_content(p), p.size());
int err = usb_control_msg(_device->udev, usb_sndctrlpipe(_device->udev, 0),
int err = usb_control_msg(&_udev, usb_sndctrlpipe(&_udev, 0),
p.control.request, p.control.request_type,
p.control.value, p.control.index, buf, p.size(),
p.control.timeout);
@ -313,7 +185,7 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
if (p.control.request == USB_REQ_CLEAR_FEATURE &&
p.control.value == USB_ENDPOINT_HALT) {
usb_reset_endpoint(_device->udev, p.control.index);
usb_reset_endpoint(&_udev, p.control.index);
}
} else {
p.control.actual_size = 0;
@ -342,24 +214,23 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
*/
struct Complete_data
{
Weak_ptr<Worker> worker;
Device *device;
Packet_descriptor packet;
Complete_data(Weak_ptr<Worker> &w, Packet_descriptor &p)
: worker(w), packet(p) { }
Complete_data(Device *device, Packet_descriptor &p)
: device(device), packet(p) { }
};
Complete_data * alloc_complete_data(Packet_descriptor &p)
{
void * data = kmalloc(sizeof(Complete_data), GFP_KERNEL);
construct_at<Complete_data>(data, this->weak_ptr(), p);
construct_at<Complete_data>(data, this, p);
return reinterpret_cast<Complete_data *>(data);
}
static void free_complete_data(Complete_data *data)
{
data->packet.~Packet_descriptor();
data->worker.~Weak_ptr<Worker>();
kfree (data);
}
@ -380,8 +251,10 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
* controller used the offsets into the original buffer to
* store the data.
*/
Genode::memcpy(_sink->packet_content(p), urb->transfer_buffer,
urb->transfer_buffer_length);
_with_packet_stream([&](Tx::Sink &sink) {
Genode::memcpy(sink.packet_content(p), urb->transfer_buffer,
urb->transfer_buffer_length);
});
}
} else if (urb->status == -ESHUTDOWN) {
p.error = Packet_descriptor::NO_DEVICE_ERROR;
@ -401,13 +274,8 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
{
Complete_data *data = (Complete_data *)urb->context;
{
Locked_ptr<Worker> worker(data->worker);
if (worker.valid())
worker->_async_finish(data->packet, urb,
!!(data->packet.transfer.ep & USB_DIR_IN));
}
data->device->_async_finish(data->packet, urb,
!!(data->packet.transfer.ep & USB_DIR_IN));
free_complete_data(data);
dma_free(urb->transfer_buffer);
@ -423,9 +291,9 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
void *buf = dma_malloc(p.size());
if (read)
pipe = usb_rcvbulkpipe(_device->udev, p.transfer.ep);
pipe = usb_rcvbulkpipe(&_udev, p.transfer.ep);
else {
pipe = usb_sndbulkpipe(_device->udev, p.transfer.ep);
pipe = usb_sndbulkpipe(&_udev, p.transfer.ep);
Genode::memcpy(buf, _sink->packet_content(p), p.size());
}
@ -433,13 +301,13 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
if (!bulk_urb) {
error("Failed to allocate bulk URB");
dma_free(buf);
p.error = Usb::Packet_descriptor::MEMORY_ERROR;
p.error = Packet_descriptor::MEMORY_ERROR;
return false;
}
Complete_data *data = alloc_complete_data(p);
usb_fill_bulk_urb(bulk_urb, _device->udev, pipe, buf, p.size(),
usb_fill_bulk_urb(bulk_urb, &_udev, pipe, buf, p.size(),
_async_complete, data);
int ret = usb_submit_urb(bulk_urb, GFP_KERNEL);
@ -471,9 +339,9 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
void *buf = dma_malloc(p.size());
if (read)
pipe = usb_rcvintpipe(_device->udev, p.transfer.ep);
pipe = usb_rcvintpipe(&_udev, p.transfer.ep);
else {
pipe = usb_sndintpipe(_device->udev, p.transfer.ep);
pipe = usb_sndintpipe(&_udev, p.transfer.ep);
Genode::memcpy(buf, _sink->packet_content(p), p.size());
}
@ -491,8 +359,8 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
if (p.transfer.polling_interval == Usb::Packet_descriptor::DEFAULT_POLLING_INTERVAL) {
usb_host_endpoint *ep = read ? _device->udev->ep_in[p.transfer.ep & 0x0f]
: _device->udev->ep_out[p.transfer.ep & 0x0f];
usb_host_endpoint *ep = read ? _udev.ep_in[p.transfer.ep & 0x0f]
: _udev.ep_out[p.transfer.ep & 0x0f];
if (!ep) {
error("could not get ep: ", p.transfer.ep);
@ -506,7 +374,7 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
} else
polling_interval = p.transfer.polling_interval;
usb_fill_int_urb(irq_urb, _device->udev, pipe, buf, p.size(),
usb_fill_int_urb(irq_urb, &_udev, pipe, buf, p.size(),
_async_complete, data, polling_interval);
int ret = usb_submit_urb(irq_urb, GFP_KERNEL);
@ -551,12 +419,12 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
void *buf = dma_malloc(p.size());
if (read) {
pipe = usb_rcvisocpipe(_device->udev, p.transfer.ep);
ep = _device->udev->ep_in[p.transfer.ep & 0x0f];
pipe = usb_rcvisocpipe(&_udev, p.transfer.ep);
ep = _udev.ep_in[p.transfer.ep & 0x0f];
}
else {
pipe = usb_sndisocpipe(_device->udev, p.transfer.ep);
ep = _device->udev->ep_out[p.transfer.ep & 0x0f];
pipe = usb_sndisocpipe(&_udev, p.transfer.ep);
ep = _udev.ep_out[p.transfer.ep & 0x0f];
Genode::memcpy(buf, _sink->packet_content(p), p.size());
}
@ -576,7 +444,7 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
}
Complete_data *data = alloc_complete_data(p);
urb->dev = _device->udev;
urb->dev = &_udev;
urb->pipe = pipe;
urb->start_frame = -1;
urb->stream_id = 0;
@ -619,8 +487,10 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
*/
void _alt_setting(Packet_descriptor &p)
{
int err = usb_set_interface(_device->udev, p.interface.number,
int err = usb_set_interface(&_udev, p.interface.number,
p.interface.alt_setting);
if (!err)
p.succeded = true;
else
@ -632,7 +502,7 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
*/
void _config(Packet_descriptor &p)
{
usb_host_config *config = _device->udev->actconfig;
usb_host_config *config = _udev.actconfig;
if (config) {
for (unsigned i = 0; i < config->desc.bNumInterfaces; i++) {
@ -643,7 +513,7 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
}
}
int err = usb_set_configuration(_device->udev, p.number);
int err = usb_set_configuration(&_udev, p.number);
if (!err)
p.succeded = true;
@ -656,7 +526,7 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
*/
void _release_interface(Packet_descriptor &p)
{
usb_interface *iface = _device->interface(p.number);
usb_interface *iface = interface(p.number);
if (!iface)
return;
@ -670,12 +540,11 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
*/
void _dispatch()
{
/*
* Get packets until there are no more free ack slots or avaiable
* packets
*/
while (_p_in_flight < _sink->ack_slots_free() && _sink->packet_avail())
{
/*
* Get packets until there are no more free ack slots or avaiable
* packets
*/
while (_sink && _p_in_flight < _sink->ack_slots_free() && _sink->packet_avail()) {
Packet_descriptor p = _sink->get_packet();
if (verbose_raw)
@ -683,13 +552,6 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
_p_in_flight++;
if (!_device || !_device->udev ||
_device->udev->state == USB_STATE_NOTATTACHED) {
p.error = Packet_descriptor::NO_DEVICE_ERROR;
_ack_packet(p);
continue;
}
if (!_sink->packet_valid(p)) {
p.error = Packet_descriptor::PACKET_INVALID_ERROR;
_ack_packet(p);
@ -741,18 +603,6 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
}
}
void _wait_for_device()
{
wait_queue_head_t wait;
_wait_event(wait, _device);
_wait_event(wait, _device->udev->actconfig);
if (_sigh_ready.valid())
Signal_transmitter(_sigh_ready).submit(1);
_device_ready = true;
}
/**
* Wait for packets
*/
@ -760,7 +610,11 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
{
/* wait for device to become ready */
init_completion(&_packet_avail);
_wait_for_device();
wait_queue_head_t wait;
_wait_event(wait, ready());
if (_sigh_ready.valid())
Signal_transmitter(_sigh_ready).submit();
while (true) {
wait_for_completion(&_packet_avail);
@ -768,53 +622,183 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
}
}
static void _run(void *data)
{
Device *device = static_cast<Device *>(data);
device->_wait();
}
public:
static void run(void *worker)
Device(usb_device &udev) : _udev(udev)
{
Worker *w = static_cast<Worker *>(worker);
w->_wait();
list()->insert(this);
if (!Lx::scheduler().active()) {
Lx::scheduler().schedule(); }
report_device_list();
}
Worker(Session::Tx::Sink *sink)
: _sink(sink)
{ }
~Worker()
~Device()
{
Weak_object<Worker>::lock_for_destruction();
}
void start()
{
if (!_task) {
_task = new (Lx::Malloc::mem()) Lx::Task(run, this, "raw_worker",
Lx::Task::PRIORITY_2,
Lx::scheduler());
if (!Lx::scheduler().active()) {
Lx::scheduler().schedule();
}
}
}
void stop()
{
if (_task) {
Lx::scheduler().remove(_task);
destroy(Lx::Malloc::mem(), _task);
_task = nullptr;
}
Lx::scheduler().remove(&_task);
list()->remove(this);
report_device_list();
}
void packet_avail() { ::complete(&_packet_avail); }
void device(Device *device, Signal_context_capability sigh_ready = Signal_context_capability())
unsigned num_interfaces() const
{
_device = device;
_sigh_ready = sigh_ready;
if (ready())
return _udev.actconfig->desc.bNumInterfaces;
return 0;
}
bool device_ready() { return _device_ready; }
void packet_stream(Tx::Sink *sink)
{
_sink = sink;
_p_in_flight = 0;
if (!_sink) {
_sigh_ready = Signal_context_capability { };
}
}
bool ready() const { return _udev.actconfig; }
void sigh_ready(Signal_context_capability sigh_ready)
{
_sigh_ready = sigh_ready;
}
static List<Device> *list()
{
static List<Device> _l;
return &_l;
}
static Device * device_by_product(uint16_t vendor, uint16_t product)
{
for (Device *d = list()->first(); d; d = d->next()) {
if (d->_udev.descriptor.idVendor == vendor && d->_udev.descriptor.idProduct == product)
return d;
}
return nullptr;
}
static Device * device_by_bus(long bus, long dev)
{
for (Device *d = list()->first(); d; d = d->next()) {
if (d->_udev.bus->busnum == bus && d->_udev.devnum == dev)
return d;
}
return nullptr;
}
static Device * device_by_class(long class_value, Session_label label)
{
for (Device *d = list()->first(); d; d = d->next()) {
if (class_value == d->device_class_value() && label == d->label())
return d;
}
return nullptr;
}
static void report_device_list();
usb_interface *interface(unsigned index)
{
if (!_udev.actconfig)
return nullptr;
if (index >= _udev.actconfig->desc.bNumInterfaces)
return nullptr;
usb_interface *iface = _udev.actconfig->interface[index];
return iface;
}
/**
* Return pseudo device class of USB device
*
* The returned value expresses the type of USB device. If the device
* has at least one HID interface, the value is USB_CLASS_HID. Otherwise,
* the class of the first interface is interpreted at type the device.
*
* Note this classification of USB devices is meant as an interim solution
* only to assist the implementation of access-control policies.
*/
unsigned device_class_value()
{
unsigned result = 0;
_with_interface(0, [&] (usb_interface &interface) {
if (interface.cur_altsetting)
result = interface.cur_altsetting->desc.bInterfaceClass; });
_for_each_interface([&] (usb_interface &interface) {
if (interface.cur_altsetting)
if (interface.cur_altsetting->desc.bInterfaceClass == USB_CLASS_HID)
result = USB_CLASS_HID; });
return result;
}
long bus() const { return _udev.bus->busnum; }
long dev() const { return _udev.devnum; }
usb_device &udev() const { return _udev; }
void report(Xml_generator &xml)
{
if (!_udev.actconfig)
return;
using namespace Genode;
using Value = String<64>;
xml.attribute("label", label());
xml.attribute("vendor_id", Value(Hex(_udev.descriptor.idVendor)));
xml.attribute("product_id", Value(Hex(_udev.descriptor.idProduct)));
xml.attribute("bus", Value(Hex(_udev.bus->busnum)));
xml.attribute("dev", Value(Hex(_udev.devnum)));
xml.attribute("class", Value(Hex(device_class_value())));
_for_each_interface([&] (usb_interface &interface) {
if (!interface.cur_altsetting)
return;
xml.node("interface", [&] () {
uint8_t const class_value =
interface.cur_altsetting->desc.bInterfaceClass;
xml.attribute("class", Value(Hex(class_value)));
});
});
}
usb_host_endpoint *endpoint(usb_interface *iface, unsigned alt_setting,
unsigned endpoint_num)
{
return &iface->altsetting[alt_setting].endpoint[endpoint_num];
}
Session_label label()
{
if (!_udev.bus)
return Session_label("usb-unknown");
return Session_label("usb-", _udev.bus->busnum, "-", _udev.devnum);
}
};
@ -858,7 +842,9 @@ class Usb::Cleaner : List<::Interface>
::Interface *interface = new(Lx::Malloc::mem()) ::Interface(iface);
insert(interface);
_task.unblock();
Lx::scheduler().schedule();
if (!Lx::scheduler().active())
Lx::scheduler().schedule();
}
};
@ -883,7 +869,6 @@ class Usb::Session_component : public Session_rpc_object,
Signal_context_capability _sigh_state_change;
Io_signal_handler<Session_component> _packet_avail;
Io_signal_handler<Session_component> _ready_ack;
Worker _worker;
Ram_dataspace_capability _tx_ds;
Usb::Cleaner &_cleaner;
@ -896,8 +881,12 @@ class Usb::Session_component : public Session_rpc_object,
void _receive()
{
_worker.packet_avail();
Lx::scheduler().schedule();
if (!_device) return;
if (!Lx::scheduler().active()) {
_device->packet_avail();
Lx::scheduler().schedule();
}
}
public:
@ -919,7 +908,7 @@ class Usb::Session_component : public Session_rpc_object,
_bus(bus), _dev(dev), _class(class_),
_packet_avail(ep, *this, &Session_component::_receive),
_ready_ack(ep, *this, &Session_component::_receive),
_worker(sink()), _tx_ds(tx_ds), _cleaner(cleaner)
_tx_ds(tx_ds), _cleaner(cleaner)
{
Device *device_ptr;
if (bus && dev) {
@ -930,8 +919,10 @@ class Usb::Session_component : public Session_rpc_object,
device_ptr = Device::device_by_class(_class, _label);
}
if (device_ptr)
if (device_ptr) {
device_ptr->packet_stream(sink());
state_change(DEVICE_ADD, device_ptr);
}
/* register signal handlers */
_tx.sigh_packet_avail(_packet_avail);
@ -940,13 +931,12 @@ class Usb::Session_component : public Session_rpc_object,
~Session_component()
{
/* release claimed interfaces */
if (_device && _device->udev && _device->udev->actconfig) {
unsigned const num = _device->udev->actconfig->desc.bNumInterfaces;
for (unsigned i = 0; i < num; i++)
if (_device && _device->ready())
for (unsigned i = 0; i < _device->num_interfaces() ; i++)
release_interface(i);
}
_worker.stop();
if (_device)
_device->packet_stream(nullptr);
}
/***********************
@ -960,7 +950,7 @@ class Usb::Session_component : public Session_rpc_object,
if (!_device)
throw Device_not_found();
usb_interface *iface = _device->interface(interface_num);
usb_interface *iface = _device->interface(interface_num);
if (!iface)
throw Interface_not_found();
@ -986,15 +976,15 @@ class Usb::Session_component : public Session_rpc_object,
if (!_device)
throw Device_not_found();
Genode::memcpy(device_descr, &_device->udev->descriptor, sizeof(usb_device_descriptor));
Genode::memcpy(device_descr, &_device->udev().descriptor, sizeof(usb_device_descriptor));
if (_device->udev->actconfig)
Genode::memcpy(config_descr, &_device->udev->actconfig->desc, sizeof(usb_config_descriptor));
if (_device->udev().actconfig)
Genode::memcpy(config_descr, &_device->udev().actconfig->desc, sizeof(usb_config_descriptor));
else
Genode::memset(config_descr, 0, sizeof(usb_config_descriptor));
device_descr->num = _device->udev->devnum;
device_descr->speed = _device->udev->speed;
device_descr->num = _device->udev().devnum;
device_descr->speed = _device->udev().speed;
}
unsigned alt_settings(unsigned index) override
@ -1054,10 +1044,10 @@ class Usb::Session_component : public Session_rpc_object,
unsigned endpoint_num,
Endpoint_descriptor *endpoint_descr) override
{
if (!_device || !_device->udev)
if (!_device)
throw Device_not_found();
usb_interface *iface = usb_ifnum_to_if(_device->udev, interface_num);
usb_interface *iface = usb_ifnum_to_if(&_device->udev(), interface_num);
if (!iface)
throw Interface_not_found();
@ -1071,12 +1061,12 @@ class Usb::Session_component : public Session_rpc_object,
bool session_device(Device *device)
{
usb_device_descriptor *descr = &device->udev->descriptor;
usb_device_descriptor *descr = &device->udev().descriptor;
usb_interface *iface = device->interface(0);
return (descr->idVendor == _vendor && descr->idProduct == _product)
|| (_bus && _dev && _bus == device->udev->bus->busnum &&
_dev == device->udev->devnum)
|| (_bus && _dev && _bus == device->bus() &&
_dev == device->dev())
|| (iface && iface->cur_altsetting &&
_class == device->device_class_value() &&
_label == device->label())? true : false;
@ -1091,20 +1081,20 @@ class Usb::Session_component : public Session_rpc_object,
if (_device)
warning("Device type already present (vendor: ",
Hex(device->udev->descriptor.idVendor),
" product: ", Hex(device->udev->descriptor.idProduct),
Hex(device->udev().descriptor.idVendor),
" product: ", Hex(device->udev().descriptor.idProduct),
") Overwrite!");
_device = device;
_worker.device(_device, _sigh_state_change);
_worker.start();
_device->packet_stream(sink());
_device->sigh_ready(_sigh_state_change);
return true;
case DEVICE_REMOVE:
if (!session_device(device))
return false;
_device = nullptr;
_worker.stop();
_signal_state_change();
return true;
}
@ -1116,8 +1106,8 @@ class Usb::Session_component : public Session_rpc_object,
{
_sigh_state_change = sigh;
if (_worker.device_ready())
Signal_transmitter(_sigh_state_change).submit(1);
if (_device && _device->ready())
Signal_transmitter(_sigh_state_change).submit();
}
Ram_dataspace_capability tx_ds() { return _tx_ds; }
@ -1278,7 +1268,7 @@ void Device::report_device_list()
for (Device *d = list()->first(); d; d = d->next()) {
if (!d->udev || !d->udev->bus) {
if (!d->udev().bus) {
Genode::warning("device ", d->label().string(), " state incomplete");
continue;
}
@ -1301,13 +1291,12 @@ int raw_notify(struct notifier_block *nb, unsigned long action, void *data)
" vendor: ", Hex(udev->descriptor.idVendor),
" product: ", Hex(udev->descriptor.idProduct));
switch (action) {
case USB_DEVICE_ADD:
{
::Session::list()->state_change(Usb::Session_component::DEVICE_ADD,
new (Lx::Malloc::mem()) Device(udev));
new (Lx::Malloc::mem()) Device(*udev));
break;
}