From: Mikel Astiz <[email protected]>
Disclaimer: this RFC is WIP and hasn't been tested, specially because I don't have the necessary hardware for it.
The goal is to have one remote_uuid per btd_profile. There are only a few exceptions to this rule, and this patchset tries to fix three of them. This basically means splitting one btd_profile per role.
Cheers,
Mikel
Mikel Astiz (5):
avrcp: Refactor server registration
audio: Split AVRCP into two btd_profile
proximity: Split internal monitor registration API
proximity: Split monitor into three btd_profile
gatt: List only GATT_UUID as remote UUID
profiles/audio/audio.conf | 2 +-
profiles/audio/avrcp.c | 115 ++++++++++++++++------
profiles/audio/avrcp.h | 6 +-
profiles/audio/manager.c | 80 +++++++++++++---
profiles/audio/manager.h | 1 +
profiles/gatt/manager.c | 2 +-
profiles/proximity/manager.c | 98 +++++++++++++++----
profiles/proximity/monitor.c | 220 ++++++++++++++++++++++++++++++++++---------
profiles/proximity/monitor.h | 17 +++-
9 files changed, 429 insertions(+), 112 deletions(-)
--
1.7.11.7
From: Mikel Astiz <[email protected]>
Use a helper function to install the AVRCP server, just like other audio
profiles such as in a2dp.c do.
---
profiles/audio/avrcp.c | 55 +++++++++++++++++++++++++++++---------------------
1 file changed, 32 insertions(+), 23 deletions(-)
diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 3ab7d35..b32c422 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -2275,12 +2275,12 @@ void avrcp_disconnect(struct audio_device *dev)
avctp_disconnect(session);
}
-int avrcp_register(const bdaddr_t *src, GKeyFile *config)
+static struct avrcp_server *avrcp_server_register(const bdaddr_t *src,
+ GKeyFile *config)
{
- sdp_record_t *record;
+ struct avrcp_server *server;
gboolean tmp, master = TRUE;
GError *err = NULL;
- struct avrcp_server *server;
if (config) {
tmp = g_key_file_get_boolean(config, "General",
@@ -2292,18 +2292,38 @@ int avrcp_register(const bdaddr_t *src, GKeyFile *config)
master = tmp;
}
+ if (avctp_register(src, master) < 0)
+ return NULL;
+
server = g_new0(struct avrcp_server, 1);
+ bacpy(&server->src, src);
+ servers = g_slist_append(servers, server);
+
+ if (!avctp_id)
+ avctp_id = avctp_add_state_cb(state_changed, NULL);
+
+ return server;
+}
+
+int avrcp_register(const bdaddr_t *src, GKeyFile *config)
+{
+ sdp_record_t *record;
+ struct avrcp_server *server;
+
+ server = avrcp_server_register(src, config);
+ if (server == NULL)
+ return -EPROTONOSUPPORT;
record = avrcp_tg_record();
if (!record) {
error("Unable to allocate new service record");
- g_free(server);
+ avrcp_unregister(src);
return -1;
}
if (add_record_to_server(src, record) < 0) {
error("Unable to register AVRCP target service record");
- g_free(server);
+ avrcp_unregister(src);
sdp_record_free(record);
return -1;
}
@@ -2312,32 +2332,18 @@ int avrcp_register(const bdaddr_t *src, GKeyFile *config)
record = avrcp_ct_record();
if (!record) {
error("Unable to allocate new service record");
- g_free(server);
+ avrcp_unregister(src);
return -1;
}
if (add_record_to_server(src, record) < 0) {
error("Unable to register AVRCP service record");
sdp_record_free(record);
- g_free(server);
+ avrcp_unregister(src);
return -1;
}
server->ct_record_id = record->handle;
- if (avctp_register(src, master) < 0) {
- remove_record_from_server(server->ct_record_id);
- remove_record_from_server(server->tg_record_id);
- g_free(server);
- return -1;
- }
-
- bacpy(&server->src, src);
-
- servers = g_slist_append(servers, server);
-
- if (!avctp_id)
- avctp_id = avctp_add_state_cb(state_changed, NULL);
-
return 0;
}
@@ -2354,8 +2360,11 @@ void avrcp_unregister(const bdaddr_t *src)
servers = g_slist_remove(servers, server);
- remove_record_from_server(server->ct_record_id);
- remove_record_from_server(server->tg_record_id);
+ if (server->ct_record_id != 0)
+ remove_record_from_server(server->ct_record_id);
+
+ if (server->tg_record_id != 0)
+ remove_record_from_server(server->tg_record_id);
avctp_unregister(&server->src);
g_free(server);
--
1.7.11.7
From: Mikel Astiz <[email protected]>
The probe function checks if both UUIDs are present, so there is no
need to list both in btd_profile.
---
profiles/gatt/manager.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/profiles/gatt/manager.c b/profiles/gatt/manager.c
index ce0ed91..e554007 100644
--- a/profiles/gatt/manager.c
+++ b/profiles/gatt/manager.c
@@ -59,7 +59,7 @@ static void gatt_driver_remove(struct btd_profile *p,
static struct btd_profile gatt_profile = {
.name = "gap-gatt-profile",
- .remote_uuids = BTD_UUIDS(GAP_UUID, GATT_UUID),
+ .remote_uuids = BTD_UUIDS(GATT_UUID),
.device_probe = gatt_driver_probe,
.device_remove = gatt_driver_remove
};
--
1.7.11.7
From: Mikel Astiz <[email protected]>
Register a separate btd_profile for each role of AVRCP.
---
profiles/audio/audio.conf | 2 +-
profiles/audio/avrcp.c | 80 ++++++++++++++++++++++++++++++++++++-----------
profiles/audio/avrcp.h | 6 ++--
profiles/audio/manager.c | 80 ++++++++++++++++++++++++++++++++++++++++-------
profiles/audio/manager.h | 1 +
5 files changed, 137 insertions(+), 32 deletions(-)
diff --git a/profiles/audio/audio.conf b/profiles/audio/audio.conf
index f556610..566454b 100644
--- a/profiles/audio/audio.conf
+++ b/profiles/audio/audio.conf
@@ -8,5 +8,5 @@
#Master=true
# If we want to disable support for specific services
-# Defaults to supporting the services: Sink, Control
+# Defaults to supporting the services: Sink, Control, Target
#Disable=Source
diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index b32c422..22dd1a5 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -2305,41 +2305,63 @@ static struct avrcp_server *avrcp_server_register(const bdaddr_t *src,
return server;
}
-int avrcp_register(const bdaddr_t *src, GKeyFile *config)
+int avrcp_target_register(const bdaddr_t *src, GKeyFile *config)
{
sdp_record_t *record;
struct avrcp_server *server;
+ server = find_server(servers, src);
+ if (server != NULL)
+ goto done;
+
server = avrcp_server_register(src, config);
if (server == NULL)
return -EPROTONOSUPPORT;
+done:
record = avrcp_tg_record();
if (!record) {
error("Unable to allocate new service record");
- avrcp_unregister(src);
+ avrcp_target_unregister(src);
return -1;
}
if (add_record_to_server(src, record) < 0) {
error("Unable to register AVRCP target service record");
- avrcp_unregister(src);
+ avrcp_target_unregister(src);
sdp_record_free(record);
return -1;
}
server->tg_record_id = record->handle;
+ return 0;
+}
+
+int avrcp_control_register(const bdaddr_t *src, GKeyFile *config)
+{
+ sdp_record_t *record;
+ struct avrcp_server *server;
+
+ server = find_server(servers, src);
+ if (server != NULL)
+ goto done;
+
+ server = avrcp_server_register(src, config);
+ if (server == NULL)
+ return -EPROTONOSUPPORT;
+
+done:
record = avrcp_ct_record();
if (!record) {
error("Unable to allocate new service record");
- avrcp_unregister(src);
+ avrcp_control_unregister(src);
return -1;
}
if (add_record_to_server(src, record) < 0) {
error("Unable to register AVRCP service record");
sdp_record_free(record);
- avrcp_unregister(src);
+ avrcp_control_unregister(src);
return -1;
}
server->ct_record_id = record->handle;
@@ -2347,25 +2369,13 @@ int avrcp_register(const bdaddr_t *src, GKeyFile *config)
return 0;
}
-void avrcp_unregister(const bdaddr_t *src)
+static void avrcp_server_unregister(struct avrcp_server *server)
{
- struct avrcp_server *server;
-
- server = find_server(servers, src);
- if (!server)
- return;
-
g_slist_free_full(server->sessions, g_free);
g_slist_free_full(server->players, player_destroy);
servers = g_slist_remove(servers, server);
- if (server->ct_record_id != 0)
- remove_record_from_server(server->ct_record_id);
-
- if (server->tg_record_id != 0)
- remove_record_from_server(server->tg_record_id);
-
avctp_unregister(&server->src);
g_free(server);
@@ -2378,6 +2388,40 @@ void avrcp_unregister(const bdaddr_t *src)
}
}
+void avrcp_target_unregister(const bdaddr_t *src)
+{
+ struct avrcp_server *server;
+
+ server = find_server(servers, src);
+ if (!server)
+ return;
+
+ if (server->tg_record_id != 0) {
+ remove_record_from_server(server->tg_record_id);
+ server->tg_record_id = 0;
+ }
+
+ if (server->ct_record_id == 0)
+ avrcp_server_unregister(server);
+}
+
+void avrcp_control_unregister(const bdaddr_t *src)
+{
+ struct avrcp_server *server;
+
+ server = find_server(servers, src);
+ if (!server)
+ return;
+
+ if (server->ct_record_id != 0) {
+ remove_record_from_server(server->ct_record_id);
+ server->ct_record_id = 0;
+ }
+
+ if (server->tg_record_id == 0)
+ avrcp_server_unregister(server);
+}
+
struct avrcp_player *avrcp_register_player(const bdaddr_t *src,
struct avrcp_player_cb *cb,
void *user_data,
diff --git a/profiles/audio/avrcp.h b/profiles/audio/avrcp.h
index e607fb1..cddf40b 100644
--- a/profiles/audio/avrcp.h
+++ b/profiles/audio/avrcp.h
@@ -92,8 +92,10 @@ struct avrcp_player_cb {
void *user_data);
};
-int avrcp_register(const bdaddr_t *src, GKeyFile *config);
-void avrcp_unregister(const bdaddr_t *src);
+int avrcp_target_register(const bdaddr_t *src, GKeyFile *config);
+void avrcp_target_unregister(const bdaddr_t *src);
+int avrcp_control_register(const bdaddr_t *src, GKeyFile *config);
+void avrcp_control_unregister(const bdaddr_t *src);
gboolean avrcp_connect(struct audio_device *dev);
void avrcp_disconnect(struct audio_device *dev);
diff --git a/profiles/audio/manager.c b/profiles/audio/manager.c
index 422316e..976a879 100644
--- a/profiles/audio/manager.c
+++ b/profiles/audio/manager.c
@@ -82,6 +82,7 @@ static struct enabled_interfaces enabled = {
.sink = TRUE,
.source = FALSE,
.control = TRUE,
+ .target = TRUE,
};
static struct audio_adapter *find_adapter(GSList *list,
@@ -371,7 +372,7 @@ static int a2dp_sink_server_probe(struct btd_profile *p,
return a2dp_sink_register(adapter_get_address(adapter), config);
}
-static int avrcp_server_probe(struct btd_profile *p,
+static int avrcp_target_server_probe(struct btd_profile *p,
struct btd_adapter *adapter)
{
struct audio_adapter *adp;
@@ -384,14 +385,50 @@ static int avrcp_server_probe(struct btd_profile *p,
if (!adp)
return -EINVAL;
- err = avrcp_register(adapter_get_address(adapter), config);
+ err = avrcp_target_register(adapter_get_address(adapter), config);
if (err < 0)
audio_adapter_unref(adp);
return err;
}
-static void avrcp_server_remove(struct btd_profile *p,
+static int avrcp_control_server_probe(struct btd_profile *p,
+ struct btd_adapter *adapter)
+{
+ struct audio_adapter *adp;
+ const gchar *path = adapter_get_path(adapter);
+ int err;
+
+ DBG("path %s", path);
+
+ adp = audio_adapter_get(adapter);
+ if (!adp)
+ return -EINVAL;
+
+ err = avrcp_control_register(adapter_get_address(adapter), config);
+ if (err < 0)
+ audio_adapter_unref(adp);
+
+ return err;
+}
+
+static void avrcp_target_server_remove(struct btd_profile *p,
+ struct btd_adapter *adapter)
+{
+ struct audio_adapter *adp;
+ const gchar *path = adapter_get_path(adapter);
+
+ DBG("path %s", path);
+
+ adp = find_adapter(adapters, adapter);
+ if (!adp)
+ return;
+
+ avrcp_target_unregister(adapter_get_address(adapter));
+ audio_adapter_unref(adp);
+}
+
+static void avrcp_control_server_remove(struct btd_profile *p,
struct btd_adapter *adapter)
{
struct audio_adapter *adp;
@@ -403,7 +440,7 @@ static void avrcp_server_remove(struct btd_profile *p,
if (!adp)
return;
- avrcp_unregister(adapter_get_address(adapter));
+ avrcp_control_unregister(adapter_get_address(adapter));
audio_adapter_unref(adp);
}
@@ -471,10 +508,21 @@ static struct btd_profile a2dp_sink_profile = {
.adapter_probe = a2dp_sink_server_probe,
};
-static struct btd_profile avrcp_profile = {
- .name = "audio-avrcp",
+static struct btd_profile avrcp_target_profile = {
+ .name = "audio-avrcp-target",
+
+ .remote_uuids = BTD_UUIDS(AVRCP_TARGET_UUID),
+ .device_probe = avrcp_probe,
+ .device_remove = audio_remove,
+
+ .adapter_probe = avrcp_target_server_probe,
+ .adapter_remove = avrcp_target_server_remove,
+};
+
+static struct btd_profile avrcp_control_profile = {
+ .name = "audio-avrcp-control",
- .remote_uuids = BTD_UUIDS(AVRCP_TARGET_UUID, AVRCP_REMOTE_UUID),
+ .remote_uuids = BTD_UUIDS(AVRCP_REMOTE_UUID),
.device_probe = avrcp_probe,
.device_remove = audio_remove,
@@ -482,8 +530,8 @@ static struct btd_profile avrcp_profile = {
.connect = avrcp_control_connect,
.disconnect = avrcp_control_disconnect,
- .adapter_probe = avrcp_server_probe,
- .adapter_remove = avrcp_server_remove,
+ .adapter_probe = avrcp_control_server_probe,
+ .adapter_remove = avrcp_control_server_remove,
};
static struct btd_adapter_driver media_driver = {
@@ -531,6 +579,8 @@ int audio_manager_init(GKeyFile *conf)
enabled.source = TRUE;
else if (g_str_equal(list[i], "Control"))
enabled.control = TRUE;
+ else if (g_str_equal(list[i], "Target"))
+ enabled.target = TRUE;
}
g_strfreev(list);
@@ -543,6 +593,8 @@ int audio_manager_init(GKeyFile *conf)
enabled.source = FALSE;
else if (g_str_equal(list[i], "Control"))
enabled.control = FALSE;
+ else if (g_str_equal(list[i], "Target"))
+ enabled.target = FALSE;
}
g_strfreev(list);
@@ -554,7 +606,10 @@ proceed:
btd_profile_register(&a2dp_sink_profile);
if (enabled.control)
- btd_profile_register(&avrcp_profile);
+ btd_profile_register(&avrcp_control_profile);
+
+ if (enabled.target)
+ btd_profile_register(&avrcp_target_profile);
btd_register_adapter_driver(&media_driver);
@@ -575,7 +630,10 @@ void audio_manager_exit(void)
btd_profile_unregister(&a2dp_sink_profile);
if (enabled.control)
- btd_profile_unregister(&avrcp_profile);
+ btd_profile_unregister(&avrcp_control_profile);
+
+ if (enabled.target)
+ btd_profile_unregister(&avrcp_target_profile);
btd_unregister_adapter_driver(&media_driver);
}
diff --git a/profiles/audio/manager.h b/profiles/audio/manager.h
index 2b924dc..fc5362b 100644
--- a/profiles/audio/manager.h
+++ b/profiles/audio/manager.h
@@ -26,6 +26,7 @@ struct enabled_interfaces {
gboolean sink;
gboolean source;
gboolean control;
+ gboolean target;
gboolean media_player;
};
--
1.7.11.7
From: Mikel Astiz <[email protected]>
Split into three btd_profile such that each of them handles one single
UUID.
---
profiles/proximity/manager.c | 102 +++++++++++++++++++++++++++++++------------
1 file changed, 75 insertions(+), 27 deletions(-)
diff --git a/profiles/proximity/manager.c b/profiles/proximity/manager.c
index 75f71ad..59c4456 100644
--- a/profiles/proximity/manager.c
+++ b/profiles/proximity/manager.c
@@ -48,42 +48,79 @@ static struct enabled enabled = {
.findme = TRUE,
};
-static int monitor_device_probe(struct btd_profile *p,
+static int monitor_linkloss_probe(struct btd_profile *p,
struct btd_device *device, GSList *uuids)
{
- struct gatt_primary *linkloss, *txpower, *immediate;
- int err = 0;
+ struct gatt_primary *linkloss;
- immediate = btd_device_get_primary(device, IMMEDIATE_ALERT_UUID);
- txpower = btd_device_get_primary(device, TX_POWER_UUID);
linkloss = btd_device_get_primary(device, LINK_LOSS_UUID);
+ if (linkloss == NULL)
+ return -1;
- if (linkloss)
- err = monitor_register_linkloss(device, &enabled, linkloss);
+ return monitor_register_linkloss(device, &enabled, linkloss);
+}
- if (err >= 0 && txpower)
- err = monitor_register_txpower(device, &enabled, txpower);
+static int monitor_immediate_probe(struct btd_profile *p,
+ struct btd_device *device, GSList *uuids)
+{
+ struct gatt_primary *immediate;
- if (err >= 0 && immediate)
- err = monitor_register_immediate(device, &enabled, immediate);
+ immediate = btd_device_get_primary(device, IMMEDIATE_ALERT_UUID);
+ if (immediate == NULL)
+ return -1;
- return err;
+ return monitor_register_immediate(device, &enabled, immediate);
}
-static void monitor_device_remove(struct btd_profile *p,
+static int monitor_txpower_probe(struct btd_profile *p,
+ struct btd_device *device, GSList *uuids)
+{
+ struct gatt_primary *txpower;
+
+ txpower = btd_device_get_primary(device, TX_POWER_UUID);
+ if (txpower == NULL)
+ return -1;
+
+ return monitor_register_txpower(device, &enabled, txpower);
+}
+
+static void monitor_linkloss_remove(struct btd_profile *p,
+ struct btd_device *device)
+{
+ monitor_unregister_linkloss(device);
+}
+
+static void monitor_immediate_remove(struct btd_profile *p,
struct btd_device *device)
{
monitor_unregister_immediate(device);
+}
+
+static void monitor_txpower_remove(struct btd_profile *p,
+ struct btd_device *device)
+{
monitor_unregister_txpower(device);
- monitor_unregister_linkloss(device);
}
-static struct btd_profile pxp_monitor_profile = {
- .name = "Proximity Monitor GATT Driver",
- .remote_uuids = BTD_UUIDS(IMMEDIATE_ALERT_UUID,
- LINK_LOSS_UUID, TX_POWER_UUID),
- .device_probe = monitor_device_probe,
- .device_remove = monitor_device_remove,
+static struct btd_profile pxp_monitor_linkloss_profile = {
+ .name = "proximity-linkloss",
+ .remote_uuids = BTD_UUIDS(LINK_LOSS_UUID),
+ .device_probe = monitor_linkloss_probe,
+ .device_remove = monitor_linkloss_remove,
+};
+
+static struct btd_profile pxp_monitor_immediate_profile = {
+ .name = "proximity-immediate",
+ .remote_uuids = BTD_UUIDS(IMMEDIATE_ALERT_UUID),
+ .device_probe = monitor_immediate_probe,
+ .device_remove = monitor_immediate_remove,
+};
+
+static struct btd_profile pxp_monitor_txpower_profile = {
+ .name = "proximity-txpower",
+ .remote_uuids = BTD_UUIDS(TX_POWER_UUID),
+ .device_probe = monitor_txpower_probe,
+ .device_remove = monitor_txpower_remove,
};
static struct btd_profile pxp_reporter_profile = {
@@ -122,19 +159,30 @@ int proximity_manager_init(GKeyFile *config)
{
load_config_file(config);
- if (btd_profile_register(&pxp_monitor_profile) < 0)
- return -1;
+ if (btd_profile_register(&pxp_monitor_linkloss_profile) < 0)
+ goto fail;
- if (btd_profile_register(&pxp_reporter_profile) < 0) {
- btd_profile_unregister(&pxp_monitor_profile);
- return -1;
- }
+ if (btd_profile_register(&pxp_monitor_immediate_profile) < 0)
+ goto fail;
+
+ if (btd_profile_register(&pxp_monitor_txpower_profile) < 0)
+ goto fail;
+
+ if (btd_profile_register(&pxp_reporter_profile) < 0)
+ goto fail;
return 0;
+
+fail:
+ proximity_manager_exit();
+
+ return -1;
}
void proximity_manager_exit(void)
{
- btd_profile_unregister(&pxp_monitor_profile);
btd_profile_unregister(&pxp_reporter_profile);
+ btd_profile_unregister(&pxp_monitor_txpower_profile);
+ btd_profile_unregister(&pxp_monitor_immediate_profile);
+ btd_profile_unregister(&pxp_monitor_linkloss_profile);
}
--
1.7.11.7
From: Mikel Astiz <[email protected]>
Split the monitor registration API into three independent registrations
each of them taking one specific GATT primary.
---
profiles/proximity/manager.c | 16 +++-
profiles/proximity/monitor.c | 220 ++++++++++++++++++++++++++++++++++---------
profiles/proximity/monitor.h | 17 +++-
3 files changed, 204 insertions(+), 49 deletions(-)
diff --git a/profiles/proximity/manager.c b/profiles/proximity/manager.c
index c3d0933..75f71ad 100644
--- a/profiles/proximity/manager.c
+++ b/profiles/proximity/manager.c
@@ -52,18 +52,30 @@ static int monitor_device_probe(struct btd_profile *p,
struct btd_device *device, GSList *uuids)
{
struct gatt_primary *linkloss, *txpower, *immediate;
+ int err = 0;
immediate = btd_device_get_primary(device, IMMEDIATE_ALERT_UUID);
txpower = btd_device_get_primary(device, TX_POWER_UUID);
linkloss = btd_device_get_primary(device, LINK_LOSS_UUID);
- return monitor_register(device, linkloss, txpower, immediate, &enabled);
+ if (linkloss)
+ err = monitor_register_linkloss(device, &enabled, linkloss);
+
+ if (err >= 0 && txpower)
+ err = monitor_register_txpower(device, &enabled, txpower);
+
+ if (err >= 0 && immediate)
+ err = monitor_register_immediate(device, &enabled, immediate);
+
+ return err;
}
static void monitor_device_remove(struct btd_profile *p,
struct btd_device *device)
{
- monitor_unregister(device);
+ monitor_unregister_immediate(device);
+ monitor_unregister_txpower(device);
+ monitor_unregister_linkloss(device);
}
static struct btd_profile pxp_monitor_profile = {
diff --git a/profiles/proximity/monitor.c b/profiles/proximity/monitor.c
index 0be0ae4..82f3a42 100644
--- a/profiles/proximity/monitor.c
+++ b/profiles/proximity/monitor.c
@@ -34,6 +34,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
+#include <glib.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/uuid.h>
@@ -83,6 +84,22 @@ struct monitor {
guint attioid;
};
+static GSList *monitors = NULL;
+
+static struct monitor *find_monitor(struct btd_device *device)
+{
+ GSList *l;
+
+ for (l = monitors; l; l = l->next) {
+ struct monitor *monitor = l->data;
+
+ if (monitor->device == device)
+ return monitor;
+ }
+
+ return NULL;
+}
+
static void write_proximity_config(struct btd_device *device, const char *alert,
const char *level)
{
@@ -572,33 +589,25 @@ static void monitor_destroy(gpointer user_data)
{
struct monitor *monitor = user_data;
- if (monitor->immediateto)
- g_source_remove(monitor->immediateto);
-
- if (monitor->attioid)
- btd_device_remove_attio_callback(monitor->device,
- monitor->attioid);
- if (monitor->attrib)
- g_attrib_unref(monitor->attrib);
-
btd_device_unref(monitor->device);
- g_free(monitor->linkloss);
- g_free(monitor->immediate);
- g_free(monitor->txpower);
g_free(monitor->linklosslevel);
g_free(monitor->immediatelevel);
g_free(monitor->signallevel);
g_free(monitor);
+
+ monitors = g_slist_remove(monitors, monitor);
}
-int monitor_register(struct btd_device *device,
- struct gatt_primary *linkloss, struct gatt_primary *txpower,
- struct gatt_primary *immediate, struct enabled *enabled)
+static struct monitor *register_monitor(struct btd_device *device)
{
const char *path = device_get_path(device);
struct monitor *monitor;
char *level;
+ monitor = find_monitor(device);
+ if (monitor != NULL)
+ return monitor;
+
level = read_proximity_config(device, "LinkLossAlertLevel");
monitor = g_new0(struct monitor, 1);
@@ -607,6 +616,8 @@ int monitor_register(struct btd_device *device,
monitor->signallevel = g_strdup("unknown");
monitor->immediatelevel = g_strdup("none");
+ monitors = g_slist_append(monitors, monitor);
+
if (g_dbus_register_interface(btd_get_dbus_connection(), path,
PROXIMITY_INTERFACE,
NULL, NULL, monitor_device_properties,
@@ -614,57 +625,180 @@ int monitor_register(struct btd_device *device,
error("D-Bus failed to register %s interface",
PROXIMITY_INTERFACE);
monitor_destroy(monitor);
- return -1;
+ return NULL;
}
DBG("Registered interface %s on path %s", PROXIMITY_INTERFACE, path);
- if (linkloss && enabled->linkloss) {
- monitor->linkloss = g_new0(struct att_range, 1);
- monitor->linkloss->start = linkloss->range.start;
- monitor->linkloss->end = linkloss->range.end;
-
- monitor->enabled.linkloss = TRUE;
- }
-
- if (immediate) {
- if (txpower && enabled->pathloss) {
- monitor->txpower = g_new0(struct att_range, 1);
- monitor->txpower->start = txpower->range.start;
- monitor->txpower->end = txpower->range.end;
-
- monitor->enabled.pathloss = TRUE;
- }
+ device_set_auto_connect(device, TRUE);
- if (enabled->pathloss || enabled->findme) {
- monitor->immediate = g_new0(struct att_range, 1);
- monitor->immediate->start = immediate->range.start;
- monitor->immediate->end = immediate->range.end;
- }
+ return monitor;
+}
- monitor->enabled.findme = enabled->findme;
- }
+static void update_monitor(struct monitor *monitor)
+{
+ if (monitor->txpower != NULL && monitor->immediate != NULL)
+ monitor->enabled.pathloss = TRUE;
+ else
+ monitor->enabled.pathloss = FALSE;
DBG("Link Loss: %s, Path Loss: %s, FindMe: %s",
monitor->enabled.linkloss ? "TRUE" : "FALSE",
monitor->enabled.pathloss ? "TRUE" : "FALSE",
monitor->enabled.findme ? "TRUE" : "FALSE");
- if (monitor->enabled.linkloss || monitor->enabled.pathloss)
- monitor->attioid = btd_device_add_attio_callback(device,
+ if (!monitor->enabled.linkloss && !monitor->enabled.pathloss)
+ return;
+
+ if (monitor->attioid != 0)
+ return;
+
+ monitor->attioid = btd_device_add_attio_callback(monitor->device,
attio_connected_cb,
attio_disconnected_cb,
monitor);
+}
- device_set_auto_connect(device, TRUE);
+int monitor_register_linkloss(struct btd_device *device,
+ struct enabled *enabled,
+ struct gatt_primary *linkloss)
+{
+ struct monitor *monitor;
+
+ if (!enabled->linkloss)
+ return 0;
+
+ monitor = register_monitor(device);
+ if (monitor == NULL)
+ return -1;
+
+ monitor->linkloss = g_new0(struct att_range, 1);
+ monitor->linkloss->start = linkloss->range.start;
+ monitor->linkloss->end = linkloss->range.end;
+ monitor->enabled.linkloss = TRUE;
+
+ update_monitor(monitor);
return 0;
}
-void monitor_unregister(struct btd_device *device)
+int monitor_register_txpower(struct btd_device *device,
+ struct enabled *enabled,
+ struct gatt_primary *txpower)
{
+ struct monitor *monitor;
+
+ if (!enabled->pathloss)
+ return 0;
+
+ monitor = register_monitor(device);
+ if (monitor == NULL)
+ return -1;
+
+ monitor->txpower = g_new0(struct att_range, 1);
+ monitor->txpower->start = txpower->range.start;
+ monitor->txpower->end = txpower->range.end;
+
+ update_monitor(monitor);
+
+ return 0;
+}
+
+int monitor_register_immediate(struct btd_device *device,
+ struct enabled *enabled,
+ struct gatt_primary *immediate)
+{
+ struct monitor *monitor;
+
+ if (!enabled->pathloss && !enabled->findme)
+ return 0;
+
+ monitor = register_monitor(device);
+ if (monitor == NULL)
+ return -1;
+
+ monitor->immediate = g_new0(struct att_range, 1);
+ monitor->immediate->start = immediate->range.start;
+ monitor->immediate->end = immediate->range.end;
+ monitor->enabled.findme = enabled->findme;
+
+ update_monitor(monitor);
+
+ return 0;
+}
+
+static void cleanup_monitor(struct monitor *monitor)
+{
+ struct btd_device *device = monitor->device;
const char *path = device_get_path(device);
+ if (monitor->immediate != NULL || monitor->txpower != NULL)
+ return;
+
+ if (monitor->immediateto != 0) {
+ g_source_remove(monitor->immediateto);
+ monitor->immediateto = 0;
+ }
+
+ if (monitor->attioid != 0) {
+ btd_device_remove_attio_callback(device, monitor->attioid);
+ monitor->attioid = 0;
+ }
+
+ if (monitor->attrib != NULL) {
+ g_attrib_unref(monitor->attrib);
+ monitor->attrib = NULL;
+ }
+
+ if (monitor->linkloss != NULL)
+ return;
+
g_dbus_unregister_interface(btd_get_dbus_connection(), path,
PROXIMITY_INTERFACE);
}
+
+void monitor_unregister_linkloss(struct btd_device *device)
+{
+ struct monitor *monitor;
+
+ monitor = find_monitor(device);
+ if (monitor == NULL)
+ return;
+
+ g_free(monitor->linkloss);
+ monitor->linkloss = NULL;
+ monitor->enabled.linkloss = TRUE;
+
+ cleanup_monitor(monitor);
+}
+
+void monitor_unregister_txpower(struct btd_device *device)
+{
+ struct monitor *monitor;
+
+ monitor = find_monitor(device);
+ if (monitor == NULL)
+ return;
+
+ g_free(monitor->txpower);
+ monitor->txpower = NULL;
+ monitor->enabled.pathloss = FALSE;
+
+ cleanup_monitor(monitor);
+}
+
+void monitor_unregister_immediate(struct btd_device *device)
+{
+ struct monitor *monitor;
+
+ monitor = find_monitor(device);
+ if (monitor == NULL)
+ return;
+
+ g_free(monitor->immediate);
+ monitor->immediate = NULL;
+ monitor->enabled.findme = FALSE;
+ monitor->enabled.pathloss = FALSE;
+
+ cleanup_monitor(monitor);
+}
diff --git a/profiles/proximity/monitor.h b/profiles/proximity/monitor.h
index 191b562..d9a40c6 100644
--- a/profiles/proximity/monitor.h
+++ b/profiles/proximity/monitor.h
@@ -28,7 +28,16 @@ struct enabled {
gboolean findme;
};
-int monitor_register(struct btd_device *device, struct gatt_primary *linkloss,
- struct gatt_primary *txpower, struct gatt_primary *immediate,
- struct enabled *enabled);
-void monitor_unregister(struct btd_device *device);
+int monitor_register_linkloss(struct btd_device *device,
+ struct enabled *enabled,
+ struct gatt_primary *linkloss);
+int monitor_register_txpower(struct btd_device *device,
+ struct enabled *enabled,
+ struct gatt_primary *txpower);
+int monitor_register_immediate(struct btd_device *device,
+ struct enabled *enabled,
+ struct gatt_primary *immediate);
+
+void monitor_unregister_linkloss(struct btd_device *device);
+void monitor_unregister_txpower(struct btd_device *device);
+void monitor_unregister_immediate(struct btd_device *device);
--
1.7.11.7