Hi, I have spent quite some time on this, but I don't seem to be getting anywhere, so I hope someone could point me in the right direction. I am learning sd_bus, my goal is to get a list of available modem services from ModemManager. To make sure that what I am looking for is actually there, I first checked with busctl: Service org.freedesktop.ModemManager1: └─/org └─/org/freedesktop └─/org/freedesktop/ModemManager1 ├─/org/freedesktop/ModemManager1/Modem │ └─/org/freedesktop/ModemManager1/Modem/0 └─/org/freedesktop/ModemManager1/SIM └─/org/freedesktop/ModemManager1/SIM/0 Service /org/freedesktop/ModemManager1: Failed to introspect object / of service /org/freedesktop/ModemManager1: Invali argument No objects discovered. The tree looks fine, the error message is a bit weird? The only things I am interested in are the paths: /org/freedesktop/ModemManager1/Modem/0 /org/freedesktop/ModemManager1/SIM/0 The above paths may change when the modem is replugged, so I'd like to query them dynamically. I learned that the call to list what I need is "GetManagedObjects": busctl call org.freedesktop.ModemManager1 /org/freedesktop/ModemManager1 org.freedesktop.DBus.ObjectManager GetManagedObjects It returns a data structure of the type a{oa{sa{sv}}} and the object paths "/org/freedesktop/ModemManager1/Modem/0" and "/org/freedesktop/ModemManager1/SIM/0" are indeed present in its output. However, when trying to parse the response in the code I only get as far as reading the first /org/freedesktop/ModemManager1/Modem/0 but I never get to the second /org/freedesktop/ModemManager1/SIM/0 entry. What I am doing is (full and compilable source is attached, here I am leaving out the error checks etc): while (sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{oa{sa{sv}}}") > 0) { while (sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "oa{sa{sv}}") > 0) { const char *path; sd_bus_message_read_basic(m, SD_BUS_TYPE_OBJECT_PATH, &path); fprintf(stderr, "Object path: %s\n", path); sd_bus_message_skip(m, "a{sa{sv}}"); /* exit dictionary entry */ sd_bus_message_exit_container(m); } // while SD_BUS_TYPE_DICT_ENTRY /* exit array */ sd_bus_message_exit_container(m); } // while SD_BUS_TYPE_ARRAY I do not get any errors in the "real" version (attached), but it never gets further to the SIM entry. What am I missing? Kind regards, Jin
/* compile: gcc `pkg-config --cflags --libs libsystemd` listpaths.c -o listpaths Looking for: /org/freedesktop/ModemManager1/Modem/0 /org/freedesktop/ModemManager1/SIM/0 $ busctl tree org.freedesktop.ModemManager1 /org/freedesktop/ModemManager1 Service org.freedesktop.ModemManager1: └─/org └─/org/freedesktop └─/org/freedesktop/ModemManager1 ├─/org/freedesktop/ModemManager1/Modem │ └─/org/freedesktop/ModemManager1/Modem/0 └─/org/freedesktop/ModemManager1/SIM └─/org/freedesktop/ModemManager1/SIM/0 */ #include <stdio.h> #include <errno.h> #include <unistd.h> #include <string.h> #include <systemd/sd-bus.h> int main() { sd_bus *bus = NULL; if (sd_bus_open_system(&bus) < 0) { return 1; } while (sd_bus_is_ready(bus) <= 0) { sd_bus_wait(bus, 1000); sd_bus_process(bus, NULL); } printf("Bus ready.\n"); sd_bus_message *m = NULL; sd_bus_error error = SD_BUS_ERROR_NULL; int ret = sd_bus_call_method(bus, "org.freedesktop.ModemManager1", "/org/freedesktop/ModemManager1", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &m, NULL); if (ret < 0) { printf("Could not get object list\n"); return ret; } while (sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{oa{sa{sv}}}") > 0) { while (sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "oa{sa{sv}}") > 0) { const char *path; if (sd_bus_message_read_basic(m, SD_BUS_TYPE_OBJECT_PATH, &path) < 0) { printf("Could not read object path\n"); goto finish; } fprintf(stderr, "Object path: %s\n", path); if (sd_bus_message_skip(m, "a{sa{sv}}") < 0) { printf("Could not skip message\n"); goto finish; } /* exit dictionary entry */ if (sd_bus_message_exit_container(m) < 0) { printf("Could not exit container (inner loop)\n"); goto finish; } } // while SD_BUS_TYPE_DICT_ENTRY /* exit array */ if (sd_bus_message_exit_container(m) < 0) { printf("Could not exit container (outer loop)\n"); goto finish; } } // while SD_BUS_TYPE_ARRAY finish: sd_bus_error_free(&error); sd_bus_message_unref(m); sd_bus_unref(bus); return 0; }
_______________________________________________ systemd-devel mailing list systemd-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/systemd-devel