@@ -81,6 +81,13 @@
static DBusConnection *dbus_conn = NULL;
static unsigned service_state_cb_id;
+static GSList *device_state_callbacks;
+
+struct device_state_callback {
+ btd_device_state_cb cb;
+ void *user_data;
+ unsigned int id;
+};
struct btd_disconnect_data {
guint id;
@@ -272,6 +279,8 @@ struct btd_device {
GIOChannel *att_io;
guint store_id;
+
+ enum btd_device_state_t state;
};
static const uint16_t uuid_list[] = {
@@ -4095,6 +4104,23 @@ static void gatt_service_removed(struct gatt_db_attribute *attr,
gatt_services_changed(device);
}
+static void device_change_state(struct btd_device *device,
+ enum btd_device_state_t new_state)
+{
+ GSList *l;
+ struct device_state_callback *cb_data;
+
+ if (device->state == new_state)
+ return;
+
+ for (l = device_state_callbacks; l != NULL; l = g_slist_next(l)) {
+ cb_data = l->data;
+ cb_data->cb(device, new_state, cb_data->user_data);
+ }
+
+ device->state = new_state;
+}
+
static struct btd_device *device_new(struct btd_adapter *adapter,
const char *address)
{
@@ -4158,6 +4184,8 @@ static struct btd_device *device_new(struct btd_adapter *adapter,
device->refresh_discovery = btd_opts.refresh_discovery;
+ device_change_state(device, BTD_DEVICE_STATE_AVAILABLE);
+
return btd_device_ref(device);
}
@@ -6839,6 +6867,7 @@ void btd_device_unref(struct btd_device *device)
DBG("Freeing device %s", device->path);
+ device_change_state(device, BTD_DEVICE_STATE_REMOVING);
g_dbus_unregister_interface(dbus_conn, device->path, DEVICE_INTERFACE);
}
@@ -6980,3 +7009,38 @@ void btd_device_cleanup(void)
{
btd_service_remove_state_cb(service_state_cb_id);
}
+
+unsigned int btd_device_add_state_cb(btd_device_state_cb cb, void *user_data)
+{
+ struct device_state_callback *cb_data;
+ static unsigned int id;
+
+ cb_data = g_new0(struct device_state_callback, 1);
+ cb_data->cb = cb;
+ cb_data->user_data = user_data;
+ cb_data->id = ++id;
+
+ device_state_callbacks = g_slist_append(device_state_callbacks,
+ cb_data);
+
+ return cb_data->id;
+}
+
+bool btd_device_remove_state_cb(unsigned int id)
+{
+ GSList *l;
+
+ for (l = device_state_callbacks; l != NULL; l = g_slist_next(l)) {
+ struct device_state_callback *cb_data = l->data;
+
+ if (cb_data && cb_data->id == id) {
+ device_state_callbacks = g_slist_remove(
+ device_state_callbacks,
+ cb_data);
+ g_free(cb_data);
+ return true;
+ }
+ }
+
+ return false;
+}
@@ -11,8 +11,18 @@
#define DEVICE_INTERFACE "org.bluez.Device1"
+enum btd_device_state_t {
+ BTD_DEVICE_STATE_INITIALIZING, /* Device object is creating */
+ BTD_DEVICE_STATE_AVAILABLE, /* Device object is registered */
+ BTD_DEVICE_STATE_REMOVING, /* Device object is being removed */
+};
+
struct btd_device;
+typedef void (*btd_device_state_cb) (struct btd_device *device,
+ enum btd_device_state_t new_state,
+ void *user_data);
+
struct btd_device *device_create(struct btd_adapter *adapter,
const bdaddr_t *address, uint8_t bdaddr_type);
struct btd_device *device_create_from_storage(struct btd_adapter *adapter,
@@ -179,3 +189,6 @@ bool btd_device_all_services_allowed(struct btd_device *dev);
void btd_device_update_allowed_services(struct btd_device *dev);
void btd_device_init(void);
void btd_device_cleanup(void);
+
+unsigned int btd_device_add_state_cb(btd_device_state_cb cb, void *user_data);
+bool btd_device_remove_state_cb(unsigned int id);