static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
static char *usb_get_dev_path(DeviceState *dev);
-static char *usbbus_get_fw_dev_path(DeviceState *dev);
+static char *usb_get_fw_dev_path(DeviceState *qdev);
static struct BusInfo usb_bus_info = {
.name = "USB",
.size = sizeof(USBBus),
.print_dev = usb_bus_dev_print,
.get_dev_path = usb_get_dev_path,
- .get_fw_dev_path = usbbus_get_fw_dev_path,
+ .get_fw_dev_path = usb_get_fw_dev_path,
.props = (Property[]) {
DEFINE_PROP_STRING("port", USBDevice, port_path),
DEFINE_PROP_END_OF_LIST()
static int next_usb_bus = 0;
static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
-void usb_bus_new(USBBus *bus, DeviceState *host)
+const VMStateDescription vmstate_usb_device = {
+ .name = "USBDevice",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT8(addr, USBDevice),
+ VMSTATE_INT32(state, USBDevice),
+ VMSTATE_INT32(remote_wakeup, USBDevice),
+ VMSTATE_INT32(setup_state, USBDevice),
+ VMSTATE_INT32(setup_len, USBDevice),
+ VMSTATE_INT32(setup_index, USBDevice),
+ VMSTATE_UINT8_ARRAY(setup_buf, USBDevice, 8),
+ VMSTATE_END_OF_LIST(),
+ }
+};
+
+void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host)
{
qbus_create_inplace(&bus->qbus, &usb_bus_info, host, NULL);
+ bus->ops = ops;
bus->busnr = next_usb_bus++;
bus->qbus.allow_hotplug = 1; /* Yes, we can */
QTAILQ_INIT(&bus->free);
static int usb_qdev_exit(DeviceState *qdev)
{
USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
+ USBBus *bus = usb_bus_from_device(dev);
- usb_device_detach(dev);
+ if (dev->attached) {
+ usb_device_detach(dev);
+ }
+ bus->ops->device_destroy(bus, dev);
if (dev->info->handle_destroy) {
dev->info->handle_destroy(dev);
}
}
void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
- USBDevice *pdev, USBPortOps *ops, int speedmask)
+ USBPortOps *ops, int speedmask)
{
port->opaque = opaque;
port->index = index;
- port->pdev = pdev;
port->opaque = opaque;
port->index = index;
port->ops = ops;
[ USB_SPEED_LOW ] = "1.5",
[ USB_SPEED_FULL ] = "12",
[ USB_SPEED_HIGH ] = "480",
+ [ USB_SPEED_SUPER ] = "5000",
};
if (speed >= ARRAY_SIZE(txt))
return "?";
return qemu_strdup(dev->port->path);
}
+static char *usb_get_fw_dev_path(DeviceState *qdev)
+{
+ USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
+ char *fw_path, *in;
+ ssize_t pos = 0, fw_len;
+ long nr;
+
+ fw_len = 32 + strlen(dev->port->path) * 6;
+ fw_path = qemu_malloc(fw_len);
+ in = dev->port->path;
+ while (fw_len - pos > 0) {
+ nr = strtol(in, &in, 10);
+ if (in[0] == '.') {
+ /* some hub between root port and device */
+ pos += snprintf(fw_path + pos, fw_len - pos, "hub@%ld/", nr);
+ in++;
+ } else {
+ /* the device itself */
+ pos += snprintf(fw_path + pos, fw_len - pos, "%s@%ld",
+ qdev_fw_name(qdev), nr);
+ break;
+ }
+ }
+ return fw_path;
+}
+
void usb_info(Monitor *mon)
{
USBBus *bus;
}
return usb->usbdevice_init(params);
}
-
-static int usbbus_get_fw_dev_path_helper(USBDevice *d, USBBus *bus, char *p,
- int len)
-{
- int l = 0;
- USBPort *port;
-
- QTAILQ_FOREACH(port, &bus->used, next) {
- if (port->dev == d) {
- if (port->pdev) {
- l = usbbus_get_fw_dev_path_helper(port->pdev, bus, p, len);
- }
- l += snprintf(p + l, len - l, "%s@%x/", qdev_fw_name(&d->qdev),
- port->index);
- break;
- }
- }
-
- return l;
-}
-
-static char *usbbus_get_fw_dev_path(DeviceState *dev)
-{
- USBDevice *d = (USBDevice*)dev;
- USBBus *bus = usb_bus_from_device(d);
- char path[100];
- int l;
-
- assert(d->attached != 0);
-
- l = usbbus_get_fw_dev_path_helper(d, bus, path, sizeof(path));
-
- if (l == 0) {
- abort();
- }
-
- path[l-1] = '\0';
-
- return strdup(path);
-}