dbus: Use new bus name, object and interface
The new interface is a more typical use of DBus, exposing multiple
methods for the functions that are available on the object. The legacy
interface by comparison exposed only one method whose arguments selected
sub-commands to be executed. The legacy approach is not terribly
discoverable and leads to a lack of clarity in the client code. The
legacy approach also obscured the implementation with its use of `struct
mbox_dbus_msg`. The new interface wraps around the existing helpers and
so also deals with `struct mbox_dbus_msg`, but this can at least be
removed in the future.
Change-Id: I7113ed8fd2324bf3fb049d8d20acb3fd7fba6de3
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
diff --git a/Documentation/mboxd.md b/Documentation/mboxd.md
index 1f3bef1..f8ae982 100644
--- a/Documentation/mboxd.md
+++ b/Documentation/mboxd.md
@@ -23,7 +23,7 @@
functions from the various mboxd_*.c files.
```
-mboxd_dbus.c - Contains the handlers for the D-Bus commands which the daemon can
+dbus.c - Contains the handlers for the D-Bus commands which the daemon can
receive.
mboxd_flash.c - Contains the functions for performing flash access including
read, write and erase.
diff --git a/Makefile.am b/Makefile.am
index fb5997a..e225ff8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,6 +7,7 @@
control.c \
control_legacy.c \
mboxd_dbus.c \
+ control_dbus.c \
mboxd_lpc.c \
mboxd_msg.c \
mboxd_windows.c \
diff --git a/control_dbus.c b/control_dbus.c
new file mode 100644
index 0000000..c970b8f
--- /dev/null
+++ b/control_dbus.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (C) 2018 IBM Corp.
+#include <assert.h>
+#include <errno.h>
+#include <systemd/sd-bus.h>
+
+#include "common.h"
+#include "dbus.h"
+#include "control_dbus.h"
+#include "mbox.h"
+
+typedef int (*control_action)(struct mbox_context *context);
+
+static int control_dbus_directive(sd_bus_message *m, void *userdata,
+ sd_bus_error *ret_error,
+ control_action action)
+{
+ struct mbox_context *context;
+ sd_bus_message *n;
+ int rc;
+
+ if (!action) {
+ MSG_ERR("No action provided\n");
+ return -EINVAL;
+ }
+
+ context = (struct mbox_context *) userdata;
+ if (!context) {
+ MSG_ERR("DBUS Internal Error\n");
+ return -EINVAL;
+ }
+
+ rc = action(context);
+ if (rc < 0) {
+ MSG_ERR("Action failed: %d\n", rc);
+ return rc;
+ }
+
+ rc = sd_bus_message_new_method_return(m, &n);
+ if (rc < 0) {
+ MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc);
+ return rc;
+ }
+
+ return sd_bus_send(NULL, n, NULL);
+}
+
+static int control_dbus_ping(sd_bus_message *m, void *userdata,
+ sd_bus_error *ret_error)
+{
+ return control_dbus_directive(m, userdata, ret_error, control_ping);
+}
+
+static int control_dbus_reset(sd_bus_message *m, void *userdata,
+ sd_bus_error *ret_error)
+{
+ return control_dbus_directive(m, userdata, ret_error, control_reset);
+}
+
+static int control_dbus_kill(sd_bus_message *m, void *userdata,
+ sd_bus_error *ret_error)
+{
+ return control_dbus_directive(m, userdata, ret_error, control_kill);
+}
+
+static int control_dbus_modified(sd_bus_message *m, void *userdata,
+ sd_bus_error *ret_error)
+{
+ return control_dbus_directive(m, userdata, ret_error, control_modified);
+}
+
+static int control_dbus_suspend(sd_bus_message *m, void *userdata,
+ sd_bus_error *ret_error)
+{
+ return control_dbus_directive(m, userdata, ret_error, control_suspend);
+}
+
+static int control_dbus_resume(sd_bus_message *m, void *userdata,
+ sd_bus_error *ret_error)
+{
+ struct mbox_context *context;
+ sd_bus_message *n;
+ bool modified;
+ int rc;
+
+ context = (struct mbox_context *) userdata;
+ if (!context) {
+ MSG_ERR("DBUS Internal Error\n");
+ return -EINVAL;
+ }
+
+ rc = sd_bus_message_read_basic(m, 'b', &modified);
+ if (rc < 0) {
+ MSG_ERR("DBUS error reading message: %s\n", strerror(-rc));
+ return rc;
+ }
+
+ rc = control_resume(context, modified);
+ if (rc < 0)
+ return rc;
+
+ rc = sd_bus_message_new_method_return(m, &n);
+ if (rc < 0) {
+ MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc);
+ return rc;
+ }
+
+ return sd_bus_send(NULL, n, NULL);
+}
+
+static int control_dbus_get_u8(sd_bus *bus, const char *path,
+ const char *interface, const char *property,
+ sd_bus_message *reply, void *userdata,
+ sd_bus_error *ret_error)
+{
+ struct mbox_context *context = userdata;
+ uint8_t value;
+
+ assert(!strcmp(MBOX_DBUS_OBJECT, path));
+
+ if (!strcmp("DaemonState", property)) {
+ value = control_daemon_state(context);
+ } else if (!strcmp("LpcState", property)) {
+ value = control_lpc_state(context);
+ } else {
+ MSG_ERR("Unknown DBus property: %s\n", property);
+ return -EINVAL;
+ }
+
+ return sd_bus_message_append(reply, "y", value);
+}
+
+static const sd_bus_vtable mboxd_vtable[] = {
+ SD_BUS_VTABLE_START(0),
+ SD_BUS_METHOD("Ping", NULL, NULL, &control_dbus_ping,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("Reset", NULL, NULL, &control_dbus_reset,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("Kill", NULL, NULL, &control_dbus_kill,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("MarkFlashModified", NULL, NULL, &control_dbus_modified,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("Suspend", NULL, NULL, &control_dbus_suspend,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("Resume", "b", NULL, &control_dbus_resume,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_PROPERTY("DaemonState", "y", &control_dbus_get_u8, 0,
+ SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("LpcState", "y", &control_dbus_get_u8, 0,
+ SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_VTABLE_END
+};
+
+int control_dbus_init(struct mbox_context *context)
+{
+ return sd_bus_add_object_vtable(context->bus, NULL,
+ MBOX_DBUS_OBJECT,
+ MBOX_DBUS_CONTROL_IFACE,
+ mboxd_vtable, context);
+}
+
+#define __unused __attribute__((unused))
+void control_dbus_free(struct mbox_context *context __unused)
+{
+ return;
+}
diff --git a/mboxd_dbus.h b/control_dbus.h
similarity index 68%
rename from mboxd_dbus.h
rename to control_dbus.h
index 82271fc..4a3b2ff 100644
--- a/mboxd_dbus.h
+++ b/control_dbus.h
@@ -1,14 +1,10 @@
-/* SPDX-License-Identifier: Apache-2.0 */
-/* Copyright (C) 2018 IBM Corp. */
+#ifndef DBUS_CONTROL_H
+#define DBUS_CONTROL_H
-#ifndef MBOXD_DBUS_H
-#define MBOXD_DBUS_H
-
-#include "dbus.h"
#include "mbox.h"
-int mboxd_dbus_init(struct mbox_context *context);
-void mboxd_dbus_free(struct mbox_context *context);
+int control_dbus_init(struct mbox_context *context);
+void control_dbus_free(struct mbox_context *context);
int control_legacy_init(struct mbox_context *context);
void control_legacy_free(struct mbox_context *context);
@@ -23,4 +19,4 @@
int control_suspend(struct mbox_context *context);
int control_resume(struct mbox_context *context, bool modified);
-#endif /* MBOXD_DBUS_H */
+#endif
diff --git a/control_legacy.c b/control_legacy.c
index d0e1e1f..08ac6f3 100644
--- a/control_legacy.c
+++ b/control_legacy.c
@@ -5,7 +5,7 @@
#include "common.h"
#include "dbus.h"
-#include "mboxd_dbus.h"
+#include "control_dbus.h"
#include "mbox.h"
/*
diff --git a/dbus.h b/dbus.h
index df31ca3..a40bfd1 100644
--- a/dbus.h
+++ b/dbus.h
@@ -1,8 +1,8 @@
/* SPDX-License-Identifier: Apache-2.0 */
/* Copyright (C) 2018 IBM Corp. */
-#ifndef MBOX_DBUS_H
-#define MBOX_DBUS_H
+#ifndef DBUS_H
+#define DBUS_H
#include <stdint.h>
#include <stddef.h>
diff --git a/mboxd.c b/mboxd.c
index bc9fd8d..efed052 100644
--- a/mboxd.c
+++ b/mboxd.c
@@ -30,7 +30,7 @@
#include "mbox.h"
#include "common.h"
#include "dbus.h"
-#include "mboxd_dbus.h"
+#include "control_dbus.h"
#include "mboxd_flash.h"
#include "mboxd_lpc.h"
#include "mboxd_msg.h"
@@ -50,6 +50,9 @@
"\t\t\t\t(default: 1MB)\n" \
"\t-f | --flash\t\tSize of flash in [K|M] bytes\n\n"
+int mboxd_dbus_init(struct mbox_context *context);
+void mboxd_dbus_free(struct mbox_context *context);
+
static int poll_loop(struct mbox_context *context)
{
int rc = 0, i;
diff --git a/mboxd_dbus.c b/mboxd_dbus.c
index 1f47026..2200bed 100644
--- a/mboxd_dbus.c
+++ b/mboxd_dbus.c
@@ -7,7 +7,7 @@
#include "common.h"
#include "dbus.h"
#include "mbox.h"
-#include "mboxd_dbus.h"
+#include "control_dbus.h"
int mboxd_dbus_init(struct mbox_context *context)
{
@@ -27,6 +27,21 @@
return rc;
}
+ rc = control_dbus_init(context);
+ if (rc < 0) {
+ MSG_ERR("Failed to initialise DBus control interface: %s\n",
+ strerror(-rc));
+ return rc;
+ }
+
+ rc = sd_bus_request_name(context->bus, MBOX_DBUS_NAME,
+ SD_BUS_NAME_ALLOW_REPLACEMENT |
+ SD_BUS_NAME_REPLACE_EXISTING);
+ if (rc < 0) {
+ MSG_ERR("Failed to request bus name: %s\n", strerror(-rc));
+ return rc;
+ }
+
rc = sd_bus_get_fd(context->bus);
if (rc < 0) {
MSG_ERR("Failed to get bus fd: %s\n", strerror(-rc));
@@ -40,6 +55,7 @@
void mboxd_dbus_free(struct mbox_context *context)
{
+ control_dbus_free(context);
control_legacy_free(context);
sd_bus_unref(context->bus);
}