qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 14/20] qdev/usb: add usb bus support to qdev, conver


From: Gerd Hoffmann
Subject: [Qemu-devel] [PATCH 14/20] qdev/usb: add usb bus support to qdev, convert drivers.
Date: Mon, 29 Jun 2009 14:46:15 +0200

 * Add USBBus.
 * Add USBDeviceInfo, move device callbacks here.
 * Add usb-qdev helper functions.
 * Switch drivers to qdev.

TODO:
 * make the rest of qemu aware of usb busses and kill the FIXMEs
   added by this patch.

Signed-off-by: Gerd Hoffmann <address@hidden>
---
 Makefile        |    2 +-
 hw/bt-hid.c     |   18 +++++-----
 hw/usb-bt.c     |   37 ++++++++++++++-----
 hw/usb-bus.c    |   65 ++++++++++++++++++++++++++++++++++
 hw/usb-hid.c    |  105 ++++++++++++++++++++++++++++++++-----------------------
 hw/usb-hub.c    |   48 +++++++++++++++----------
 hw/usb-msd.c    |   44 +++++++++++++++--------
 hw/usb-musb.c   |    2 +-
 hw/usb-net.c    |   44 ++++++++++++++++-------
 hw/usb-ohci.c   |    4 +-
 hw/usb-serial.c |   47 ++++++++++++++++--------
 hw/usb-uhci.c   |    4 ++-
 hw/usb-wacom.c  |   33 +++++++++++------
 hw/usb.c        |   16 ++++----
 hw/usb.h        |   62 ++++++++++++++++++++------------
 usb-linux.c     |   52 +++++++++++++++++++--------
 vl.c            |    4 +-
 17 files changed, 394 insertions(+), 193 deletions(-)
 create mode 100644 hw/usb-bus.c

diff --git a/Makefile b/Makefile
index a06c9bf..e150ab1 100644
--- a/Makefile
+++ b/Makefile
@@ -103,7 +103,7 @@ OBJS+=tmp105.o lm832x.o eeprom93xx.o tsc2005.o
 OBJS+=scsi-disk.o cdrom.o
 OBJS+=scsi-generic.o
 OBJS+=usb.o usb-hub.o usb-$(HOST_USB).o usb-hid.o usb-msd.o usb-wacom.o
-OBJS+=usb-serial.o usb-net.o
+OBJS+=usb-serial.o usb-net.o usb-bus.o
 OBJS+=sd.o ssi-sd.o
 OBJS+=bt.o bt-host.o bt-vhci.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o usb-bt.o
 OBJS+=bt-hci-csr.o
diff --git a/hw/bt-hid.c b/hw/bt-hid.c
index af0c3d5..97c8d79 100644
--- a/hw/bt-hid.c
+++ b/hw/bt-hid.c
@@ -112,7 +112,7 @@ static void bt_hid_reset(struct bt_hid_device_s *s)
     bt_l2cap_device_done(&s->btdev);
     bt_l2cap_device_init(&s->btdev, net);
 
-    s->usbdev->handle_reset(s->usbdev);
+    s->usbdev->info->handle_reset(s->usbdev);
     s->proto = BT_HID_PROTO_REPORT;
     s->state = bt_state_ready;
     s->dataother.len = 0;
@@ -132,7 +132,7 @@ static int bt_hid_out(struct bt_hid_device_s *s)
         p.devep = 1;
         p.data = s->dataout.buffer;
         p.len = s->dataout.len;
-        s->dataout.len = s->usbdev->handle_data(s->usbdev, &p);
+        s->dataout.len = s->usbdev->info->handle_data(s->usbdev, &p);
 
         return s->dataout.len;
     }
@@ -155,7 +155,7 @@ static int bt_hid_in(struct bt_hid_device_s *s)
     p.devep = 1;
     p.data = s->datain.buffer;
     p.len = sizeof(s->datain.buffer);
-    s->datain.len = s->usbdev->handle_data(s->usbdev, &p);
+    s->datain.len = s->usbdev->info->handle_data(s->usbdev, &p);
 
     return s->datain.len;
 }
@@ -324,8 +324,8 @@ static void bt_hid_control_transaction(struct 
bt_hid_device_s *s,
             break;
         }
         s->proto = parameter;
-        s->usbdev->handle_control(s->usbdev, SET_PROTOCOL, s->proto, 0, 0,
-                                  NULL);
+        s->usbdev->info->handle_control(s->usbdev, SET_PROTOCOL, s->proto, 0, 
0,
+                                        NULL);
         ret = BT_HS_SUCCESSFUL;
         break;
 
@@ -334,7 +334,7 @@ static void bt_hid_control_transaction(struct 
bt_hid_device_s *s,
             ret = BT_HS_ERR_INVALID_PARAMETER;
             break;
         }
