aboutsummaryrefslogtreecommitdiff
path: root/hw/usb/bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/usb/bus.c')
-rw-r--r--hw/usb/bus.c187
1 files changed, 69 insertions, 118 deletions
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index 11f7720d71..bfab2807d7 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -1,10 +1,13 @@
#include "qemu/osdep.h"
-#include "hw/hw.h"
+#include "hw/qdev-properties.h"
#include "hw/usb.h"
-#include "hw/qdev.h"
#include "qapi/error.h"
+#include "qapi/qapi-commands-machine.h"
+#include "qapi/type-helpers.h"
#include "qemu/error-report.h"
+#include "qemu/module.h"
#include "sysemu/sysemu.h"
+#include "migration/vmstate.h"
#include "monitor/monitor.h"
#include "trace.h"
#include "qemu/cutils.h"
@@ -13,15 +16,14 @@ static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
static char *usb_get_dev_path(DeviceState *dev);
static char *usb_get_fw_dev_path(DeviceState *qdev);
-static void usb_qdev_unrealize(DeviceState *qdev, Error **errp);
+static void usb_qdev_unrealize(DeviceState *qdev);
static Property usb_props[] = {
DEFINE_PROP_STRING("port", USBDevice, port_path),
DEFINE_PROP_STRING("serial", USBDevice, serial),
- DEFINE_PROP_BIT("full-path", USBDevice, flags,
- USB_DEV_FLAG_FULL_PATH, true),
DEFINE_PROP_BIT("msos-desc", USBDevice, flags,
USB_DEV_FLAG_MSOS_DESC_ENABLE, true),
+ DEFINE_PROP_STRING("pcap", USBDevice, pcap_filename),
DEFINE_PROP_END_OF_LIST()
};
@@ -59,12 +61,6 @@ static int usb_device_post_load(void *opaque, int version_id)
} else {
dev->attached = true;
}
- if (dev->setup_index < 0 ||
- dev->setup_len < 0 ||
- dev->setup_index > dev->setup_len ||
- dev->setup_len > sizeof(dev->data_buf)) {
- return -EINVAL;
- }
return 0;
}
@@ -73,7 +69,7 @@ const VMStateDescription vmstate_usb_device = {
.version_id = 1,
.minimum_version_id = 1,
.post_load = usb_device_post_load,
- .fields = (VMStateField[]) {
+ .fields = (const VMStateField[]) {
VMSTATE_UINT8(addr, USBDevice),
VMSTATE_INT32(state, USBDevice),
VMSTATE_INT32(remote_wakeup, USBDevice),
@@ -88,8 +84,8 @@ const VMStateDescription vmstate_usb_device = {
void usb_bus_new(USBBus *bus, size_t bus_size,
USBBusOps *ops, DeviceState *host)
{
- qbus_create_inplace(bus, bus_size, TYPE_USB_BUS, host, NULL);
- qbus_set_bus_hotplug_handler(BUS(bus), &error_abort);
+ qbus_init(bus, bus_size, TYPE_USB_BUS, host, NULL);
+ qbus_set_bus_hotplug_handler(BUS(bus));
bus->ops = ops;
bus->busnr = next_usb_bus++;
QTAILQ_INIT(&bus->free);
@@ -104,19 +100,6 @@ void usb_bus_release(USBBus *bus)
QTAILQ_REMOVE(&busses, bus, next);
}
-USBBus *usb_bus_find(int busnr)
-{
- USBBus *bus;
-
- if (-1 == busnr)
- return QTAILQ_FIRST(&busses);
- QTAILQ_FOREACH(bus, &busses, next) {
- if (bus->busnr == busnr)
- return bus;
- }
- return NULL;
-}
-
static void usb_device_realize(USBDevice *dev, Error **errp)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
@@ -135,12 +118,12 @@ USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr)
return NULL;
}
-static void usb_device_unrealize(USBDevice *dev, Error **errp)
+static void usb_device_unrealize(USBDevice *dev)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
if (klass->unrealize) {
- klass->unrealize(dev, errp);
+ klass->unrealize(dev);
}
}
@@ -270,14 +253,26 @@ static void usb_qdev_realize(DeviceState *qdev, Error **errp)
if (dev->auto_attach) {
usb_device_attach(dev, &local_err);
if (local_err) {
- usb_qdev_unrealize(qdev, NULL);
+ usb_qdev_unrealize(qdev);
error_propagate(errp, local_err);
return;
}
}
+
+ if (dev->pcap_filename) {
+ int fd = qemu_open_old(dev->pcap_filename,
+ O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, 0666);
+ if (fd < 0) {
+ error_setg(errp, "open %s failed", dev->pcap_filename);
+ usb_qdev_unrealize(qdev);
+ return;
+ }
+ dev->pcap = fdopen(fd, "wb");
+ usb_pcap_init(dev->pcap);
+ }
}
-static void usb_qdev_unrealize(DeviceState *qdev, Error **errp)
+static void usb_qdev_unrealize(DeviceState *qdev)
{
USBDevice *dev = USB_DEVICE(qdev);
USBDescString *s, *next;
@@ -288,10 +283,14 @@ static void usb_qdev_unrealize(DeviceState *qdev, Error **errp)
g_free(s);
}
+ if (dev->pcap) {
+ fclose(dev->pcap);
+ }
+
if (dev->attached) {
usb_device_detach(dev);
}
- usb_device_unrealize(dev, errp);
+ usb_device_unrealize(dev);
if (dev->port) {
usb_release_port(dev);
}
@@ -301,14 +300,13 @@ typedef struct LegacyUSBFactory
{
const char *name;
const char *usbdevice_name;
- USBDevice *(*usbdevice_init)(USBBus *bus, const char *params);
+ USBDevice *(*usbdevice_init)(void);
} LegacyUSBFactory;
static GSList *legacy_usb_factory;
void usb_legacy_register(const char *typename, const char *usbdevice_name,
- USBDevice *(*usbdevice_init)(USBBus *bus,
- const char *params))
+ USBDevice *(*usbdevice_init)(void))
{
if (usbdevice_name) {
LegacyUSBFactory *f = g_malloc0(sizeof(*f));
@@ -319,39 +317,6 @@ void usb_legacy_register(const char *typename, const char *usbdevice_name,
}
}
-USBDevice *usb_create(USBBus *bus, const char *name)
-{
- DeviceState *dev;
-
- dev = qdev_create(&bus->qbus, name);
- return USB_DEVICE(dev);
-}
-
-static USBDevice *usb_try_create_simple(USBBus *bus, const char *name,
- Error **errp)
-{
- Error *err = NULL;
- USBDevice *dev;
-
- dev = USB_DEVICE(qdev_try_create(&bus->qbus, name));
- if (!dev) {
- error_setg(errp, "Failed to create USB device '%s'", name);
- return NULL;
- }
- object_property_set_bool(OBJECT(dev), true, "realized", &err);
- if (err) {
- error_propagate(errp, err);
- error_prepend(errp, "Failed to initialize USB device '%s': ", name);
- return NULL;
- }
- return dev;
-}
-
-USBDevice *usb_create_simple(USBBus *bus, const char *name)
-{
- return usb_try_create_simple(bus, name, &error_abort);
-}
-
static void usb_fill_port(USBPort *port, void *opaque, int index,
USBPortOps *ops, int speedmask)
{
@@ -429,6 +394,7 @@ void usb_claim_port(USBDevice *dev, Error **errp)
{
USBBus *bus = usb_bus_from_device(dev);
USBPort *port;
+ USBDevice *hub;
assert(dev->port == NULL);
@@ -446,7 +412,10 @@ void usb_claim_port(USBDevice *dev, Error **errp)
} else {
if (bus->nfree == 1 && strcmp(object_get_typename(OBJECT(dev)), "usb-hub") != 0) {
/* Create a new hub and chain it on */
- usb_try_create_simple(bus, "usb-hub", NULL);
+ hub = usb_try_new("usb-hub");
+ if (hub) {
+ usb_realize_and_unref(hub, bus, NULL);
+ }
}
if (bus->nfree == 0) {
error_setg(errp, "tried to attach usb device %s to a bus "
@@ -505,6 +474,10 @@ static void usb_mask_to_str(char *dest, size_t size,
speeds[i].name);
}
}
+
+ if (pos == 0) {
+ snprintf(dest, size, "unknown");
+ }
}
void usb_check_attach(USBDevice *dev, Error **errp)
@@ -588,11 +561,8 @@ static char *usb_get_dev_path(DeviceState *qdev)
{
USBDevice *dev = USB_DEVICE(qdev);
DeviceState *hcd = qdev->parent_bus->parent;
- char *id = NULL;
+ char *id = qdev_get_dev_path(hcd);
- if (dev->flags & (1 << USB_DEV_FLAG_FULL_PATH)) {
- id = qdev_get_dev_path(hcd);
- }
if (id) {
char *ret = g_strdup_printf("%s/%s", id, dev->port->path);
g_free(id);
@@ -620,23 +590,24 @@ static char *usb_get_fw_dev_path(DeviceState *qdev)
in++;
} else {
/* the device itself */
- pos += snprintf(fw_path + pos, fw_len - pos, "%s@%lx",
- qdev_fw_name(qdev), nr);
+ snprintf(fw_path + pos, fw_len - pos, "%s@%lx",
+ qdev_fw_name(qdev), nr);
break;
}
}
return fw_path;
}
-void hmp_info_usb(Monitor *mon, const QDict *qdict)
+HumanReadableText *qmp_x_query_usb(Error **errp)
{
+ g_autoptr(GString) buf = g_string_new("");
USBBus *bus;
USBDevice *dev;
USBPort *port;
if (QTAILQ_EMPTY(&busses)) {
- monitor_printf(mon, "USB support not enabled\n");
- return;
+ error_setg(errp, "USB support not enabled");
+ return NULL;
}
QTAILQ_FOREACH(bus, &busses, next) {
@@ -644,38 +615,31 @@ void hmp_info_usb(Monitor *mon, const QDict *qdict)
dev = port->dev;
if (!dev)
continue;
- monitor_printf(mon, " Device %d.%d, Port %s, Speed %s Mb/s, "
- "Product %s%s%s\n",
- bus->busnr, dev->addr, port->path,
- usb_speed(dev->speed), dev->product_desc,
- dev->qdev.id ? ", ID: " : "",
- dev->qdev.id ?: "");
+ g_string_append_printf(buf,
+ " Device %d.%d, Port %s, Speed %s Mb/s, "
+ "Product %s%s%s\n",
+ bus->busnr, dev->addr, port->path,
+ usb_speed(dev->speed), dev->product_desc,
+ dev->qdev.id ? ", ID: " : "",
+ dev->qdev.id ?: "");
}
}
+
+ return human_readable_text_from_str(buf);
}
/* handle legacy -usbdevice cmd line option */
-USBDevice *usbdevice_create(const char *cmdline)
+USBDevice *usbdevice_create(const char *driver)
{
- USBBus *bus = usb_bus_find(-1 /* any */);
+ USBBus *bus = QTAILQ_FIRST(&busses);
LegacyUSBFactory *f = NULL;
Error *err = NULL;
GSList *i;
- char driver[32];
- const char *params;
- int len;
USBDevice *dev;
- params = strchr(cmdline,':');
- if (params) {
- params++;
- len = params - cmdline;
- if (len > sizeof(driver))
- len = sizeof(driver);
- pstrcpy(driver, len, cmdline);
- } else {
- params = "";
- pstrcpy(driver, sizeof(driver), cmdline);
+ if (strchr(driver, ':')) {
+ error_report("usbdevice parameters are not supported anymore");
+ return NULL;
}
for (i = legacy_usb_factory; i; i = i->next) {
@@ -699,21 +663,12 @@ USBDevice *usbdevice_create(const char *cmdline)
return NULL;
}
- if (f->usbdevice_init) {
- dev = f->usbdevice_init(bus, params);
- } else {
- if (*params) {
- error_report("usbdevice %s accepts no params", driver);
- return NULL;
- }
- dev = usb_create(bus, f->name);
- }
+ dev = f->usbdevice_init ? f->usbdevice_init() : usb_new(f->name);
if (!dev) {
error_report("Failed to create USB device '%s'", f->name);
return NULL;
}
- object_property_set_bool(OBJECT(dev), true, "realized", &err);
- if (err) {
+ if (!usb_realize_and_unref(dev, bus, &err)) {
error_reportf_err(err, "Failed to initialize USB device '%s': ",
f->name);
object_unparent(OBJECT(dev));
@@ -732,15 +687,13 @@ static bool usb_get_attached(Object *obj, Error **errp)
static void usb_set_attached(Object *obj, bool value, Error **errp)
{
USBDevice *dev = USB_DEVICE(obj);
- Error *err = NULL;
if (dev->attached == value) {
return;
}
if (value) {
- usb_device_attach(dev, &err);
- error_propagate(errp, err);
+ usb_device_attach(dev, errp);
} else {
usb_device_detach(dev);
}
@@ -753,12 +706,10 @@ static void usb_device_instance_init(Object *obj)
if (klass->attached_settable) {
object_property_add_bool(obj, "attached",
- usb_get_attached, usb_set_attached,
- NULL);
+ usb_get_attached, usb_set_attached);
} else {
object_property_add_bool(obj, "attached",
- usb_get_attached, NULL,
- NULL);
+ usb_get_attached, NULL);
}
}
@@ -768,7 +719,7 @@ static void usb_device_class_init(ObjectClass *klass, void *data)
k->bus_type = TYPE_USB_BUS;
k->realize = usb_qdev_realize;
k->unrealize = usb_qdev_unrealize;
- k->props = usb_props;
+ device_class_set_props(k, usb_props);
}
static const TypeInfo usb_device_type_info = {