bluetooth - 如何使用 dbus/gio 向 bluez 注册配置文件?

标签 bluetooth glib dbus bluez gio

我正在尝试通过 D-Bus/Gio 向 bluez 注册配置文件。当我调用 RegisterProfile 时一切正常。我检查了我的 GError,它是 NULL,我的返回值是一个空的 GVariant。我已经尝试了很多东西,但这是我最新的代码。当我运行它时,它会打印“g_dbus_connection_call_sync successed”,但我无法使用 d-feet 在 D-Bus 中看到我的新配置文件,并且无法使用我的测试设备连接到它。我知道测试设备上的代码可以工作,或者至少可以直接使用 bluez,但我正在尝试弄清楚如何将 bluez 与 D-Bus 结合使用。

这是我的代码 .h 文件:

#ifndef BT_SERVER_H
#define BT_SERVER_H

#include <glib.h>
#include <gio/gio.h>

// ---------------------------------------------------------------------------

class BTProfile
{
public:
    BTProfile();
    void init();
    void destroy();

    static void method_call(GDBusConnection *connection,
        const gchar *sender, const gchar *object_path,
        const gchar *interface_name, const gchar *method_name,
        GVariant *parameters, GDBusMethodInvocation *invocation,
        gpointer user_data);
    static GVariant *get_property(GDBusConnection *connection,
        const gchar *sender, const gchar *object_path,
        const gchar *interface_name, const gchar *property_name,
        GError **error, gpointer user_data);
    static gboolean set_property(GDBusConnection *connection,
        const gchar *sender, const gchar *object_path,
        const gchar *interface_name, const gchar *property_name,
        GVariant *value, GError **error, gpointer userData);

protected:
    GDBusConnection *bus_connection;
};

这是我的 .cpp 文件:

#include <stdio.h>
#include "bt_server.h"

static const char *serial_service_class_uuid =
    "00001101-0000-1000-8000-00805F9B34FB";
static const char *my_service_uuid =
    "E62C4DCA-9ABC-11E5-8994-FEFF819CDC9F";

static const gchar btp_introspection_xml[] =
    "<node>"
    "  <interface name='org.bluez.Profile1'>"
    "    <method name='Release' />"
    "    <method name='NewConnection'>"
    "      <arg type='o' name='device' direction='in' />"
    "      <arg type='h' name='fd' direction='in' />"
    "      <arg type='a{sv}' name='fd_properties' direction='in' />"
    "    </method>"
    "    <method name='RequestDisconnection'>"
    "      <arg type='o' name='device' direction='in' />"
    "    </method>"
    "  </interface>"
    "</node>";

static const GDBusInterfaceVTable btp_interface_vtable =
{
    BTProfile::method_call,
    BTProfile::get_property,
    BTProfile::set_property
};

BTProfile::BTProfile() : bus_connection(NULL)
{
}

// ---------------------------------------------------------------------------

void BTProfile::init()
{
    GError *error = NULL;
    GDBusNodeInfo *introspection = g_dbus_node_info_new_for_xml(
        btp_introspection_xml, &error);
    if (!error)
    {
        GDBusInterfaceInfo *interface_info = g_dbus_node_info_lookup_interface(
            introspection, "org.bluez.Profile1");
        bus_connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
        if (!error)
        {
            g_dbus_connection_register_object(bus_connection,
                "/org/bluez/myprofile", interface_info, &btp_interface_vtable,
                this, NULL, &error);
            if (!error)
            {
                GVariantBuilder builder;
                g_variant_builder_init(&builder, G_VARIANT_TYPE_DICTIONARY);
                g_variant_builder_add(&builder, "{sv}", "Name",
                    g_variant_new("s", "myprofile"));
                g_variant_builder_add(&builder, "{sv}", "Service",
                    g_variant_new("s", serial_service_class_uuid));
                g_variant_builder_add(&builder, "{sv}", "Channel",
                    g_variant_new("q", 1));
                g_variant_builder_add(&builder, "{sv}", "RequireAuthentication",
                    g_variant_new("b", FALSE));
                g_variant_builder_add(&builder, "{sv}", "Role",
                    g_variant_new("s", "client"));
                g_variant_builder_add(&builder, "{sv}", "Version",
                    g_variant_new("q", 1));
                g_variant_builder_add(&builder, "{sv}", "AutoConnect",
                    g_variant_new("b", true));
                g_dbus_connection_call_sync(bus_connection, "org.bluez",
                    "/org/bluez", "org.bluez.ProfileManager1",
                    "RegisterProfile", g_variant_new("(osa{sv})",
                    "/org/bluez/myprofile", my_service_uuid, &builder),
                    NULL, G_DBUS_CALL_FLAGS_NONE, G_MAXINT, NULL, &error);
                if (!error)
                {
                    g_print("g_dbus_connection_call_sync succeeded\n");
                }
                else
                {
                    g_print("g_dbus_connection_call_sync failed: %s\n",
                        error->message);
                    g_error_free(error);
                }
            }
            else
            {
                g_print("g_dbus_connection_register_object failed: %s\n",
                    error->message);
                g_error_free(error);
            }
        }
        else
        {
            g_print("g_bus_get_sync failed: %s\n", error->message);
            g_error_free(error);
        }
    }
    else
    {
        g_print("g_dbus_node_info_new_for_xml failed: %s\n", error->message);
        g_error_free(error);
    }
}

