summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlliver Schinagl <o.schinagl@ultimaker.com>2015-05-18 11:34:57 (GMT)
committerOlliver Schinagl <o.schinagl@ultimaker.com>2015-05-18 13:50:01 (GMT)
commit3fc08a5e8c4ff92daf39f98a106fc3e0c5e1840f (patch)
tree8adf5af04fcfcd93eaf43051c38c5a611a1cc940
parent0ef725d3698d1e58ad7a5de00caeda8f89a65184 (diff)
downloadeulogium-3fc08a5e8c4ff92daf39f98a106fc3e0c5e1840f.zip
eulogium-3fc08a5e8c4ff92daf39f98a106fc3e0c5e1840f.tar.gz
eulogium-3fc08a5e8c4ff92daf39f98a106fc3e0c5e1840f.tar.bz2
[griffin.display] Add initial USB mount detection support
This patch adds support for external mounts, when a user inserts or removes a USB stick (technically, if the fs is being mounted) and systemd takes notice of this, an eeze_disk object is created for this. Other media types are ignored for now, until they can be properly identified. All storage kinds should eventually end up in the mounts struct, so that the UI can scan that for mount points. Right now, only USB storage is added to this. A hack to add local storage will be required (tmpfs?) Also, all available storage is scanned during startup, in case storage was mounted during boot and thus no hotplug event is being generated. Signed-off-by: Olliver Schinagl <o.schinagl@ultimaker.com>
-rw-r--r--src/eulogium.c266
-rw-r--r--src/eulogium.h8
2 files changed, 274 insertions, 0 deletions
diff --git a/src/eulogium.c b/src/eulogium.c
index 6f8bba0..c6316b4 100644
--- a/src/eulogium.c
+++ b/src/eulogium.c
@@ -1127,9 +1127,16 @@ Evas_Object *eulogium_main_menu(Evas_Object *window, struct eulogium_data *eulog
static void eulogium_setup(struct eulogium_data *eulogium)
{
+ struct mount_data *mount;
+
while (screen_data.screen[screen_data.count].type != END)
screen_data.count++;
+ /* eina_list_append() appends data to an existing list, or creates a new list. We need to know the location
+ * of the list beforehand and thus we need to create a list with a dummy entry */
+ mount = calloc(1, sizeof(struct mount_data));
+ mount->id = "sentinel";
+ eulogium->mounts = eina_list_append(NULL, mount);
eulogium->progress_data_refresh = NULL;
eulogium->print.name = NULL;
eulogium->print.file = NULL;
@@ -1325,9 +1332,241 @@ static void _on_status_changed_ret(void *data, const Eldbus_Message *msg)
_on_get_status_ret(data, msg, NULL);
}
+static void eulogium_disk_free(struct mount_data *mount)
+{
+ eeze_disk_free(mount->disk);
+ if (mount->id)
+ free(mount->id);
+ eldbus_proxy_unref(mount->proxy);
+ free(mount);
+ mount = NULL;
+}
+
+static void _on_where_ret(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
+{
+ struct mount_data *mount = data;
+ const char *errname, *errmsg;
+ Eldbus_Message_Iter *var = NULL;
+ char *where;
+
+ if (eldbus_message_error_get(msg, &errname, &errmsg)) {
+ EINA_LOG_ERR("%s %s", errname, errmsg);
+ return;
+ }
+ if (!eldbus_message_arguments_get(msg, "v", &var)) {
+ EINA_LOG_ERR("Message content does not match expected \"v\" signature. (%s)", eldbus_message_signature_get(msg));
+ return;
+ }
+ if (!eldbus_message_iter_arguments_get(var, "s", &where)) {
+ EINA_LOG_ERR("Message content does not match expected \"s\" signature. (%s)", eldbus_message_iter_signature_get(var));
+ return;
+ }
+ if (!where)
+ return;
+
+ /* Never use a medium that is mounted under dev, proc, run or sys. */
+ if (!(strncmp(where, "/dev/", 5) &&
+ strncmp(where, "/proc/", 6) &&
+ strncmp(where, "/run/", 5) &&
+ strncmp(where, "/sys/", 5)))
+ return;
+
+ mount->disk = eeze_disk_new_from_mount(where);
+ eeze_disk_scan(mount->disk);
+ EINA_LOG_ERR("Medium mounted at %s of type %d", where, eeze_disk_type_get(mount->disk));
+ if (eeze_disk_type_get(mount->disk) == EEZE_DISK_TYPE_USB)
+ *mount->mounts = eina_list_append(*mount->mounts, mount); /* XXX DANGER! if _append returns a new list location, eulogium->mounts won't know about it breaking everything! REWRITE!! */
+ else
+ eulogium_disk_free(mount);
+ /* TODO: UI Stuffs/signals */
+}
+
+static void _on_result_ret(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
+{
+ struct mount_data *mount = data;
+ const char *errname, *errmsg;
+ Eldbus_Message_Iter *var = NULL;
+ char *result;
+
+ if (eldbus_message_error_get(msg, &errname, &errmsg)) {
+ EINA_LOG_ERR("%s %s", errname, errmsg);
+ return;
+ }
+ if (!eldbus_message_arguments_get(msg, "v", &var)) {
+ EINA_LOG_ERR("Message content does not match expected \"v\" signature. (%s)", eldbus_message_signature_get(msg));
+ return;
+ }
+ if (!eldbus_message_iter_arguments_get(var, "s", &result)) {
+ EINA_LOG_ERR("Message content does not match expected \"s\" signature. (%s)", eldbus_message_iter_signature_get(var));
+ return;
+ }
+ if (strncmp(result, "success", 7)) {
+ return;
+ }
+
+ eldbus_proxy_property_get(mount->proxy, "Where", _on_where_ret, mount);
+}
+
+static void _on_unit_new_ret(void *data, const Eldbus_Message *msg)
+{
+ const char *errname, *errmsg;
+ struct eulogium_data *eulogium = data;
+ char *id, *unit, *ext;
+ size_t id_len;
+ Eldbus_Object *obj;
+ struct mount_data *mount;
+
+ if (eldbus_message_error_get(msg, &errname, &errmsg)) {
+ EINA_LOG_ERR("%s %s", errname, errmsg);
+ return;
+ }
+ if (!eldbus_message_arguments_get(msg, "so", &id, &unit)) {
+ EINA_LOG_ERR("Message content does not match expected \"so\" signature.");
+ return;
+ }
+ ext = ecore_file_ext_get(id);
+ if (strncmp(ext, "mount", 5))
+ return;
+
+ obj = eldbus_object_get(eulogium->dbus.conn, "org.freedesktop.systemd1", unit);
+ if (!obj) {
+ EINA_LOG_WARN("Could not get org.freedesktop.systemd1-mount object. (%s)", unit);
+ return;
+ }
+ mount = calloc(1, sizeof(struct mount_data));
+ if (!mount) {
+ EINA_LOG_ERR("Unable to allocate memory for mountpoint %s", id);
+ return;
+ }
+ id_len = strlen(id);
+ mount->id = malloc(id_len + 1);
+ if (!mount->id) {
+ EINA_LOG_ERR("Unable to allocate memory for id %s", id);
+ free(mount);
+ return;
+ }
+ strncpy(mount->id, id, id_len);
+ mount->proxy = eldbus_proxy_get(obj, "org.freedesktop.systemd1.Mount");
+ mount->mounts = &eulogium->mounts;
+ if (!mount->proxy) {
+ EINA_LOG_WARN("Could not get dbus proxy for (%s).", id);
+ free(mount->id);
+ free(mount);
+ return;
+ }
+ EINA_LOG_ERR("Medium inserted (%s)", id);
+ eldbus_proxy_property_get(mount->proxy, "Result", _on_result_ret, mount);
+}
+
+static void _on_list_units_ret(void *data, const Eldbus_Message *msg, Eldbus_Pending *Pending EINA_UNUSED)
+{
+ const char *errname, *errmsg;
+ struct eulogium_data *eulogium = data;
+ Eldbus_Message_Iter *array, *dbus_struct;
+ char *id, *unit;
+ char *dummy;
+ uint_fast32_t dummy_int;
+
+ if (eldbus_message_error_get(msg, &errname, &errmsg)) {
+ EINA_LOG_ERR("%s %s", errname, errmsg);
+ return;
+ }
+ if (!eldbus_message_arguments_get(msg, "a(ssssssouso)", &array)) {
+ EINA_LOG_ERR("Message content does not match expected \"a(ssssssouso)\" signature. (%s)", eldbus_message_signature_get(msg));
+ return;
+ }
+ while (eldbus_message_iter_get_and_next(array, 'r', &dbus_struct)) {
+ if (eldbus_message_iter_arguments_get(dbus_struct, "ssssssouso", &id, &dummy, &dummy, &dummy, &dummy, &dummy, &unit, &dummy_int, &dummy, &dummy)) {
+ Eldbus_Object *obj;
+ struct mount_data *mount;
+ size_t id_len;
+
+ obj = eldbus_object_get(eulogium->dbus.conn, "org.freedesktop.systemd1", unit);
+ if (!obj) {
+ EINA_LOG_WARN("Could not get org.freedesktop.systemd1-mount object. (%s)", unit);
+ return;
+ }
+ mount = calloc(1, sizeof(struct mount_data));
+ if (!mount) {
+ EINA_LOG_ERR("Unable to allocate memory for mountpoint %s", id);
+ break;
+ }
+ id_len = strlen(id);
+ mount->id = malloc(id_len + 1);
+ if (!mount->id) {
+ EINA_LOG_ERR("Unable to allocate memory for id %s", id);
+ free(mount);
+ break;
+ }
+ strncpy(mount->id, id, id_len);
+ mount->proxy = eldbus_proxy_get(obj, "org.freedesktop.systemd1.Mount");
+ if (!mount->proxy) {
+ EINA_LOG_WARN("Could not get dbus proxy for (%s).", id);
+ free(mount->id);
+ free(mount);
+ break;
+ }
+ mount->mounts = &eulogium->mounts;
+ EINA_LOG_ERR("Medium detected (%s)", id);
+ eldbus_proxy_property_get(mount->proxy, "Result", _on_result_ret, mount);
+ } else {
+ EINA_LOG_ERR("Unable to decode dbus-struct\n");
+ }
+ }
+}
+
+static int _mount_find_cb(const void *haystack, const void *needle)
+{
+ const struct mount_data *mount = haystack;
+ const char *id = needle;
+
+ return strncmp(id, mount->id, strlen(id));
+}
+
+static void _on_unit_removed_ret(void *data, const Eldbus_Message *msg)
+{
+ const char *errname, *errmsg;
+ struct eulogium_data *eulogium = data;
+ char *id, *unit, *ext;
+ Eldbus_Object *obj;
+ struct mount_data *mount;
+ Eina_List *list;
+
+ if (eldbus_message_error_get(msg, &errname, &errmsg)) {
+ EINA_LOG_ERR("%s %s", errname, errmsg);
+ return;
+ }
+ if (!eldbus_message_arguments_get(msg, "so", &id, &unit)) {
+ EINA_LOG_ERR("Message content does not match expected \"so\" signature.");
+ return;
+ }
+ ext = ecore_file_ext_get(id);
+ if (strncmp(ext, "mount", 5))
+ return;
+
+ obj = eldbus_object_get(eulogium->dbus.conn, "org.freedesktop.systemd1", unit);
+ if (!obj) {
+ EINA_LOG_WARN("Could not get org.freedesktop.systemd1-mount object (%s).", unit);
+ return;
+ }
+ EINA_LOG_ERR("Medium remove request (%s)", id);
+ list = eina_list_search_unsorted_list(eulogium->mounts, _mount_find_cb, id);
+ mount = eina_list_data_get(list);
+ if (!mount) {
+ EINA_LOG_CRIT("Mount %s is NULL, this should not happen!", id);
+ } else {
+ eulogium_disk_free(mount);
+ eulogium->mounts = eina_list_remove_list(eulogium->mounts, list);
+ }
+ /* TODO: UI Stuff/signals */
+}
+
static int eulogium_dbus_init(struct eulogium_data *eulogium)
{
Eldbus_Object *obj;
+ Eldbus_Proxy *proxy;
+ Eldbus_Message_Iter *iter, *array;
+ Eldbus_Message *msg;
eulogium->dbus.conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
if (!eulogium->dbus.conn) {
@@ -1335,6 +1574,20 @@ static int eulogium_dbus_init(struct eulogium_data *eulogium)
return -ECONNREFUSED;
}
+ obj = eldbus_object_get(eulogium->dbus.conn, "org.freedesktop.systemd1", "/org/freedesktop/systemd1");
+ if (!obj) {
+ EINA_LOG_WARN("Could not get org.freedesktop.systemd1 object.");
+ return -EFAULT;
+ }
+
+ /* XXX We currently monitor systemd for new mounts. This functionality should really be handled by eeze and once it may does, this has to be re-written. */
+ proxy = eldbus_proxy_get(obj, "org.freedesktop.systemd1.Manager");
+ if (!proxy) {
+ EINA_LOG_WARN("Could not get dbus systemd-manager proxy.");
+ return -EFAULT;
+ }
+ eldbus_name_owner_changed_callback_add(eulogium->dbus.conn, "org.freedesktop.systemd1.Manager", on_name_owner_changed, eulogium->dbus.conn, EINA_TRUE);
+
/* TODO: Make nice loop that gets BUS/PATH from a predefined array? */
obj = eldbus_object_get(eulogium->dbus.conn, "nl.ultimaker.harma", "/nl/ultimaker/harma");
if (!obj) {
@@ -1382,6 +1635,19 @@ static int eulogium_dbus_init(struct eulogium_data *eulogium)
eldbus_proxy_call(eulogium->dbus.proxy[PRINTER], "getStatus", _on_get_status_ret, eulogium, -1, "");
eldbus_proxy_signal_handler_add(eulogium->dbus.proxy[PRINTER], "statusChanged", _on_status_changed_ret, eulogium);
+ eldbus_proxy_signal_handler_add(proxy, "UnitNew", _on_unit_new_ret, eulogium);
+ eldbus_proxy_signal_handler_add(proxy, "UnitRemoved", _on_unit_removed_ret, eulogium);
+
+ msg = eldbus_proxy_method_call_new(proxy, "ListUnitsFiltered");
+ iter = eldbus_message_iter_get(msg);
+ array = eldbus_message_iter_container_new(iter, 'a', "s");
+ if (!array)
+ EINA_LOG_ERR("Empty container");
+ eldbus_message_iter_basic_append(array, 's', "mounted");
+ eldbus_message_iter_container_close(iter, array);
+ eldbus_proxy_send(proxy, msg, _on_list_units_ret, eulogium, -1);
+ /* eldbus_proxy_call(proxy, "ListUnitsFiltered", _on_list_units_ret, eulogium, -1, "as", "{mounted}"); */
+
return 0;
}
diff --git a/src/eulogium.h b/src/eulogium.h
index a4c16b0..ca9c1b6 100644
--- a/src/eulogium.h
+++ b/src/eulogium.h
@@ -68,6 +68,13 @@ struct dbus_data {
Eldbus_Proxy *proxy[LAST];
};
+struct mount_data {
+ char *id;
+ Eldbus_Proxy *proxy;
+ Eeze_Disk *disk;
+ Eina_List **mounts;
+};
+
struct eulogium_data {
Evas_Object *navi;
Evas_Object *time;
@@ -78,6 +85,7 @@ struct eulogium_data {
struct printer_data printer;
struct print_data print;
struct dbus_data dbus;
+ Eina_List *mounts;
void *data;
};