-        s->usbdev->handle_control(s->usbdev, GET_IDLE, 0, 0, 1,
+        s->usbdev->info->handle_control(s->usbdev, GET_IDLE, 0, 0, 1,
                         s->control->sdu_out(s->control, 1));
         s->control->sdu_submit(s->control);
         break;
@@ -347,7 +347,7 @@ static void bt_hid_control_transaction(struct 
bt_hid_device_s *s,
 
         /* We don't need to know about the Idle Rate here really,
          * so just pass it on to the device.  */
-        ret = s->usbdev->handle_control(s->usbdev,
+        ret = s->usbdev->info->handle_control(s->usbdev,
                         SET_IDLE, data[1], 0, 0, NULL) ?
                 BT_HS_SUCCESSFUL : BT_HS_ERR_INVALID_PARAMETER;
         /* XXX: Does this generate a handshake? */
@@ -451,7 +451,7 @@ static void bt_hid_connected_update(struct bt_hid_device_s 
*hid)
     hid->btdev.device.inquiry_scan = !hid->connected;
 
     if (hid->connected && !prev) {
-        hid->usbdev->handle_reset(hid->usbdev);
+        hid->usbdev->info->handle_reset(hid->usbdev);
         hid->proto = BT_HID_PROTO_REPORT;
     }
 
@@ -519,7 +519,7 @@ static void bt_hid_destroy(struct bt_device_s *dev)
         bt_hid_send_control(hid, BT_HC_VIRTUAL_CABLE_UNPLUG);
     bt_l2cap_device_done(&hid->btdev);
 
-    hid->usbdev->handle_destroy(hid->usbdev);
+    hid->usbdev->info->handle_destroy(hid->usbdev);
 
     qemu_free(hid);
 }
diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index 53ad9a8..f1d237b 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -618,22 +618,22 @@ static void usb_bt_handle_destroy(USBDevice *dev)
     qemu_free(s);
 }
 
+static void usb_bt_initfn(USBDevice *dev)
+{
+    struct USBBtState *s = DO_UPCAST(struct USBBtState, dev, dev);
+    s->dev.speed = USB_SPEED_HIGH;
+}
+
 USBDevice *usb_bt_init(HCIInfo *hci)
 {
+    USBDevice *dev;
     struct USBBtState *s;
 
     if (!hci)
         return NULL;
-    s = qemu_mallocz(sizeof(struct USBBtState));
+    dev = usb_create_simple(NULL /* FIXME */, "QEMU BT dongle");
+    s = DO_UPCAST(struct USBBtState, dev, dev);
     s->dev.opaque = s;
-    s->dev.speed = USB_SPEED_HIGH;
-    s->dev.handle_packet = usb_generic_handle_packet;
-    pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU BT dongle");
-
-    s->dev.handle_reset = usb_bt_handle_reset;
-    s->dev.handle_control = usb_bt_handle_control;
-    s->dev.handle_data = usb_bt_handle_data;
-    s->dev.handle_destroy = usb_bt_handle_destroy;
 
     s->hci = hci;
     s->hci->opaque = s;
@@ -642,5 +642,22 @@ USBDevice *usb_bt_init(HCIInfo *hci)
 
     usb_bt_handle_reset(&s->dev);
 
-    return &s->dev;
+    return dev;
+}
+
+static struct USBDeviceInfo bt_info = {
+    .qdev.name      = "QEMU BT dongle",
+    .qdev.size      = sizeof(struct USBBtState),
+    .init           = usb_bt_initfn,
+    .handle_packet  = usb_generic_handle_packet,
+    .handle_reset   = usb_bt_handle_reset,
+    .handle_control = usb_bt_handle_control,
+    .handle_data    = usb_bt_handle_data,
+    .handle_destroy = usb_bt_handle_destroy,
+};
+
+static void usb_bt_register_devices(void)
+{
+    usb_qdev_register(&bt_info);
 }
+device_init(usb_bt_register_devices)
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
new file mode 100644
index 0000000..669c1f7
--- /dev/null
+++ b/hw/usb-bus.c
@@ -0,0 +1,65 @@
+#include "hw.h"
+#include "usb.h"
+#include "qdev.h"
+
+static struct BusInfo usb_bus_info = {
+    .name  = "USB",
+    .size  = sizeof(USBBus),
+};
+static int next_usb_bus = 0;
+static USBBus *usbbus; /* hack alert */
+
+USBBus *usb_bus_new(DeviceState *host)
+{
+    USBBus *bus;
+    char name[32];
+
+    snprintf(name, sizeof(name), "usb%d", next_usb_bus);
+    bus = FROM_QBUS(USBBus, qbus_create(&usb_bus_info, host, name));
+    if (!usbbus)
+        usbbus = bus;
+    next_usb_bus++;
+    return bus;
+}
+
+static void usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
+{
+    USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
+    USBDeviceInfo *info = DO_UPCAST(USBDeviceInfo, qdev, base);
+
+    pstrcpy(dev->devname, sizeof(dev->devname), qdev->info->name);
+    dev->info = info;
+    dev->info->init(dev);
+}
+
+void usb_qdev_register(USBDeviceInfo *info)
+{
+    info->qdev.bus_info = &usb_bus_info;
+    info->qdev.init     = usb_qdev_init;
+    qdev_register(&info->qdev);
+}
+
+void usb_qdev_register_many(USBDeviceInfo *info)
+{
+    while (info->qdev.name) {
+        usb_qdev_register(info);
+        info++;
+    }
+}
+
+USBDevice *usb_create_simple(USBBus *bus, const char *name)
+{
+    DeviceState *dev;
+
+#if 1
+    /* temporary stopgap until all usb is properly qdev-ified */
+    if (!bus)
+        bus = usbbus;
+    if (!bus)
+        bus = usb_bus_new(NULL);
+#endif
+
+    dev = qdev_create(&bus->qbus, name);
+    qdev_init(dev);
+    return DO_UPCAST(USBDevice, qdev, dev);
+}
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index c850a91..d4b2e1a 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -846,65 +846,43 @@ static void usb_hid_handle_destroy(USBDevice *dev)
     qemu_free(s);
 }
 