// ---------------------------------------------------------------------------

void BTProfile::destroy()
{
    if (bus_connection)
    {
        g_object_unref(bus_connection);
    }
}

// ---------------------------------------------------------------------------

void BTProfile::method_call(GDBusConnection *connection, const gchar *sender,
    const gchar *object_path, const gchar *interface_name,
    const gchar *method_name, GVariant *parameters,
    GDBusMethodInvocation *invocation, gpointer user_data)
{
    g_print("handle_method_call: called\n");
    g_dbus_method_invocation_return_value(invocation, NULL);
}

// ---------------------------------------------------------------------------

GVariant *BTProfile::get_property(GDBusConnection *connection,
    const gchar *sender, const gchar *object_path, const gchar *interface_name,
    const gchar *property_name, GError **error, gpointer user_data)
{
    g_print("get_property: called\n");
    return NULL;
}

// ---------------------------------------------------------------------------

gboolean BTProfile::set_property(GDBusConnection *connection,
    const gchar *sender, const gchar *object_path, const gchar *interface_name,
    const gchar *property_name, GVariant *value, GError **error,
    gpointer userData)
{
    g_print("set_property: called\n");
    return false;
}

看到我如何没有收到错误信息,我有点迷失了。 谢谢大家。

编辑: 经过一番挖掘后,我找到了 dbus bluetooth.conf 文件,这是我的:

<!-- This configuration file specifies the required security policies
     for Bluetooth core daemon to work. -->

<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>

  <!-- ../system.conf have denied everything, so we just punch some holes -->

  <policy user="root">
    <allow own="org.bluez"/>
    <allow send_destination="org.bluez"/>
    <allow send_interface="org.bluez.Agent1"/>
    <allow send_interface="org.bluez.MediaEndpoint1"/>
    <allow send_interface="org.bluez.MediaPlayer1"/>
    <allow send_interface="org.bluez.ThermometerWatcher1"/>
    <allow send_interface="org.bluez.AlertAgent1"/>
    <allow send_interface="org.bluez.Profile1"/>
    <allow send_interface="org.bluez.HeartRateWatcher1"/>
    <allow send_interface="org.bluez.CyclingSpeedWatcher1"/>
    <allow send_interface="org.bluez.GattCharacteristic1"/>
    <allow send_interface="org.bluez.GattDescriptor1"/>
    <allow send_interface="org.bluez.ProfileManager1"/>
    <allow send_interface="org.bluez.Device1"/>
    <allow send_interface="org.freedesktop.DBus.ObjectManager"/>
    <allow send_interface="org.freedesktop.DBus.Properties"/>
  </policy>

  <policy at_console="true">
    <allow send_destination="org.bluez"/>
  </policy>

  <!-- allow users of lp group (printing subsystem) to 
       communicate with bluetoothd -->
  <policy group="lp">
    <allow send_destination="org.bluez"/>
  </policy>

  <policy context="default">
    <deny send_destination="org.bluez"/>
  </policy>

</busconfig>

我向其中添加了 ProfileManager1 和 Device1,但仍然没有成功。有谁知道我在这里缺少什么?我可以使用直接 bluez 注册和使用配置文件,所以我知道这是 bluez/dbus 问题。

最佳答案

我相信我已经明白了。无论如何我都可以使用它。经过多次重新阅读示例后,我最终这样做了:

1:拥有一个带有 g_bus_own_name 的总线名称。

2:在 on_bus_acquired 回调中,我使用 GDBusConnection 作为 g_dbus_connection_register_object 的参数(而不是尝试自己创建 GDBusConnection)

3:调用RegisterProfile方法

如果有人感兴趣,我可以发布代码。

现在一切似乎都正常。另一件让我困惑的事情是 RegisterProfile 的参数。我使用 SerialUUID 进行连接,但首先我还将角色参数设置为“服务器”。这导致我的个人资料拒绝连接。我认为该参数仅适用于不同类型的配置文件,但我不确定。有谁确切知道吗?

关于bluetooth - 如何使用 dbus/gio 向 bluez 注册配置文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37573014/

相关文章:

android - 从 android 应用程序中的 OBD II 蓝牙适配器读取值

ios - CBConcreteCentralManager 未开机错误

c - Glib:创建 GDBusProxy 时内存泄漏

dbus - 如何使用DBusWatch函数接收异步请求?

android - 在 Android 中检测蓝牙 Le 设备

swift - 在用户 200 米范围内构建近距离应用程序的最佳方法是什么?

c - 使用 C 和 GSList 迭代文件夹读取

c - gstreamer 示例文档代码未运行

dbus - 通过 Dbus 联系 Pulse Audio

notifications - 使用 dbus-rs 的 D-Bus 桌面通知