diff --git a/src/device.c b/src/device.c
index 3466adb..33e35ab 100644
--- a/src/device.c
+++ b/src/device.c
gpointer user_data;
};
+typedef void (*attio_error_cb) (const GError *gerr, gpointer user_data);
+typedef void (*attio_success_cb) (gpointer user_data);
+
+struct att_callbacks {
+ attio_error_cb error; /* Callback for error */
+ attio_success_cb success; /* Callback for success */
+ gpointer user_data;
+};
+
struct btd_device {
bdaddr_t bdaddr;
addr_type_t type;
static void att_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
{
- struct btd_device *device = user_data;
+ struct att_callbacks *attcb = user_data;
+ struct btd_device *device = attcb->user_data;
GAttrib *attrib;
g_io_channel_unref(device->att_io);
if (gerr) {
DBG("%s", gerr->message);
- if (device->auto_connect)
- device->auto_id = g_timeout_add_seconds_full(
- G_PRIORITY_DEFAULT_IDLE,
- AUTO_CONNECTION_INTERVAL,
- att_connect, device,
- att_connect_dispatched);
+ if (attcb->error)
+ attcb->error(gerr, user_data);
- return;
+ goto done;
}
attrib = g_attrib_new(io);
if (device->attachid == 0)
error("Attribute server attach failure!");
- if (device->attios) {
- device->attrib = attrib;
- g_attrib_set_disconnect_function(device->attrib,
- attrib_disconnected, device);
- g_slist_foreach(device->attios, attio_connected,
- device->attrib);
- }
+ device->attrib = attrib;
+ g_attrib_set_disconnect_function(device->attrib,
+ attrib_disconnected, device);
+
+ if (attcb->success)
+ attcb->success(user_data);
+done:
+ g_free(attcb);
+}
+
+static void att_error_cb(const GError *gerr, gpointer user_data)
+{
+ struct att_callbacks *attcb = user_data;
+ struct btd_device *device = attcb->user_data;
+
+ if (device->auto_connect == FALSE)
+ return;
+
+ device->auto_id = g_timeout_add_seconds_full(G_PRIORITY_DEFAULT_IDLE,
+ AUTO_CONNECTION_INTERVAL,
+ att_connect, device,
+ att_connect_dispatched);
+
+ DBG("Enabling automatic connections");
+}
+
+static void att_success_cb(gpointer user_data)
+{
+ struct att_callbacks *attcb = user_data;
+ struct btd_device *device = attcb->user_data;
+
+ if (device->attios == NULL)
+ return;
+
+ g_slist_foreach(device->attios, attio_connected, device->attrib);
}
static gboolean att_connect(gpointer user_data)
{
struct btd_device *device = user_data;
struct btd_adapter *adapter = device->adapter;
+ struct att_callbacks *attcb;
GIOChannel *io;
GError *gerr = NULL;
char addr[18];
DBG("Connection attempt to: %s", addr);
+ attcb = g_new0(struct att_callbacks, 1);
+ attcb->error = att_error_cb;
+ attcb->success = att_success_cb;
+ attcb->user_data = device;
+
if (device_is_bredr(device)) {
io = bt_io_connect(BT_IO_L2CAP, att_connect_cb,
- device, NULL, &gerr,
+ attcb, NULL, &gerr,
BT_IO_OPT_SOURCE_BDADDR, &sba,
BT_IO_OPT_DEST_BDADDR, &device->bdaddr,
BT_IO_OPT_PSM, ATT_PSM,
BT_IO_OPT_INVALID);
} else {
io = bt_io_connect(BT_IO_L2CAP, att_connect_cb,
- device, NULL, &gerr,
+ attcb, NULL, &gerr,
BT_IO_OPT_SOURCE_BDADDR, &sba,
BT_IO_OPT_DEST_BDADDR, &device->bdaddr,
BT_IO_OPT_CID, ATT_CID,
if (io == NULL) {
error("ATT bt_io_connect(%s): %s", addr, gerr->message);
g_error_free(gerr);
+ g_free(attcb);
return FALSE;
}
return FALSE;
}
-static void browse_primary_connect_cb(GIOChannel *io, GError *gerr,
- gpointer user_data)
+static void att_browse_error_cb(const GError *gerr, gpointer user_data)
{
- struct btd_device *device = user_data;
+ struct att_callbacks *attcb = user_data;
+ struct btd_device *device = attcb->user_data;
struct browse_req *req = device->browse;
- g_io_channel_unref(device->att_io);
- device->att_io = NULL;
-
- if (gerr) {
+ if (req->msg) {
DBusMessage *reply;
- DBG("%s", gerr->message);
-
reply = btd_error_failed(req->msg, gerr->message);
g_dbus_send_message(req->conn, reply);
-
- device->browse = NULL;
- browse_request_free(req);
-
- return;
}
- device->attrib = g_attrib_new(io);
- device->attachid = attrib_channel_attach(device->attrib, TRUE);
- if (device->attachid == 0)
- error("Attribute server attach failure!");
+ device->browse = NULL;
+ browse_request_free(req);
+}
- gatt_discover_primary(device->attrib, NULL, primary_cb, req);
+static void att_browse_cb(gpointer user_data)
+{
+ struct att_callbacks *attcb = user_data;
+ struct btd_device *device = attcb->user_data;
+
+ gatt_discover_primary(device->attrib, NULL, primary_cb,
+ device->browse);
}
int device_browse_primary(struct btd_device *device, DBusConnection *conn,
DBusMessage *msg, gboolean secure)
{
struct btd_adapter *adapter = device->adapter;
+ struct att_callbacks *attcb;
struct browse_req *req;
BtIOSecLevel sec_level;
bdaddr_t src;
sec_level = secure ? BT_IO_SEC_HIGH : BT_IO_SEC_LOW;
- device->att_io = bt_io_connect(BT_IO_L2CAP, browse_primary_connect_cb,
- device, NULL, NULL,
+ attcb = g_new0(struct att_callbacks, 1);
+ attcb->error = att_browse_error_cb;
+ attcb->success = att_browse_cb;
+ attcb->user_data = device;
+
+ device->att_io = bt_io_connect(BT_IO_L2CAP, att_connect_cb,
+ attcb, NULL, NULL,
BT_IO_OPT_SOURCE_BDADDR, &src,
BT_IO_OPT_DEST_BDADDR, &device->bdaddr,
BT_IO_OPT_CID, ATT_CID,
if (device->att_io == NULL) {
browse_request_free(req);
+ g_free(attcb);
return -EIO;
}
}
}
-static void bonding_connect_cb(GIOChannel *io, GError *gerr,
- gpointer user_data)
-{
- struct btd_device *device = user_data;
-
- g_io_channel_unref(device->att_io);
- device->att_io = NULL;
-
- if (gerr) {
- DBusMessage *reply = btd_error_failed(device->bonding->msg,
- gerr->message);
-
- g_dbus_send_message(device->bonding->conn, reply);
- DBG("%s", gerr->message);
- return;
- }
-
- device->attrib = g_attrib_new(io);
- device->attachid = attrib_channel_attach(device->attrib, TRUE);
- if (device->attachid == 0)
- error("Attribute server attach failure!");
-}
-
DBusMessage *device_create_bonding(struct btd_device *device,
DBusConnection *conn,
DBusMessage *msg,
return btd_error_already_exists(msg);
if (device_is_le(device)) {
+ struct att_callbacks *attcb;
GError *gerr = NULL;
bdaddr_t sba;
adapter_get_address(adapter, &sba);
- device->att_io = bt_io_connect(BT_IO_L2CAP, bonding_connect_cb,
- device, NULL, &gerr,
+ attcb = g_new0(struct att_callbacks, 1);
+ attcb->user_data = device;
+
+ device->att_io = bt_io_connect(BT_IO_L2CAP, att_connect_cb,
+ attcb, NULL, &gerr,
BT_IO_OPT_SOURCE_BDADDR, &sba,
BT_IO_OPT_DEST_BDADDR,&device->bdaddr,
BT_IO_OPT_CID, ATT_CID,
error("Bonding bt_io_connect(): %s", gerr->message);
g_error_free(gerr);
+ g_free(attcb);
return reply;
}
}