diff --git a/hw/qdev.c b/hw/qdev.c
index 89ba986..4be2f66 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -151,7 +151,7 @@ static int set_property(const char *name, const char *value, void *opaque)
     return 0;
 }
 
-static int show_device_props(const char *driver)
+static int show_device_props(const char *driver, const char *prefix)
 {
     DeviceInfo *info;
     Property *prop;
@@ -161,6 +161,10 @@ static int show_device_props(const char *driver)
         return 0;
     }
 
+    if (!prefix) {
+        prefix = "";
+    }
+
     for (prop = info->props; prop && prop->name; prop++) {
         /*
          * TODO Properties without a parser are just for dirty hacks.
@@ -171,7 +175,7 @@ static int show_device_props(const char *driver)
         if (!prop->info->parse) {
             continue;           /* no way to set it, don't show */
         }
-        error_printf("%s.%s=%s, %s\n", info->name, prop->name,
+        error_printf("%s%s.%s=%s, %s\n", prefix, info->name, prop->name,
                      prop->info->name, prop->desc ?: "");
     }
     return 1;
@@ -183,12 +187,15 @@ int qdev_device_help(QemuOpts *opts)
     DeviceInfo *info;
 
     driver = qemu_opt_get(opts, "driver");
-    if (driver && !strcmp(driver, "?")) {
+    if (driver && (!strcmp(driver, "?") || !strcmp(driver, "help"))) {
         for (info = device_info_list; info != NULL; info = info->next) {
             if (info->no_user) {
                 continue;       /* not available, don't show */
             }
             qdev_print_devinfo(info);
+            if (!strcmp(driver, "help")) {
+                show_device_props(info->name, "\t");
+            }
         }
         return 1;
     }
@@ -197,7 +204,7 @@ int qdev_device_help(QemuOpts *opts)
         return 0;
     }
 
-    return show_device_props(driver);
+    return show_device_props(driver, NULL);
 }
 
 DeviceState *qdev_device_add(QemuOpts *opts)