-USBDevice *usb_tablet_init(void)
+static void usb_hid_initfn(USBDevice *dev, int kind)
 {
-    USBHIDState *s;
-
-    s = qemu_mallocz(sizeof(USBHIDState));
+    USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
     s->dev.speed = USB_SPEED_FULL;
-    s->dev.handle_packet = usb_generic_handle_packet;
-
-    s->dev.handle_reset = usb_mouse_handle_reset;
-    s->dev.handle_control = usb_hid_handle_control;
-    s->dev.handle_data = usb_hid_handle_data;
-    s->dev.handle_destroy = usb_hid_handle_destroy;
-    s->kind = USB_TABLET;
+    s->kind = kind;
     /* Force poll routine to be run and grab input the first time.  */
     s->changed = 1;
-
-    pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
-
-    return (USBDevice *)s;
 }
 
-USBDevice *usb_mouse_init(void)
+static void usb_tablet_initfn(USBDevice *dev)
 {
-    USBHIDState *s;
+    usb_hid_initfn(dev, USB_TABLET);
+}
 
-    s = qemu_mallocz(sizeof(USBHIDState));
-    s->dev.speed = USB_SPEED_FULL;
-    s->dev.handle_packet = usb_generic_handle_packet;
+static void usb_mouse_initfn(USBDevice *dev)
+{
+    usb_hid_initfn(dev, USB_MOUSE);
+}
 
-    s->dev.handle_reset = usb_mouse_handle_reset;
-    s->dev.handle_control = usb_hid_handle_control;
-    s->dev.handle_data = usb_hid_handle_data;
-    s->dev.handle_destroy = usb_hid_handle_destroy;
-    s->kind = USB_MOUSE;
-    /* Force poll routine to be run and grab input the first time.  */
-    s->changed = 1;
+static void usb_keyboard_initfn(USBDevice *dev)
+{
+    usb_hid_initfn(dev, USB_KEYBOARD);
+}
 
-    pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
+USBDevice *usb_tablet_init(void)
+{
+    return usb_create_simple(NULL /* FIXME */, "QEMU USB Tablet");
+}
 
-    return (USBDevice *)s;
+USBDevice *usb_mouse_init(void)
+{
+    return usb_create_simple(NULL /* FIXME */, "QEMU USB Mouse");
 }
 
 USBDevice *usb_keyboard_init(void)
 {
-    USBHIDState *s;
-
-    s = qemu_mallocz(sizeof(USBHIDState));
-    s->dev.speed = USB_SPEED_FULL;
-    s->dev.handle_packet = usb_generic_handle_packet;
-
-    s->dev.handle_reset = usb_keyboard_handle_reset;
-    s->dev.handle_control = usb_hid_handle_control;
-    s->dev.handle_data = usb_hid_handle_data;
-    s->dev.handle_destroy = usb_hid_handle_destroy;
-    s->kind = USB_KEYBOARD;
-
-    pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Keyboard");
-
-    return (USBDevice *) s;
+    return usb_create_simple(NULL /* FIXME */, "QEMU USB Keyboard");
 }
 
 void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
@@ -914,3 +892,42 @@ void usb_hid_datain_cb(USBDevice *dev, void *opaque, void 
(*datain)(void *))
     s->datain_opaque = opaque;
     s->datain = datain;
 }
+
+static struct USBDeviceInfo hid_info[] = {
+    {
+        .qdev.name      = "QEMU USB Tablet",
+        .qdev.size      = sizeof(USBHIDState),
+        .init           = usb_tablet_initfn,
+        .handle_packet  = usb_generic_handle_packet,
+        .handle_reset   = usb_mouse_handle_reset,
+        .handle_control = usb_hid_handle_control,
+        .handle_data    = usb_hid_handle_data,
+        .handle_destroy = usb_hid_handle_destroy,
+    },{
+        .qdev.name      = "QEMU USB Mouse",
+        .qdev.size      = sizeof(USBHIDState),
+        .init           = usb_mouse_initfn,
+        .handle_packet  = usb_generic_handle_packet,
+        .handle_reset   = usb_mouse_handle_reset,
+        .handle_control = usb_hid_handle_control,
+        .handle_data    = usb_hid_handle_data,
+        .handle_destroy = usb_hid_handle_destroy,
+    },{
+        .qdev.name      = "QEMU USB Keyboard",
+        .qdev.size      = sizeof(USBHIDState),
+        .init           = usb_keyboard_initfn,
+        .handle_packet  = usb_generic_handle_packet,
+        .handle_reset   = usb_keyboard_handle_reset,
+        .handle_control = usb_hid_handle_control,
+        .handle_data    = usb_hid_handle_data,
+        .handle_destroy = usb_hid_handle_destroy,
+    },{
+        /* end of list */
+    }
+};
+
+static void usb_hid_register_devices(void)
+{
+    usb_qdev_register_many(hid_info);
+}
+device_init(usb_hid_register_devices)
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 9f26bbe..bd4eb31 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -486,7 +486,7 @@ static int usb_hub_broadcast_packet(USBHubState *s, 
USBPacket *p)
         port = &s->ports[i];
         dev = port->port.dev;
         if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) {
-            ret = dev->handle_packet(dev, p);
+            ret = dev->info->handle_packet(dev, p);
             if (ret != USB_RET_NODEV) {
                 return ret;
             }
@@ -521,32 +521,40 @@ static void usb_hub_handle_destroy(USBDevice *dev)
     qemu_free(s);
 }
 
