qemu-devel
[Top][All Lists]
Advanced

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

[PATCH 1/2] printer: Introduce printer subsystem


From: Ruien Zhang
Subject: [PATCH 1/2] printer: Introduce printer subsystem
Date: Thu, 13 Jan 2022 19:56:58 +0800

From: zhangruien <zhangruien@bytedance.com>

This patch describes the skeleton of QEMU printer subsystem with a
dummy builtin driver.

Signed-off-by: zhangruien <zhangruien@bytedance.com>
---
 MAINTAINERS               |   7 ++
 include/printer/printer.h |  42 ++++++++++
 meson.build               |  12 ++-
 meson_options.txt         |   3 +
 printer/builtin.c         |  61 +++++++++++++++
 printer/meson.build       |  14 ++++
 printer/printer.c         | 191 ++++++++++++++++++++++++++++++++++++++++++++++
 printer/trace-events      |   5 ++
 printer/trace.h           |   1 +
 qapi/meson.build          |   1 +
 qapi/printer.json         |  47 ++++++++++++
 qapi/qapi-schema.json     |   1 +
 qemu-options.hx           |   8 ++
 softmmu/vl.c              |   4 +
 14 files changed, 396 insertions(+), 1 deletion(-)
 create mode 100644 include/printer/printer.h
 create mode 100644 printer/builtin.c
 create mode 100644 printer/meson.build
 create mode 100644 printer/printer.c
 create mode 100644 printer/trace-events
 create mode 100644 printer/trace.h
 create mode 100644 qapi/printer.json

diff --git a/MAINTAINERS b/MAINTAINERS
index c98a61caee..689f20d740 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3086,6 +3086,13 @@ F: hw/core/clock-vmstate.c
 F: hw/core/qdev-clock.c
 F: docs/devel/clocks.rst
 
+Printer Subsystem
+M: Ruien Zhang <zhangruien@bytedance.com>
+S: Maintained
+F: include/printer
+F: printer
+F: qapi/printer.json
+
 Usermode Emulation
 ------------------
 Overall usermode emulation
diff --git a/include/printer/printer.h b/include/printer/printer.h
new file mode 100644
index 0000000000..c8afbc64c8
--- /dev/null
+++ b/include/printer/printer.h
@@ -0,0 +1,42 @@
+/*
+ * QEMU Printer subsystem header
+ *
+ * Copyright (c) 2022 ByteDance, Inc.
+ *
+ * Author:
+ *   Ruien Zhang <zhangruien@bytedance.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef QEMU_PRINTER_H
+#define QEMU_PRINTER_H
+
+#include "hw/qdev-properties.h"
+#include "hw/qdev-properties-system.h"
+#include "qapi/qapi-types-printer.h"
+
+#define TYPE_PRINTERDEV "printerdev"
+
+struct QEMUPrinter {
+    Object  *parent_obj;
+
+    char *model;
+    Printerdev *dev;
+
+    QLIST_ENTRY(QEMUPrinter) list;
+};
+
+OBJECT_DECLARE_TYPE(QEMUPrinter, QEMUPrinterClass, PRINTERDEV)
+
+struct QEMUPrinterClass {
+    ObjectClass parent_class;
+};
+
+void qemu_printer_new_from_opts(const char *opt);
+void qemu_printer_del(QEMUPrinter *printer);
+const char *qemu_printer_id(QEMUPrinter *printer);
+QEMUPrinter *qemu_printer_by_id(const char *id);
+
+#endif /* QEMU_PRINTER_H */
diff --git a/meson.build b/meson.build
index c1b1db1e28..b3db26190d 100644
--- a/meson.build
+++ b/meson.build
@@ -2397,6 +2397,7 @@ genh += hxdep
 authz_ss = ss.source_set()
 blockdev_ss = ss.source_set()
 block_ss = ss.source_set()
+printer_ss = ss.source_set()
 chardev_ss = ss.source_set()
 common_ss = ss.source_set()
 common_user_ss = ss.source_set()
@@ -2455,6 +2456,7 @@ if have_system
     'audio',
     'backends',
     'backends/tpm',
+    'printer',
     'chardev',
     'ebpf',
     'hw/9pfs',
@@ -2574,6 +2576,7 @@ endif
 
 subdir('audio')
 subdir('io')
+subdir('printer')
 subdir('chardev')
 subdir('fsdev')
 subdir('dump')
