mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 15:32:25 +00:00
usb_drv: generate a device list report
The report lists all connected devices and gets updated when devices are added or removed. Example report: <devices> <device vendor_id="0x17ef" product_id="0x4816"/> <device vendor_id="0x0a5c" product_id="0x217f"/> <device vendor_id="0x8087" product_id="0x0020"/> <device vendor_id="0x8087" product_id="0x0020"/> <device vendor_id="0x1d6b" product_id="0x0002"/> <device vendor_id="0x1d6b" product_id="0x0002"/> </devices> There is no distinction yet for multiple devices of the same type. The report is named "devices" and an example policy for 'report_rom' would look like: <policy label="vbox -> usb_devices" report="usb_drv -> devices"/> The report only gets generated if enabled in the 'usb_drv' configuration: <config> <raw> <report devices="yes"/> </raw> </config> Fixes #1506
This commit is contained in:
parent
e8f82a1da3
commit
2d869dd15e
@ -178,3 +178,35 @@ component can control the wireless driver. An example therefore is the Qt
|
||||
based component in 'src/app/qt_wifi_connect'.
|
||||
|
||||
Currently only WPA/WPA2 protection using a pre-shared key is supported.
|
||||
|
||||
RAW
|
||||
~~~
|
||||
|
||||
Allows raw access to USB devices via the 'Usb' session interface.
|
||||
|
||||
Configuration snippet:
|
||||
|
||||
!<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"/>
|
||||
! </raw>
|
||||
! </config>
|
||||
!</start>
|
||||
|
||||
The optional 'devices' report lists the connected devices and gets updated when devices are added or removed.
|
||||
|
||||
Example report:
|
||||
|
||||
<devices>
|
||||
<device vendor_id="0x17ef" product_id="0x4816"/>
|
||||
<device vendor_id="0x0a5c" product_id="0x217f"/>
|
||||
<device vendor_id="0x8087" product_id="0x0020"/>
|
||||
<device vendor_id="0x8087" product_id="0x0020"/>
|
||||
<device vendor_id="0x1d6b" product_id="0x0002"/>
|
||||
<device vendor_id="0x1d6b" product_id="0x0002"/>
|
||||
</devices>
|
||||
|
||||
There is no distinction yet for multiple devices of the same type.
|
||||
|
@ -241,12 +241,8 @@ int kthread_stop(struct task_struct *k) { TRACE; return 0; }
|
||||
** linux/notifier.h **
|
||||
**********************/
|
||||
|
||||
int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
|
||||
struct notifier_block *nb) { TRACE; return 0; }
|
||||
int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
|
||||
struct notifier_block *nb) { TRACE; return 0; }
|
||||
int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
|
||||
unsigned long val, void *v) { TRACE; return 0; }
|
||||
int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
|
||||
struct notifier_block *nb) { TRACE; return 0; }
|
||||
int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
|
||||
|
@ -1337,6 +1337,13 @@ enum {
|
||||
|
||||
struct notifier_block {
|
||||
int (*notifier_call)(struct notifier_block *, unsigned long, void *);
|
||||
struct notifier_block *next;
|
||||
int priority;
|
||||
};
|
||||
|
||||
struct raw_notifier_head
|
||||
{
|
||||
struct notifier_block *head;
|
||||
};
|
||||
|
||||
struct atomic_notifier_head {
|
||||
|
@ -43,6 +43,9 @@ struct Services
|
||||
unsigned long screen_width = 0;
|
||||
unsigned long screen_height = 0;
|
||||
|
||||
/* report generation */
|
||||
bool raw_report_device_list = false;
|
||||
|
||||
Services()
|
||||
{
|
||||
using namespace Genode;
|
||||
@ -79,8 +82,13 @@ struct Services
|
||||
}
|
||||
|
||||
try {
|
||||
config()->xml_node().sub_node("raw");
|
||||
Genode::Xml_node node_raw = config()->xml_node().sub_node("raw");
|
||||
raw = true;
|
||||
|
||||
try {
|
||||
Genode::Xml_node node_report = node_raw.sub_node("report");
|
||||
raw_report_device_list = node_report.attribute("devices").has_value("yes");
|
||||
} catch (...) { }
|
||||
} catch (Xml_node::Nonexistent_sub_node) {
|
||||
PDBG("No <raw> config node found - not starting external USB service");
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ namespace Nic
|
||||
|
||||
namespace Raw
|
||||
{
|
||||
void init(Server::Entrypoint &ep);
|
||||
void init(Server::Entrypoint &ep, bool report_device_list);
|
||||
}
|
||||
|
||||
#endif /* _SIGNAL_H_ */
|
||||
|
@ -1299,3 +1299,61 @@ int utf16s_to_utf8s(const wchar_t *pwcs, int len,
|
||||
|
||||
return 2 * length;
|
||||
}
|
||||
|
||||
/**********************
|
||||
** linux/notifier.h **
|
||||
**********************/
|
||||
|
||||
int raw_notifier_chain_register(struct raw_notifier_head *nh,
|
||||
struct notifier_block *n)
|
||||
{
|
||||
struct notifier_block *nl = nh->head;
|
||||
struct notifier_block *pr = 0;
|
||||
while (nl) {
|
||||
if (n->priority > nl->priority)
|
||||
break;
|
||||
pr = nl;
|
||||
nl = nl->next;
|
||||
}
|
||||
|
||||
n->next = nl;
|
||||
if (pr)
|
||||
pr->next = n;
|
||||
else
|
||||
nh->head = n;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int raw_notifier_call_chain(struct raw_notifier_head *nh,
|
||||
unsigned long val, void *v)
|
||||
{
|
||||
int ret = NOTIFY_DONE;
|
||||
struct notifier_block *nb = nh->head;
|
||||
|
||||
while (nb) {
|
||||
|
||||
ret = nb->notifier_call(nb, val, v);
|
||||
if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK)
|
||||
break;
|
||||
|
||||
nb = nb->next;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
|
||||
struct notifier_block *n)
|
||||
{
|
||||
return raw_notifier_chain_register((struct raw_notifier_head *)nh, n);
|
||||
}
|
||||
|
||||
|
||||
int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
|
||||
unsigned long val, void *v)
|
||||
{
|
||||
return raw_notifier_call_chain((struct raw_notifier_head *)nh, val, v);
|
||||
}
|
||||
|
@ -59,6 +59,14 @@ static void init(Services *services)
|
||||
/* start jiffies */
|
||||
dde_kit_timer_init(0, 0);
|
||||
|
||||
/*
|
||||
* The RAW driver is initialized first to make sure that it doesn't miss
|
||||
* notifications about added devices.
|
||||
*/
|
||||
if (services->raw)
|
||||
/* low level interface */
|
||||
module_raw_driver_init();
|
||||
|
||||
/* USB */
|
||||
subsys_usb_init();
|
||||
|
||||
@ -82,10 +90,6 @@ static void init(Services *services)
|
||||
/* storage */
|
||||
if (services->stor)
|
||||
module_usb_storage_driver_init();
|
||||
|
||||
if (services->raw)
|
||||
/* low level interface */
|
||||
module_raw_driver_init();
|
||||
}
|
||||
|
||||
|
||||
@ -103,7 +107,7 @@ void start_usb_driver(Server::Entrypoint &ep)
|
||||
Nic::init(ep);
|
||||
|
||||
if (services.raw)
|
||||
Raw::init(ep);
|
||||
Raw::init(ep, services.raw_report_device_list);
|
||||
|
||||
Routine::add(0, 0, "Main", true);
|
||||
Routine::make_main_current();
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include <base/env.h>
|
||||
#include <base/printf.h>
|
||||
#include <os/reporter.h>
|
||||
#include <root/component.h>
|
||||
#include <usb_session/rpc_object.h>
|
||||
#include <util/list.h>
|
||||
@ -43,13 +44,6 @@ struct Device : List<Device>::Element
|
||||
{
|
||||
usb_device *udev;
|
||||
|
||||
Device(usb_device *udev) : udev(udev)
|
||||
{
|
||||
list()->insert(this);
|
||||
}
|
||||
|
||||
~Device() { list()->remove(this); }
|
||||
|
||||
static List<Device> *list()
|
||||
{
|
||||
static List<Device> _l;
|
||||
@ -66,6 +60,50 @@ struct Device : List<Device>::Element
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static Genode::Reporter &device_list_reporter()
|
||||
{
|
||||
static Genode::Reporter _r("devices", 512*1024);
|
||||
return _r;
|
||||
}
|
||||
|
||||
static void report_device_list()
|
||||
{
|
||||
Genode::Reporter::Xml_generator xml(device_list_reporter(), [&] ()
|
||||
{
|
||||
|
||||
for (Device *d = list()->first(); d; d = d->next()) {
|
||||
xml.node("device", [&] ()
|
||||
{
|
||||
char buf[7];
|
||||
|
||||
Genode::snprintf(buf, sizeof(buf), "0x%4x",
|
||||
d->udev->descriptor.idVendor);
|
||||
xml.attribute("vendor_id", buf);
|
||||
|
||||
Genode::snprintf(buf, sizeof(buf), "0x%4x",
|
||||
d->udev->descriptor.idProduct);
|
||||
xml.attribute("product_id", buf);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Device(usb_device *udev) : udev(udev)
|
||||
{
|
||||
list()->insert(this);
|
||||
|
||||
if (device_list_reporter().is_enabled())
|
||||
report_device_list();
|
||||
}
|
||||
|
||||
~Device()
|
||||
{
|
||||
list()->remove(this);
|
||||
|
||||
if (device_list_reporter().is_enabled())
|
||||
report_device_list();
|
||||
}
|
||||
|
||||
usb_interface *interface(unsigned index)
|
||||
{
|
||||
usb_interface *iface = udev->actconfig->interface[index];
|
||||
@ -387,9 +425,6 @@ class Usb::Worker
|
||||
_wait_event(_device);
|
||||
_wait_event(_device->udev->actconfig);
|
||||
|
||||
/* set raw driver */
|
||||
_device->udev->dev.driver = &raw_driver.drvwrap.driver;
|
||||
|
||||
if (_sigh_ready.valid())
|
||||
Signal_transmitter(_sigh_ready).submit(1);
|
||||
|
||||
@ -510,6 +545,11 @@ class Usb::Session_component : public Session_rpc_object,
|
||||
_tx.sigh_packet_avail(_packet_avail);
|
||||
}
|
||||
|
||||
~Session_component()
|
||||
{
|
||||
_worker.stop();
|
||||
}
|
||||
|
||||
/***********************
|
||||
** Session interface **
|
||||
***********************/
|
||||
@ -677,6 +717,12 @@ class Usb::Root : public Genode::Root_component<Session_component>
|
||||
return session;
|
||||
}
|
||||
|
||||
void _destroy_session(Session_component *session)
|
||||
{
|
||||
::Session::list()->remove(session);
|
||||
Genode::Root_component<Session_component>::_destroy_session(session);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Root(Server::Entrypoint &session_ep,
|
||||
@ -686,8 +732,9 @@ class Usb::Root : public Genode::Root_component<Session_component>
|
||||
};
|
||||
|
||||
|
||||
void Raw::init(Server::Entrypoint &ep)
|
||||
void Raw::init(Server::Entrypoint &ep, bool report_device_list)
|
||||
{
|
||||
Device::device_list_reporter().enabled(report_device_list);
|
||||
static Usb::Root root(ep, env()->heap());
|
||||
Genode::env()->parent()->announce(ep.rpc_ep().manage(&root));
|
||||
}
|
||||
@ -697,18 +744,36 @@ void Raw::init(Server::Entrypoint &ep)
|
||||
** C interface **
|
||||
*****************/
|
||||
|
||||
void raw_register_device(struct usb_device *udev)
|
||||
int raw_notify(struct notifier_block *nb, unsigned long action, void *data)
|
||||
{
|
||||
::Session::list()->state_change(Usb::Session_component::DEVICE_ADD,
|
||||
new (env()->heap()) Device(udev));
|
||||
struct usb_device *udev = (struct usb_device*)data;
|
||||
|
||||
switch (action) {
|
||||
|
||||
case USB_DEVICE_ADD:
|
||||
{
|
||||
::Session::list()->state_change(Usb::Session_component::DEVICE_ADD,
|
||||
new (env()->heap()) Device(udev));
|
||||
break;
|
||||
}
|
||||
|
||||
case USB_DEVICE_REMOVE:
|
||||
{
|
||||
Device *dev = Device::device(udev->descriptor.idVendor,
|
||||
udev->descriptor.idProduct);
|
||||
if (dev) {
|
||||
::Session::list()->state_change(Usb::Session_component::DEVICE_REMOVE, dev);
|
||||
destroy(env()->heap(), dev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case USB_BUS_ADD:
|
||||
break;
|
||||
|
||||
case USB_BUS_REMOVE:
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
|
||||
void raw_unregister_device(struct usb_device *udev)
|
||||
{
|
||||
Device *dev = Device::device(udev->descriptor.idVendor,
|
||||
udev->descriptor.idProduct);
|
||||
if (dev)
|
||||
::Session::list()->state_change(Usb::Session_component::DEVICE_REMOVE, dev);
|
||||
}
|
||||
|
||||
|
@ -7,8 +7,6 @@ struct usb_driver;
|
||||
extern struct usb_device_driver raw_driver;
|
||||
extern struct usb_driver raw_intf_driver;
|
||||
|
||||
void raw_register_device(struct usb_device *udev);
|
||||
void raw_unregister_device(struct usb_device *udev);
|
||||
|
||||
int raw_notify(struct notifier_block *nb, unsigned long action, void *data);
|
||||
|
||||
#endif /* _RAW_H_ */
|
||||
|
@ -19,15 +19,12 @@ static int raw_probe(struct usb_device *udev)
|
||||
printk("RAW: vendor: %x product: %x dev %p\n",
|
||||
udev->descriptor.idVendor, udev->descriptor.idProduct, udev);
|
||||
|
||||
raw_register_device(udev);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void raw_disconnect(struct usb_device *udev)
|
||||
{
|
||||
printk("driver disconnect called\n");
|
||||
raw_unregister_device(udev);
|
||||
}
|
||||
|
||||
|
||||
@ -67,6 +64,12 @@ struct usb_driver raw_intf_driver =
|
||||
};
|
||||
|
||||
|
||||
struct notifier_block usb_nb =
|
||||
{
|
||||
.notifier_call = raw_notify
|
||||
};
|
||||
|
||||
|
||||
static int raw_driver_init(void)
|
||||
{
|
||||
int err;
|
||||
@ -81,6 +84,10 @@ static int raw_driver_init(void)
|
||||
|
||||
printk("RAW: interface driver registered\n");
|
||||
|
||||
usb_register_notify(&usb_nb);
|
||||
|
||||
printk("RAW: notify function registered\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user