-USBDevice *usb_hub_init(int nb_ports)
+static void usb_hub_initfn(USBDevice *dev)
 {
-    USBHubState *s;
+    USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
     USBHubPort *port;
     int i;
 
-    if (nb_ports > MAX_PORTS)
-        return NULL;
-    s = qemu_mallocz(sizeof(USBHubState));
-    s->dev.speed = USB_SPEED_FULL;
-    s->dev.handle_packet = usb_hub_handle_packet;
-
-    /* generic USB device init */
-    s->dev.handle_reset = usb_hub_handle_reset;
-    s->dev.handle_control = usb_hub_handle_control;
-    s->dev.handle_data = usb_hub_handle_data;
-    s->dev.handle_destroy = usb_hub_handle_destroy;
-
-    pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Hub");
-
-    s->nb_ports = nb_ports;
-    for(i = 0; i < s->nb_ports; i++) {
+    s->dev.speed  = USB_SPEED_FULL,
+    s->nb_ports = MAX_PORTS; /* FIXME: make configurable */
+    for (i = 0; i < s->nb_ports; i++) {
         port = &s->ports[i];
         qemu_register_usb_port(&port->port, s, i, usb_hub_attach);
         port->wPortStatus = PORT_STAT_POWER;
         port->wPortChange = 0;
     }
-    return (USBDevice *)s;
 }
+
+USBDevice *usb_hub_init(int nb_ports)
+{
+    return usb_create_simple(NULL /* FIXME */, "QEMU USB Hub");
+}
+
+static struct USBDeviceInfo hub_info = {
+    .qdev.name      = "QEMU USB Hub",
+    .qdev.size      = sizeof(USBHubState),
+    .init           = usb_hub_initfn,
+    .handle_packet  = usb_hub_handle_packet,
+    .handle_reset   = usb_hub_handle_reset,
+    .handle_control = usb_hub_handle_control,
+    .handle_data    = usb_hub_handle_data,
+    .handle_destroy = usb_hub_handle_destroy,
+};
+
+static void usb_hub_register_devices(void)
+{
+    usb_qdev_register(&hub_info);
+}
+device_init(usb_hub_register_devices)
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 3a3eb4a..535178f 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -514,8 +514,16 @@ static void usb_msd_handle_destroy(USBDevice *dev)
     qemu_free(s);
 }
 
+static void usb_msd_initfn(USBDevice *dev)
+{
+    MSDState *s = DO_UPCAST(MSDState, dev, dev);
+
+    s->dev.speed = USB_SPEED_FULL;
+}
+
 USBDevice *usb_msd_init(const char *filename)
 {
+    USBDevice *dev;
     MSDState *s;
     BlockDriverState *bdrv;
     BlockDriver *drv = NULL;
@@ -548,30 +556,19 @@ USBDevice *usb_msd_init(const char *filename)
         return NULL;
     }
 
-    s = qemu_mallocz(sizeof(MSDState));
-
     bdrv = bdrv_new("usb");
     if (bdrv_open2(bdrv, filename, 0, drv) < 0)
-        goto fail;
-    s->bs = bdrv;
-
-    s->dev.speed = USB_SPEED_FULL;
-    s->dev.handle_packet = usb_generic_handle_packet;
-
-    s->dev.handle_reset = usb_msd_handle_reset;
-    s->dev.handle_control = usb_msd_handle_control;
-    s->dev.handle_data = usb_msd_handle_data;
-    s->dev.handle_destroy = usb_msd_handle_destroy;
+        return NULL;
 
+    dev = usb_create_simple(NULL /* FIXME */, "QEMU USB MSD");
+    s = DO_UPCAST(MSDState, dev, dev);
+    s->bs = bdrv;
     snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB MSD(%.16s)",
              filename);
 
     s->scsi_dev = scsi_disk_init(bdrv, 0, usb_msd_command_complete, s);
     usb_msd_handle_reset((USBDevice *)s);
     return (USBDevice *)s;
- fail:
-    qemu_free(s);
-    return NULL;
 }
 
 BlockDriverState *usb_msd_get_bdrv(USBDevice *dev)
@@ -580,3 +577,20 @@ BlockDriverState *usb_msd_get_bdrv(USBDevice *dev)
 
     return s->bs;
 }
