Diff between a5c85eabb5e8eb8dfec5066d6e0c0e52cfdb9244 and 32a4ce9475d5804b854df0ec145c535b11b147a5

Changed Files

File Additions Deletions Status
src/service.c +47 -0 modified
src/service.h +9 -0 modified

Full Patch

diff --git a/src/service.c b/src/service.c
index 6228de1..eb765f2 100644
--- a/src/service.c
+++ b/src/service.c
@@ -55,6 +55,14 @@ struct btd_service {
 	int			err;
 };
 
+struct service_state_callback {
+	btd_service_state_cb	cb;
+	void			*user_data;
+	unsigned int		id;
+};
+
+static GSList *state_callbacks = NULL;
+
 static const char *state2str(btd_service_state_t state)
 {
 	switch (state) {
@@ -78,6 +86,7 @@ static void change_state(struct btd_service *service, btd_service_state_t state,
 {
 	btd_service_state_t old = service->state;
 	char addr[18];
+	GSList *l;
 
 	if (state == old)
 		return;
@@ -92,6 +101,12 @@ static void change_state(struct btd_service *service, btd_service_state_t state,
 	DBG("%p: device %s profile %s state changed: %s -> %s (%d)", service,
 					addr, service->profile->name,
 					state2str(old), state2str(state), err);
+
+	for (l = state_callbacks; l != NULL; l = g_slist_next(l)) {
+		struct service_state_callback *cb = l->data;
+
+		cb->cb(service, old, state, cb->user_data);
+	}
 }
 
 struct btd_service *btd_service_ref(struct btd_service *service)
@@ -263,6 +278,38 @@ int btd_service_get_error(const struct btd_service *service)
 	return service->err;
 }
 
+unsigned int btd_service_add_state_cb(btd_service_state_cb cb, void *user_data)
+{
+	struct service_state_callback *state_cb;
+	static unsigned int id = 0;
+
+	state_cb = g_new0(struct service_state_callback, 1);
+	state_cb->cb = cb;
+	state_cb->user_data = user_data;
+	state_cb->id = ++id;
+
+	state_callbacks = g_slist_append(state_callbacks, state_cb);
+
+	return state_cb->id;
+}
+
+bool btd_service_remove_state_cb(unsigned int id)
+{
+	GSList *l;
+
+	for (l = state_callbacks; l != NULL; l = g_slist_next(l)) {
+		struct service_state_callback *cb = l->data;
+
+		if (cb && cb->id == id) {
+			state_callbacks = g_slist_remove(state_callbacks, cb);
+			g_free(cb);
+			return true;
+		}
+	}
+
+	return false;
+}
+
 void btd_service_connecting_complete(struct btd_service *service, int err)
 {
 	if (service->state != BTD_SERVICE_STATE_DISCONNECTED &&
diff --git a/src/service.h b/src/service.h
index e3bc6e5..6ee8f17 100644
--- a/src/service.h
+++ b/src/service.h
@@ -33,6 +33,11 @@ struct btd_service;
 struct btd_device;
 struct btd_profile;
 
+typedef void (*btd_service_state_cb) (struct btd_service *service,
+						btd_service_state_t old_state,
+						btd_service_state_t new_state,
+						void *user_data);
+
 struct btd_service *btd_service_ref(struct btd_service *service);
 void btd_service_unref(struct btd_service *service);
 
@@ -53,6 +58,10 @@ struct btd_profile *btd_service_get_profile(const struct btd_service *service);
 btd_service_state_t btd_service_get_state(const struct btd_service *service);
 int btd_service_get_error(const struct btd_service *service);
 
+unsigned int btd_service_add_state_cb(btd_service_state_cb cb,
+							void *user_data);
+bool btd_service_remove_state_cb(unsigned int id);
+
 /* Functions used by profile implementation */
 void btd_service_connecting_complete(struct btd_service *service, int err);
 void btd_service_disconnecting_complete(struct btd_service *service, int err);