@@ -2843,6 +2846,13 @@ libqmp = static_library('qmp', qmp_ss.sources() + genh,
 
 qmp = declare_dependency(link_whole: [libqmp])
 
+printer_ss = printer_ss.apply(config_host, strict: false)
+libprinter = static_library('printer', printer_ss.sources() + genh,
+                            name_suffix: 'fa',
+                            build_by_default: false)
+
+printer = declare_dependency(link_whole: libprinter)
+
 libchardev = static_library('chardev', chardev_ss.sources() + genh,
                             name_suffix: 'fa',
                             dependencies: [gnutls],
@@ -2869,7 +2879,7 @@ foreach m : block_mods + softmmu_mods
                 install_dir: qemu_moddir)
 endforeach
 
-softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
+softmmu_ss.add(authz, blockdev, printer, chardev, crypto, io, qmp)
 common_ss.add(qom, qemuutil)
 
 common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
diff --git a/meson_options.txt b/meson_options.txt
index 921967eddb..5b3b502798 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -208,3 +208,6 @@ option('fdt', type: 'combo', value: 'auto',
 
 option('selinux', type: 'feature', value: 'auto',
        description: 'SELinux support in qemu-nbd')
+
+option('printer', type: 'feature', value: 'auto',
+       description: 'Printer subsystem support')
diff --git a/printer/builtin.c b/printer/builtin.c
new file mode 100644
index 0000000000..bc33a1d363
--- /dev/null
+++ b/printer/builtin.c
@@ -0,0 +1,61 @@
+/*
+ * QEMU Builtin printer backend
+ *
+ * Copyright (c) 2022 ByteDance, Inc.
+ *
+ * Author:
+ *   Ruien Zhang <zhangruien@bytedance.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "qemu/log.h"
+#include "qemu/main-loop.h"
+#include "qom/object.h"
+#include "qapi/error.h"
+#include "qapi/visitor.h"
+#include "qapi/qapi-visit-printer.h"
+#include "printer/printer.h"
+#include "trace.h"
+
+#define TYPE_PRINTER_BUILTIN TYPE_PRINTERDEV"-builtin"
+
+typedef struct PrinterBuiltin {
+    QEMUPrinter parent;
+
+    void *opaque; /* used by driver itself */
+} PrinterBuiltin;
+
+DECLARE_INSTANCE_CHECKER(PrinterBuiltin, PRINTER_BUILTIN_DEV,
+                         TYPE_PRINTER_BUILTIN)
+
+static void printer_builtin_init(Object *obj)
+{
+}
+
+static void printer_builtin_finalize(Object *obj)
+{
+}
+
+static void printer_builtin_class_init(ObjectClass *oc, void *data)
+{
+}
+
+static const TypeInfo printer_builtin_type_info = {
+    .name = TYPE_PRINTER_BUILTIN,
+    .parent = TYPE_PRINTERDEV,
+    .instance_size = sizeof(PrinterBuiltin),
+    .instance_init = printer_builtin_init,
+    .instance_finalize = printer_builtin_finalize,
+    .class_init = printer_builtin_class_init,
+};
+
+static void register_types(void)
+{
+    type_register_static(&printer_builtin_type_info);
+}
+
+type_init(register_types);
diff --git a/printer/meson.build b/printer/meson.build
new file mode 100644
index 0000000000..9814de2a57
--- /dev/null
+++ b/printer/meson.build
@@ -0,0 +1,14 @@
+printer_ss.add([files(
+  'printer.c',
+)])
+
+printer_modules = {}
+foreach m : [
+  ['builtin', files('builtin.c')],
+]
+  module_ss = ss.source_set()
+  module_ss.add(m[1])
+  printer_modules += {m[0] : module_ss}
+endforeach
+
+modules += {'printer': printer_modules}
diff --git a/printer/printer.c b/printer/printer.c
new file mode 100644
index 0000000000..2d3f57a6e1
--- /dev/null
+++ b/printer/printer.c
@@ -0,0 +1,191 @@
+/*
+ * QEMU Printer subsystem
+ *
+ * Copyright (c) 2022 ByteDance, Inc.
+ *
+ * Author:
+ *   Ruien Zhang <zhangruien@bytedance.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/help_option.h"
+#include "qemu/iov.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qemu/qemu-print.h"
+#include "qom/object.h"
+#include "qapi/error.h"
+#include "qapi/visitor.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qapi/qapi-visit-printer.h"
+#include "printer/printer.h"
+#include "trace.h"
+
+static QLIST_HEAD(, QEMUPrinter) qemu_printers;
+
+const char *qemu_printer_id(QEMUPrinter *printer)
+{
+    if (printer->dev && printer->dev->id) {
+        return printer->dev->id;
+    }
+
+    return "";
+}
+
+QEMUPrinter *qemu_printer_by_id(const char *id)
+{
+    QEMUPrinter *printer;
+
+    if (!id) {
+        return NULL;
+    }
+
+    QLIST_FOREACH(printer, &qemu_printers, list) {
+        if (!strcmp(qemu_printer_id(printer), id)) {
+            return printer;
+        }
+    }
+
+    return NULL;
+}
+
+static const QEMUPrinterClass *printer_get_class(const char *typename,
+                                               Error **errp)
+{
+    ObjectClass *oc;
+
+    oc = module_object_class_by_name(typename);
+
+    if (!object_class_dynamic_cast(oc, TYPE_PRINTERDEV)) {
+        error_setg(errp, "%s: missing %s implementation",
+                   TYPE_PRINTERDEV, typename);
+        return NULL;
+    }
+
+    if (object_class_is_abstract(oc)) {
+        error_setg(errp, "%s: %s is abstract type", TYPE_PRINTERDEV, typename);
+        return NULL;
+    }
+
+    return PRINTERDEV_CLASS(oc);
+}
+
+static QEMUPrinter *qemu_printer_new(Printerdev *dev, Error **errp)
+{
+    Object *obj;
+    QEMUPrinter *printer = NULL;
+    g_autofree char *typename = NULL;
+    const char *driver = PrinterdevDriver_str(dev->driver);
+
+    typename = g_strdup_printf("%s-%s", TYPE_PRINTERDEV, driver);
+    if (!printer_get_class(typename, errp)) {
+        return NULL;
+    }
+
+    obj = object_new(typename);
+    if (!obj) {
+        return NULL;
+    }
+
+    printer = PRINTERDEV(obj);
+    printer->dev = dev;
+
+    QLIST_INSERT_HEAD(&qemu_printers, printer, list);
+    trace_qemu_printer_new(qemu_printer_id(printer), typename);
+
+    return printer;
+}
+
+typedef struct PrinterdevClassFE {
+    void (*fn)(const char *name, void *opaque);
+    void *opaque;
+} PrinterdevClassFE;
+
+static void printerdev_class_foreach(ObjectClass *klass, void *opaque)
+{
+    PrinterdevClassFE *fe = opaque;
+
+    assert(g_str_has_prefix(object_class_get_name(klass), TYPE_PRINTERDEV"-"));
+    fe->fn(object_class_get_name(klass) + 11, fe->opaque);
+}
+
+static void printerdev_name_foreach(void (*fn)(const char *name, void *opaque),
+                                   void *opaque)
+{
+    PrinterdevClassFE fe = { .fn = fn, .opaque = opaque };
+
+    object_class_foreach(printerdev_class_foreach, TYPE_PRINTERDEV, false, 
&fe);
+}
+
+static void help_string_append(const char *name, void *opaque)
+{
+    GString *str = opaque;
+
+    g_string_append_printf(str, "\n  %s", name);
+}
+
+void qemu_printer_new_from_opts(const char *opt)
+{
+    Printerdev *dev;
+
+    if (opt && is_help_option(opt)) {
+        GString *str = g_string_new("");
+
+        printerdev_name_foreach(help_string_append, str);
+
+        qemu_printf("Available printerdev backend types: %s\n", str->str);
+        g_string_free(str, true);
+        return;
+    }
+
+    Visitor *v = qobject_input_visitor_new_str(opt, "driver", &error_fatal);
+    visit_type_Printerdev(v, NULL, &dev, &error_fatal);
+    visit_free(v);
+
+    if (qemu_printer_by_id(dev->id)) {
+        error_setg(&error_fatal, "%s: id %s already existed",
+                   TYPE_PRINTERDEV, dev->id);
+    }
+
+    if (!qemu_printer_new(dev, &error_fatal)) {
+        qapi_free_Printerdev(dev);
+    }
+}
+
+void qemu_printer_del(QEMUPrinter *printer)
+{
+    trace_qemu_printer_del(qemu_printer_id(printer));
+
+    QLIST_REMOVE(printer, list);
+    qapi_free_Printerdev(printer->dev);
+    object_unref(printer);
+}
+
+
+static void printer_init(Object *obj)
+{
+}
+
+static void printer_finalize(Object *obj)
+{
+}
+
+static const TypeInfo printer_type_info = {
+    .name = TYPE_PRINTERDEV,
+    .parent = TYPE_OBJECT,
+    .instance_size = sizeof(QEMUPrinter),
+    .instance_init = printer_init,
+    .instance_finalize = printer_finalize,
+    .abstract = true,
+    .class_size = sizeof(QEMUPrinterClass),
+};
+
+static void register_types(void)
+{
+    type_register_static(&printer_type_info);
+}
+
+type_init(register_types);
diff --git a/printer/trace-events b/printer/trace-events
new file mode 100644
index 0000000000..e453bbe691
--- /dev/null
+++ b/printer/trace-events
@@ -0,0 +1,5 @@
+# See docs/devel/tracing.rst for syntax documentation.
+
+# printer.c
+qemu_printer_new(const char *dev, char *typename) "%s: new printer with type 
%s"
+qemu_printer_del(const char *dev) "%s: delete printer"
diff --git a/printer/trace.h b/printer/trace.h
new file mode 100644
index 0000000000..9717d37ac7
--- /dev/null
+++ b/printer/trace.h
@@ -0,0 +1 @@
+#include "trace/trace-printer.h"
diff --git a/qapi/meson.build b/qapi/meson.build
index c0c49c15e4..f85af6b7d6 100644
--- a/qapi/meson.build
+++ b/qapi/meson.build
@@ -59,6 +59,7 @@ if have_system
     'rdma',
     'rocker',
     'tpm',
+    'printer',
   ]
 endif
 if have_system or have_tools
diff --git a/qapi/printer.json b/qapi/printer.json
new file mode 100644
index 0000000000..9c2ecfe874
--- /dev/null
+++ b/qapi/printer.json
@@ -0,0 +1,47 @@
+# -*- mode: python -*-
+#
+# Copyright (C) 2022 Ruien Zhang <zhangruien@bytedance.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+
+##
+# = Printer
+##
+
+##
+# @PrinterBuiltinOptions:
+#
+# Options of the builtin printer.
+#
+# Since: 6.3
+##
+{ 'struct': 'PrinterBuiltinOptions',
+  'data': {} }
+
+##
+# @PrinterdevDriver:
+#
+# An enumeration of possible printer backend drivers.
+#
+# Since: 6.3
+##
+{ 'enum': 'PrinterdevDriver',
+  'data': [ 'builtin' ] }
+
+##
+# @Printerdev:
+#
+# Captures the configuration of a printer device.
+#
+# @id: identifier for monitor commands.
+#
+# Since: 6.3
+##
+{ 'union': 'Printerdev',
+  'base': {
+    'id': 'str',
+    'driver': 'PrinterdevDriver'},
+  'discriminator': 'driver',
+  'data': {
+    'builtin': 'PrinterBuiltinOptions' } }
diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json
index 4912b9744e..114b6a80cb 100644
--- a/qapi/qapi-schema.json
+++ b/qapi/qapi-schema.json
@@ -93,3 +93,4 @@
 { 'include': 'audio.json' }
 { 'include': 'acpi.json' }
 { 'include': 'pci.json' }
+{ 'include': 'printer.json' }
diff --git a/qemu-options.hx b/qemu-options.hx
index ec90505d84..448a456f86 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3564,6 +3564,14 @@ The available backends are:
     traffic identified by a name (preferably a fqdn).
 ERST
 
+DEFHEADING(Printer device options:)
+
+DEF("printerdev", HAS_ARG, QEMU_OPTION_printerdev,
+    "-printerdev help\n"
+    "-printerdev builtin,id=id\n"
+    , QEMU_ARCH_ALL
+)
+
 DEFHEADING()
 
 #ifdef CONFIG_TPM
diff --git a/softmmu/vl.c b/softmmu/vl.c
index a8cad43691..67b3c48fa1 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -94,6 +94,7 @@
 #ifdef CONFIG_VIRTFS
 #include "fsdev/qemu-fsdev.h"
 #endif
+#include "printer/printer.h"
 #include "sysemu/qtest.h"
 
 #include "disas/disas.h"
@@ -3247,6 +3248,9 @@ void qemu_init(int argc, char **argv, char **envp)
                              qemu_opt_get(opts, "mount_tag"), &error_abort);
                 break;
             }
+            case QEMU_OPTION_printerdev:
+                qemu_printer_new_from_opts(optarg);
+                break;
             case QEMU_OPTION_serial:
                 add_device_config(DEV_SERIAL, optarg);
                 default_serial = 0;
-- 
2.11.0




reply via email to

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