+
+static struct USBDeviceInfo msd_info = {
+    .qdev.name      = "QEMU USB MSD",
+    .qdev.size      = sizeof(MSDState),
+    .init           = usb_msd_initfn,
+    .handle_packet  = usb_generic_handle_packet,
+    .handle_reset   = usb_msd_handle_reset,
+    .handle_control = usb_msd_handle_control,
+    .handle_data    = usb_msd_handle_data,
+    .handle_destroy = usb_msd_handle_destroy,
+};
+
+static void usb_msd_register_devices(void)
+{
+    usb_qdev_register(&msd_info);
+}
+device_init(usb_msd_register_devices)
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 451bc8d..bf9a555 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -591,7 +591,7 @@ static inline void musb_packet(MUSBState *s, MUSBEndPoint 
*ep,
     ep->packey[dir].complete_opaque = ep;
 
     if (s->port.dev)
-        ret = s->port.dev->handle_packet(s->port.dev, &ep->packey[dir]);
+        ret = s->port.dev->info->handle_packet(s->port.dev, &ep->packey[dir]);
     else
         ret = USB_RET_NODEV;
 
diff --git a/hw/usb-net.c b/hw/usb-net.c
index 0e80ca6..fde814b 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1432,32 +1432,33 @@ static void usb_net_handle_destroy(USBDevice *dev)
     qemu_del_vlan_client(s->vc);
 }
 
-USBDevice *usb_net_init(NICInfo *nd)
+static void usb_net_initfn(USBDevice *dev)
 {
-    USBNetState *s;
-
-    s = qemu_mallocz(sizeof(USBNetState));
-    s->dev.speed = USB_SPEED_FULL;
-    s->dev.handle_packet = usb_generic_handle_packet;
+    USBNetState *s = DO_UPCAST(USBNetState, dev, dev);
 
-    s->dev.handle_reset = usb_net_handle_reset;
-    s->dev.handle_control = usb_net_handle_control;
-    s->dev.handle_data = usb_net_handle_data;
-    s->dev.handle_destroy = usb_net_handle_destroy;
+    s->dev.speed  = USB_SPEED_FULL;
 
     s->rndis = 1;
     s->rndis_state = RNDIS_UNINITIALIZED;
+    TAILQ_INIT(&s->rndis_resp);
+
     s->medium = 0;     /* NDIS_MEDIUM_802_3 */
     s->speed = 1000000; /* 100MBps, in 100Bps units */
     s->media_state = 0;        /* NDIS_MEDIA_STATE_CONNECTED */;
     s->filter = 0;
     s->vendorid = 0x1234;
+}
+
+USBDevice *usb_net_init(NICInfo *nd)
+{
+    USBDevice *dev;
+    USBNetState *s;
+
+    dev = usb_create_simple(NULL /* FIXME */, "QEMU USB Network Interface");
+    s = DO_UPCAST(USBNetState, dev, dev);
 
     memcpy(s->mac, nd->macaddr, 6);
-    TAILQ_INIT(&s->rndis_resp);
 
-    pstrcpy(s->dev.devname, sizeof(s->dev.devname),
-                    "QEMU USB Network Interface");
     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
                                  usbnet_can_receive,
                                  usbnet_receive,
@@ -1476,3 +1477,20 @@ USBDevice *usb_net_init(NICInfo *nd)
 
     return (USBDevice *) s;
 }
+
+static struct USBDeviceInfo net_info = {
+    .qdev.name      = "QEMU USB Network Interface",
+    .qdev.size      = sizeof(USBNetState),
+    .init           = usb_net_initfn,
+    .handle_packet  = usb_generic_handle_packet,
+    .handle_reset   = usb_net_handle_reset,
+    .handle_control = usb_net_handle_control,
+    .handle_data    = usb_net_handle_data,
+    .handle_destroy = usb_net_handle_destroy,
+};
+
+static void usb_net_register_devices(void)
+{
+    usb_qdev_register(&net_info);
+}
+device_init(usb_net_register_devices)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index c575480..8cc6677 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -755,7 +755,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct 
ohci_ed *ed,
             ohci->usb_packet.len = len;
             ohci->usb_packet.complete_cb = ohci_async_complete_packet;
             ohci->usb_packet.complete_opaque = ohci;
-            ret = dev->handle_packet(dev, &ohci->usb_packet);
+            ret = dev->info->handle_packet(dev, &ohci->usb_packet);
             if (ret != USB_RET_NODEV)
                 break;
         }
@@ -945,7 +945,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed 
*ed)
             ohci->usb_packet.len = len;
             ohci->usb_packet.complete_cb = ohci_async_complete_packet;
             ohci->usb_packet.complete_opaque = ohci;
-            ret = dev->handle_packet(dev, &ohci->usb_packet);
+            ret = dev->info->handle_packet(dev, &ohci->usb_packet);
             if (ret != USB_RET_NODEV)
                 break;
         }
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index 19870a5..24de936 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -524,8 +524,15 @@ static void usb_serial_event(void *opaque, int event)
     }
 }
 
