I need to register bluetooth service on Linux PC in C++ and so far, I am able to do it with such code: (taken and shorthened from here).
#include <cstdio>
#include <gio/gio.h>
#include <glib.h>
#define SERIAL_PORT_PROFILE_UUID "00001101-0000-1000-8000-00805F9B34FB"
#define CUSTOM_UUID "22222222-2222-2222-2222-222222222222" //"E62C4DCA-9ABC-11E5-8994-FEFF819CDC9F"
int register_profile(GDBusProxy *proxy){
GVariant *profile;
GVariantBuilder profile_builder;
GError *error = NULL;
printf("register_profile called!\n");
g_variant_builder_init(&profile_builder, G_VARIANT_TYPE("(osa{sv})"));
if (g_variant_is_object_path("/org/bluez/customprofile")) {
printf("object path is good!\n");
}
g_variant_builder_add (&profile_builder, "o",
"/org/bluez/customprofile");
g_variant_builder_add (&profile_builder, "s", SERIAL_PORT_PROFILE_UUID);
g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("a{sv}"));
g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
g_variant_builder_add (&profile_builder, "s", "Channel");
g_variant_builder_add (&profile_builder, "v", g_variant_new_uint16(22));
g_variant_builder_close(&profile_builder);
g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
g_variant_builder_add (&profile_builder, "s", "Service");
g_variant_builder_add (&profile_builder, "v", g_variant_new_string(CUSTOM_UUID));
g_variant_builder_close(&profile_builder);
g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
g_variant_builder_add (&profile_builder, "s", "Name");
g_variant_builder_add (&profile_builder, "v", g_variant_new_string("Custom Serial Port"));
g_variant_builder_close(&profile_builder);
g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
g_variant_builder_add (&profile_builder, "s", "Role");
g_variant_builder_add (&profile_builder, "v", g_variant_new_string("server"));
g_variant_builder_close(&profile_builder);
g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
g_variant_builder_add (&profile_builder, "s", "RequireAuthentication");
g_variant_builder_add (&profile_builder, "v", g_variant_new_boolean(FALSE));
g_variant_builder_close(&profile_builder);
g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
g_variant_builder_add (&profile_builder, "s", "RequireAuthorization");
g_variant_builder_add (&profile_builder, "v", g_variant_new_boolean(FALSE));
g_variant_builder_close(&profile_builder);
g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
g_variant_builder_add (&profile_builder, "s", "AutoConnect");
g_variant_builder_add (&profile_builder, "v", g_variant_new_boolean(TRUE));
g_variant_builder_close(&profile_builder);
g_variant_builder_close(&profile_builder);
profile = g_variant_builder_end(&profile_builder);
GVariant * ret = g_dbus_proxy_call_sync (proxy,
"RegisterProfile",
profile,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
g_assert_no_error(error);
if(ret != NULL && error==NULL){
return 0;
} else {
return 1;
}
}
void init_server()
{
GDBusProxy *proxy;
GDBusConnection *conn;
GError *error = nullptr;
GMainLoop *loop = g_main_loop_new (nullptr, false);
conn = g_bus_get_sync (G_BUS_TYPE_SYSTEM, nullptr, &error);
g_assert_no_error (error);
proxy = g_dbus_proxy_new_sync (conn,
G_DBUS_PROXY_FLAGS_NONE,
nullptr,/* GDBusInterfaceInfo */
"org.bluez",/* name */
"/org/bluez",/* object path */
"org.bluez.ProfileManager1",/* interface */
nullptr,/* GCancellable */
&error);
g_assert_no_error (error);
error=nullptr;
if (register_profile (proxy)) {
printf("profile register failed\n");
return;
}
printf("SPP profile registered");
g_main_loop_run (loop);
g_object_unref (proxy);
g_object_unref (conn);
}
int main(int argc, const char** argv) {
init_server();
}
Everyting works great, and I can see the service in bluetoothctl or sdptool browse (from other PC).
The problem is: I want to continue the programm execution after the registration, but I do not understand how I can exit the loop after the execution of the g_main_loop_run (loop);
. If i simply remove all calls to the main loop (GMainLoop *loop = g_main_loop_new (nullptr, false);
and previous) then service ceases to appear in bluetoothctl/sdptool browse. And if I add line g_main_loop_quit(loop);
right after the g_main_loop_run (loop);
, it also will not be executed, because the loop is still running. So what shall I do?
I've read the GMainLoop and GDBusProxy descriptions (GMainLoop, GDBusProxy), but it did not helped a lot. I've also seen this question, but code listed there is not complete and I am not sure what I should take from there and what I shouldn't.