0

我需要用 C++ 在 Linux PC 上注册蓝牙服务,到目前为止,我可以用这样的代码来做到这一点:(从这里截取和缩短)。

#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 效果很好,我可以在 bluetoothctl 或 sdptool 浏览器中看到该服务(来自其他 PC)。

问题是:我想在注册后继续执行程序,但是我不明白如何在g_main_loop_run (loop);. 如果我只是删除对主循环(GMainLoop *loop = g_main_loop_new (nullptr, false);和以前的)的所有调用,那么服务将不再出现在 bluetoothctl/sdptool 浏览中。如果我在g_main_loop_quit(loop);之后添加行g_main_loop_run (loop);,它也不会被执行,因为循环仍在运行。那我该怎么办?

我已经阅读了 GMainLoop 和 GDBusProxy 描述(GMainLoopGDBusProxy),但它并没有太大帮助。我也看到了这个问题,但是那里列出的代码不完整,我不确定我应该从那里拿什么,不应该拿什么。

4

0 回答 0