+static void usb_serial_initfn(USBDevice *dev)
+{
+    USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
+    s->dev.speed = USB_SPEED_FULL;
+}
+
 USBDevice *usb_serial_init(const char *filename)
 {
+    USBDevice *dev;
     USBSerialState *s;
     CharDriverState *cdrv;
     unsigned short vendorid = 0x0403, productid = 0x6001;
@@ -561,32 +568,40 @@ USBDevice *usb_serial_init(const char *filename)
         return NULL;
     }
     filename++;
-    s = qemu_mallocz(sizeof(USBSerialState));
 
     snprintf(label, sizeof(label), "usbserial%d", index++);
     cdrv = qemu_chr_open(label, filename, NULL);
     if (!cdrv)
-        goto fail;
-    s->cs = cdrv;
-    qemu_chr_add_handlers(cdrv, usb_serial_can_read, usb_serial_read, 
usb_serial_event, s);
-
-    s->dev.speed = USB_SPEED_FULL;
-    s->dev.handle_packet = usb_generic_handle_packet;
-
-    s->dev.handle_reset = usb_serial_handle_reset;
-    s->dev.handle_control = usb_serial_handle_control;
-    s->dev.handle_data = usb_serial_handle_data;
-    s->dev.handle_destroy = usb_serial_handle_destroy;
+        return NULL;
 
+    dev = usb_create_simple(NULL /* FIXME */, "QEMU USB Serial");
+    s = DO_UPCAST(USBSerialState, dev, dev);
+    s->cs = cdrv;
     s->vendorid = vendorid;
     s->productid = productid;
-
     snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Serial(%.16s)",
              filename);
 
+    qemu_chr_add_handlers(cdrv, usb_serial_can_read, usb_serial_read,
+                          usb_serial_event, s);
+
     usb_serial_handle_reset((USBDevice *)s);
     return (USBDevice *)s;
- fail:
-    qemu_free(s);
-    return NULL;
 }
+
+static struct USBDeviceInfo serial_info = {
+    .qdev.name      = "QEMU USB Serial",
+    .qdev.size      = sizeof(USBSerialState),
+    .init           = usb_serial_initfn,
+    .handle_packet  = usb_generic_handle_packet,
+    .handle_reset   = usb_serial_handle_reset,
+    .handle_control = usb_serial_handle_control,
+    .handle_data    = usb_serial_handle_data,
+    .handle_destroy = usb_serial_handle_destroy,
+};
+
+static void usb_serial_register_devices(void)
+{
+    usb_qdev_register(&serial_info);
+}
+device_init(usb_serial_register_devices)
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 9ec270e..6daeb33 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -122,6 +122,7 @@ typedef struct UHCIPort {
 
 typedef struct UHCIState {
     PCIDevice dev;
+    USBBus *bus;
     uint16_t cmd; /* cmd register */
     uint16_t status;
     uint16_t intr; /* interrupt enable register */
@@ -660,7 +661,7 @@ static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
         USBDevice *dev = port->port.dev;
 
         if (dev && (port->ctrl & UHCI_PORT_EN))
-            ret = dev->handle_packet(dev, p);
+            ret = dev->info->handle_packet(dev, p);
     }
 
     dprintf("uhci: packet exit. ret %d len %d\n", ret, p->len);
@@ -1095,6 +1096,7 @@ static void usb_uhci_common_initfn(UHCIState *s)
     pci_register_bar(&s->dev, 4, 0x20,
                            PCI_ADDRESS_SPACE_IO, uhci_map);
 
+    s->bus = usb_bus_new(&s->dev.qdev);
     register_savevm("uhci", 0, 1, uhci_save, uhci_load, s);
 }
 
diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
index eaf0d29..05b317a 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -392,21 +392,30 @@ static void usb_wacom_handle_destroy(USBDevice *dev)
     qemu_free(s);
 }
 
-USBDevice *usb_wacom_init(void)
+static void usb_wacom_initfn(USBDevice *dev)
 {
-    USBWacomState *s;
-
-    s = qemu_mallocz(sizeof(USBWacomState));
+    USBWacomState *s = DO_UPCAST(USBWacomState, dev, dev);
     s->dev.speed = USB_SPEED_FULL;
-    s->dev.handle_packet = usb_generic_handle_packet;
+}
 
-    s->dev.handle_reset = usb_wacom_handle_reset;
-    s->dev.handle_control = usb_wacom_handle_control;
-    s->dev.handle_data = usb_wacom_handle_data;
-    s->dev.handle_destroy = usb_wacom_handle_destroy;
+USBDevice *usb_wacom_init(void)
+{
+    return usb_create_simple(NULL /* FIXME */, "QEMU PenPartner Tablet");
+}
 
-    pstrcpy(s->dev.devname, sizeof(s->dev.devname),
-            "QEMU PenPartner Tablet");
+static struct USBDeviceInfo wacom_info = {
+    .qdev.name      = "QEMU PenPartner Tablet",
+    .qdev.size      = sizeof(USBWacomState),
+    .init           = usb_wacom_initfn,
+    .handle_packet  = usb_generic_handle_packet,
+    .handle_reset   = usb_wacom_handle_reset,
+    .handle_control = usb_wacom_handle_control,
+    .handle_data    = usb_wacom_handle_data,
+    .handle_destroy = usb_wacom_handle_destroy,
+};
 
