How do I register a profile with bluez using dbus/gio?

为君一笑 提交于 2019-12-08 11:25:57

问题


I'm trying to register a profile with bluez through D-Bus/Gio. When I call RegisterProfile everything goes OK. I check my GError and it's NULL and my return value is an empty GVariant. I've tried many things, but here is my latest code. When I run it, it prints "g_dbus_connection_call_sync succeeded", but I can't see my new profile in D-Bus using d-feet and I cannot connect to it using a my test device. I know the code on the test device works, or at least did work with straight bluez, but I'm trying to figure out how to use bluez with D-Bus.

Here is my code .h file:

#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;
};

Here is my .cpp file:

#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;
}

I'm a bit lost seeing as how I get no error information. Thanks everyone.

EDIT: After digging around I found the dbus bluetooth.conf file, here is mine:

<!-- 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>

I added ProfileManager1 and Device1 to it, but still no luck. Does anyone know what I'm missing here? I can register and use profiles using straight bluez, so I know it's a bluez/dbus issue.


回答1:


I believe I've figured it out. I have it working anyway. After much re-reading of the examples I ended up doing this:

1: own a bus name with g_bus_own_name.

2: in my on_bus_acquired callback I use that GDBusConnection as a parameter for g_dbus_connection_register_object (as opposed to trying to create the GDBusConnection myself)

3: call the RegisterProfile method

I can post code if anyone is interested.

Everything seems to be working now. Another thing that tripped me up were the parameters to RegisterProfile. I'm using the SerialUUID to connect, but at first I was also setting the role paramter to "server". It was causing my profile to reject connections. I think that parameter is only for a different kind of profile, but I'm not sure. Does anyone know for certain?



来源:https://stackoverflow.com/questions/37573014/how-do-i-register-a-profile-with-bluez-using-dbus-gio

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!