mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 23:42:32 +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'.
|
based component in 'src/app/qt_wifi_connect'.
|
||||||
|
|
||||||
Currently only WPA/WPA2 protection using a pre-shared key is supported.
|
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 **
|
** 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,
|
int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
|
||||||
struct notifier_block *nb) { TRACE; return 0; }
|
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,
|
int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
|
||||||
struct notifier_block *nb) { TRACE; return 0; }
|
struct notifier_block *nb) { TRACE; return 0; }
|
||||||
int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
|
int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
|
||||||
|
@ -1337,6 +1337,13 @@ enum {
|
|||||||
|
|
||||||
struct notifier_block {
|
struct notifier_block {
|
||||||
int (*notifier_call)(struct notifier_block *, unsigned long, void *);
|
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 {
|
struct atomic_notifier_head {
|
||||||
|
@ -43,6 +43,9 @@ struct Services
|
|||||||
unsigned long screen_width = 0;
|
unsigned long screen_width = 0;
|
||||||
unsigned long screen_height = 0;
|
unsigned long screen_height = 0;
|
||||||
|
|
||||||
|
/* report generation */
|
||||||
|
bool raw_report_device_list = false;
|
||||||
|
|
||||||
Services()
|
Services()
|
||||||
{
|
{
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
@ -79,8 +82,13 @@ struct Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
config()->xml_node().sub_node("raw");
|
Genode::Xml_node node_raw = config()->xml_node().sub_node("raw");
|
||||||
raw = true;
|
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) {
|
} catch (Xml_node::Nonexistent_sub_node) {
|
||||||
PDBG("No <raw> config node found - not starting external USB service");
|
PDBG("No <raw> config node found - not starting external USB service");
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ namespace Nic
|
|||||||
|
|
||||||
namespace Raw
|
namespace Raw
|
||||||
{
|
{
|
||||||
void init(Server::Entrypoint &ep);
|
void init(Server::Entrypoint &ep, bool report_device_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _SIGNAL_H_ */
|
#endif /* _SIGNAL_H_ */
|
||||||
|
@ -1299,3 +1299,61 @@ int utf16s_to_utf8s(const wchar_t *pwcs, int len,
|
|||||||
|
|
||||||
return 2 * length;
|
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 */
|
/* start jiffies */
|
||||||
dde_kit_timer_init(0, 0);
|
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 */
|
/* USB */
|
||||||
subsys_usb_init();
|
subsys_usb_init();
|
||||||
|
|
||||||
@ -82,10 +90,6 @@ static void init(Services *services)
|
|||||||
/* storage */
|
/* storage */
|
||||||
if (services->stor)
|
if (services->stor)
|
||||||
module_usb_storage_driver_init();
|
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);
|
Nic::init(ep);
|
||||||
|
|
||||||
if (services.raw)
|
if (services.raw)
|
||||||
Raw::init(ep);
|
Raw::init(ep, services.raw_report_device_list);
|
||||||
|
|
||||||
Routine::add(0, 0, "Main", true);
|
Routine::add(0, 0, "Main", true);
|
||||||
Routine::make_main_current();
|
Routine::make_main_current();
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <base/env.h>
|
#include <base/env.h>
|
||||||
#include <base/printf.h>
|
#include <base/printf.h>
|
||||||
|
#include <os/reporter.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>
|
||||||
@ -43,13 +44,6 @@ struct Device : List<Device>::Element
|
|||||||
{
|
{
|
||||||
usb_device *udev;
|
usb_device *udev;
|
||||||
|
|
||||||
Device(usb_device *udev) : udev(udev)
|
|
||||||
{
|
|
||||||
list()->insert(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
~Device() { list()->remove(this); }
|
|
||||||
|
|
||||||
static List<Device> *list()
|
static List<Device> *list()
|
||||||
{
|
{
|
||||||
static List<Device> _l;
|
static List<Device> _l;
|
||||||
@ -66,6 +60,50 @@ struct Device : List<Device>::Element
|
|||||||
return nullptr;
|
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 *interface(unsigned index)
|
||||||
{
|
{
|
||||||
usb_interface *iface = udev->actconfig->interface[index];
|
usb_interface *iface = udev->actconfig->interface[index];
|
||||||
@ -387,9 +425,6 @@ class Usb::Worker
|
|||||||
_wait_event(_device);
|
_wait_event(_device);
|
||||||
_wait_event(_device->udev->actconfig);
|
_wait_event(_device->udev->actconfig);
|
||||||
|
|
||||||
/* set raw driver */
|
|
||||||
_device->udev->dev.driver = &raw_driver.drvwrap.driver;
|
|
||||||
|
|
||||||
if (_sigh_ready.valid())
|
if (_sigh_ready.valid())
|
||||||
Signal_transmitter(_sigh_ready).submit(1);
|
Signal_transmitter(_sigh_ready).submit(1);
|
||||||
|
|
||||||
@ -510,6 +545,11 @@ class Usb::Session_component : public Session_rpc_object,
|
|||||||
_tx.sigh_packet_avail(_packet_avail);
|
_tx.sigh_packet_avail(_packet_avail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~Session_component()
|
||||||
|
{
|
||||||
|
_worker.stop();
|
||||||
|
}
|
||||||
|
|
||||||
/***********************
|
/***********************
|
||||||
** Session interface **
|
** Session interface **
|
||||||
***********************/
|
***********************/
|
||||||
@ -677,6 +717,12 @@ class Usb::Root : public Genode::Root_component<Session_component>
|
|||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _destroy_session(Session_component *session)
|
||||||
|
{
|
||||||
|
::Session::list()->remove(session);
|
||||||
|
Genode::Root_component<Session_component>::_destroy_session(session);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Root(Server::Entrypoint &session_ep,
|
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());
|
static Usb::Root root(ep, env()->heap());
|
||||||
Genode::env()->parent()->announce(ep.rpc_ep().manage(&root));
|
Genode::env()->parent()->announce(ep.rpc_ep().manage(&root));
|
||||||
}
|
}
|
||||||
@ -697,18 +744,36 @@ void Raw::init(Server::Entrypoint &ep)
|
|||||||
** C interface **
|
** 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,
|
struct usb_device *udev = (struct usb_device*)data;
|
||||||
new (env()->heap()) Device(udev));
|
|
||||||
|
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_device_driver raw_driver;
|
||||||
extern struct usb_driver raw_intf_driver;
|
extern struct usb_driver raw_intf_driver;
|
||||||
|
|
||||||
void raw_register_device(struct usb_device *udev);
|
int raw_notify(struct notifier_block *nb, unsigned long action, void *data);
|
||||||
void raw_unregister_device(struct usb_device *udev);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _RAW_H_ */
|
#endif /* _RAW_H_ */
|
||||||
|
@ -19,15 +19,12 @@ static int raw_probe(struct usb_device *udev)
|
|||||||
printk("RAW: vendor: %x product: %x dev %p\n",
|
printk("RAW: vendor: %x product: %x dev %p\n",
|
||||||
udev->descriptor.idVendor, udev->descriptor.idProduct, udev);
|
udev->descriptor.idVendor, udev->descriptor.idProduct, udev);
|
||||||
|
|
||||||
raw_register_device(udev);
|
|
||||||
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void raw_disconnect(struct usb_device *udev)
|
static void raw_disconnect(struct usb_device *udev)
|
||||||
{
|
{
|
||||||
printk("driver disconnect called\n");
|
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)
|
static int raw_driver_init(void)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
@ -81,6 +84,10 @@ static int raw_driver_init(void)
|
|||||||
|
|
||||||
printk("RAW: interface driver registered\n");
|
printk("RAW: interface driver registered\n");
|
||||||
|
|
||||||
|
usb_register_notify(&usb_nb);
|
||||||
|
|
||||||
|
printk("RAW: notify function registered\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user