Example output for QEMU command-line: $ qemu-system-x86_64 -machine q35,usb=on -S \ -device usb-hub,port=2 -device usb-tablet,port=2.4
Output: {"available":true,"count":12, "device-types":["usb-device"],"hotpluggable":true, "opts":[ {"option":"port","values":["1","3","4","5","6","2.1","2.2","2.3","2.5","2.6","2.7","2.8"]}, {"option":"bus","values":"usb-bus.0"}], "opts-complete":true} {"available":false,"count":1,"device":"/machine/peripheral-anon/device[1]", "device-types":["usb-device"],"hotpluggable":true, "opts":[{"option":"port","values":"2"},{"option":"bus","values":"usb-bus.0"}], "opts-complete":true} {"available":false,"count":1,"device":"/machine/peripheral-anon/device[2]", "device-types":["usb-device"],"hotpluggable":true, "opts":[{"option":"port","values":"2.4"},{"option":"bus","values":"usb-bus.0"}], "opts-complete":true} TODO: Introduce USBPortList typedef in a separate patch TODO: decide if "bus" should be included in the output, or we should make "port" the only parameter required to identify where the device will be plugged. Cc: Gerd Hoffmann <kra...@redhat.com> Signed-off-by: Eduardo Habkost <ehabk...@redhat.com> --- include/hw/usb.h | 6 ++++-- hw/usb/bus.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/include/hw/usb.h b/include/hw/usb.h index eb28655..f8119c9 100644 --- a/include/hw/usb.h +++ b/include/hw/usb.h @@ -509,14 +509,16 @@ void musb_set_size(MUSBState *s, int epnum, int size, int is_tx); #define TYPE_USB_BUS "usb-bus" #define USB_BUS(obj) OBJECT_CHECK(USBBus, (obj), TYPE_USB_BUS) +typedef QTAILQ_HEAD(, USBPort) USBPortList; + struct USBBus { BusState qbus; USBBusOps *ops; int busnr; int nfree; int nused; - QTAILQ_HEAD(, USBPort) free; - QTAILQ_HEAD(, USBPort) used; + USBPortList free; + USBPortList used; QTAILQ_ENTRY(USBBus) next; }; diff --git a/hw/usb/bus.c b/hw/usb/bus.c index 42f85a7..fd00269 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -2,6 +2,7 @@ #include "hw/hw.h" #include "hw/usb.h" #include "hw/qdev.h" +#include "hw/qdev-slotinfo.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "sysemu/sysemu.h" @@ -25,6 +26,40 @@ static Property usb_props[] = { DEFINE_PROP_END_OF_LIST() }; +static void usb_bus_enumerate_slot_list(DeviceSlotInfoList **r, USBBus *bus, USBPortList *l) +{ + USBPort *port; + + QTAILQ_FOREACH(port, l, next) { + DeviceSlotInfo *slot = make_slot(BUS(bus)); + /* + * TODO: should the "bus" option be included, or is + * "port" enough to identify the USB bus + port? + */ + slot_add_opt_str(slot, "port", port->path); + slot->opts_complete = slot; + if (port->dev) { + slot->has_device = true; + slot->device = object_get_canonical_path(OBJECT(port->dev)); + slot->available = false; + } + slot->has_count = 1; + slot->count = 1; + + slot_list_add_slot(r, slot); + } +} + +static DeviceSlotInfoList *usb_bus_enumerate_slots(BusState *bus) +{ + USBBus *ub = USB_BUS(bus); + DeviceSlotInfoList *r = NULL; + + usb_bus_enumerate_slot_list(&r, ub, &ub->free); + usb_bus_enumerate_slot_list(&r, ub, &ub->used); + return r; +} + static void usb_bus_class_init(ObjectClass *klass, void *data) { BusClass *k = BUS_CLASS(klass); @@ -34,6 +69,7 @@ static void usb_bus_class_init(ObjectClass *klass, void *data) k->get_dev_path = usb_get_dev_path; k->get_fw_dev_path = usb_get_fw_dev_path; k->device_type = TYPE_USB_DEVICE; + k->enumerate_slots = usb_bus_enumerate_slots; hc->unplug = qdev_simple_device_unplug_cb; } -- 2.9.4