usb_drv: change Usb session and raw driver
- Use 'label' attribute to identify device instead of bus/dev and vendor_id/product_id - Implement release_interface RPC - Report 'label' as well as 'bus' and 'dev' - Add policy handling to raw driver (includes reconfiguration at runtime) - Use own memory backing store for large DMA allocations Issue #1863.
This commit is contained in:
parent
3daa8a3d04
commit
716eab21e3
|
@ -208,17 +208,46 @@ Configuration snippet:
|
||||||
! </config>
|
! </config>
|
||||||
!</start>
|
!</start>
|
||||||
|
|
||||||
The optional 'devices' report lists the connected devices and gets updated when devices are added or removed.
|
The optional 'devices' report lists the connected devices and gets updated
|
||||||
|
when devices are added or removed.
|
||||||
|
|
||||||
Example report:
|
Example report:
|
||||||
|
|
||||||
<devices>
|
!<devices>
|
||||||
<device vendor_id="0x17ef" product_id="0x4816"/>
|
! <device label="usb-1-7" vendor_id="0x1f75" product_id="0x0917" bus="0x0001" dev="0x0007"/>
|
||||||
<device vendor_id="0x0a5c" product_id="0x217f"/>
|
! <device label="usb-1-6" vendor_id="0x13fe" product_id="0x5200" bus="0x0001" dev="0x0006"/>
|
||||||
<device vendor_id="0x8087" product_id="0x0020"/>
|
! <device label="usb-1-4" vendor_id="0x17ef" product_id="0x4816" bus="0x0001" dev="0x0004"/>
|
||||||
<device vendor_id="0x8087" product_id="0x0020"/>
|
! <device label="usb-1-3" vendor_id="0x0a5c" product_id="0x217f" bus="0x0001" dev="0x0003"/>
|
||||||
<device vendor_id="0x1d6b" product_id="0x0002"/>
|
! <device label="usb-2-2" vendor_id="0x8087" product_id="0x0020" bus="0x0002" dev="0x0002"/>
|
||||||
<device vendor_id="0x1d6b" product_id="0x0002"/>
|
! <device label="usb-1-2" vendor_id="0x8087" product_id="0x0020" bus="0x0001" dev="0x0002"/>
|
||||||
</devices>
|
! <device label="usb-2-1" vendor_id="0x1d6b" product_id="0x0002" bus="0x0002" dev="0x0001"/>
|
||||||
|
! <device label="usb-1-1" vendor_id="0x1d6b" product_id="0x0002" bus="0x0001" dev="0x0001"/>
|
||||||
|
!</devices>
|
||||||
|
|
||||||
There is no distinction yet for multiple devices of the same type.
|
For every device a unique identifier is generated that is used to access the
|
||||||
|
USB device. Only devices that have a valid policy configured at the USB driver
|
||||||
|
can be accessed by a client. The following configuration allows 'comp1' to
|
||||||
|
access the device 'usb-1-6':
|
||||||
|
|
||||||
|
!<start name="usb_drv">
|
||||||
|
! <resource name="RAM" quantum="8M"/>
|
||||||
|
! <provides><service name="Usb"/></provides>
|
||||||
|
! <config uhci="yes" ehci="yes" xhci="yes">
|
||||||
|
! <raw>
|
||||||
|
! <report devices="yes"/>
|
||||||
|
! <policy label="comp1 -> usb-1-6" vendor_id="0x13fe" product_id="0x5200" bus="0x0001" dev="0x0006"/>
|
||||||
|
! </raw>
|
||||||
|
! </config>
|
||||||
|
!</start>
|
||||||
|
|
||||||
|
In addition to the mandatory 'label' attribute the policy node also
|
||||||
|
contains optional attribute tuples of which at least one has to be present.
|
||||||
|
The 'vendor_id' and 'product_id' tuple selects a device regardless of its
|
||||||
|
location on the USB bus and is mostly used in static configurations. The
|
||||||
|
'bus' and 'dev' tuple selects a specific device via its bus locations and
|
||||||
|
device address. It is mostly used in dynamic configurations because the device
|
||||||
|
address is not fixed and may change every time the same device is plugged in.
|
||||||
|
|
||||||
|
The configuration of the USB driver can be changed at runtime to satisfy
|
||||||
|
dynamic configurations or rather policies when using the 'Usb' session
|
||||||
|
interface.
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
|
set usb_raw_device ""
|
||||||
|
|
||||||
#
|
#
|
||||||
# Check if USB_RAW_DEVICE is set for Qemu
|
# Check if USB_RAW_DEVICE is set for Qemu
|
||||||
#
|
#
|
||||||
if {![info exists ::env(USB_RAW_DEVICE)] && [have_include power_on/qemu]} {
|
if {[have_include power_on/qemu]} {
|
||||||
|
if {![info exists ::env(USB_RAW_DEVICE)]} {
|
||||||
puts "\nPlease define USB_RAW_DEVICE environment variable and set it to your USB device <bus.device>\n"
|
puts "\nPlease define USB_RAW_DEVICE environment variable and set it to your USB device <bus.device>\n"
|
||||||
exit 0
|
exit 0
|
||||||
|
}
|
||||||
|
set usb_raw_device $::env(USB_RAW_DEVICE)
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -67,7 +72,9 @@ append config {
|
||||||
<resource name="RAM" quantum="7M"/>
|
<resource name="RAM" quantum="7M"/>
|
||||||
<provides><service name="Usb"/></provides>
|
<provides><service name="Usb"/></provides>
|
||||||
<config uhci="yes" ehci="yes" xhci="yes">
|
<config uhci="yes" ehci="yes" xhci="yes">
|
||||||
<raw/>
|
<raw>
|
||||||
|
<policy label="usb_terminal -> usb_serial" vendor_id="0x67b" product_id="0x2303"/>
|
||||||
|
</raw>
|
||||||
</config>
|
</config>
|
||||||
</start>
|
</start>
|
||||||
<start name="usb_terminal">
|
<start name="usb_terminal">
|
||||||
|
@ -97,7 +104,7 @@ append_platform_drv_boot_modules
|
||||||
|
|
||||||
build_boot_image $boot_modules
|
build_boot_image $boot_modules
|
||||||
|
|
||||||
append qemu_args " -m 256 -nographic -usb -usbdevice host:$::env(USB_RAW_DEVICE) -nographic"
|
append qemu_args " -m 256 -nographic -usb -usbdevice host:$usb_raw_device -nographic"
|
||||||
|
|
||||||
|
|
||||||
run_genode_until forever
|
run_genode_until forever
|
||||||
|
|
|
@ -930,6 +930,12 @@ void kfree(const void *);
|
||||||
void *kmalloc(size_t size, gfp_t flags);
|
void *kmalloc(size_t size, gfp_t flags);
|
||||||
void *kcalloc(size_t n, size_t size, gfp_t flags);
|
void *kcalloc(size_t n, size_t size, gfp_t flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Genode specific for large DMA allocations
|
||||||
|
*/
|
||||||
|
void *dma_malloc(size_t size);
|
||||||
|
void dma_free(void *ptr);
|
||||||
|
|
||||||
struct kmem_cache;
|
struct kmem_cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -110,6 +110,11 @@ class Genode::Slab_backend_alloc : public Genode::Allocator,
|
||||||
return _range.alloc(size, out_addr);
|
return _range.alloc(size, out_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void free(void *addr)
|
||||||
|
{
|
||||||
|
_range.free(addr);
|
||||||
|
}
|
||||||
|
|
||||||
void free(void *addr, size_t /* size */) override { }
|
void free(void *addr, size_t /* size */) override { }
|
||||||
size_t overhead(size_t size) const override { return 0; }
|
size_t overhead(size_t size) const override { return 0; }
|
||||||
bool need_size_for_free() const override { return false; }
|
bool need_size_for_free() const override { return false; }
|
||||||
|
@ -303,6 +308,22 @@ class Malloc
|
||||||
_allocator[nr]->free((void *)(addr - 1));
|
_allocator[nr]->free((void *)(addr - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *alloc_large(size_t size)
|
||||||
|
{
|
||||||
|
void *addr;
|
||||||
|
if (!_back_allocator->alloc(size, &addr)) {
|
||||||
|
PERR("Large back end allocation failed (%zu bytes)", size);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_large(void *ptr)
|
||||||
|
{
|
||||||
|
_back_allocator->free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
Genode::addr_t phys_addr(void *a)
|
Genode::addr_t phys_addr(void *a)
|
||||||
{
|
{
|
||||||
return _back_allocator->phys_addr((addr_t)a);
|
return _back_allocator->phys_addr((addr_t)a);
|
||||||
|
@ -376,6 +397,18 @@ void atomic_set(atomic_t *p, unsigned int v) { (*(volatile int *)p) = v; }
|
||||||
** Memory allocation, linux/slab.h **
|
** Memory allocation, linux/slab.h **
|
||||||
*************************************/
|
*************************************/
|
||||||
|
|
||||||
|
void *dma_malloc(size_t size)
|
||||||
|
{
|
||||||
|
return Malloc::dma()->alloc_large(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dma_free(void *ptr)
|
||||||
|
{
|
||||||
|
Malloc::dma()->free_large(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void *kmalloc(size_t size, gfp_t flags)
|
void *kmalloc(size_t size, gfp_t flags)
|
||||||
{
|
{
|
||||||
void *addr = flags & GFP_NOIO ? Malloc::dma()->alloc(size) : Malloc::mem()->alloc(size);
|
void *addr = flags & GFP_NOIO ? Malloc::dma()->alloc(size) : Malloc::mem()->alloc(size);
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <base/env.h>
|
#include <base/env.h>
|
||||||
#include <base/printf.h>
|
#include <base/printf.h>
|
||||||
#include <os/reporter.h>
|
#include <os/reporter.h>
|
||||||
|
#include <os/session_policy.h>
|
||||||
#include <root/component.h>
|
#include <root/component.h>
|
||||||
#include <usb_session/rpc_object.h>
|
#include <usb_session/rpc_object.h>
|
||||||
#include <util/list.h>
|
#include <util/list.h>
|
||||||
|
@ -21,6 +22,7 @@
|
||||||
#include <extern_c_begin.h>
|
#include <extern_c_begin.h>
|
||||||
#include <linux/usb.h>
|
#include <linux/usb.h>
|
||||||
#include "raw.h"
|
#include "raw.h"
|
||||||
|
#include "lx_emul.h"
|
||||||
#include <extern_c_end.h>
|
#include <extern_c_end.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
|
@ -50,7 +52,7 @@ struct Device : List<Device>::Element
|
||||||
return &_l;
|
return &_l;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Device * device(uint16_t vendor, uint16_t product)
|
static Device * device_product(uint16_t vendor, uint16_t product)
|
||||||
{
|
{
|
||||||
for (Device *d = list()->first(); d; d = d->next()) {
|
for (Device *d = list()->first(); d; d = d->next()) {
|
||||||
if (d->udev->descriptor.idVendor == vendor && d->udev->descriptor.idProduct == product)
|
if (d->udev->descriptor.idVendor == vendor && d->udev->descriptor.idProduct == product)
|
||||||
|
@ -60,6 +62,18 @@ struct Device : List<Device>::Element
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Device * device_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 Genode::Reporter &device_list_reporter()
|
static Genode::Reporter &device_list_reporter()
|
||||||
{
|
{
|
||||||
static Genode::Reporter _r("devices", 512*1024);
|
static Genode::Reporter _r("devices", 512*1024);
|
||||||
|
@ -74,7 +88,13 @@ struct Device : List<Device>::Element
|
||||||
for (Device *d = list()->first(); d; d = d->next()) {
|
for (Device *d = list()->first(); d; d = d->next()) {
|
||||||
xml.node("device", [&] ()
|
xml.node("device", [&] ()
|
||||||
{
|
{
|
||||||
char buf[7];
|
char buf[16];
|
||||||
|
|
||||||
|
unsigned const bus = d->udev->bus->busnum;
|
||||||
|
unsigned const dev = d->udev->devnum;
|
||||||
|
|
||||||
|
Genode::snprintf(buf, sizeof(buf), "usb-%d-%d", bus, dev);
|
||||||
|
xml.attribute("label", buf);
|
||||||
|
|
||||||
Genode::snprintf(buf, sizeof(buf), "0x%4x",
|
Genode::snprintf(buf, sizeof(buf), "0x%4x",
|
||||||
d->udev->descriptor.idVendor);
|
d->udev->descriptor.idVendor);
|
||||||
|
@ -83,6 +103,12 @@ struct Device : List<Device>::Element
|
||||||
Genode::snprintf(buf, sizeof(buf), "0x%4x",
|
Genode::snprintf(buf, sizeof(buf), "0x%4x",
|
||||||
d->udev->descriptor.idProduct);
|
d->udev->descriptor.idProduct);
|
||||||
xml.attribute("product_id", buf);
|
xml.attribute("product_id", buf);
|
||||||
|
|
||||||
|
Genode::snprintf(buf, sizeof(buf), "0x%4x", bus);
|
||||||
|
xml.attribute("bus", buf);
|
||||||
|
|
||||||
|
Genode::snprintf(buf, sizeof(buf), "0x%4x", dev);
|
||||||
|
xml.attribute("dev", buf);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -176,13 +202,9 @@ class Usb::Worker
|
||||||
|
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
|
|
||||||
if (err < 0 && err != -EPIPE) {
|
|
||||||
p.succeded = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.control.actual_size = err;
|
p.control.actual_size = err;
|
||||||
p.succeded = true;
|
|
||||||
|
p.succeded = (err < 0 && err != -EPIPE) ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -237,7 +259,7 @@ class Usb::Worker
|
||||||
data->worker->_async_finish(data->packet, urb,
|
data->worker->_async_finish(data->packet, urb,
|
||||||
!!(data->packet.transfer.ep & USB_DIR_IN));
|
!!(data->packet.transfer.ep & USB_DIR_IN));
|
||||||
kfree (data);
|
kfree (data);
|
||||||
kfree (urb->transfer_buffer);
|
dma_free(urb->transfer_buffer);
|
||||||
usb_free_urb(urb);
|
usb_free_urb(urb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +269,7 @@ class Usb::Worker
|
||||||
bool _bulk(Packet_descriptor &p, bool read)
|
bool _bulk(Packet_descriptor &p, bool read)
|
||||||
{
|
{
|
||||||
unsigned pipe;
|
unsigned pipe;
|
||||||
void *buf = kmalloc(p.size(), GFP_NOIO);
|
void *buf = dma_malloc(p.size());
|
||||||
|
|
||||||
if (read)
|
if (read)
|
||||||
pipe = usb_rcvbulkpipe(_device->udev, p.transfer.ep);
|
pipe = usb_rcvbulkpipe(_device->udev, p.transfer.ep);
|
||||||
|
@ -282,7 +304,7 @@ class Usb::Worker
|
||||||
bool _irq(Packet_descriptor &p, bool read)
|
bool _irq(Packet_descriptor &p, bool read)
|
||||||
{
|
{
|
||||||
unsigned pipe;
|
unsigned pipe;
|
||||||
void *buf = kmalloc(p.size(), GFP_NOIO);
|
void *buf = dma_malloc(p.size());
|
||||||
|
|
||||||
if (read)
|
if (read)
|
||||||
pipe = usb_rcvintpipe(_device->udev, p.transfer.ep);
|
pipe = usb_rcvintpipe(_device->udev, p.transfer.ep);
|
||||||
|
@ -501,11 +523,14 @@ class Usb::Session_component : public Session_rpc_object,
|
||||||
Server::Entrypoint &_ep;
|
Server::Entrypoint &_ep;
|
||||||
unsigned long _vendor;
|
unsigned long _vendor;
|
||||||
unsigned long _product;
|
unsigned long _product;
|
||||||
|
long _bus = 0;
|
||||||
|
long _dev = 0;
|
||||||
Device *_device = nullptr;
|
Device *_device = nullptr;
|
||||||
Signal_context_capability _sigh_state_change;
|
Signal_context_capability _sigh_state_change;
|
||||||
Signal_rpc_member<Session_component> _packet_avail;
|
Signal_rpc_member<Session_component> _packet_avail;
|
||||||
Signal_rpc_member<Session_component> _ready_ack;
|
Signal_rpc_member<Session_component> _ready_ack;
|
||||||
Worker _worker;
|
Worker _worker;
|
||||||
|
Ram_dataspace_capability _tx_ds;
|
||||||
|
|
||||||
|
|
||||||
void _signal_state_change()
|
void _signal_state_change()
|
||||||
|
@ -526,18 +551,22 @@ class Usb::Session_component : public Session_rpc_object,
|
||||||
DEVICE_REMOVE,
|
DEVICE_REMOVE,
|
||||||
};
|
};
|
||||||
|
|
||||||
Session_component(Genode::Dataspace_capability tx_ds, Server::Entrypoint &ep,
|
Session_component(Genode::Ram_dataspace_capability tx_ds, Server::Entrypoint &ep,
|
||||||
unsigned long vendor, unsigned long product)
|
unsigned long vendor, unsigned long product,
|
||||||
|
long bus, long dev)
|
||||||
: Session_rpc_object(tx_ds, ep.rpc_ep()),
|
: Session_rpc_object(tx_ds, ep.rpc_ep()),
|
||||||
_ep(ep),
|
_ep(ep),
|
||||||
_vendor(vendor), _product(product),
|
_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())
|
_worker(sink()), _tx_ds(tx_ds)
|
||||||
{
|
{
|
||||||
Device *device = Device::device(_vendor, _product);
|
Device *device;
|
||||||
|
if (bus && dev)
|
||||||
|
device = Device::device_bus(bus, dev);
|
||||||
|
else
|
||||||
|
device = Device::device_product(_vendor, _product);
|
||||||
if (device) {
|
if (device) {
|
||||||
PDBG("Found device");
|
|
||||||
state_change(DEVICE_ADD, device);
|
state_change(DEVICE_ADD, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,6 +595,15 @@ class Usb::Session_component : public Session_rpc_object,
|
||||||
throw Interface_already_claimed();
|
throw Interface_already_claimed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void release_interface(unsigned interface_num) override
|
||||||
|
{
|
||||||
|
usb_interface *iface = _device->interface(interface_num);
|
||||||
|
if (!iface)
|
||||||
|
throw Interface_not_found();
|
||||||
|
|
||||||
|
usb_driver_release_interface(&raw_intf_driver, iface);
|
||||||
|
}
|
||||||
|
|
||||||
void config_descriptor(Device_descriptor *device_descr,
|
void config_descriptor(Device_descriptor *device_descr,
|
||||||
Config_descriptor *config_descr) override
|
Config_descriptor *config_descr) override
|
||||||
{
|
{
|
||||||
|
@ -622,7 +660,9 @@ class Usb::Session_component : public Session_rpc_object,
|
||||||
bool session_device(Device *device)
|
bool session_device(Device *device)
|
||||||
{
|
{
|
||||||
usb_device_descriptor *descr = &device->udev->descriptor;
|
usb_device_descriptor *descr = &device->udev->descriptor;
|
||||||
return (descr->idVendor == _vendor && descr->idProduct == _product) ? true : false;
|
return (descr->idVendor == _vendor && descr->idProduct == _product)
|
||||||
|
|| (_bus && _dev && _bus == device->udev->bus->busnum &&
|
||||||
|
_dev == device->udev->devnum) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool state_change(State state, Device *device)
|
bool state_change(State state, Device *device)
|
||||||
|
@ -661,6 +701,8 @@ class Usb::Session_component : public Session_rpc_object,
|
||||||
if (_worker.device_ready())
|
if (_worker.device_ready())
|
||||||
Signal_transmitter(_sigh_state_change).submit(1);
|
Signal_transmitter(_sigh_state_change).submit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ram_dataspace_capability tx_ds() { return _tx_ds; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -687,17 +729,51 @@ class Usb::Root : public Genode::Root_component<Session_component>
|
||||||
|
|
||||||
Server::Entrypoint &_ep;
|
Server::Entrypoint &_ep;
|
||||||
|
|
||||||
|
Genode::Signal_rpc_member<Usb::Root> _config_dispatcher = {
|
||||||
|
_ep, *this, &Usb::Root::_handle_config };
|
||||||
|
|
||||||
|
Genode::Reporter _config_reporter { "config" };
|
||||||
|
|
||||||
|
void _handle_config(unsigned)
|
||||||
|
{
|
||||||
|
Genode::config()->reload();
|
||||||
|
|
||||||
|
Genode::Xml_node config = Genode::config()->xml_node();
|
||||||
|
|
||||||
|
if (!_config_reporter.is_enabled())
|
||||||
|
_config_reporter.enabled(true);
|
||||||
|
|
||||||
|
bool const uhci = config.attribute_value<bool>("uhci", false);
|
||||||
|
bool const ehci = config.attribute_value<bool>("ehci", false);
|
||||||
|
bool const xhci = config.attribute_value<bool>("xhci", false);
|
||||||
|
|
||||||
|
Genode::Reporter::Xml_generator xml(_config_reporter, [&] {
|
||||||
|
if (uhci) xml.attribute("uhci", "yes");
|
||||||
|
if (ehci) xml.attribute("ehci", "yes");
|
||||||
|
if (xhci) xml.attribute("xhci", "yes");
|
||||||
|
|
||||||
|
xml.append(config.content_base(), config.content_size());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
Session_component *_create_session(const char *args)
|
Session_component *_create_session(const char *args)
|
||||||
{
|
{
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Xml_node raw = Genode::config()->xml_node().sub_node("raw");
|
||||||
|
Genode::Session_label label(args);
|
||||||
|
Genode::Session_policy policy(label, raw);
|
||||||
|
|
||||||
size_t ram_quota = Arg_string::find_arg(args, "ram_quota" ).ulong_value(0);
|
size_t ram_quota = Arg_string::find_arg(args, "ram_quota" ).ulong_value(0);
|
||||||
size_t tx_buf_size = Arg_string::find_arg(args, "tx_buf_size").ulong_value(0);
|
size_t tx_buf_size = Arg_string::find_arg(args, "tx_buf_size").ulong_value(0);
|
||||||
|
|
||||||
unsigned long vendor = Arg_string::find_arg(args, "vendor").ulong_value(0);
|
unsigned long vendor = policy.attribute_value<unsigned long>("vendor", 0);
|
||||||
unsigned long product = Arg_string::find_arg(args, "product").ulong_value(0);
|
unsigned long product = policy.attribute_value<unsigned long>("product", 0);
|
||||||
|
unsigned long bus = policy.attribute_value<unsigned long>("bus", 0);
|
||||||
|
unsigned long dev = policy.attribute_value<unsigned long>("dev", 0);
|
||||||
|
|
||||||
/* check session quota */
|
/* check session quota */
|
||||||
size_t session_size = max<size_t>(4096, sizeof(Session_component));
|
size_t session_size = max<size_t>(4096, sizeof(Session_component));
|
||||||
|
@ -710,17 +786,26 @@ class Usb::Root : public Genode::Root_component<Session_component>
|
||||||
throw Root::Quota_exceeded();
|
throw Root::Quota_exceeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
Dataspace_capability tx_ds = env()->ram_session()->alloc(tx_buf_size);
|
Ram_dataspace_capability tx_ds = env()->ram_session()->alloc(tx_buf_size);
|
||||||
Session_component *session = new (md_alloc())
|
Session_component *session = new (md_alloc())
|
||||||
Session_component(tx_ds, _ep, vendor, product);
|
Session_component(tx_ds, _ep, vendor, product, bus, dev);
|
||||||
::Session::list()->insert(session);
|
::Session::list()->insert(session);
|
||||||
return session;
|
return session;
|
||||||
|
} catch (Genode::Session_policy::No_policy_defined) {
|
||||||
|
PERR("Invalid session request, no matching policy for '%s'",
|
||||||
|
Genode::Session_label(args).string());
|
||||||
|
throw Genode::Root::Unavailable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _destroy_session(Session_component *session)
|
void _destroy_session(Session_component *session)
|
||||||
{
|
{
|
||||||
|
Ram_dataspace_capability tx_ds = session->tx_ds();
|
||||||
|
|
||||||
::Session::list()->remove(session);
|
::Session::list()->remove(session);
|
||||||
Genode::Root_component<Session_component>::_destroy_session(session);
|
Genode::Root_component<Session_component>::_destroy_session(session);
|
||||||
|
|
||||||
|
Genode::env()->ram_session()->free(tx_ds);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -728,7 +813,10 @@ class Usb::Root : public Genode::Root_component<Session_component>
|
||||||
Root(Server::Entrypoint &session_ep,
|
Root(Server::Entrypoint &session_ep,
|
||||||
Genode::Allocator *md_alloc)
|
Genode::Allocator *md_alloc)
|
||||||
: Genode::Root_component<Session_component>(&session_ep.rpc_ep(), md_alloc),
|
: Genode::Root_component<Session_component>(&session_ep.rpc_ep(), md_alloc),
|
||||||
_ep(session_ep) { }
|
_ep(session_ep)
|
||||||
|
{
|
||||||
|
Genode::config()->sigh(_config_dispatcher);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -759,8 +847,8 @@ int raw_notify(struct notifier_block *nb, unsigned long action, void *data)
|
||||||
|
|
||||||
case USB_DEVICE_REMOVE:
|
case USB_DEVICE_REMOVE:
|
||||||
{
|
{
|
||||||
Device *dev = Device::device(udev->descriptor.idVendor,
|
Device *dev = Device::device_bus(udev->bus->busnum,
|
||||||
udev->descriptor.idProduct);
|
udev->devnum);
|
||||||
if (dev) {
|
if (dev) {
|
||||||
::Session::list()->state_change(Usb::Session_component::DEVICE_REMOVE, dev);
|
::Session::list()->state_change(Usb::Session_component::DEVICE_REMOVE, dev);
|
||||||
destroy(env()->heap(), dev);
|
destroy(env()->heap(), dev);
|
||||||
|
|
|
@ -62,7 +62,7 @@ struct Usb::Pl2303_driver : Completion
|
||||||
Server::Entrypoint &ep;
|
Server::Entrypoint &ep;
|
||||||
Server::Signal_rpc_member<Pl2303_driver> dispatcher{ ep, *this, &Pl2303_driver::state_change };
|
Server::Signal_rpc_member<Pl2303_driver> dispatcher{ ep, *this, &Pl2303_driver::state_change };
|
||||||
Genode::Allocator_avl alloc;
|
Genode::Allocator_avl alloc;
|
||||||
Usb::Connection connection{ &alloc, VENDOR, PRODUCT, 512 * 1024, dispatcher };
|
Usb::Connection connection{ &alloc, "usb_serial", 512 * 1024, dispatcher };
|
||||||
Usb::Device device;
|
Usb::Device device;
|
||||||
Signal_context_capability connected_sigh;
|
Signal_context_capability connected_sigh;
|
||||||
Signal_context_capability read_sigh;
|
Signal_context_capability read_sigh;
|
||||||
|
|
|
@ -91,6 +91,11 @@ class Usb::Session_client : public Genode::Rpc_client<Session>
|
||||||
{
|
{
|
||||||
call<Rpc_claim_interface>(interface_num);
|
call<Rpc_claim_interface>(interface_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void release_interface(unsigned interface_num)
|
||||||
|
{
|
||||||
|
call<Rpc_release_interface>(interface_num);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _INCLUDE__USB_SESSION__CLIENT_H_ */
|
#endif /* _INCLUDE__USB_SESSION__CLIENT_H_ */
|
||||||
|
|
|
@ -22,14 +22,17 @@ namespace Usb { struct Connection; }
|
||||||
|
|
||||||
struct Usb::Connection : Genode::Connection<Session>, Session_client
|
struct Usb::Connection : Genode::Connection<Session>, Session_client
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Connect to a USB device.
|
||||||
|
*/
|
||||||
Connection(Genode::Range_allocator *tx_block_alloc,
|
Connection(Genode::Range_allocator *tx_block_alloc,
|
||||||
unsigned long vendor_id, unsigned long product_id,
|
char const *label = "",
|
||||||
Genode::size_t tx_buf_size = 512 * 1024,
|
Genode::size_t tx_buf_size = 512 * 1024,
|
||||||
Genode::Signal_context_capability sigh_state_changed =
|
Genode::Signal_context_capability sigh_state_changed =
|
||||||
Genode::Signal_context_capability())
|
Genode::Signal_context_capability())
|
||||||
:
|
:
|
||||||
Genode::Connection<Session>(session("ram_quota=%zd, tx_buf_size=%zd, vendor=%lu, product=%lu",
|
Genode::Connection<Session>(session("ram_quota=%zd, tx_buf_size=%zd, label=\"%s\"",
|
||||||
3 * 4096 + tx_buf_size, tx_buf_size, vendor_id, product_id)),
|
3 * 4096 + tx_buf_size, tx_buf_size, label)),
|
||||||
Session_client(cap(), tx_block_alloc, sigh_state_changed)
|
Session_client(cap(), tx_block_alloc, sigh_state_changed)
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
|
@ -177,6 +177,11 @@ struct Usb::Session : public Genode::Session
|
||||||
*/
|
*/
|
||||||
virtual void claim_interface(unsigned interface_num) = 0;
|
virtual void claim_interface(unsigned interface_num) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release an interface number
|
||||||
|
*/
|
||||||
|
virtual void release_interface(unsigned interface_num) = 0;
|
||||||
|
|
||||||
GENODE_RPC(Rpc_plugged, bool, plugged);
|
GENODE_RPC(Rpc_plugged, bool, plugged);
|
||||||
GENODE_RPC(Rpc_sigh_state_change, void, sigh_state_change, Signal_context_capability);
|
GENODE_RPC(Rpc_sigh_state_change, void, sigh_state_change, Signal_context_capability);
|
||||||
GENODE_RPC(Rpc_tx_cap, Capability<Tx>, _tx_cap);
|
GENODE_RPC(Rpc_tx_cap, Capability<Tx>, _tx_cap);
|
||||||
|
@ -192,7 +197,8 @@ struct Usb::Session : public Genode::Session
|
||||||
GENODE_RPC_THROW(Rpc_release_interface, void, release_interface, GENODE_TYPE_LIST(Interface_not_found),
|
GENODE_RPC_THROW(Rpc_release_interface, void, release_interface, GENODE_TYPE_LIST(Interface_not_found),
|
||||||
unsigned);
|
unsigned);
|
||||||
GENODE_RPC_INTERFACE(Rpc_plugged, Rpc_sigh_state_change, Rpc_tx_cap, Rpc_config_descr,
|
GENODE_RPC_INTERFACE(Rpc_plugged, Rpc_sigh_state_change, Rpc_tx_cap, Rpc_config_descr,
|
||||||
Rpc_iface_descr, Rpc_ep_descr, Rpc_alt_settings, Rpc_claim_interface);
|
Rpc_iface_descr, Rpc_ep_descr, Rpc_alt_settings, Rpc_claim_interface,
|
||||||
|
Rpc_release_interface);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _INCLUDE__USB_SESSION__USB_SESSION_H_ */
|
#endif /* _INCLUDE__USB_SESSION__USB_SESSION_H_ */
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace Usb_proxy_device_genode {
|
||||||
|
|
||||||
Data(unsigned int vendor_id, unsigned int product_id)
|
Data(unsigned int vendor_id, unsigned int product_id)
|
||||||
: _alloc(Genode::env()->heap()),
|
: _alloc(Genode::env()->heap()),
|
||||||
usb_connection(&_alloc, vendor_id, product_id)
|
usb_connection(&_alloc)
|
||||||
{
|
{
|
||||||
/* wait until device and server are ready */
|
/* wait until device and server are ready */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue