[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 16/30] usb: rework attach/detach workflow
From: |
Gerd Hoffmann |
Subject: |
[Qemu-devel] [PATCH 16/30] usb: rework attach/detach workflow |
Date: |
Fri, 17 Dec 2010 12:26:32 +0100 |
Add separate detach callback to USBPortOps, split
uhci/ohci/musb/usbhub attach functions into two.
Move common code to the usb_attach() function, only
the hardware-specific bits remain in the attach/detach
callbacks.
Keep track of the port it is attached to for each usb device.
[ v3: fix tyops in usb-musb.c ]
Signed-off-by: Gerd Hoffmann <address@hidden>
---
hw/usb-hub.c | 46 ++++++++++++++------------------
hw/usb-musb.c | 36 ++++++++-----------------
hw/usb-ohci.c | 80 +++++++++++++++++++++++++++------------------------------
hw/usb-uhci.c | 69 +++++++++++++++++++++---------------------------
hw/usb.c | 20 +++++++++++++-
hw/usb.h | 4 ++-
6 files changed, 122 insertions(+), 133 deletions(-)
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 1de2e0f..5aa1d0b 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -218,37 +218,30 @@ static const uint8_t qemu_hub_hub_descriptor[] =
/* DeviceRemovable and PortPwrCtrlMask patched in later */
};
-static void usb_hub_attach(USBPort *port1, USBDevice *dev)
+static void usb_hub_attach(USBPort *port1)
{
USBHubState *s = port1->opaque;
USBHubPort *port = &s->ports[port1->index];
- if (dev) {
- if (port->port.dev)
- usb_attach(port1, NULL);
-
- port->wPortStatus |= PORT_STAT_CONNECTION;
- port->wPortChange |= PORT_STAT_C_CONNECTION;
- if (dev->speed == USB_SPEED_LOW)
- port->wPortStatus |= PORT_STAT_LOW_SPEED;
- else
- port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
- port->port.dev = dev;
- /* send the attach message */
- usb_send_msg(dev, USB_MSG_ATTACH);
+ port->wPortStatus |= PORT_STAT_CONNECTION;
+ port->wPortChange |= PORT_STAT_C_CONNECTION;
+ if (port->port.dev->speed == USB_SPEED_LOW) {
+ port->wPortStatus |= PORT_STAT_LOW_SPEED;
} else {
- dev = port->port.dev;
- if (dev) {
- port->wPortStatus &= ~PORT_STAT_CONNECTION;
- port->wPortChange |= PORT_STAT_C_CONNECTION;
- if (port->wPortStatus & PORT_STAT_ENABLE) {
- port->wPortStatus &= ~PORT_STAT_ENABLE;
- port->wPortChange |= PORT_STAT_C_ENABLE;
- }
- /* send the detach message */
- usb_send_msg(dev, USB_MSG_DETACH);
- port->port.dev = NULL;
- }
+ port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
+ }
+}
+
+static void usb_hub_detach(USBPort *port1)
+{
+ USBHubState *s = port1->opaque;
+ USBHubPort *port = &s->ports[port1->index];
+
+ port->wPortStatus &= ~PORT_STAT_CONNECTION;
+ port->wPortChange |= PORT_STAT_C_CONNECTION;
+ if (port->wPortStatus & PORT_STAT_ENABLE) {
+ port->wPortStatus &= ~PORT_STAT_ENABLE;
+ port->wPortChange |= PORT_STAT_C_ENABLE;
}
}
@@ -508,6 +501,7 @@ static void usb_hub_handle_destroy(USBDevice *dev)
static USBPortOps usb_hub_port_ops = {
.attach = usb_hub_attach,
+ .detach = usb_hub_detach,
};
static int usb_hub_initfn(USBDevice *dev)
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 916aa06..983a4db 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -259,10 +259,12 @@
#endif
-static void musb_attach(USBPort *port, USBDevice *dev);
+static void musb_attach(USBPort *port);
+static void musb_detach(USBPort *port);
static USBPortOps musb_port_ops = {
.attach = musb_attach,
+ .detach = musb_detach,
};
typedef struct {
@@ -464,34 +466,20 @@ static void musb_session_update(MUSBState *s, int
prev_dev, int prev_sess)
}
/* Attach or detach a device on our only port. */
-static void musb_attach(USBPort *port, USBDevice *dev)
+static void musb_attach(USBPort *port)
{
MUSBState *s = (MUSBState *) port->opaque;
- USBDevice *curr;
- port = &s->port;
- curr = port->dev;
-
- if (dev) {
- if (curr) {
- usb_attach(port, NULL);
- /* TODO: signal some interrupts */
- }
-
- musb_intr_set(s, musb_irq_vbus_request, 1);
-
- /* Send the attach message to device */
- usb_send_msg(dev, USB_MSG_ATTACH);
- } else if (curr) {
- /* Send the detach message */
- usb_send_msg(curr, USB_MSG_DETACH);
-
- musb_intr_set(s, musb_irq_disconnect, 1);
- }
+ musb_intr_set(s, musb_irq_vbus_request, 1);
+ musb_session_update(s, 0, s->session);
+}
- port->dev = dev;
+static void musb_detach(USBPort *port)
+{
+ MUSBState *s = (MUSBState *) port->opaque;
- musb_session_update(s, !!curr, s->session);
+ musb_intr_set(s, musb_irq_disconnect, 1);
+ musb_session_update(s, 1, s->session);
}
static inline void musb_cb_tick0(void *opaque)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 3f71291..ed6b3e7 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -322,52 +322,46 @@ static inline void ohci_set_interrupt(OHCIState *ohci,
uint32_t intr)
}
/* Attach or detach a device on a root hub port. */
-static void ohci_attach(USBPort *port1, USBDevice *dev)
+static void ohci_attach(USBPort *port1)
{
OHCIState *s = port1->opaque;
OHCIPort *port = &s->rhport[port1->index];
- uint32_t old_state = port->ctrl;
- if (dev) {
- if (port->port.dev) {
- usb_attach(port1, NULL);
- }
- /* set connect status */
- port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
-
- /* update speed */
- if (dev->speed == USB_SPEED_LOW)
- port->ctrl |= OHCI_PORT_LSDA;
- else
- port->ctrl &= ~OHCI_PORT_LSDA;
- port->port.dev = dev;
-
- /* notify of remote-wakeup */
- if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND)
- ohci_set_interrupt(s, OHCI_INTR_RD);
-
- /* send the attach message */
- usb_send_msg(dev, USB_MSG_ATTACH);
- DPRINTF("usb-ohci: Attached port %d\n", port1->index);
+ /* set connect status */
+ port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
+
+ /* update speed */
+ if (port->port.dev->speed == USB_SPEED_LOW) {
+ port->ctrl |= OHCI_PORT_LSDA;
} else {
- /* set connect status */
- if (port->ctrl & OHCI_PORT_CCS) {
- port->ctrl &= ~OHCI_PORT_CCS;
- port->ctrl |= OHCI_PORT_CSC;
- }
- /* disable port */
- if (port->ctrl & OHCI_PORT_PES) {
- port->ctrl &= ~OHCI_PORT_PES;
- port->ctrl |= OHCI_PORT_PESC;
- }
- dev = port->port.dev;
- if (dev) {
- /* send the detach message */
- usb_send_msg(dev, USB_MSG_DETACH);
- }
- port->port.dev = NULL;
- DPRINTF("usb-ohci: Detached port %d\n", port1->index);
+ port->ctrl &= ~OHCI_PORT_LSDA;
+ }
+
+ /* notify of remote-wakeup */
+ if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
+ ohci_set_interrupt(s, OHCI_INTR_RD);
+ }
+
+ DPRINTF("usb-ohci: Attached port %d\n", port1->index);
+}
+
+static void ohci_detach(USBPort *port1)
+{
+ OHCIState *s = port1->opaque;
+ OHCIPort *port = &s->rhport[port1->index];
+ uint32_t old_state = port->ctrl;
+
+ /* set connect status */
+ if (port->ctrl & OHCI_PORT_CCS) {
+ port->ctrl &= ~OHCI_PORT_CCS;
+ port->ctrl |= OHCI_PORT_CSC;
+ }
+ /* disable port */
+ if (port->ctrl & OHCI_PORT_PES) {
+ port->ctrl &= ~OHCI_PORT_PES;
+ port->ctrl |= OHCI_PORT_PESC;
}
+ DPRINTF("usb-ohci: Detached port %d\n", port1->index);
if (old_state != port->ctrl)
ohci_set_interrupt(s, OHCI_INTR_RHSC);
@@ -413,8 +407,9 @@ static void ohci_reset(void *opaque)
{
port = &ohci->rhport[i];
port->ctrl = 0;
- if (port->port.dev)
- ohci_attach(&port->port, port->port.dev);
+ if (port->port.dev) {
+ usb_attach(&port->port, port->port.dev);
+ }
}
if (ohci->async_td) {
usb_cancel_packet(&ohci->usb_packet);
@@ -1678,6 +1673,7 @@ static CPUWriteMemoryFunc * const ohci_writefn[3]={
static USBPortOps ohci_port_ops = {
.attach = ohci_attach,
+ .detach = ohci_detach,
};
static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 1427c2f..debf7f7 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -307,8 +307,6 @@ static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t
addr, uint32_t token
return match;
}
-static void uhci_attach(USBPort *port1, USBDevice *dev);
-
static void uhci_update_irq(UHCIState *s)
{
int level;
@@ -348,8 +346,9 @@ static void uhci_reset(void *opaque)
for(i = 0; i < NB_PORTS; i++) {
port = &s->ports[i];
port->ctrl = 0x0080;
- if (port->port.dev)
- uhci_attach(&port->port, port->port.dev);
+ if (port->port.dev) {
+ usb_attach(&port->port, port->port.dev);
+ }
}
uhci_async_cancel_all(s);
@@ -593,50 +592,41 @@ static void uhci_resume (void *opaque)
}
}
-static void uhci_attach(USBPort *port1, USBDevice *dev)
+static void uhci_attach(USBPort *port1)
{
UHCIState *s = port1->opaque;
UHCIPort *port = &s->ports[port1->index];
- if (dev) {
- if (port->port.dev) {
- usb_attach(port1, NULL);
- }
- /* set connect status */
- port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
+ /* set connect status */
+ port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
- /* update speed */
- if (dev->speed == USB_SPEED_LOW)
- port->ctrl |= UHCI_PORT_LSDA;
- else
- port->ctrl &= ~UHCI_PORT_LSDA;
-
- uhci_resume(s);
-
- port->port.dev = dev;
- /* send the attach message */
- usb_send_msg(dev, USB_MSG_ATTACH);
+ /* update speed */
+ if (port->port.dev->speed == USB_SPEED_LOW) {
+ port->ctrl |= UHCI_PORT_LSDA;
} else {
- /* set connect status */
- if (port->ctrl & UHCI_PORT_CCS) {
- port->ctrl &= ~UHCI_PORT_CCS;
- port->ctrl |= UHCI_PORT_CSC;
- }
- /* disable port */
- if (port->ctrl & UHCI_PORT_EN) {
- port->ctrl &= ~UHCI_PORT_EN;
- port->ctrl |= UHCI_PORT_ENC;
- }
+ port->ctrl &= ~UHCI_PORT_LSDA;
+ }
- uhci_resume(s);
+ uhci_resume(s);
+}
- dev = port->port.dev;
- if (dev) {
- /* send the detach message */
- usb_send_msg(dev, USB_MSG_DETACH);
- }
- port->port.dev = NULL;
+static void uhci_detach(USBPort *port1)
+{
+ UHCIState *s = port1->opaque;
+ UHCIPort *port = &s->ports[port1->index];
+
+ /* set connect status */
+ if (port->ctrl & UHCI_PORT_CCS) {
+ port->ctrl &= ~UHCI_PORT_CCS;
+ port->ctrl |= UHCI_PORT_CSC;
}
+ /* disable port */
+ if (port->ctrl & UHCI_PORT_EN) {
+ port->ctrl &= ~UHCI_PORT_EN;
+ port->ctrl |= UHCI_PORT_ENC;
+ }
+
+ uhci_resume(s);
}
static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
@@ -1103,6 +1093,7 @@ static void uhci_map(PCIDevice *pci_dev, int region_num,
static USBPortOps uhci_port_ops = {
.attach = uhci_attach,
+ .detach = uhci_detach,
};
static int usb_uhci_common_initfn(UHCIState *s)
diff --git a/hw/usb.c b/hw/usb.c
index 39d29f3..2eda86a 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -28,7 +28,25 @@
void usb_attach(USBPort *port, USBDevice *dev)
{
- port->ops->attach(port, dev);
+ if (dev != NULL) {
+ /* attach */
+ if (port->dev) {
+ usb_attach(port, NULL);
+ }
+ dev->port = port;
+ port->dev = dev;
+ port->ops->attach(port);
+ usb_send_msg(dev, USB_MSG_ATTACH);
+ } else {
+ /* detach */
+ dev = port->dev;
+ port->ops->detach(port);
+ if (dev) {
+ usb_send_msg(dev, USB_MSG_DETACH);
+ dev->port = NULL;
+ port->dev = NULL;
+ }
+ }
}
/**********************/
diff --git a/hw/usb.h b/hw/usb.h
index e98808a..6b008cc 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -147,6 +147,7 @@ struct USBDescString {
struct USBDevice {
DeviceState qdev;
USBDeviceInfo *info;
+ USBPort *port;
void *opaque;
int speed;
@@ -217,7 +218,8 @@ struct USBDeviceInfo {
};
typedef struct USBPortOps {
- void (*attach)(USBPort *port, USBDevice *dev);
+ void (*attach)(USBPort *port);
+ void (*detach)(USBPort *port);
} USBPortOps;
/* USB port on which a device can be connected */
--
1.7.1
- [Qemu-devel] [PATCH 14/30] usb: move remote wakeup handling to common code, (continued)
- [Qemu-devel] [PATCH 14/30] usb: move remote wakeup handling to common code, Gerd Hoffmann, 2010/12/17
- [Qemu-devel] [PATCH 13/30] usb: move USB_REQ_{GET, SET}_CONFIGURATION handling to common code, Gerd Hoffmann, 2010/12/17
- [Qemu-devel] [PATCH 19/30] usb: hub: remote wakeup support., Gerd Hoffmann, 2010/12/17
- [Qemu-devel] [PATCH 15/30] usb: create USBPortOps, move attach there., Gerd Hoffmann, 2010/12/17
- [Qemu-devel] [PATCH 11/30] usb network: use new descriptor infrastructure., Gerd Hoffmann, 2010/12/17
- [Qemu-devel] [PATCH 20/30] usb: hid: remote wakeup support., Gerd Hoffmann, 2010/12/17
- [Qemu-devel] [PATCH 21/30] usb: hid: change serial number to "42"., Gerd Hoffmann, 2010/12/17
- [Qemu-devel] [PATCH 27/30] usb storage: fix status reporting, Gerd Hoffmann, 2010/12/17
- [Qemu-devel] [PATCH 28/30] usb storage: handle long responses, Gerd Hoffmann, 2010/12/17
- [Qemu-devel] [PATCH 24/30] usb: add usb_desc_attach, Gerd Hoffmann, 2010/12/17
- [Qemu-devel] [PATCH 16/30] usb: rework attach/detach workflow,
Gerd Hoffmann <=
- [Qemu-devel] [PATCH 22/30] usb: add speed mask to ports, Gerd Hoffmann, 2010/12/17
- [Qemu-devel] [PATCH 26/30] usb storage: high speed support, Gerd Hoffmann, 2010/12/17
- [Qemu-devel] [PATCH 23/30] usb: add attach callback, Gerd Hoffmann, 2010/12/17
- [Qemu-devel] [PATCH 25/30] usb: add device qualifier support, Gerd Hoffmann, 2010/12/17
- [Qemu-devel] [PATCH 18/30] usb: uhci: remote wakeup support., Gerd Hoffmann, 2010/12/17
- [Qemu-devel] [PATCH 29/30] usb: keep track of physical port address., Gerd Hoffmann, 2010/12/17
- [Qemu-devel] [PATCH 30/30] usb: add port property., Gerd Hoffmann, 2010/12/17