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);
 }