Reputation: 10413
I am trying to learn how to connect a server and client using bluetooth in C language and the GLib (to connect via D-Bus). I have successfully registered my service with it's own UUID with this code:
Register function:
int register_profile(GDBusProxy *proxy,
gchar *service_path,
gchar *service_name,
gint service_channel,
gchar *service_uuid)
{
GVariant *profile;
GVariantBuilder profile_builder;
GError *error = NULL;
g_variant_builder_init(&profile_builder, G_VARIANT_TYPE("(osa{sv})"));
if (!g_variant_is_object_path(service_path))
{
return ERR_CUSTOM_PATH_INVALID;
}
g_variant_builder_add(&profile_builder, "o", service_path);
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(service_channel));
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(service_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(service_name));
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 RESULT_OK;
}
return -1;
}
The code to receive connections events:
static void signal_device_changed(GDBusConnection *conn,
const gchar *sender,
const gchar *path,
const gchar *interface,
const gchar *signal,
GVariant *params,
void *userdata)
{
g_print("Signal Device changed");
}
I initialize the code with this:
int register_service(char *service_path,
char *service_name,
int service_channel,
char *service_uuid)
{
GDBusProxy *proxy;
GDBusConnection *conn, *pconn;
GError *error = NULL;
conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
g_assert_no_error(error);
proxy = g_dbus_proxy_new_sync(conn,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
"org.bluez",
"/org/bluez",
"org.bluez.ProfileManager1",
NULL,
&error);
g_assert_no_error(error);
error = NULL;
int result = register_profile(proxy, service_path, service_name, service_channel, service_uuid);
if (result != RESULT_OK)
{
return result;
}
pconn = g_dbus_proxy_get_connection(proxy);
guint sub_id = g_dbus_connection_signal_subscribe(pconn,
"org.bluez",
"org.freedesktop.DBus.Properties",
"PropertiesChanged",
NULL,
"org.bluez.Device1",
G_DBUS_SIGNAL_FLAGS_NONE,
signal_device_changed,
NULL,
NULL);
g_print("Registration successful with subscription id [%d]. Press [ENTER] to exit.", sub_id);
char c;
result = scanf("%c", &c);
g_dbus_connection_signal_unsubscribe(pconn, sub_id);
g_object_unref(pconn);
g_object_unref(proxy);
g_object_unref(conn);
return RESULT_OK;
}
I use a python client application (which I tested with a python server and it worked on the device I used to test) to connect to the above server:
signal_device_changed
function being calledI have tried using the conn
rather than the proxy connection with same results.
Did I forget anything?
I used information from:
Upvotes: 2
Views: 385
Reputation: 10413
As advised by @ukBaz I needed to be in a main loop. I have modified the code as followed in the service registration:
// Beginning is same
serverUserData *userData = malloc(sizeof(serverUserData));
userData->loop = g_main_loop_new(NULL, FALSE);
guint sub_id = g_dbus_connection_signal_subscribe(pconn,
"org.bluez",
"org.freedesktop.DBus.Properties",
"PropertiesChanged",
NULL,
"org.bluez.Device1",
G_DBUS_SIGNAL_FLAGS_NONE,
signal_device_changed,
userData,
NULL);
if (sub_id > 0)
{
g_print("Registration successful with subscription id [%d].\n", sub_id);
}
g_main_loop_run(userData->loop);
g_dbus_connection_signal_unsubscribe(pconn, sub_id);
if (pconn != NULL)
g_object_unref(pconn);
if (proxy != NULL)
g_object_unref(proxy);
if (conn != NULL)
g_object_unref(conn);
And I quit the main loop when the device is disconnected.
Next I need to figure out how to create an RFCOMM socket connection and listen on it. But if I face issue I'll do in another question.
Upvotes: 1