Loading hw/usb/dev-hub.c +63 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu-common.h" #include "qemu/timer.h" #include "trace.h" #include "hw/usb.h" #include "desc.h" Loading @@ -41,6 +42,8 @@ typedef struct USBHubState { USBDevice dev; USBEndpoint *intr; uint32_t num_ports; bool port_power; QEMUTimer *port_timer; USBHubPort ports[MAX_PORTS]; } USBHubState; Loading Loading @@ -203,6 +206,20 @@ static bool usb_hub_port_update(USBHubPort *port) return notify; } static void usb_hub_port_update_timer(void *opaque) { USBHubState *s = opaque; bool notify = false; int i; for (i = 0; i < s->num_ports; i++) { notify |= usb_hub_port_update(&s->ports[i]); } if (notify) { usb_wakeup(s->intr, 0); } } static void usb_hub_attach(USBPort *port1) { USBHubState *s = port1->opaque; Loading Loading @@ -405,6 +422,11 @@ static void usb_hub_handle_control(USBDevice *dev, USBPacket *p, usb_wakeup(s->intr, 0); break; case PORT_POWER: if (s->port_power) { int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); usb_hub_port_set(port, PORT_STAT_POWER); timer_mod(s->port_timer, now + 5000000); /* 5 ms */ } break; default: goto fail; Loading Loading @@ -445,6 +467,14 @@ static void usb_hub_handle_control(USBDevice *dev, USBPacket *p, case PORT_C_RESET: port->wPortChange &= ~PORT_STAT_C_RESET; break; case PORT_POWER: if (s->port_power) { usb_hub_port_clear(port, PORT_STAT_POWER); usb_hub_port_clear(port, PORT_STAT_CONNECTION); usb_hub_port_clear(port, PORT_STAT_ENABLE); usb_hub_port_clear(port, PORT_STAT_SUSPEND); port->wPortChange = 0; } default: goto fail; } Loading @@ -457,6 +487,11 @@ static void usb_hub_handle_control(USBDevice *dev, USBPacket *p, sizeof(qemu_hub_hub_descriptor)); data[2] = s->num_ports; if (s->port_power) { data[3] &= ~0x03; data[3] |= 0x01; } /* fill DeviceRemovable bits */ limit = DIV_ROUND_UP(s->num_ports + 1, 8) + 7; for (n = 7; n < limit; n++) { Loading Loading @@ -536,6 +571,9 @@ static void usb_hub_unrealize(USBDevice *dev, Error **errp) usb_unregister_port(usb_bus_from_device(dev), &s->ports[i].port); } timer_del(s->port_timer); timer_free(s->port_timer); } static USBPortOps usb_hub_port_ops = { Loading Loading @@ -565,6 +603,8 @@ static void usb_hub_realize(USBDevice *dev, Error **errp) usb_desc_create_serial(dev); usb_desc_init(dev); s->port_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, usb_hub_port_update_timer, s); s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1); for (i = 0; i < s->num_ports; i++) { port = &s->ports[i]; Loading @@ -587,6 +627,24 @@ static const VMStateDescription vmstate_usb_hub_port = { } }; static bool usb_hub_port_timer_needed(void *opaque) { USBHubState *s = opaque; return s->port_power; } static const VMStateDescription vmstate_usb_hub_port_timer = { .name = "usb-hub/port-timer", .version_id = 1, .minimum_version_id = 1, .needed = usb_hub_port_timer_needed, .fields = (VMStateField[]) { VMSTATE_TIMER_PTR(port_timer, USBHubState), VMSTATE_END_OF_LIST() }, }; static const VMStateDescription vmstate_usb_hub = { .name = "usb-hub", .version_id = 1, Loading @@ -596,11 +654,16 @@ static const VMStateDescription vmstate_usb_hub = { VMSTATE_STRUCT_ARRAY(ports, USBHubState, MAX_PORTS, 0, vmstate_usb_hub_port, USBHubPort), VMSTATE_END_OF_LIST() }, .subsections = (const VMStateDescription * []) { &vmstate_usb_hub_port_timer, NULL } }; static Property usb_hub_properties[] = { DEFINE_PROP_UINT32("ports", USBHubState, num_ports, 8), DEFINE_PROP_BOOL("port-power", USBHubState, port_power, false), DEFINE_PROP_END_OF_LIST(), }; Loading Loading
hw/usb/dev-hub.c +63 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu-common.h" #include "qemu/timer.h" #include "trace.h" #include "hw/usb.h" #include "desc.h" Loading @@ -41,6 +42,8 @@ typedef struct USBHubState { USBDevice dev; USBEndpoint *intr; uint32_t num_ports; bool port_power; QEMUTimer *port_timer; USBHubPort ports[MAX_PORTS]; } USBHubState; Loading Loading @@ -203,6 +206,20 @@ static bool usb_hub_port_update(USBHubPort *port) return notify; } static void usb_hub_port_update_timer(void *opaque) { USBHubState *s = opaque; bool notify = false; int i; for (i = 0; i < s->num_ports; i++) { notify |= usb_hub_port_update(&s->ports[i]); } if (notify) { usb_wakeup(s->intr, 0); } } static void usb_hub_attach(USBPort *port1) { USBHubState *s = port1->opaque; Loading Loading @@ -405,6 +422,11 @@ static void usb_hub_handle_control(USBDevice *dev, USBPacket *p, usb_wakeup(s->intr, 0); break; case PORT_POWER: if (s->port_power) { int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); usb_hub_port_set(port, PORT_STAT_POWER); timer_mod(s->port_timer, now + 5000000); /* 5 ms */ } break; default: goto fail; Loading Loading @@ -445,6 +467,14 @@ static void usb_hub_handle_control(USBDevice *dev, USBPacket *p, case PORT_C_RESET: port->wPortChange &= ~PORT_STAT_C_RESET; break; case PORT_POWER: if (s->port_power) { usb_hub_port_clear(port, PORT_STAT_POWER); usb_hub_port_clear(port, PORT_STAT_CONNECTION); usb_hub_port_clear(port, PORT_STAT_ENABLE); usb_hub_port_clear(port, PORT_STAT_SUSPEND); port->wPortChange = 0; } default: goto fail; } Loading @@ -457,6 +487,11 @@ static void usb_hub_handle_control(USBDevice *dev, USBPacket *p, sizeof(qemu_hub_hub_descriptor)); data[2] = s->num_ports; if (s->port_power) { data[3] &= ~0x03; data[3] |= 0x01; } /* fill DeviceRemovable bits */ limit = DIV_ROUND_UP(s->num_ports + 1, 8) + 7; for (n = 7; n < limit; n++) { Loading Loading @@ -536,6 +571,9 @@ static void usb_hub_unrealize(USBDevice *dev, Error **errp) usb_unregister_port(usb_bus_from_device(dev), &s->ports[i].port); } timer_del(s->port_timer); timer_free(s->port_timer); } static USBPortOps usb_hub_port_ops = { Loading Loading @@ -565,6 +603,8 @@ static void usb_hub_realize(USBDevice *dev, Error **errp) usb_desc_create_serial(dev); usb_desc_init(dev); s->port_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, usb_hub_port_update_timer, s); s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1); for (i = 0; i < s->num_ports; i++) { port = &s->ports[i]; Loading @@ -587,6 +627,24 @@ static const VMStateDescription vmstate_usb_hub_port = { } }; static bool usb_hub_port_timer_needed(void *opaque) { USBHubState *s = opaque; return s->port_power; } static const VMStateDescription vmstate_usb_hub_port_timer = { .name = "usb-hub/port-timer", .version_id = 1, .minimum_version_id = 1, .needed = usb_hub_port_timer_needed, .fields = (VMStateField[]) { VMSTATE_TIMER_PTR(port_timer, USBHubState), VMSTATE_END_OF_LIST() }, }; static const VMStateDescription vmstate_usb_hub = { .name = "usb-hub", .version_id = 1, Loading @@ -596,11 +654,16 @@ static const VMStateDescription vmstate_usb_hub = { VMSTATE_STRUCT_ARRAY(ports, USBHubState, MAX_PORTS, 0, vmstate_usb_hub_port, USBHubPort), VMSTATE_END_OF_LIST() }, .subsections = (const VMStateDescription * []) { &vmstate_usb_hub_port_timer, NULL } }; static Property usb_hub_properties[] = { DEFINE_PROP_UINT32("ports", USBHubState, num_ports, 8), DEFINE_PROP_BOOL("port-power", USBHubState, port_power, false), DEFINE_PROP_END_OF_LIST(), }; Loading