diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 2a1edfc..0f8d060 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -23,10 +23,11 @@
  */
 #include "qemu-common.h"
 #include "usb.h"
+#include "usb-desc.h"
 
 //#define DEBUG
 
-#define MAX_PORTS 8
+#define NUM_PORTS 8
 
 typedef struct USBHubPort {
     USBPort port;
@@ -36,8 +37,7 @@ typedef struct USBHubPort {
 
 typedef struct USBHubState {
     USBDevice dev;
-    int nb_ports;
-    USBHubPort ports[MAX_PORTS];
+    USBHubPort ports[NUM_PORTS];
 } USBHubState;
 
 #define ClearHubFeature		(0x2000 | USB_REQ_CLEAR_FEATURE)
@@ -83,6 +83,60 @@ typedef struct USBHubState {
 
 /* same as Linux kernel root hubs */
 
+enum {
+    STR_MANUFACTURER = 1,
+    STR_PRODUCT,
+    STR_SERIALNUMBER,
+};
+
+static const USBDescStrings desc_strings = {
+    [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
+    [STR_PRODUCT]      = "QEMU USB Hub",
+    [STR_SERIALNUMBER] = "314159",
+};
+
+static const USBDescIface desc_iface_hub = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 1,
+    .bInterfaceClass               = USB_CLASS_HUB,
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_INT,
+            .wMaxPacketSize        = 1 + (NUM_PORTS + 7) / 8,
+            .bInterval             = 0xff,
+        },
+    }
+};
+
+static const USBDescDevice desc_device_hub = {
+    .bcdUSB                        = 0x0110,
+    .bDeviceClass                  = USB_CLASS_HUB,
+    .bMaxPacketSize0               = 8,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .bmAttributes          = 0xe0,
+            .ifs = &desc_iface_hub,
+        },
+    },
+};
+
+static const USBDesc desc_hub = {
+    .id = {
+        .idVendor          = 0,
+        .idProduct         = 0,
+        .bcdDevice         = 0x0101,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device_hub,
+    .str  = desc_strings,
+};
+
 static const uint8_t qemu_hub_dev_descriptor[] = {
 	0x12,       /*  u8 bLength; */
 	0x01,       /*  u8 bDescriptorType; Device */
@@ -209,6 +263,11 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
     USBHubState *s = (USBHubState *)dev;
     int ret;
 
+    ret = usb_desc_handle_control(dev, request, value, index, length, data);
+    if (ret >= 0) {
+        return ret;
+    }
+
     switch(request) {
     case DeviceRequest | USB_REQ_GET_STATUS:
         data[0] = (1 << USB_DEVICE_SELF_POWERED) |
@@ -242,53 +301,6 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
         dev->addr = value;
         ret = 0;
         break;
-    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
-        switch(value >> 8) {
-        case USB_DT_DEVICE:
-            memcpy(data, qemu_hub_dev_descriptor,
-                   sizeof(qemu_hub_dev_descriptor));
-            ret = sizeof(qemu_hub_dev_descriptor);
-            break;
-        case USB_DT_CONFIG:
-            memcpy(data, qemu_hub_config_descriptor,
-                   sizeof(qemu_hub_config_descriptor));
-
-            /* status change endpoint size based on number
-             * of ports */
-            data[22] = (s->nb_ports + 1 + 7) / 8;
-
-            ret = sizeof(qemu_hub_config_descriptor);
-            break;
-        case USB_DT_STRING:
-            switch(value & 0xff) {
-            case 0:
-                /* language ids */
-                data[0] = 4;
-                data[1] = 3;
-                data[2] = 0x09;
-                data[3] = 0x04;
-                ret = 4;
-                break;
-            case 1:
-                /* serial number */
-                ret = set_usb_string(data, "314159");
-                break;
-            case 2:
-                /* product description */
-                ret = set_usb_string(data, "QEMU USB Hub");
-                break;
-            case 3:
-                /* vendor description */
-                ret = set_usb_string(data, "QEMU " QEMU_VERSION);
-                break;
-            default:
-                goto fail;
-            }
-            break;
-        default:
-            goto fail;
-        }
-        break;
     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
         data[0] = 1;
         ret = 1;
@@ -315,8 +327,9 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
         {
             unsigned int n = index - 1;
             USBHubPort *port;
-            if (n >= s->nb_ports)
+            if (n >= NUM_PORTS) {
                 goto fail;
+            }
             port = &s->ports[n];
             data[0] = port->wPortStatus;
             data[1] = port->wPortStatus >> 8;
@@ -338,8 +351,9 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
             unsigned int n = index - 1;
             USBHubPort *port;
             USBDevice *dev;
-            if (n >= s->nb_ports)
+            if (n >= NUM_PORTS) {
                 goto fail;
+            }
             port = &s->ports[n];
             dev = port->port.dev;
             switch(value) {
@@ -367,8 +381,9 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
             unsigned int n = index - 1;
             USBHubPort *port;
 
-            if (n >= s->nb_ports)
+            if (n >= NUM_PORTS) {
                 goto fail;
+            }
             port = &s->ports[n];
             switch(value) {
             case PORT_ENABLE:
@@ -403,17 +418,17 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
             unsigned int n, limit, var_hub_size = 0;
             memcpy(data, qemu_hub_hub_descriptor,
                    sizeof(qemu_hub_hub_descriptor));
-            data[2] = s->nb_ports;
+            data[2] = NUM_PORTS;
 
             /* fill DeviceRemovable bits */
-            limit = ((s->nb_ports + 1 + 7) / 8) + 7;
+            limit = ((NUM_PORTS + 1 + 7) / 8) + 7;
             for (n = 7; n < limit; n++) {
                 data[n] = 0x00;
                 var_hub_size++;
             }
 
             /* fill PortPwrCtrlMask bits */
-            limit = limit + ((s->nb_ports + 7) / 8);
+            limit = limit + ((NUM_PORTS + 7) / 8);
             for (;n < limit; n++) {
                 data[n] = 0xff;
                 var_hub_size++;
@@ -442,14 +457,14 @@ static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
             USBHubPort *port;
             unsigned int status;
             int i, n;
-            n = (s->nb_ports + 1 + 7) / 8;
+            n = (NUM_PORTS + 1 + 7) / 8;
             if (p->len == 1) { /* FreeBSD workaround */
                 n = 1;
             } else if (n > p->len) {
                 return USB_RET_BABBLE;
             }
             status = 0;
-            for(i = 0; i < s->nb_ports; i++) {
+            for(i = 0; i < NUM_PORTS; i++) {
                 port = &s->ports[i];
                 if (port->wPortChange)
                     status |= (1 << (i + 1));
@@ -481,7 +496,7 @@ static int usb_hub_broadcast_packet(USBHubState *s, USBPacket *p)
     USBDevice *dev;
     int i, ret;
 
-    for(i = 0; i < s->nb_ports; i++) {
+    for(i = 0; i < NUM_PORTS; i++) {
         port = &s->ports[i];
         dev = port->port.dev;
         if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) {
@@ -518,7 +533,7 @@ static void usb_hub_handle_destroy(USBDevice *dev)
     USBHubState *s = (USBHubState *)dev;
     int i;
 
-    for (i = 0; i < s->nb_ports; i++) {
+    for (i = 0; i < NUM_PORTS; i++) {
         usb_unregister_port(usb_bus_from_device(dev),
                             &s->ports[i].port);
     }
@@ -530,9 +545,8 @@ static int usb_hub_initfn(USBDevice *dev)
     USBHubPort *port;
     int i;
 
-    s->dev.speed  = USB_SPEED_FULL,
-    s->nb_ports = MAX_PORTS; /* FIXME: make configurable */
-    for (i = 0; i < s->nb_ports; i++) {
+    s->dev.speed = USB_SPEED_FULL;
+    for (i = 0; i < NUM_PORTS; i++) {
         port = &s->ports[i];
         usb_register_port(usb_bus_from_device(dev),
                           &port->port, s, i, usb_hub_attach);
@@ -546,6 +560,7 @@ static struct USBDeviceInfo hub_info = {
     .product_desc   = "QEMU USB Hub",
     .qdev.name      = "usb-hub",
     .qdev.size      = sizeof(USBHubState),
+    .usb_desc       = &desc_hub,
     .init           = usb_hub_initfn,
     .handle_packet  = usb_hub_handle_packet,
     .handle_reset   = usb_hub_handle_reset,