-    return (USBDevice *) s;
+static void usb_wacom_register_devices(void)
+{
+    usb_qdev_register(&wacom_info);
 }
+device_init(usb_wacom_register_devices)
diff --git a/hw/usb.c b/hw/usb.c
index c17266d..a326bcf 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -59,8 +59,8 @@ static int do_token_setup(USBDevice *s, USBPacket *p)
     index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
  
     if (s->setup_buf[0] & USB_DIR_IN) {
-        ret = s->handle_control(s, request, value, index, 
-                                s->setup_len, s->data_buf);
+        ret = s->info->handle_control(s, request, value, index, 
+                                      s->setup_len, s->data_buf);
         if (ret < 0)
             return ret;
 
@@ -83,7 +83,7 @@ static int do_token_in(USBDevice *s, USBPacket *p)
     int ret = 0;
 
     if (p->devep != 0)
-        return s->handle_data(s, p);
+        return s->info->handle_data(s, p);
 
     request = (s->setup_buf[0] << 8) | s->setup_buf[1];
     value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
@@ -93,8 +93,8 @@ static int do_token_in(USBDevice *s, USBPacket *p)
     case SETUP_STATE_ACK:
         if (!(s->setup_buf[0] & USB_DIR_IN)) {
             s->setup_state = SETUP_STATE_IDLE;
-            ret = s->handle_control(s, request, value, index,
-                                    s->setup_len, s->data_buf);
+            ret = s->info->handle_control(s, request, value, index,
+                                          s->setup_len, s->data_buf);
             if (ret > 0)
                 return 0;
             return ret;
@@ -126,7 +126,7 @@ static int do_token_in(USBDevice *s, USBPacket *p)
 static int do_token_out(USBDevice *s, USBPacket *p)
 {
     if (p->devep != 0)
-        return s->handle_data(s, p);
+        return s->info->handle_data(s, p);
 
     switch(s->setup_state) {
     case SETUP_STATE_ACK:
@@ -179,7 +179,7 @@ int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
         s->remote_wakeup = 0;
         s->addr = 0;
         s->state = USB_STATE_DEFAULT;
-        s->handle_reset(s);
+        s->info->handle_reset(s);
         return 0;
     }
 
@@ -225,7 +225,7 @@ void usb_send_msg(USBDevice *dev, int msg)
     USBPacket p;
     memset(&p, 0, sizeof(p));
     p.pid = msg;
-    dev->handle_packet(dev, &p);
+    dev->info->handle_packet(dev, &p);
 
     /* This _must_ be synchronous */
 }
diff --git a/hw/usb.h b/hw/usb.h
index e9d4bc2..e39d917 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -23,6 +23,7 @@
  */
 
 #include "block.h"
+#include "qdev.h"
 
 #define USB_TOKEN_SETUP 0x2d
 #define USB_TOKEN_IN    0x69 /* device -> host */
@@ -116,37 +117,52 @@
 #define USB_ENDPOINT_XFER_BULK         2
 #define USB_ENDPOINT_XFER_INT          3
 
+typedef struct USBBus USBBus;
 typedef struct USBPort USBPort;
 typedef struct USBDevice USBDevice;
+typedef struct USBDeviceInfo USBDeviceInfo;
 typedef struct USBPacket USBPacket;
 
 /* definition of a USB device */
 struct USBDevice {
+    DeviceState qdev;
+    USBDeviceInfo *info;
     void *opaque;
 
-    /* 
-     * Process USB packet. 
+    int speed;
+    uint8_t addr;
+    char devname[32];
+
+    int state;
+    uint8_t setup_buf[8];
+    uint8_t data_buf[1024];
+    int remote_wakeup;
+    int setup_state;
+    int setup_len;
+    int setup_index;
+};
+
+struct USBDeviceInfo {
+    DeviceInfo qdev;
+    void (*init)(USBDevice *dev);
+
+    /*
+     * Process USB packet.
      * Called by the HC (Host Controller).
      *
-     * Returns length of the transaction 
+     * Returns length of the transaction
      * or one of the USB_RET_XXX codes.
-     */ 
+     */
     int (*handle_packet)(USBDevice *dev, USBPacket *p);
 
-    /* 
+    /*
      * Called when device is destroyed.
      */
     void (*handle_destroy)(USBDevice *dev);
 
-    int speed;
-
-    /* The following fields are used by the generic USB device
-       layer. They are here just to avoid creating a new structure 
-       for them. */
-
     /*
      * Reset the device
-     */  
+     */
     void (*handle_reset)(USBDevice *dev);
 
     /*
@@ -165,17 +181,6 @@ struct USBDevice {
      * Returns length or one of the USB_RET_ codes.
      */
     int (*handle_data)(USBDevice *dev, USBPacket *p);
-
-    uint8_t addr;
-    char devname[32];
-
-    int state;
-    uint8_t setup_buf[8];
-    uint8_t data_buf[1024];
-    int remote_wakeup;
-    int setup_state;
-    int setup_len;
-    int setup_index;
 };
 
 typedef void (*usb_attachfn)(USBPort *port, USBDevice *dev);
@@ -297,3 +302,14 @@ MUSBState *musb_init(qemu_irq *irqs);
 uint32_t musb_core_intr_get(MUSBState *s);
 void musb_core_intr_clear(MUSBState *s, uint32_t mask);
 void musb_set_size(MUSBState *s, int epnum, int size, int is_tx);
+
+/* usb-bus.c */
+
+struct USBBus {
+    BusState qbus;
+};
+
+USBBus *usb_bus_new(DeviceState *host);
+void usb_qdev_register(USBDeviceInfo *info);
+void usb_qdev_register_many(USBDeviceInfo *info);
+USBDevice *usb_create_simple(USBBus *bus, const char *name);
diff --git a/usb-linux.c b/usb-linux.c
index 67e4acd..3ac7ab3 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -751,7 +751,7 @@ static int usb_host_handle_packet(USBDevice *s, USBPacket 
*p)
         s->remote_wakeup = 0;
         s->addr = 0;
         s->state = USB_STATE_DEFAULT;
-        s->handle_reset(s);
+        s->info->handle_reset(s);
         return 0;
     }
 
@@ -881,18 +881,18 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
     return 0;
 }
 
