如何使用 dbus/gio 向 bluez 注册个人资料?
Posted
技术标签:
【中文标题】如何使用 dbus/gio 向 bluez 注册个人资料?【英文标题】:How do I register a profile with bluez using dbus/gio? 【发布时间】:2016-10-01 01:52:59 【问题描述】:我正在尝试通过 D-Bus/Gio 向 bluez 注册个人资料。当我调用 RegisterProfile 时,一切正常。我检查了我的 GError,它是 NULL,我的返回值是一个空的 GVariant。我已经尝试了很多东西,但这是我最新的代码。当我运行它时,它会打印“g_dbus_connection_call_sync 成功”,但我无法使用 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='asv' 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("(osasv)",
"/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】:我相信我已经弄明白了。反正我有它的工作。在反复阅读示例后,我最终这样做了:
1:拥有一个带有 g_bus_own_name 的总线名称。
2:在我的 on_bus_acquired 回调中,我使用 GDBusConnection 作为 g_dbus_connection_register_object 的参数(而不是尝试自己创建 GDBusConnection)
3:调用RegisterProfile方法
如果有人感兴趣,我可以发布代码。
现在似乎一切正常。让我感到困惑的另一件事是 RegisterProfile 的参数。我正在使用 SerialUUID 进行连接,但起初我还将角色参数设置为“服务器”。这导致我的个人资料拒绝连接。我认为该参数仅适用于不同类型的配置文件,但我不确定。有人知道吗?
【讨论】:
如果您不介意分享,我想看看最终结果。我也很想知道,上面的GVariantBuilder
,用g_variant_builder_init(&builder, G_VARIANT_TYPE_DICTIONARY)
初始化它。不应该是g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY)
吗?以上是关于如何使用 dbus/gio 向 bluez 注册个人资料?的主要内容,如果未能解决你的问题,请参考以下文章