+static void usb_host_initfn(USBDevice *dev)
+{
+}
+
 static USBDevice *usb_host_device_open_addr(int bus_num, int addr, const char 
*prod_name)
 {
     int fd = -1, ret;
-    USBHostDevice *dev = NULL;
+    USBDevice *d = NULL;
+    USBHostDevice *dev;
     struct usbdevfs_connectinfo ci;
     char buf[1024];
 
-    dev = qemu_mallocz(sizeof(USBHostDevice));
-
-    dev->bus_num = bus_num;
-    dev->addr = addr;
-
     printf("husb: open device %d.%d\n", bus_num, addr);
 
     if (!usb_host_device_path) {
@@ -908,6 +908,12 @@ static USBDevice *usb_host_device_open_addr(int bus_num, 
int addr, const char *p
     }
     dprintf("husb: opened %s\n", buf);
 
+    d = usb_create_simple(NULL /* FIXME */, "USB Host Device");
+    dev = DO_UPCAST(USBHostDevice, dev, d);
+
+    dev->bus_num = bus_num;
+    dev->addr = addr;
+
     /* read the device description */
     dev->descr_len = read(fd, dev->descr, sizeof(dev->descr));
     if (dev->descr_len <= 0) {
@@ -925,7 +931,6 @@ static USBDevice *usb_host_device_open_addr(int bus_num, 
int addr, const char *p
     }
 #endif
 
-    dev->fd = fd;
 
     /* 
      * Initial configuration is -1 which makes us claim first 
@@ -953,10 +958,6 @@ static USBDevice *usb_host_device_open_addr(int bus_num, 
int addr, const char *p
     else
         dev->dev.speed = USB_SPEED_HIGH;
 
-    dev->dev.handle_packet  = usb_host_handle_packet;
-    dev->dev.handle_reset   = usb_host_handle_reset;
-    dev->dev.handle_destroy = usb_host_handle_destroy;
-
     if (!prod_name || prod_name[0] == '\0')
         snprintf(dev->dev.devname, sizeof(dev->dev.devname),
                  "host:%d.%d", bus_num, addr);
@@ -972,13 +973,32 @@ static USBDevice *usb_host_device_open_addr(int bus_num, 
int addr, const char *p
     return (USBDevice *) dev;
 
 fail:
-    if (dev)
-        qemu_free(dev);
-
-    close(fd);
+    if (d)
+        qdev_free(&d->qdev);
+    if (fd != -1)
+        close(fd);
     return NULL;
 }
 
+static struct USBDeviceInfo usb_host_dev_info = {
+    .qdev.name      = "USB Host Device",
+    .qdev.size      = sizeof(USBHostDevice),
+    .init           = usb_host_initfn,
+    .handle_packet  = usb_host_handle_packet,
+    .handle_reset   = usb_host_handle_reset,
+#if 0
+    .handle_control = usb_host_handle_control,
+    .handle_data    = usb_host_handle_data,
+#endif
+    .handle_destroy = usb_host_handle_destroy,
+};
+
+static void usb_host_register_devices(void)
+{
+    usb_qdev_register(&usb_host_dev_info);
+}
+device_init(usb_host_register_devices)
+
 static int usb_host_auto_add(const char *spec);
 static int usb_host_auto_del(const char *spec);
 
diff --git a/vl.c b/vl.c
index 60a00e1..99090ad 100644
--- a/vl.c
+++ b/vl.c
@@ -2667,7 +2667,7 @@ static void usb_msd_password_cb(void *opaque, int err)
     if (!err)
         usb_device_add_dev(dev);
     else
-        dev->handle_destroy(dev);
+        dev->info->handle_destroy(dev);
 }
 
 static int usb_device_add(const char *devname, int is_hotplug)
@@ -2753,7 +2753,7 @@ int usb_device_del_addr(int bus_num, int addr)
     dev = port->dev;
     *lastp = port->next;
     usb_attach(port, NULL);
-    dev->handle_destroy(dev);
+    dev->info->handle_destroy(dev);
     port->next = free_usb_ports;
     free_usb_ports = port;
     return 0;
-- 
1.6.2.5





reply via email to

[Prev in Thread] Current Thread [Next in Thread]