2013-04-05 11:45:37

by Mikel Astiz

[permalink] [raw]
Subject: [RFC v2 00/11] struct btd_service in core

From: Mikel Astiz <[email protected]>

v1 does not apply anymore so I'm sending an updated version of the patchset.

v2 is similar to the pervious version but with minor changes in patch 1 as pointed out by Johan and Anderson. Besides, patch 11 has been updated to the latest changes in profiles/audio.

>From original cover-letter:

This RFC proposes a somewhat intrusive change in the core with the adoption of struct btd_service, with the following main goals:

1. Support for multiple instances of the same UUID.
2. Better support for connection-handling plugins/components (e.g. automotive).
3. Exposure of remote services in D-Bus (not implemented here).
4. Improve code readability and reduce profile-implementation code size.

Mikel Astiz (11):
core: Add btd_service to represent device services
device: Use btd_service to represent profiles
device: Replace connected_profiles with btd_service
device: Find services instead of profiles
device: Replace pending profile list with services
profile: Use btd_service for probing profiles
audio: Hold a reference to btd_service
network: Hold a reference to btd_service
input: Hold a reference to btd_service
service: Add callbacks to track state changes
profile: Use btd_service for connect/disconnect

Makefile.am | 1 +
Makefile.plugins | 4 +-
profiles/audio/avrcp.c | 16 +--
profiles/audio/control.c | 48 ++++++-
profiles/audio/control.h | 12 +-
profiles/audio/manager.c | 88 ++++--------
profiles/audio/manager.h | 9 --
profiles/audio/sink.c | 24 ++--
profiles/audio/sink.h | 4 +-
profiles/audio/source.c | 25 ++--
profiles/audio/source.h | 5 +-
profiles/cyclingspeed/cyclingspeed.c | 9 +-
profiles/deviceinfo/deviceinfo.c | 11 +-
profiles/gatt/gas.c | 10 +-
profiles/health/hdp_manager.c | 10 +-
profiles/heartrate/heartrate.c | 10 +-
profiles/input/device.c | 95 +++++++------
profiles/input/device.h | 13 +-
profiles/input/hog.c | 8 +-
profiles/input/manager.c | 51 +------
profiles/input/manager.h | 25 ----
profiles/network/connection.c | 77 ++++++-----
profiles/network/connection.h | 8 +-
profiles/network/manager.c | 123 ++---------------
profiles/network/manager.h | 25 ----
profiles/proximity/manager.c | 28 ++--
profiles/proximity/reporter.c | 8 +-
profiles/proximity/reporter.h | 5 +-
profiles/sap/manager.c | 1 +
profiles/scanparam/scan.c | 9 +-
profiles/thermometer/thermometer.c | 11 +-
src/device.c | 242 +++++++++++++++++++++-----------
src/device.h | 5 -
src/profile.c | 40 ++++--
src/profile.h | 14 +-
src/service.c | 260 +++++++++++++++++++++++++++++++++++
src/service.h | 61 ++++++++
37 files changed, 825 insertions(+), 570 deletions(-)
delete mode 100644 profiles/input/manager.h
delete mode 100644 profiles/network/manager.h
create mode 100644 src/service.c
create mode 100644 src/service.h

--
1.8.1.4



2013-04-17 09:44:57

by Johan Hedberg

[permalink] [raw]
Subject: Re: [RFC v2 01/11] core: Add btd_service to represent device services

Hi Mikel,

I did a quick read through of the patches and in general they seem quite
good. A couple of issues though:

> +struct btd_service *service_create(struct btd_device *device,
> + struct btd_profile *profile)
> +{
> + struct btd_service *service;
> +
> + service = g_try_new0(struct btd_service, 1);
> + if (!service) {
> + error("service_create: failed to alloc memory");
> + return NULL;
> + }
> +
> + service->ref = 1;
> + service->device = btd_device_ref(device);

I don't think we want to have this pointer impacting reference count of
the device. The device "owns" the service and maintains a list of them
so when device.c calls service_create it shouldn't cause a new
reference for the device. We follow the same principle with adapters and
devices too: when an adapter creates a new device object the device
objects adapter pointer doesn't use ref().

One thing that you may need to pay attention to though is if for
whatever reason (buggy plugins) all service references aren't released
when a device gets removed, the device pointer should at least get set
to NULL (or maybe just have a big assert if this should only happen in
the case of a bug).

> +struct btd_service *service_create(struct btd_device *device,
> + struct btd_profile *profile);
> +
> +struct btd_service *btd_service_ref(struct btd_service *service);
> +void btd_service_unref(struct btd_service *service);
> +
> +struct btd_device *btd_service_get_device(const struct btd_service *service);
> +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);
> +
> +void btd_service_set_user_data(struct btd_service *service, void *user_data);
> +void *btd_service_get_user_data(const struct btd_service *service);
> +int btd_service_get_error(const struct btd_service *service);
> +
> +void btd_service_probed(struct btd_service *service);
> +void btd_service_connecting(struct btd_service *service);
> +void btd_service_connecting_complete(struct btd_service *service, int err);
> +void btd_service_disconnecting(struct btd_service *service);
> +void btd_service_disconnecting_complete(struct btd_service *service, int err);
> +void btd_service_unavailable(struct btd_service *service);

Since you're adding all these APIs without any actual users in this
patch I'd appreciate a short description of the expected uses of them.
You could e.g. put it to the cover letter or even the commit message.

Johan

2013-04-17 08:22:33

by Mikel Astiz

[permalink] [raw]
Subject: Re: [RFC v2 00/11] struct btd_service in core

Hi,

On Fri, Apr 5, 2013 at 1:45 PM, Mikel Astiz <[email protected]> wrote:
> From: Mikel Astiz <[email protected]>
>
> v1 does not apply anymore so I'm sending an updated version of the patchset.
>
> v2 is similar to the pervious version but with minor changes in patch 1 as pointed out by Johan and Anderson. Besides, patch 11 has been updated to the latest changes in profiles/audio.
>
> From original cover-letter:
>
> This RFC proposes a somewhat intrusive change in the core with the adoption of struct btd_service, with the following main goals:
>
> 1. Support for multiple instances of the same UUID.
> 2. Better support for connection-handling plugins/components (e.g. automotive).
> 3. Exposure of remote services in D-Bus (not implemented here).
> 4. Improve code readability and reduce profile-implementation code size.
>
> Mikel Astiz (11):
> core: Add btd_service to represent device services
> device: Use btd_service to represent profiles
> device: Replace connected_profiles with btd_service
> device: Find services instead of profiles
> device: Replace pending profile list with services
> profile: Use btd_service for probing profiles
> audio: Hold a reference to btd_service
> network: Hold a reference to btd_service
> input: Hold a reference to btd_service
> service: Add callbacks to track state changes
> profile: Use btd_service for connect/disconnect
>
> Makefile.am | 1 +
> Makefile.plugins | 4 +-
> profiles/audio/avrcp.c | 16 +--
> profiles/audio/control.c | 48 ++++++-
> profiles/audio/control.h | 12 +-
> profiles/audio/manager.c | 88 ++++--------
> profiles/audio/manager.h | 9 --
> profiles/audio/sink.c | 24 ++--
> profiles/audio/sink.h | 4 +-
> profiles/audio/source.c | 25 ++--
> profiles/audio/source.h | 5 +-
> profiles/cyclingspeed/cyclingspeed.c | 9 +-
> profiles/deviceinfo/deviceinfo.c | 11 +-
> profiles/gatt/gas.c | 10 +-
> profiles/health/hdp_manager.c | 10 +-
> profiles/heartrate/heartrate.c | 10 +-
> profiles/input/device.c | 95 +++++++------
> profiles/input/device.h | 13 +-
> profiles/input/hog.c | 8 +-
> profiles/input/manager.c | 51 +------
> profiles/input/manager.h | 25 ----
> profiles/network/connection.c | 77 ++++++-----
> profiles/network/connection.h | 8 +-
> profiles/network/manager.c | 123 ++---------------
> profiles/network/manager.h | 25 ----
> profiles/proximity/manager.c | 28 ++--
> profiles/proximity/reporter.c | 8 +-
> profiles/proximity/reporter.h | 5 +-
> profiles/sap/manager.c | 1 +
> profiles/scanparam/scan.c | 9 +-
> profiles/thermometer/thermometer.c | 11 +-
> src/device.c | 242 +++++++++++++++++++++-----------
> src/device.h | 5 -
> src/profile.c | 40 ++++--
> src/profile.h | 14 +-
> src/service.c | 260 +++++++++++++++++++++++++++++++++++
> src/service.h | 61 ++++++++
> 37 files changed, 825 insertions(+), 570 deletions(-)
> delete mode 100644 profiles/input/manager.h
> delete mode 100644 profiles/network/manager.h
> create mode 100644 src/service.c
> create mode 100644 src/service.h
>
> --
> 1.8.1.4
>

Ping.

Cheers,
Mikel

2013-04-05 11:45:48

by Mikel Astiz

[permalink] [raw]
Subject: [RFC v2 11/11] profile: Use btd_service for connect/disconnect

From: Mikel Astiz <[email protected]>

Change the btd_profile connect/disconnect callbacks to receive a
btd_service pointer. This should make it possible to handle multiple
instances of the same profile in a specific device.

The patch strongly influences how the profiles should interact with the
core. The state transitions, previously reported using the device.h API
(device_profile_connected() and device_profile_disconnected()), have
now been replaced by the btd_service API.

The transitions will then be propagated to device.c by means of the
conventional state-changed callback mechanism.
---
Makefile.plugins | 4 +--
profiles/audio/avrcp.c | 16 ++++-----
profiles/audio/control.c | 20 +++++++++++
profiles/audio/control.h | 5 +++
profiles/audio/manager.c | 64 +++++++----------------------------
profiles/audio/manager.h | 9 -----
profiles/audio/sink.c | 18 +++++-----
profiles/audio/source.c | 18 +++++-----
profiles/input/device.c | 21 +++++-------
profiles/input/device.h | 5 ++-
profiles/input/manager.c | 11 ------
profiles/input/manager.h | 25 --------------
profiles/network/connection.c | 39 ++++++---------------
profiles/network/connection.h | 4 +--
profiles/network/manager.c | 79 ++++---------------------------------------
profiles/network/manager.h | 25 --------------
src/device.c | 40 +++++++++++++---------
src/device.h | 5 ---
src/profile.c | 29 ++++++++++------
src/profile.h | 6 ++--
20 files changed, 138 insertions(+), 305 deletions(-)
delete mode 100644 profiles/input/manager.h
delete mode 100644 profiles/network/manager.h

diff --git a/Makefile.plugins b/Makefile.plugins
index f497782..44e6eca 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -41,14 +41,14 @@ builtin_sources += profiles/audio/main.c \
profiles/audio/a2dp-codecs.h

builtin_modules += network
-builtin_sources += profiles/network/manager.h profiles/network/manager.c \
+builtin_sources += profiles/network/manager.c \
profiles/network/common.h profiles/network/common.c \
profiles/network/server.h profiles/network/server.c \
profiles/network/connection.h \
profiles/network/connection.c

builtin_modules += input
-builtin_sources += profiles/input/manager.h profiles/input/manager.c \
+builtin_sources += profiles/input/manager.c \
profiles/input/server.h profiles/input/server.c \
profiles/input/device.h profiles/input/device.c

diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 512b018..b7de051 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -2668,7 +2668,7 @@ static void session_tg_init_control(struct avrcp *session)
avrcp_register_notification(session,
AVRCP_EVENT_VOLUME_CHANGED);

- audio_controller_connected(session->dev->btd_dev, 0);
+ control_remote_connected(session->dev->control, 0);
}

static void session_ct_init_browsing(struct avrcp *session)
@@ -2694,7 +2694,7 @@ static void session_ct_init_control(struct avrcp *session)
if (session->version >= 0x0104)
session->supported_events = (1 << AVRCP_EVENT_VOLUME_CHANGED);

- audio_target_connected(session->dev->btd_dev, 0);
+ control_target_connected(session->dev->control, 0);

player = create_ct_player(session, 0);
if (player == NULL)
@@ -2731,9 +2731,9 @@ static void session_tg_destroy(struct avrcp *session)
player->sessions = g_slist_remove(player->sessions, session);

if (session->control_id == 0)
- audio_controller_connected(session->dev->btd_dev, -EIO);
-
- audio_controller_disconnected(session->dev->btd_dev, 0);
+ control_remote_connected(session->dev->control, -EIO);
+ else
+ control_remote_disconnected(session->dev->control, 0);

session_destroy(session);
}
@@ -2745,9 +2745,9 @@ static void session_ct_destroy(struct avrcp *session)
g_slist_free_full(session->players, player_destroy);

if (session->control_id == 0)
- audio_target_connected(session->dev->btd_dev, -EIO);
-
- audio_target_disconnected(session->dev->btd_dev, 0);
+ control_target_connected(session->dev->control, -EIO);
+ else
+ control_target_disconnected(session->dev->control, 0);

session_destroy(session);
}
diff --git a/profiles/audio/control.c b/profiles/audio/control.c
index 10cd1de..cdba385 100644
--- a/profiles/audio/control.c
+++ b/profiles/audio/control.c
@@ -68,6 +68,26 @@ struct control {
unsigned int avctp_id;
};

+void control_target_connected(struct control *control, int err)
+{
+ btd_service_connecting_complete(control->target, err);
+}
+
+void control_target_disconnected(struct control *control, int err)
+{
+ btd_service_disconnecting_complete(control->target, err);
+}
+
+void control_remote_connected(struct control *control, int err)
+{
+ btd_service_connecting_complete(control->remote, err);
+}
+
+void control_remote_disconnected(struct control *control, int err)
+{
+ btd_service_disconnecting_complete(control->remote, err);
+}
+
static void state_changed(struct audio_device *dev, avctp_state_t old_state,
avctp_state_t new_state)
{
diff --git a/profiles/audio/control.h b/profiles/audio/control.h
index 0176b54..0a0f208 100644
--- a/profiles/audio/control.h
+++ b/profiles/audio/control.h
@@ -34,3 +34,8 @@ gboolean control_is_active(struct audio_device *dev);

int control_connect(struct audio_device *dev);
int control_disconnect(struct audio_device *dev);
+
+void control_target_connected(struct control *control, int err);
+void control_target_disconnected(struct control *control, int err);
+void control_remote_connected(struct control *control, int err);
+void control_remote_disconnected(struct control *control, int err);
diff --git a/profiles/audio/manager.c b/profiles/audio/manager.c
index e886e12..15226e4 100644
--- a/profiles/audio/manager.c
+++ b/profiles/audio/manager.c
@@ -157,9 +157,9 @@ static int avrcp_probe(struct btd_service *service)
return 0;
}

-static int a2dp_source_connect(struct btd_device *dev,
- struct btd_profile *profile)
+static int a2dp_source_connect(struct btd_service *service)
{
+ struct btd_device *dev = btd_service_get_device(service);
const char *path = device_get_path(dev);
struct audio_device *audio_dev;

@@ -174,9 +174,9 @@ static int a2dp_source_connect(struct btd_device *dev,
return source_connect(audio_dev);
}

-static int a2dp_source_disconnect(struct btd_device *dev,
- struct btd_profile *profile)
+static int a2dp_source_disconnect(struct btd_service *service)
{
+ struct btd_device *dev = btd_service_get_device(service);
const char *path = device_get_path(dev);
struct audio_device *audio_dev;

@@ -191,9 +191,9 @@ static int a2dp_source_disconnect(struct btd_device *dev,
return source_disconnect(audio_dev, FALSE);
}

-static int a2dp_sink_connect(struct btd_device *dev,
- struct btd_profile *profile)
+static int a2dp_sink_connect(struct btd_service *service)
{
+ struct btd_device *dev = btd_service_get_device(service);
const char *path = device_get_path(dev);
struct audio_device *audio_dev;

@@ -208,9 +208,9 @@ static int a2dp_sink_connect(struct btd_device *dev,
return sink_connect(audio_dev);
}

-static int a2dp_sink_disconnect(struct btd_device *dev,
- struct btd_profile *profile)
+static int a2dp_sink_disconnect(struct btd_service *service)
{
+ struct btd_device *dev = btd_service_get_device(service);
const char *path = device_get_path(dev);
struct audio_device *audio_dev;

@@ -225,9 +225,9 @@ static int a2dp_sink_disconnect(struct btd_device *dev,
return sink_disconnect(audio_dev, FALSE);
}

-static int avrcp_target_connect(struct btd_device *dev,
- struct btd_profile *profile)
+static int avrcp_target_connect(struct btd_service *service)
{
+ struct btd_device *dev = btd_service_get_device(service);
const char *path = device_get_path(dev);
struct audio_device *audio_dev;

@@ -242,9 +242,9 @@ static int avrcp_target_connect(struct btd_device *dev,
return control_connect(audio_dev);
}

-static int avrcp_target_disconnect(struct btd_device *dev,
- struct btd_profile *profile)
+static int avrcp_target_disconnect(struct btd_service *service)
{
+ struct btd_device *dev = btd_service_get_device(service);
const char *path = device_get_path(dev);
struct audio_device *audio_dev;

@@ -401,46 +401,6 @@ static struct btd_adapter_driver media_driver = {
.remove = media_server_remove,
};

-void audio_sink_connected(struct btd_device *dev, int err)
-{
- device_profile_connected(dev, &a2dp_sink_profile, err);
-}
-
-void audio_sink_disconnected(struct btd_device *dev, int err)
-{
- device_profile_disconnected(dev, &a2dp_sink_profile, err);
-}
-
-void audio_source_connected(struct btd_device *dev, int err)
-{
- device_profile_connected(dev, &a2dp_source_profile, err);
-}
-
-void audio_source_disconnected(struct btd_device *dev, int err)
-{
- device_profile_disconnected(dev, &a2dp_source_profile, err);
-}
-
-void audio_target_connected(struct btd_device *dev, int err)
-{
- device_profile_connected(dev, &avrcp_target_profile, err);
-}
-
-void audio_target_disconnected(struct btd_device *dev, int err)
-{
- device_profile_disconnected(dev, &avrcp_target_profile, err);
-}
-
-void audio_controller_connected(struct btd_device *dev, int err)
-{
- device_profile_connected(dev, &avrcp_remote_profile, err);
-}
-
-void audio_controller_disconnected(struct btd_device *dev, int err)
-{
- device_profile_disconnected(dev, &avrcp_remote_profile, err);
-}
-
int audio_manager_init(GKeyFile *conf)
{
if (conf)
diff --git a/profiles/audio/manager.h b/profiles/audio/manager.h
index 9b5af5f..b8d8ef7 100644
--- a/profiles/audio/manager.h
+++ b/profiles/audio/manager.h
@@ -29,15 +29,6 @@ struct enabled_interfaces {
gboolean media_player;
};

-void audio_sink_connected(struct btd_device *dev, int err);
-void audio_sink_disconnected(struct btd_device *dev, int err);
-void audio_source_connected(struct btd_device *dev, int err);
-void audio_source_disconnected(struct btd_device *dev, int err);
-void audio_target_connected(struct btd_device *dev, int err);
-void audio_target_disconnected(struct btd_device *dev, int err);
-void audio_controller_connected(struct btd_device *dev, int err);
-void audio_controller_disconnected(struct btd_device *dev, int err);
-
int audio_manager_init(GKeyFile *config);
void audio_manager_exit(void);

diff --git a/profiles/audio/sink.c b/profiles/audio/sink.c
index 9f1a2d9..3969417 100644
--- a/profiles/audio/sink.c
+++ b/profiles/audio/sink.c
@@ -149,7 +149,7 @@ static void stream_state_changed(struct avdtp_stream *stream,

switch (new_state) {
case AVDTP_STATE_IDLE:
- audio_sink_disconnected(dev->btd_dev, 0);
+ btd_service_disconnecting_complete(sink->service, 0);

if (sink->disconnect_id > 0) {
a2dp_cancel(dev, sink->disconnect_id);
@@ -194,7 +194,7 @@ static gboolean stream_setup_retry(gpointer user_data)
err = -EIO;
}

- audio_sink_connected(sink->dev->btd_dev, err);
+ btd_service_connecting_complete(sink->service, err);

if (sink->connect_id > 0) {
a2dp_cancel(sink->dev, sink->connect_id);
@@ -214,7 +214,7 @@ static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep,

if (stream) {
DBG("Stream successfully created");
- audio_sink_connected(sink->dev->btd_dev, 0);
+ btd_service_connecting_complete(sink->service, 0);
return;
}

@@ -228,7 +228,7 @@ static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
sink);
} else {
DBG("Stream setup failed : %s", avdtp_strerror(err));
- audio_sink_connected(sink->dev->btd_dev, -EIO);
+ btd_service_connecting_complete(sink->service, -EIO);
}
}

@@ -248,7 +248,7 @@ static void select_complete(struct avdtp *session, struct a2dp_sep *sep,
return;

failed:
- audio_sink_connected(sink->dev->btd_dev, -EIO);
+ btd_service_connecting_complete(sink->service, -EIO);

avdtp_unref(sink->session);
sink->session = NULL;
@@ -286,7 +286,7 @@ static void discovery_complete(struct avdtp *session, GSList *seps, struct avdtp
return;

failed:
- audio_sink_connected(sink->dev->btd_dev, -EIO);
+ btd_service_connecting_complete(sink->service, -EIO);
avdtp_unref(sink->session);
sink->session = NULL;
}
@@ -348,13 +348,13 @@ static void sink_free(struct audio_device *dev)
avdtp_unref(sink->session);

if (sink->connect_id > 0) {
- audio_sink_connected(dev->btd_dev, -ECANCELED);
+ btd_service_connecting_complete(sink->service, -ECANCELED);
a2dp_cancel(dev, sink->connect_id);
sink->connect_id = 0;
}

if (sink->disconnect_id > 0) {
- audio_sink_disconnected(dev->btd_dev, -ECANCELED);
+ btd_service_disconnecting_complete(sink->service, -ECANCELED);
a2dp_cancel(dev, sink->disconnect_id);
sink->disconnect_id = 0;
}
@@ -434,7 +434,7 @@ int sink_disconnect(struct audio_device *dev, gboolean shutdown)
if (sink->connect_id > 0) {
a2dp_cancel(dev, sink->connect_id);
sink->connect_id = 0;
- audio_sink_connected(dev->btd_dev, -ECANCELED);
+ btd_service_connecting_complete(sink->service, -ECANCELED);

avdtp_unref(sink->session);
sink->session = NULL;
diff --git a/profiles/audio/source.c b/profiles/audio/source.c
index 20fd412..226c372 100644
--- a/profiles/audio/source.c
+++ b/profiles/audio/source.c
@@ -150,7 +150,7 @@ static void stream_state_changed(struct avdtp_stream *stream,

switch (new_state) {
case AVDTP_STATE_IDLE:
- audio_source_disconnected(dev->btd_dev, 0);
+ btd_service_disconnecting_complete(source->service, 0);

if (source->disconnect_id > 0) {
a2dp_cancel(dev, source->disconnect_id);
@@ -195,7 +195,7 @@ static gboolean stream_setup_retry(gpointer user_data)
err = -EIO;
}

- audio_source_connected(source->dev->btd_dev, err);
+ btd_service_connecting_complete(source->service, err);

if (source->connect_id > 0) {
a2dp_cancel(source->dev, source->connect_id);
@@ -215,7 +215,7 @@ static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep,

if (stream) {
DBG("Stream successfully created");
- audio_source_connected(source->dev->btd_dev, 0);
+ btd_service_connecting_complete(source->service, 0);
return;
}

@@ -229,7 +229,7 @@ static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
source);
} else {
DBG("Stream setup failed : %s", avdtp_strerror(err));
- audio_source_connected(source->dev->btd_dev, -EIO);
+ btd_service_connecting_complete(source->service, -EIO);
}
}

@@ -252,7 +252,7 @@ static void select_complete(struct avdtp *session, struct a2dp_sep *sep,
return;

failed:
- audio_source_connected(source->dev->btd_dev, -EIO);
+ btd_service_connecting_complete(source->service, -EIO);

avdtp_unref(source->session);
source->session = NULL;
@@ -290,7 +290,7 @@ static void discovery_complete(struct avdtp *session, GSList *seps, struct avdtp
return;

failed:
- audio_source_connected(source->dev->btd_dev, -EIO);
+ btd_service_connecting_complete(source->service, -EIO);
avdtp_unref(source->session);
source->session = NULL;
}
@@ -352,13 +352,13 @@ static void source_free(struct audio_device *dev)
avdtp_unref(source->session);

if (source->connect_id > 0) {
- audio_source_connected(dev->btd_dev, -ECANCELED);
+ btd_service_connecting_complete(source->service, -ECANCELED);
a2dp_cancel(dev, source->connect_id);
source->connect_id = 0;
}

if (source->disconnect_id > 0) {
- audio_source_disconnected(dev->btd_dev, -ECANCELED);
+ btd_service_disconnecting_complete(source->service, -ECANCELED);
a2dp_cancel(dev, source->disconnect_id);
source->disconnect_id = 0;
}
@@ -431,7 +431,7 @@ int source_disconnect(struct audio_device *dev, gboolean shutdown)
if (source->connect_id > 0) {
a2dp_cancel(dev, source->connect_id);
source->connect_id = 0;
- audio_source_connected(dev->btd_dev, -ECANCELED);
+ btd_service_connecting_complete(source->service, -ECANCELED);

avdtp_unref(source->session);
source->session = NULL;
diff --git a/profiles/input/device.c b/profiles/input/device.c
index 2115111..1df12cc 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
@@ -48,7 +48,6 @@
#include "../src/storage.h"
#include "../src/dbus-common.h"

-#include "manager.h"
#include "device.h"
#include "error.h"
#include <btio/btio.h>
@@ -534,7 +533,7 @@ static int input_device_connected(struct input_device *idev)
idev->dc_id = device_add_disconnect_watch(idev->device, disconnect_cb,
idev, NULL);

- input_manager_device_connected(idev->device, 0);
+ btd_service_connecting_complete(idev->service, 0);

return 0;
}
@@ -561,7 +560,7 @@ static void interrupt_connect_cb(GIOChannel *chan, GError *conn_err,
return;

failed:
- input_manager_device_connected(idev->device, err);
+ btd_service_connecting_complete(idev->service, err);

/* So we guarantee the interrupt channel is closed before the
* control channel (if we only do unref GLib will close it only
@@ -613,7 +612,7 @@ static void control_connect_cb(GIOChannel *chan, GError *conn_err,
return;

failed:
- input_manager_device_connected(idev->device, -EIO);
+ btd_service_connecting_complete(idev->service, -EIO);
g_io_channel_unref(idev->ctrl_io);
idev->ctrl_io = NULL;
}
@@ -644,13 +643,11 @@ static int dev_connect(struct input_device *idev)
return -EIO;
}

-int input_device_connect(struct btd_device *dev, struct btd_profile *profile)
+int input_device_connect(struct btd_service *service)
{
struct input_device *idev;

- idev = find_device_by_path(devices, device_get_path(dev));
- if (!idev)
- return -ENOENT;
+ idev = btd_service_get_user_data(service);

if (idev->ctrl_io)
return -EBUSY;
@@ -661,20 +658,18 @@ int input_device_connect(struct btd_device *dev, struct btd_profile *profile)
return dev_connect(idev);
}

-int input_device_disconnect(struct btd_device *dev, struct btd_profile *profile)
+int input_device_disconnect(struct btd_service *service)
{
struct input_device *idev;
int err;

- idev = find_device_by_path(devices, device_get_path(dev));
- if (!idev)
- return -ENOENT;
+ idev = btd_service_get_user_data(service);

err = connection_disconnect(idev, 0);
if (err < 0)
return err;

- device_profile_disconnected(dev, profile, 0);
+ btd_service_disconnecting_complete(service, 0);

return 0;
}
diff --git a/profiles/input/device.h b/profiles/input/device.h
index fd7f847..39c642d 100644
--- a/profiles/input/device.h
+++ b/profiles/input/device.h
@@ -36,6 +36,5 @@ int input_device_set_channel(const bdaddr_t *src, const bdaddr_t *dst, int psm,
GIOChannel *io);
int input_device_close_channels(const bdaddr_t *src, const bdaddr_t *dst);

-int input_device_connect(struct btd_device *dev, struct btd_profile *profile);
-int input_device_disconnect(struct btd_device *dev,
- struct btd_profile *profile);
+int input_device_connect(struct btd_service *service);
+int input_device_disconnect(struct btd_service *service);
diff --git a/profiles/input/manager.c b/profiles/input/manager.c
index dc771a6..689ccdd 100644
--- a/profiles/input/manager.c
+++ b/profiles/input/manager.c
@@ -43,7 +43,6 @@

#include "device.h"
#include "server.h"
-#include "manager.h"

static int hid_server_probe(struct btd_profile *p, struct btd_adapter *adapter)
{
@@ -72,16 +71,6 @@ static struct btd_profile input_profile = {
.adapter_remove = hid_server_remove,
};

-void input_manager_device_connected(struct btd_device *dev, int err)
-{
- device_profile_connected(dev, &input_profile, err);
-}
-
-void input_manager_device_disconnected(struct btd_device *dev, int err)
-{
- device_profile_disconnected(dev, &input_profile, err);
-}
-
static GKeyFile *load_config_file(const char *file)
{
GKeyFile *keyfile;
diff --git a/profiles/input/manager.h b/profiles/input/manager.h
deleted file mode 100644
index 3a05094..0000000
--- a/profiles/input/manager.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2004-2010 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-void input_manager_device_connected(struct btd_device *dev, int err);
-void input_manager_device_disconnected(struct btd_device *dev, int err);
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index 1ecff4d..38c9eba 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -48,7 +48,6 @@

#include "error.h"
#include "common.h"
-#include "manager.h"
#include "connection.h"

#define NETWORK_PEER_INTERFACE "org.bluez.Network1"
@@ -146,7 +145,7 @@ static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
device_remove_disconnect_watch(nc->peer->device, nc->dc_id);
nc->dc_id = 0;

- network_disconnected(nc->peer->device, nc->id, 0);
+ btd_service_disconnecting_complete(nc->service, 0);

info("%s disconnected", nc->dev);

@@ -183,7 +182,7 @@ static void cancel_connection(struct network_conn *nc, int err)
nc->timeout_source = 0;
}

- network_connected(nc->peer->device, nc->id, err);
+ btd_service_connecting_complete(nc->service, err);
if (nc->connect)
local_connect_cb(nc, err);

@@ -291,7 +290,7 @@ static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,

bnep_if_up(nc->dev);

- network_connected(nc->peer->device, nc->id, 0);
+ btd_service_connecting_complete(nc->service, 0);
if (nc->connect)
local_connect_cb(nc, 0);

@@ -432,7 +431,7 @@ static DBusMessage *local_connect(DBusConnection *conn,
if (nc && nc->connect)
return btd_error_busy(msg);

- err = connection_connect(peer->device, id);
+ err = connection_connect(nc->service);
if (err < 0)
return btd_error_failed(msg, strerror(-err));

@@ -446,24 +445,17 @@ static DBusMessage *local_connect(DBusConnection *conn,
}

/* Connect and initiate BNEP session */
-int connection_connect(struct btd_device *device, uint16_t id)
+int connection_connect(struct btd_service *service)
{
- struct network_peer *peer;
- struct network_conn *nc;
+ struct network_conn *nc = btd_service_get_user_data(service);
+ struct network_peer *peer = nc->peer;
+ uint16_t id = get_service_id(service);
GError *err = NULL;
const bdaddr_t *src;
const bdaddr_t *dst;

DBG("id %u", id);

- peer = find_peer(peers, device);
- if (!peer)
- return -ENOENT;
-
- nc = find_connection(peer->connections, id);
- if (!nc)
- return -ENOTSUP;
-
if (nc->state != DISCONNECTED)
return -EALREADY;

@@ -487,18 +479,9 @@ int connection_connect(struct btd_device *device, uint16_t id)
return 0;
}

-int connection_disconnect(struct btd_device *device, uint16_t id)
+int connection_disconnect(struct btd_service *service)
{
- struct network_peer *peer;
- struct network_conn *nc;
-
- peer = find_peer(peers, device);
- if (!peer)
- return -ENOENT;
-
- nc = find_connection(peer->connections, id);
- if (!nc)
- return -ENOTSUP;
+ struct network_conn *nc = btd_service_get_user_data(service);

if (nc->state == DISCONNECTED)
return 0;
@@ -521,7 +504,7 @@ static DBusMessage *local_disconnect(DBusConnection *conn,
if (nc->state == DISCONNECTED)
continue;

- err = connection_disconnect(peer->device, nc->id);
+ err = connection_disconnect(nc->service);
if (err < 0)
return btd_error_failed(msg, strerror(-err));

diff --git a/profiles/network/connection.h b/profiles/network/connection.h
index 1e7eedb..4a8b43b 100644
--- a/profiles/network/connection.h
+++ b/profiles/network/connection.h
@@ -23,5 +23,5 @@

int connection_register(struct btd_service *service);
void connection_unregister(struct btd_service *service);
-int connection_connect(struct btd_device *device, uint16_t id);
-int connection_disconnect(struct btd_device *device, uint16_t id);
+int connection_connect(struct btd_service *service);
+int connection_disconnect(struct btd_service *service);
diff --git a/profiles/network/manager.c b/profiles/network/manager.c
index f37954a..03b1b3d 100644
--- a/profiles/network/manager.c
+++ b/profiles/network/manager.c
@@ -42,7 +42,6 @@
#include "device.h"
#include "profile.h"
#include "service.h"
-#include "manager.h"
#include "common.h"
#include "connection.h"
#include "server.h"
@@ -75,16 +74,6 @@ done:
conf_security ? "true" : "false");
}

-static int panu_connect(struct btd_device *dev, struct btd_profile *profile)
-{
- return connection_connect(dev, BNEP_SVC_PANU);
-}
-
-static int panu_disconnect(struct btd_device *dev, struct btd_profile *profile)
-{
- return connection_disconnect(dev, BNEP_SVC_PANU);
-}
-
static int panu_server_probe(struct btd_profile *p, struct btd_adapter *adapter)
{
const char *path = adapter_get_path(adapter);
@@ -104,16 +93,6 @@ static void panu_server_remove(struct btd_profile *p,
server_unregister(adapter, BNEP_SVC_PANU);
}

-static int gn_connect(struct btd_device *dev, struct btd_profile *profile)
-{
- return connection_connect(dev, BNEP_SVC_GN);
-}
-
-static int gn_disconnect(struct btd_device *dev, struct btd_profile *profile)
-{
- return connection_disconnect(dev, BNEP_SVC_GN);
-}
-
static int gn_server_probe(struct btd_profile *p, struct btd_adapter *adapter)
{
const char *path = adapter_get_path(adapter);
@@ -133,16 +112,6 @@ static void gn_server_remove(struct btd_profile *p,
server_unregister(adapter, BNEP_SVC_GN);
}

-static int nap_connect(struct btd_device *dev, struct btd_profile *profile)
-{
- return connection_connect(dev, BNEP_SVC_NAP);
-}
-
-static int nap_disconnect(struct btd_device *dev, struct btd_profile *profile)
-{
- return connection_disconnect(dev, BNEP_SVC_NAP);
-}
-
static int nap_server_probe(struct btd_profile *p, struct btd_adapter *adapter)
{
const char *path = adapter_get_path(adapter);
@@ -168,8 +137,8 @@ static struct btd_profile panu_profile = {
.remote_uuid = PANU_UUID,
.device_probe = connection_register,
.device_remove = connection_unregister,
- .connect = panu_connect,
- .disconnect = panu_disconnect,
+ .connect = connection_connect,
+ .disconnect = connection_disconnect,
.adapter_probe = panu_server_probe,
.adapter_remove = panu_server_remove,
};
@@ -180,8 +149,8 @@ static struct btd_profile gn_profile = {
.remote_uuid = GN_UUID,
.device_probe = connection_register,
.device_remove = connection_unregister,
- .connect = gn_connect,
- .disconnect = gn_disconnect,
+ .connect = connection_connect,
+ .disconnect = connection_disconnect,
.adapter_probe = gn_server_probe,
.adapter_remove = gn_server_remove,
};
@@ -192,48 +161,12 @@ static struct btd_profile nap_profile = {
.remote_uuid = NAP_UUID,
.device_probe = connection_register,
.device_remove = connection_unregister,
- .connect = nap_connect,
- .disconnect = nap_disconnect,
+ .connect = connection_connect,
+ .disconnect = connection_disconnect,
.adapter_probe = nap_server_probe,
.adapter_remove = nap_server_remove,
};

-void network_connected(struct btd_device *dev, int id, int err)
-{
- switch (id) {
- case BNEP_SVC_PANU:
- device_profile_connected(dev, &panu_profile, err);
- break;
- case BNEP_SVC_GN:
- device_profile_connected(dev, &gn_profile, err);
- break;
- case BNEP_SVC_NAP:
- device_profile_connected(dev, &nap_profile, err);
- break;
- default:
- error("Invalid id %d passed to network_connected", id);
- break;
- }
-}
-
-void network_disconnected(struct btd_device *dev, int id, int err)
-{
- switch (id) {
- case BNEP_SVC_PANU:
- device_profile_disconnected(dev, &panu_profile, err);
- break;
- case BNEP_SVC_GN:
- device_profile_disconnected(dev, &gn_profile, err);
- break;
- case BNEP_SVC_NAP:
- device_profile_disconnected(dev, &gn_profile, err);
- break;
- default:
- error("Invalid id %d passed to network_disconnected", id);
- break;
- }
-}
-
static int network_init(void)
{
read_config(CONFIGDIR "/network.conf");
diff --git a/profiles/network/manager.h b/profiles/network/manager.h
deleted file mode 100644
index 8a8c065..0000000
--- a/profiles/network/manager.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2004-2010 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-void network_connected(struct btd_device *dev, int id, int err);
-void network_disconnected(struct btd_device *dev, int id, int err);
diff --git a/src/device.c b/src/device.c
index 22fbfcb..f3b3c9a 100644
--- a/src/device.c
+++ b/src/device.c
@@ -73,6 +73,7 @@
#define DISCOVERY_TIMER 1

static DBusConnection *dbus_conn = NULL;
+guint service_state_cb_id;

struct btd_disconnect_data {
guint id;
@@ -1003,7 +1004,6 @@ static void dev_disconn_service(gpointer a, gpointer b)
{
struct btd_service *service = a;
struct btd_profile *profile = btd_service_get_profile(service);
- struct btd_device *dev = btd_service_get_device(service);
btd_service_state_t state = btd_service_get_state(service);
int err;

@@ -1016,7 +1016,7 @@ static void dev_disconn_service(gpointer a, gpointer b)

btd_service_disconnecting(service);

- err = profile->disconnect(dev, profile);
+ err = profile->disconnect(service);
if (err != 0)
btd_service_disconnecting_complete(service, err);
}
@@ -1110,7 +1110,7 @@ static int connect_next(struct btd_device *dev)

btd_service_connecting(service);

- err = profile->connect(dev, profile);
+ err = profile->connect(service);
if (err == 0)
return 0;

@@ -1125,7 +1125,7 @@ static int connect_next(struct btd_device *dev)
return err;
}

-void device_profile_connected(struct btd_device *dev,
+static void device_profile_connected(struct btd_device *dev,
struct btd_profile *profile, int err)
{
struct btd_service *pending;
@@ -1141,10 +1141,6 @@ void device_profile_connected(struct btd_device *dev,
if (l != NULL)
dev->pending = g_slist_delete_link(dev->pending, l);

- l = g_slist_find_custom(dev->services, profile, service_profile_cmp);
- if (l != NULL)
- btd_service_connecting_complete(l->data, err);
-
/* Only continue connecting the next profile if it matches the first
* pending, otherwise it will trigger another connect to the same
* profile
@@ -1347,15 +1343,9 @@ static DBusMessage *connect_profile(DBusConnection *conn, DBusMessage *msg,
return reply;
}

-void device_profile_disconnected(struct btd_device *dev,
+static void device_profile_disconnected(struct btd_device *dev,
struct btd_profile *profile, int err)
{
- GSList *l;
-
- l = g_slist_find_custom(dev->services, profile, service_profile_cmp);
- if (l != NULL)
- btd_service_disconnecting_complete(l->data, err);
-
if (!dev->disconnect)
return;

@@ -1402,7 +1392,7 @@ static DBusMessage *disconnect_profile(DBusConnection *conn, DBusMessage *msg,

btd_service_disconnecting(service);

- err = p->disconnect(dev, p);
+ err = p->disconnect(service);
if (err < 0) {
btd_service_disconnecting_complete(service, err);
return btd_error_failed(msg, strerror(-err));
@@ -4356,11 +4346,29 @@ void btd_device_set_pnpid(struct btd_device *device, uint16_t source,
store_device_info(device);
}

+static void service_state_changed(struct btd_service *service,
+ btd_service_state_t old_state,
+ btd_service_state_t new_state,
+ void *user_data)
+{
+ struct btd_profile *profile = btd_service_get_profile(service);
+ struct btd_device *device = btd_service_get_device(service);
+ int err = btd_service_get_error(service);
+
+ if (old_state == BTD_SERVICE_STATE_CONNECTING)
+ device_profile_connected(device, profile, err);
+ else if (old_state == BTD_SERVICE_STATE_DISCONNECTING)
+ device_profile_disconnected(device, profile, err);
+}
+
void btd_device_init(void)
{
dbus_conn = btd_get_dbus_connection();
+ service_state_cb_id = btd_service_add_state_cb(
+ service_state_changed, NULL);
}

void btd_device_cleanup(void)
{
+ btd_service_remove_state_cb(service_state_cb_id);
}
diff --git a/src/device.h b/src/device.h
index d072015..df6cbd8 100644
--- a/src/device.h
+++ b/src/device.h
@@ -122,10 +122,5 @@ bool device_remove_svc_complete_callback(struct btd_device *dev,

struct btd_profile;

-void device_profile_connected(struct btd_device *dev,
- struct btd_profile *profile, int err);
-void device_profile_disconnected(struct btd_device *dev,
- struct btd_profile *profile, int err);
-
void btd_device_init(void);
void btd_device_cleanup(void);
diff --git a/src/profile.c b/src/profile.c
index d0aa332..2175a20 100644
--- a/src/profile.c
+++ b/src/profile.c
@@ -553,6 +553,7 @@ struct ext_io {
guint io_id;
struct btd_adapter *adapter;
struct btd_device *device;
+ struct btd_service *service;

bool resolving;
bool connected;
@@ -684,6 +685,9 @@ static void ext_io_destroy(gpointer p)
if (ext_io->device)
btd_device_unref(ext_io->device);

+ if (ext_io->service)
+ btd_service_unref(ext_io->service);
+
g_free(ext_io);
}

@@ -708,7 +712,7 @@ static gboolean ext_io_disconnected(GIOChannel *io, GIOCondition cond,

DBG("%s disconnected from %s", ext->name, addr);
drop:
- device_profile_disconnected(conn->device, &ext->p, 0);
+ btd_service_disconnecting_complete(conn->service, 0);
ext->conns = g_slist_remove(ext->conns, conn);
ext_io_destroy(conn);
return FALSE;
@@ -730,7 +734,7 @@ static void new_conn_reply(DBusPendingCall *call, void *user_data)
conn->pending = NULL;

if (!dbus_error_is_set(&err)) {
- device_profile_connected(conn->device, &ext->p, 0);
+ btd_service_connecting_complete(conn->service, 0);
conn->connected = true;
return;
}
@@ -738,7 +742,7 @@ static void new_conn_reply(DBusPendingCall *call, void *user_data)
error("%s replied with an error: %s, %s", ext->name,
err.name, err.message);

- device_profile_connected(conn->device, &ext->p, -ECONNREFUSED);
+ btd_service_connecting_complete(conn->service, -ECONNREFUSED);

if (dbus_error_has_name(&err, DBUS_ERROR_NO_REPLY))
ext_cancel(ext);
@@ -765,14 +769,14 @@ static void disconn_reply(DBusPendingCall *call, void *user_data)
conn->pending = NULL;

if (!dbus_error_is_set(&err)) {
- device_profile_disconnected(conn->device, &ext->p, 0);
+ btd_service_disconnecting_complete(conn->service, 0);
goto disconnect;
}

error("%s replied with an error: %s, %s", ext->name,
err.name, err.message);

- device_profile_disconnected(conn->device, &ext->p, -ECONNREFUSED);
+ btd_service_disconnecting_complete(conn->service, -ECONNREFUSED);

if (dbus_error_has_name(&err, DBUS_ERROR_NO_REPLY))
ext_cancel(ext);
@@ -948,8 +952,7 @@ static void ext_connect(GIOChannel *io, GError *err, gpointer user_data)
return;

drop:
- device_profile_connected(conn->device, &ext->p,
- err ? -err->code : -EIO);
+ btd_service_connecting_complete(conn->service, err ? -err->code : -EIO);
if (io_err)
g_error_free(io_err);
ext->conns = g_slist_remove(ext->conns, conn);
@@ -1531,7 +1534,7 @@ static void record_cb(sdp_list_t *recs, int err, gpointer user_data)
return;

failed:
- device_profile_connected(conn->device, &ext->p, err);
+ btd_service_connecting_complete(conn->service, err);
ext->conns = g_slist_remove(ext->conns, conn);
ext_io_destroy(conn);
}
@@ -1553,8 +1556,10 @@ static int resolve_service(struct ext_io *conn, const bdaddr_t *src,
return err;
}

-static int ext_connect_dev(struct btd_device *dev, struct btd_profile *profile)
+static int ext_connect_dev(struct btd_service *service)
{
+ struct btd_device *dev = btd_service_get_device(service);
+ struct btd_profile *profile = btd_service_get_profile(service);
struct btd_adapter *adapter;
struct ext_io *conn;
struct ext_profile *ext;
@@ -1588,6 +1593,7 @@ static int ext_connect_dev(struct btd_device *dev, struct btd_profile *profile)

conn->adapter = btd_adapter_ref(adapter);
conn->device = btd_device_ref(dev);
+ conn->service = btd_service_ref(service);

ext->conns = g_slist_append(ext->conns, conn);

@@ -1630,9 +1636,10 @@ static int send_disconn_req(struct ext_profile *ext, struct ext_io *conn)
return 0;
}

-static int ext_disconnect_dev(struct btd_device *dev,
- struct btd_profile *profile)
+static int ext_disconnect_dev(struct btd_service *service)
{
+ struct btd_device *dev = btd_service_get_device(service);
+ struct btd_profile *profile = btd_service_get_profile(service);
struct ext_profile *ext;
struct ext_io *conn;
int err;
diff --git a/src/profile.h b/src/profile.h
index 8daa358..9aec27e 100644
--- a/src/profile.h
+++ b/src/profile.h
@@ -39,10 +39,8 @@ struct btd_profile {
int (*device_probe) (struct btd_service *service);
void (*device_remove) (struct btd_service *service);

- int (*connect) (struct btd_device *device,
- struct btd_profile *profile);
- int (*disconnect) (struct btd_device *device,
- struct btd_profile *profile);
+ int (*connect) (struct btd_service *service);
+ int (*disconnect) (struct btd_service *service);

int (*adapter_probe) (struct btd_profile *p,
struct btd_adapter *adapter);
--
1.8.1.4


2013-04-05 11:45:45

by Mikel Astiz

[permalink] [raw]
Subject: [RFC v2 08/11] network: Hold a reference to btd_service

From: Mikel Astiz <[email protected]>

Profile implementations are expected to hold a reference to probed
services, so update the network profiles accordingly.
---
profiles/network/connection.c | 38 ++++++++++++++++++++++++++--------
profiles/network/connection.h | 4 ++--
profiles/network/manager.c | 48 ++++++-------------------------------------
3 files changed, 37 insertions(+), 53 deletions(-)

diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index 3a913cf..1ecff4d 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -43,6 +43,8 @@
#include "dbus-common.h"
#include "adapter.h"
#include "device.h"
+#include "profile.h"
+#include "service.h"

#include "error.h"
#include "common.h"
@@ -65,6 +67,7 @@ struct network_peer {
};

struct network_conn {
+ struct btd_service *service;
char dev[16]; /* Interface name */
uint16_t id; /* Role: Service Class Identifier */
conn_state state;
@@ -83,6 +86,13 @@ struct __service_16 {

static GSList *peers = NULL;

+static uint16_t get_service_id(struct btd_service *service)
+{
+ struct btd_profile *p = btd_service_get_profile(service);
+
+ return bnep_service_id(p->remote_uuid);
+}
+
static struct network_peer *find_peer(GSList *list, struct btd_device *device)
{
for (; list; list = list->next) {
@@ -599,6 +609,7 @@ static void connection_free(void *data)
if (nc->connect)
dbus_message_unref(nc->connect);

+ btd_service_unref(nc->service);
g_free(nc);
}

@@ -639,13 +650,14 @@ static const GDBusPropertyTable connection_properties[] = {
{ }
};

-void connection_unregister(struct btd_device *device)
+void connection_unregister(struct btd_service *service)
{
- struct network_peer *peer;
+ struct btd_device *device = btd_service_get_device(service);
+ struct network_conn *conn = btd_service_get_user_data(service);
+ struct network_peer *peer = conn->peer;
+ uint16_t id = get_service_id(service);

- peer = find_peer(peers, device);
- if (!peer)
- return;
+ DBG("%s id %u", device_get_path(device), id);

g_slist_free_full(peer->connections, connection_free);
peer->connections = NULL;
@@ -682,12 +694,14 @@ static struct network_peer *create_peer(struct btd_device *device)
return peer;
}

-int connection_register(struct btd_device *device, uint16_t id)
+int connection_register(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
struct network_peer *peer;
struct network_conn *nc;
+ uint16_t id = get_service_id(service);

- DBG("id %u", id);
+ DBG("%s id %u", device_get_path(device), id);

peer = find_peer(peers, device);
if (!peer) {
@@ -698,16 +712,22 @@ int connection_register(struct btd_device *device, uint16_t id)
}

nc = find_connection(peer->connections, id);
- if (nc)
- return 0;
+ if (nc) {
+ error("Device %s has multiple connection instances of %d",
+ device_get_path(device), id);
+ return -1;
+ }

nc = g_new0(struct network_conn, 1);
nc->id = id;
memset(nc->dev, 0, sizeof(nc->dev));
strcpy(nc->dev, "bnep%d");
+ nc->service = btd_service_ref(service);
nc->state = DISCONNECTED;
nc->peer = peer;

+ btd_service_set_user_data(service, nc);
+
DBG("id %u registered", id);

peer->connections = g_slist_append(peer->connections, nc);
diff --git a/profiles/network/connection.h b/profiles/network/connection.h
index 32356f9..1e7eedb 100644
--- a/profiles/network/connection.h
+++ b/profiles/network/connection.h
@@ -21,7 +21,7 @@
*
*/

-int connection_register(struct btd_device *device, uint16_t id);
-void connection_unregister(struct btd_device *device);
+int connection_register(struct btd_service *service);
+void connection_unregister(struct btd_service *service);
int connection_connect(struct btd_device *device, uint16_t id);
int connection_disconnect(struct btd_device *device, uint16_t id);
diff --git a/profiles/network/manager.c b/profiles/network/manager.c
index d860cc0..f37954a 100644
--- a/profiles/network/manager.c
+++ b/profiles/network/manager.c
@@ -75,24 +75,6 @@ done:
conf_security ? "true" : "false");
}

-static int panu_probe(struct btd_service *service)
-{
- struct btd_device *device = btd_service_get_device(service);
-
- DBG("path %s", device_get_path(device));
-
- return connection_register(device, BNEP_SVC_PANU);
-}
-
-static void network_remove(struct btd_service *service)
-{
- struct btd_device *device = btd_service_get_device(service);
-
- DBG("path %s", device_get_path(device));
-
- connection_unregister(device);
-}
-
static int panu_connect(struct btd_device *dev, struct btd_profile *profile)
{
return connection_connect(dev, BNEP_SVC_PANU);
@@ -122,15 +104,6 @@ static void panu_server_remove(struct btd_profile *p,
server_unregister(adapter, BNEP_SVC_PANU);
}

-static int gn_probe(struct btd_service *service)
-{
- struct btd_device *device = btd_service_get_device(service);
-
- DBG("path %s", device_get_path(device));
-
- return connection_register(device, BNEP_SVC_GN);
-}
-
static int gn_connect(struct btd_device *dev, struct btd_profile *profile)
{
return connection_connect(dev, BNEP_SVC_GN);
@@ -160,15 +133,6 @@ static void gn_server_remove(struct btd_profile *p,
server_unregister(adapter, BNEP_SVC_GN);
}

-static int nap_probe(struct btd_service *service)
-{
- struct btd_device *device = btd_service_get_device(service);
-
- DBG("path %s", device_get_path(device));
-
- return connection_register(device, BNEP_SVC_NAP);
-}
-
static int nap_connect(struct btd_device *dev, struct btd_profile *profile)
{
return connection_connect(dev, BNEP_SVC_NAP);
@@ -202,8 +166,8 @@ static struct btd_profile panu_profile = {
.name = "network-panu",
.local_uuid = NAP_UUID,
.remote_uuid = PANU_UUID,
- .device_probe = panu_probe,
- .device_remove = network_remove,
+ .device_probe = connection_register,
+ .device_remove = connection_unregister,
.connect = panu_connect,
.disconnect = panu_disconnect,
.adapter_probe = panu_server_probe,
@@ -214,8 +178,8 @@ static struct btd_profile gn_profile = {
.name = "network-gn",
.local_uuid = PANU_UUID,
.remote_uuid = GN_UUID,
- .device_probe = gn_probe,
- .device_remove = network_remove,
+ .device_probe = connection_register,
+ .device_remove = connection_unregister,
.connect = gn_connect,
.disconnect = gn_disconnect,
.adapter_probe = gn_server_probe,
@@ -226,8 +190,8 @@ static struct btd_profile nap_profile = {
.name = "network-nap",
.local_uuid = PANU_UUID,
.remote_uuid = NAP_UUID,
- .device_probe = nap_probe,
- .device_remove = network_remove,
+ .device_probe = connection_register,
+ .device_remove = connection_unregister,
.connect = nap_connect,
.disconnect = nap_disconnect,
.adapter_probe = nap_server_probe,
--
1.8.1.4


2013-04-05 11:45:46

by Mikel Astiz

[permalink] [raw]
Subject: [RFC v2 09/11] input: Hold a reference to btd_service

From: Mikel Astiz <[email protected]>

Profile implementations are expected to hold a reference to probed
services, so update the input profiles accordingly.
---
profiles/input/device.c | 74 +++++++++++++++++++++++++-----------------------
profiles/input/device.h | 8 +++---
profiles/input/manager.c | 41 ++++-----------------------
3 files changed, 48 insertions(+), 75 deletions(-)

diff --git a/profiles/input/device.c b/profiles/input/device.c
index 1da9d99..2115111 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
@@ -44,6 +44,7 @@
#include "../src/adapter.h"
#include "../src/device.h"
#include "../src/profile.h"
+#include "../src/service.h"
#include "../src/storage.h"
#include "../src/dbus-common.h"

@@ -55,9 +56,9 @@
#include "sdp-client.h"

struct input_device {
+ struct btd_service *service;
struct btd_device *device;
char *path;
- char *uuid;
bdaddr_t src;
bdaddr_t dst;
uint32_t handle;
@@ -66,7 +67,6 @@ struct input_device {
guint ctrl_watch;
guint intr_watch;
guint sec_watch;
- int timeout;
struct hidp_connadd_req *req;
guint dc_id;
gboolean disable_sdp;
@@ -74,6 +74,12 @@ struct input_device {
};

static GSList *devices = NULL;
+static int idle_timeout = 0;
+
+void input_set_idle_timeout(int timeout)
+{
+ idle_timeout = timeout;
+}

static struct input_device *find_device_by_path(GSList *list, const char *path)
{
@@ -92,6 +98,7 @@ static void input_device_free(struct input_device *idev)
if (idev->dc_id)
device_remove_disconnect_watch(idev->device, idev->dc_id);

+ btd_service_unref(idev->service);
btd_device_unref(idev->device);
g_free(idev->name);
g_free(idev->path);
@@ -111,8 +118,6 @@ static void input_device_free(struct input_device *idev)
if (idev->ctrl_io)
g_io_channel_unref(idev->ctrl_io);

- g_free(idev->uuid);
-
g_free(idev);
}

@@ -366,7 +371,7 @@ static int hidp_add_connection(struct input_device *idev)
req->ctrl_sock = g_io_channel_unix_get_fd(idev->ctrl_io);
req->intr_sock = g_io_channel_unix_get_fd(idev->intr_io);
req->flags = 0;
- req->idle_to = idev->timeout;
+ req->idle_to = idle_timeout;

ba2str(&idev->src, src_addr);
ba2str(&idev->dst, dst_addr);
@@ -674,10 +679,21 @@ int input_device_disconnect(struct btd_device *dev, struct btd_profile *profile)
return 0;
}

-static struct input_device *input_device_new(struct btd_device *device,
- const char *path, const uint32_t handle,
- gboolean disable_sdp)
+static gboolean is_device_sdp_disable(const sdp_record_t *rec)
{
+ sdp_data_t *data;
+
+ data = sdp_data_get(rec, SDP_ATTR_HID_SDP_DISABLE);
+
+ return data && data->val.uint8;
+}
+
+static struct input_device *input_device_new(struct btd_service *service)
+{
+ struct btd_device *device = btd_service_get_device(service);
+ const char *path = device_get_path(device);
+ struct btd_profile *p = btd_service_get_profile(service);
+ const sdp_record_t *rec = btd_device_get_record(device, p->remote_uuid);
struct btd_adapter *adapter = device_get_adapter(device);
struct input_device *idev;
char name[HCI_MAX_NAME_LENGTH + 1];
@@ -685,10 +701,11 @@ static struct input_device *input_device_new(struct btd_device *device,
idev = g_new0(struct input_device, 1);
bacpy(&idev->src, adapter_get_address(adapter));
bacpy(&idev->dst, device_get_address(device));
+ idev->service = btd_service_ref(service);
idev->device = btd_device_ref(device);
idev->path = g_strdup(path);
- idev->handle = handle;
- idev->disable_sdp = disable_sdp;
+ idev->handle = rec->handle;
+ idev->disable_sdp = is_device_sdp_disable(rec);

device_get_name(device, name, HCI_MAX_NAME_LENGTH);
if (strlen(name) > 0)
@@ -697,19 +714,10 @@ static struct input_device *input_device_new(struct btd_device *device,
return idev;
}

-static gboolean is_device_sdp_disable(const sdp_record_t *rec)
-{
- sdp_data_t *data;
-
- data = sdp_data_get(rec, SDP_ATTR_HID_SDP_DISABLE);
-
- return data && data->val.uint8;
-}
-
-int input_device_register(struct btd_device *device,
- const char *path, const char *uuid,
- const sdp_record_t *rec, int timeout)
+int input_device_register(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
+ const char *path = device_get_path(device);
struct input_device *idev;

DBG("%s", path);
@@ -718,13 +726,11 @@ int input_device_register(struct btd_device *device,
if (idev)
return -EEXIST;

- idev = input_device_new(device, path, rec->handle,
- is_device_sdp_disable(rec));
+ idev = input_device_new(service);
if (!idev)
return -EINVAL;

- idev->timeout = timeout;
- idev->uuid = g_strdup(uuid);
+ btd_service_set_user_data(service, idev);

devices = g_slist_append(devices, idev);

@@ -746,25 +752,21 @@ static struct input_device *find_device(const bdaddr_t *src,
return NULL;
}

-int input_device_unregister(const char *path, const char *uuid)
+void input_device_unregister(struct btd_service *service)
{
- struct input_device *idev;
+ struct btd_device *device = btd_service_get_device(service);
+ const char *path = device_get_path(device);
+ struct input_device *idev = btd_service_get_user_data(service);

DBG("%s", path);

- idev = find_device_by_path(devices, path);
- if (idev == NULL)
- return -EINVAL;
-
if (idev->ctrl_io) {
- /* Pending connection running */
- return -EBUSY;
+ /* FIXME: pending connection running */
+ return;
}

devices = g_slist_remove(devices, idev);
input_device_free(idev);
-
- return 0;
}

static int input_device_connadd(struct input_device *idev)
diff --git a/profiles/input/device.h b/profiles/input/device.h
index aabc79c..fd7f847 100644
--- a/profiles/input/device.h
+++ b/profiles/input/device.h
@@ -27,10 +27,10 @@
struct input_device;
struct input_conn;

-int input_device_register(struct btd_device *device, const char *path,
- const char *uuid, const sdp_record_t *rec,
- int timeout);
-int input_device_unregister(const char *path, const char *uuid);
+void input_set_idle_timeout(int timeout);
+
+int input_device_register(struct btd_service *service);
+void input_device_unregister(struct btd_service *service);

int input_device_set_channel(const bdaddr_t *src, const bdaddr_t *dst, int psm,
GIOChannel *io);
diff --git a/profiles/input/manager.c b/profiles/input/manager.c
index 72a4e3b..dc771a6 100644
--- a/profiles/input/manager.c
+++ b/profiles/input/manager.c
@@ -45,39 +45,6 @@
#include "server.h"
#include "manager.h"

-static int idle_timeout = 0;
-
-static void input_remove(struct btd_device *device, const char *uuid)
-{
- const char *path = device_get_path(device);
-
- DBG("path %s", path);
-
- input_device_unregister(path, uuid);
-}
-
-static int hid_device_probe(struct btd_service *service)
-{
- struct btd_device *device = btd_service_get_device(service);
- const char *path = device_get_path(device);
- const sdp_record_t *rec = btd_device_get_record(device, HID_UUID);
-
- DBG("path %s", path);
-
- if (!rec)
- return -1;
-
- return input_device_register(device, path, HID_UUID, rec,
- idle_timeout * 60);
-}
-
-static void hid_device_remove(struct btd_service *service)
-{
- struct btd_device *device = btd_service_get_device(service);
-
- input_remove(device, HID_UUID);
-}
-
static int hid_server_probe(struct btd_profile *p, struct btd_adapter *adapter)
{
return server_start(adapter_get_address(adapter));
@@ -98,8 +65,8 @@ static struct btd_profile input_profile = {
.connect = input_device_connect,
.disconnect = input_device_disconnect,

- .device_probe = hid_device_probe,
- .device_remove = hid_device_remove,
+ .device_probe = input_device_register,
+ .device_remove = input_device_unregister,

.adapter_probe = hid_server_probe,
.adapter_remove = hid_server_remove,
@@ -140,12 +107,16 @@ static int input_init(void)

config = load_config_file(CONFIGDIR "/input.conf");
if (config) {
+ int idle_timeout;
+
idle_timeout = g_key_file_get_integer(config, "General",
"IdleTimeout", &err);
if (err) {
DBG("input.conf: %s", err->message);
g_error_free(err);
}
+
+ input_set_idle_timeout(idle_timeout * 60);
}

btd_profile_register(&input_profile);
--
1.8.1.4


2013-04-05 11:45:47

by Mikel Astiz

[permalink] [raw]
Subject: [RFC v2 10/11] service: Add callbacks to track state changes

From: Mikel Astiz <[email protected]>

Extend the btd_service API to support state observers.
---
src/service.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
src/service.h | 8 ++++++++
2 files changed, 56 insertions(+)

diff --git a/src/service.c b/src/service.c
index abbee08..6bce59f 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;
+ guint id;
+};
+
+static GSList *state_callbacks;
+
static const char *state2str(btd_service_state_t state)
{
switch (state) {
@@ -108,6 +116,7 @@ static void service_set_state(struct btd_service *service,
btd_service_state_t state)
{
btd_service_state_t old = service->state;
+ GSList *l;

if (state == old)
return;
@@ -116,6 +125,45 @@ static void service_set_state(struct btd_service *service,

DBG("State changed %p: %s -> %s", service, state2str(old),
state2str(state));
+
+ 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);
+ }
+}
+
+guint btd_service_add_state_cb(btd_service_state_cb cb, void *user_data)
+{
+ struct service_state_callback *state_cb;
+ static guint 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;
+}
+
+gboolean btd_service_remove_state_cb(guint 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_link(state_callbacks,
+ l);
+ g_free(cb);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
}

struct btd_service *service_create(struct btd_device *device,
diff --git a/src/service.h b/src/service.h
index 596898b..63537d7 100644
--- a/src/service.h
+++ b/src/service.h
@@ -31,6 +31,11 @@ typedef enum {

struct btd_service;

+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 *service_create(struct btd_device *device,
struct btd_profile *profile);

@@ -41,6 +46,9 @@ struct btd_device *btd_service_get_device(const struct btd_service *service);
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);

+guint btd_service_add_state_cb(btd_service_state_cb cb, void *user_data);
+gboolean btd_service_remove_state_cb(guint id);
+
void btd_service_set_user_data(struct btd_service *service, void *user_data);
void *btd_service_get_user_data(const struct btd_service *service);
int btd_service_get_error(const struct btd_service *service);
--
1.8.1.4


2013-04-05 11:45:43

by Mikel Astiz

[permalink] [raw]
Subject: [RFC v2 06/11] profile: Use btd_service for probing profiles

From: Mikel Astiz <[email protected]>

Change the profile probe mechanism in order to pass the btd_service
instance representing the remote service. This object is bound to a
btd_profile and a btd_device, thus replacing the previous parameters.

The probe callback is allowed to hold a reference to the btd_service
by means of btd_service_ref(), which should be unreferenced during
removal. In addition, the probe callback is allowed to set the
user_data pointer associated to the btd_service by using
service_set_user_data().

Keeping such a reference of the btd_service allows supporting multiple
instances of the same UUID, since the reference can serve as a handle
during the interactions between the profile implementation and the core.
---
profiles/audio/control.c | 8 ++++----
profiles/audio/control.h | 4 ++--
profiles/audio/manager.c | 21 ++++++++++++---------
profiles/cyclingspeed/cyclingspeed.c | 9 +++++----
profiles/deviceinfo/deviceinfo.c | 11 ++++++-----
profiles/gatt/gas.c | 10 ++++++----
profiles/health/hdp_manager.c | 10 +++++++---
profiles/heartrate/heartrate.c | 10 ++++++----
profiles/input/hog.c | 8 +++++---
profiles/input/manager.c | 11 +++++++----
profiles/network/manager.c | 20 +++++++++++++-------
profiles/proximity/manager.c | 28 ++++++++++++++++------------
profiles/proximity/reporter.c | 8 +++++---
profiles/proximity/reporter.h | 5 ++---
profiles/sap/manager.c | 1 +
profiles/scanparam/scan.c | 9 ++++++---
profiles/thermometer/thermometer.c | 11 ++++++-----
src/device.c | 11 +++--------
src/profile.c | 11 +++++++----
src/profile.h | 8 ++++----
20 files changed, 123 insertions(+), 91 deletions(-)

diff --git a/profiles/audio/control.c b/profiles/audio/control.c
index 6086bde..fd5ff92 100644
--- a/profiles/audio/control.c
+++ b/profiles/audio/control.c
@@ -253,13 +253,13 @@ void control_unregister(struct audio_device *dev)
AUDIO_CONTROL_INTERFACE);
}

-void control_update(struct control *control, GSList *uuids)
+void control_update(struct control *control, const char *uuid)
{
- if (g_slist_find_custom(uuids, AVRCP_TARGET_UUID, bt_uuid_strcmp))
+ if (bt_uuid_strcmp(uuid, AVRCP_TARGET_UUID) == 0)
control->target = TRUE;
}

-struct control *control_init(struct audio_device *dev, GSList *uuids)
+struct control *control_init(struct audio_device *dev, const char *uuid)
{
struct control *control;

@@ -276,7 +276,7 @@ struct control *control_init(struct audio_device *dev, GSList *uuids)

control = g_new0(struct control, 1);

- control_update(control, uuids);
+ control_update(control, uuid);

control->avctp_id = avctp_add_state_cb(dev, state_changed);

diff --git a/profiles/audio/control.h b/profiles/audio/control.h
index de0259e..82ad0d2 100644
--- a/profiles/audio/control.h
+++ b/profiles/audio/control.h
@@ -24,8 +24,8 @@

#define AUDIO_CONTROL_INTERFACE "org.bluez.MediaControl1"

-struct control *control_init(struct audio_device *dev, GSList *uuids);
-void control_update(struct control *control, GSList *uuids);
+struct control *control_init(struct audio_device *dev, const char *uuid);
+void control_update(struct control *control, const char *uuid);
void control_unregister(struct audio_device *dev);
gboolean control_is_active(struct audio_device *dev);

diff --git a/profiles/audio/manager.c b/profiles/audio/manager.c
index 4517815..ff4590e 100644
--- a/profiles/audio/manager.c
+++ b/profiles/audio/manager.c
@@ -53,6 +53,7 @@
#include "../src/adapter.h"
#include "../src/device.h"
#include "../src/profile.h"
+#include "../src/service.h"

#include "log.h"
#include "device.h"
@@ -89,8 +90,9 @@ static struct audio_device *manager_find_device(struct btd_device *device)
return NULL;
}

-static void audio_remove(struct btd_profile *p, struct btd_device *device)
+static void audio_remove(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
struct audio_device *dev;

dev = manager_find_device(device);
@@ -101,9 +103,9 @@ static void audio_remove(struct btd_profile *p, struct btd_device *device)
audio_device_unregister(dev);
}

-static int a2dp_source_probe(struct btd_profile *p, struct btd_device *device,
- GSList *uuids)
+static int a2dp_source_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
struct audio_device *audio_dev;

audio_dev = get_audio_dev(device);
@@ -117,9 +119,9 @@ static int a2dp_source_probe(struct btd_profile *p, struct btd_device *device,
return 0;
}

-static int a2dp_sink_probe(struct btd_profile *p, struct btd_device *device,
- GSList *uuids)
+static int a2dp_sink_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
struct audio_device *audio_dev;

audio_dev = get_audio_dev(device);
@@ -133,9 +135,10 @@ static int a2dp_sink_probe(struct btd_profile *p, struct btd_device *device,
return 0;
}

-static int avrcp_probe(struct btd_profile *p, struct btd_device *device,
- GSList *uuids)
+static int avrcp_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
+ struct btd_profile *p = btd_service_get_profile(service);
struct audio_device *audio_dev;

audio_dev = get_audio_dev(device);
@@ -145,9 +148,9 @@ static int avrcp_probe(struct btd_profile *p, struct btd_device *device,
}

if (audio_dev->control)
- control_update(audio_dev->control, uuids);
+ control_update(audio_dev->control, p->remote_uuid);
else
- audio_dev->control = control_init(audio_dev, uuids);
+ audio_dev->control = control_init(audio_dev, p->remote_uuid);

if (audio_dev->sink && sink_is_active(audio_dev))
avrcp_connect(audio_dev);
diff --git a/profiles/cyclingspeed/cyclingspeed.c b/profiles/cyclingspeed/cyclingspeed.c
index 125007e..6080f09 100644
--- a/profiles/cyclingspeed/cyclingspeed.c
+++ b/profiles/cyclingspeed/cyclingspeed.c
@@ -34,6 +34,7 @@
#include "adapter.h"
#include "device.h"
#include "profile.h"
+#include "service.h"
#include "dbus-common.h"
#include "error.h"
#include "attrib/gattrib.h"
@@ -1180,9 +1181,9 @@ static const GDBusMethodTable cyclingspeed_device_methods[] = {
{ }
};

-static int csc_device_probe(struct btd_profile *p,
- struct btd_device *device, GSList *uuids)
+static int csc_device_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
struct btd_adapter *adapter;
struct csc_adapter *cadapter;
struct csc *csc;
@@ -1227,9 +1228,9 @@ static int csc_device_probe(struct btd_profile *p,
return 0;
}

-static void csc_device_remove(struct btd_profile *p,
- struct btd_device *device)
+static void csc_device_remove(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
struct btd_adapter *adapter;
struct csc_adapter *cadapter;
struct csc *csc;
diff --git a/profiles/deviceinfo/deviceinfo.c b/profiles/deviceinfo/deviceinfo.c
index 471241b..fc8babd 100644
--- a/profiles/deviceinfo/deviceinfo.c
+++ b/profiles/deviceinfo/deviceinfo.c
@@ -34,6 +34,7 @@
#include "adapter.h"
#include "device.h"
#include "profile.h"
+#include "service.h"
#include "attrib/gattrib.h"
#include "attio.h"
#include "attrib/att.h"
@@ -198,10 +199,9 @@ static void deviceinfo_unregister(struct btd_device *device)
deviceinfo_free(d);
}

-static int deviceinfo_driver_probe(struct btd_profile *p,
- struct btd_device *device,
- GSList *uuids)
+static int deviceinfo_driver_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
struct gatt_primary *prim;

prim = btd_device_get_primary(device, DEVICE_INFORMATION_UUID);
@@ -211,9 +211,10 @@ static int deviceinfo_driver_probe(struct btd_profile *p,
return deviceinfo_register(device, prim);
}

-static void deviceinfo_driver_remove(struct btd_profile *p,
- struct btd_device *device)
+static void deviceinfo_driver_remove(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
+
deviceinfo_unregister(device);
}

diff --git a/profiles/gatt/gas.c b/profiles/gatt/gas.c
index bc8dbb5..33a680f 100644
--- a/profiles/gatt/gas.c
+++ b/profiles/gatt/gas.c
@@ -39,6 +39,7 @@
#include "adapter.h"
#include "device.h"
#include "profile.h"
+#include "service.h"
#include "attrib/att.h"
#include "attrib/gattrib.h"
#include "attio.h"
@@ -407,9 +408,9 @@ static void gas_unregister(struct btd_device *device)
gas_free(gas);
}

-static int gatt_driver_probe(struct btd_profile *p, struct btd_device *device,
- GSList *uuids)
+static int gatt_driver_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
struct gatt_primary *gap, *gatt;

gap = btd_device_get_primary(device, GAP_UUID);
@@ -423,9 +424,10 @@ static int gatt_driver_probe(struct btd_profile *p, struct btd_device *device,
return gas_register(device, &gap->range, &gatt->range);
}

-static void gatt_driver_remove(struct btd_profile *p,
- struct btd_device *device)
+static void gatt_driver_remove(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
+
gas_unregister(device);
}

diff --git a/profiles/health/hdp_manager.c b/profiles/health/hdp_manager.c
index 5428724..1bb6007 100644
--- a/profiles/health/hdp_manager.c
+++ b/profiles/health/hdp_manager.c
@@ -34,6 +34,7 @@
#include <adapter.h>
#include <device.h>
#include <profile.h>
+#include <service.h>
#include <glib-helper.h>
#include <log.h>

@@ -54,14 +55,17 @@ static void hdp_adapter_remove(struct btd_profile *p,
hdp_adapter_unregister(adapter);
}

-static int hdp_driver_probe(struct btd_profile *p, struct btd_device *device,
- GSList *uuids)
+static int hdp_driver_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
+
return hdp_device_register(device);
}

-static void hdp_driver_remove(struct btd_profile *p, struct btd_device *device)
+static void hdp_driver_remove(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
+
hdp_device_unregister(device);
}

diff --git a/profiles/heartrate/heartrate.c b/profiles/heartrate/heartrate.c
index 0520f5c..3a2d419 100644
--- a/profiles/heartrate/heartrate.c
+++ b/profiles/heartrate/heartrate.c
@@ -35,6 +35,7 @@
#include "dbus-common.h"
#include "device.h"
#include "profile.h"
+#include "service.h"
#include "error.h"
#include "attrib/gattrib.h"
#include "attrib/att.h"
@@ -841,9 +842,9 @@ static void heartrate_adapter_remove(struct btd_profile *p,
heartrate_adapter_unregister(adapter);
}

-static int heartrate_device_probe(struct btd_profile *p,
- struct btd_device *device, GSList *uuids)
+static int heartrate_device_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
struct gatt_primary *prim;

prim = btd_device_get_primary(device, HEART_RATE_UUID);
@@ -853,9 +854,10 @@ static int heartrate_device_probe(struct btd_profile *p,
return heartrate_device_register(device, prim);
}

-static void heartrate_device_remove(struct btd_profile *p,
- struct btd_device *device)
+static void heartrate_device_remove(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
+
heartrate_device_unregister(device);
}

diff --git a/profiles/input/hog.c b/profiles/input/hog.c
index eadc860..c092875 100644
--- a/profiles/input/hog.c
+++ b/profiles/input/hog.c
@@ -46,6 +46,7 @@
#include "src/adapter.h"
#include "src/device.h"
#include "src/profile.h"
+#include "src/service.h"

#include "plugin.h"
#include "suspend.h"
@@ -820,9 +821,9 @@ static void resume_callback(void)
g_slist_foreach(devices, set_suspend, GINT_TO_POINTER(suspend));
}

-static int hog_probe(struct btd_profile *p, struct btd_device *device,
- GSList *uuids)
+static int hog_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
const char *path = device_get_path(device);
GSList *primaries, *l;

@@ -861,8 +862,9 @@ static void remove_device(gpointer a, gpointer b)
hog_unregister_device(hogdev);
}

-static void hog_remove(struct btd_profile *p, struct btd_device *device)
+static void hog_remove(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
const char *path = device_get_path(device);

DBG("path %s", path);
diff --git a/profiles/input/manager.c b/profiles/input/manager.c
index d30ba67..72a4e3b 100644
--- a/profiles/input/manager.c
+++ b/profiles/input/manager.c
@@ -39,6 +39,7 @@
#include "../src/adapter.h"
#include "../src/device.h"
#include "../src/profile.h"
+#include "../src/service.h"

#include "device.h"
#include "server.h"
@@ -55,11 +56,11 @@ static void input_remove(struct btd_device *device, const char *uuid)
input_device_unregister(path, uuid);
}

-static int hid_device_probe(struct btd_profile *p, struct btd_device *device,
- GSList *uuids)
+static int hid_device_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
const char *path = device_get_path(device);
- const sdp_record_t *rec = btd_device_get_record(device, uuids->data);
+ const sdp_record_t *rec = btd_device_get_record(device, HID_UUID);

DBG("path %s", path);

@@ -70,8 +71,10 @@ static int hid_device_probe(struct btd_profile *p, struct btd_device *device,
idle_timeout * 60);
}

-static void hid_device_remove(struct btd_profile *p, struct btd_device *device)
+static void hid_device_remove(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
+
input_remove(device, HID_UUID);
}

diff --git a/profiles/network/manager.c b/profiles/network/manager.c
index 53bb652..d860cc0 100644
--- a/profiles/network/manager.c
+++ b/profiles/network/manager.c
@@ -41,6 +41,7 @@
#include "adapter.h"
#include "device.h"
#include "profile.h"
+#include "service.h"
#include "manager.h"
#include "common.h"
#include "connection.h"
@@ -74,16 +75,19 @@ done:
conf_security ? "true" : "false");
}

-static int panu_probe(struct btd_profile *p, struct btd_device *device,
- GSList *uuids)
+static int panu_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
+
DBG("path %s", device_get_path(device));

return connection_register(device, BNEP_SVC_PANU);
}

-static void network_remove(struct btd_profile *p, struct btd_device *device)
+static void network_remove(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
+
DBG("path %s", device_get_path(device));

connection_unregister(device);
@@ -118,9 +122,10 @@ static void panu_server_remove(struct btd_profile *p,
server_unregister(adapter, BNEP_SVC_PANU);
}

-static int gn_probe(struct btd_profile *p, struct btd_device *device,
- GSList *uuids)
+static int gn_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
+
DBG("path %s", device_get_path(device));

return connection_register(device, BNEP_SVC_GN);
@@ -155,9 +160,10 @@ static void gn_server_remove(struct btd_profile *p,
server_unregister(adapter, BNEP_SVC_GN);
}

-static int nap_probe(struct btd_profile *p, struct btd_device *device,
- GSList *uuids)
+static int nap_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
+
DBG("path %s", device_get_path(device));

return connection_register(device, BNEP_SVC_NAP);
diff --git a/profiles/proximity/manager.c b/profiles/proximity/manager.c
index 81bfc3b..7dab23f 100644
--- a/profiles/proximity/manager.c
+++ b/profiles/proximity/manager.c
@@ -35,6 +35,7 @@
#include "adapter.h"
#include "device.h"
#include "profile.h"
+#include "service.h"
#include "attrib/att.h"
#include "attrib/gattrib.h"
#include "attrib/gatt.h"
@@ -48,9 +49,9 @@ static struct enabled enabled = {
.findme = TRUE,
};

-static int monitor_linkloss_probe(struct btd_profile *p,
- struct btd_device *device, GSList *uuids)
+static int monitor_linkloss_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
struct gatt_primary *linkloss;

linkloss = btd_device_get_primary(device, LINK_LOSS_UUID);
@@ -60,9 +61,9 @@ static int monitor_linkloss_probe(struct btd_profile *p,
return monitor_register_linkloss(device, &enabled, linkloss);
}

-static int monitor_immediate_probe(struct btd_profile *p,
- struct btd_device *device, GSList *uuids)
+static int monitor_immediate_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
struct gatt_primary *immediate;

immediate = btd_device_get_primary(device, IMMEDIATE_ALERT_UUID);
@@ -72,9 +73,9 @@ static int monitor_immediate_probe(struct btd_profile *p,
return monitor_register_immediate(device, &enabled, immediate);
}

-static int monitor_txpower_probe(struct btd_profile *p,
- struct btd_device *device, GSList *uuids)
+static int monitor_txpower_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
struct gatt_primary *txpower;

txpower = btd_device_get_primary(device, TX_POWER_UUID);
@@ -84,21 +85,24 @@ static int monitor_txpower_probe(struct btd_profile *p,
return monitor_register_txpower(device, &enabled, txpower);
}

-static void monitor_linkloss_remove(struct btd_profile *p,
- struct btd_device *device)
+static void monitor_linkloss_remove(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
+
monitor_unregister_linkloss(device);
}

-static void monitor_immediate_remove(struct btd_profile *p,
- struct btd_device *device)
+static void monitor_immediate_remove(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
+
monitor_unregister_immediate(device);
}

-static void monitor_txpower_remove(struct btd_profile *p,
- struct btd_device *device)
+static void monitor_txpower_remove(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
+
monitor_unregister_txpower(device);
}

diff --git a/profiles/proximity/reporter.c b/profiles/proximity/reporter.c
index 31c33ef..dbb593a 100644
--- a/profiles/proximity/reporter.c
+++ b/profiles/proximity/reporter.c
@@ -42,6 +42,7 @@
#include "error.h"
#include "device.h"
#include "profile.h"
+#include "service.h"
#include "hcid.h"
#include "attrib/gattrib.h"
#include "attrib/att.h"
@@ -203,9 +204,9 @@ static void register_reporter_device(struct btd_device *device,
radapter->devices = g_slist_prepend(radapter->devices, device);
}

-int reporter_device_probe(struct btd_profile *p, struct btd_device *device,
- GSList *uuids)
+int reporter_device_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
struct reporter_adapter *radapter;
struct btd_adapter *adapter = device_get_adapter(device);

@@ -218,8 +219,9 @@ int reporter_device_probe(struct btd_profile *p, struct btd_device *device,
return 0;
}

-void reporter_device_remove(struct btd_profile *p, struct btd_device *device)
+void reporter_device_remove(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
struct reporter_adapter *radapter;
struct btd_adapter *adapter = device_get_adapter(device);

diff --git a/profiles/proximity/reporter.h b/profiles/proximity/reporter.h
index 6a7066d..a8e1aac 100644
--- a/profiles/proximity/reporter.h
+++ b/profiles/proximity/reporter.h
@@ -36,9 +36,8 @@ enum {
HIGH_ALERT = 0x02,
};

-void reporter_device_remove(struct btd_profile *p, struct btd_device *device);
-int reporter_device_probe(struct btd_profile *p, struct btd_device *device,
- GSList *uuids);
+void reporter_device_remove(struct btd_service *service);
+int reporter_device_probe(struct btd_service *service);

int reporter_adapter_probe(struct btd_profile *p, struct btd_adapter *adapter);
void reporter_adapter_remove(struct btd_profile *p,
diff --git a/profiles/sap/manager.c b/profiles/sap/manager.c
index fddd7aa..24b73e7 100644
--- a/profiles/sap/manager.c
+++ b/profiles/sap/manager.c
@@ -28,6 +28,7 @@
#include "adapter.h"
#include "device.h"
#include "profile.h"
+#include "service.h"

#include "manager.h"
#include "server.h"
diff --git a/profiles/scanparam/scan.c b/profiles/scanparam/scan.c
index abbd129..dbbb4ea 100644
--- a/profiles/scanparam/scan.c
+++ b/profiles/scanparam/scan.c
@@ -37,6 +37,7 @@
#include "adapter.h"
#include "device.h"
#include "profile.h"
+#include "service.h"
#include "attrib/att.h"
#include "attrib/gattrib.h"
#include "attrib/gatt.h"
@@ -266,9 +267,9 @@ static void scan_unregister(struct btd_device *device)
g_free(scan);
}

-static int scan_param_probe(struct btd_profile *p, struct btd_device *device,
- GSList *uuids)
+static int scan_param_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
struct gatt_primary *prim;

DBG("Probing Scan Parameters");
@@ -280,8 +281,10 @@ static int scan_param_probe(struct btd_profile *p, struct btd_device *device,
return scan_register(device, prim);
}

-static void scan_param_remove(struct btd_profile *p, struct btd_device *device)
+static void scan_param_remove(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
+
scan_unregister(device);
}

diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index 8550500..3757b25 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -35,6 +35,7 @@
#include "adapter.h"
#include "device.h"
#include "profile.h"
+#include "service.h"
#include "error.h"
#include "log.h"
#include "attrib/gattrib.h"
@@ -1280,10 +1281,9 @@ static void thermometer_adapter_unregister(struct btd_adapter *adapter)
THERMOMETER_MANAGER_INTERFACE);
}

-static int thermometer_device_probe(struct btd_profile *p,
- struct btd_device *device,
- GSList *uuids)
+static int thermometer_device_probe(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
struct gatt_primary *tattr;

tattr = btd_device_get_primary(device, HEALTH_THERMOMETER_UUID);
@@ -1293,9 +1293,10 @@ static int thermometer_device_probe(struct btd_profile *p,
return thermometer_register(device, tattr);
}

-static void thermometer_device_remove(struct btd_profile *p,
- struct btd_device *device)
+static void thermometer_device_remove(struct btd_service *service)
{
+ struct btd_device *device = btd_service_get_device(service);
+
thermometer_unregister(device);
}

diff --git a/src/device.c b/src/device.c
index dd2b7af..22fbfcb 100644
--- a/src/device.c
+++ b/src/device.c
@@ -905,7 +905,7 @@ static void service_remove(struct btd_service *service)
struct btd_device *device = btd_service_get_device(service);

btd_service_unavailable(service);
- profile->device_remove(profile, device);
+ profile->device_remove(service);
device->pending = g_slist_remove(device->pending, service);
btd_service_unref(service);
}
@@ -2392,7 +2392,6 @@ struct probe_data {
static void dev_probe(struct btd_profile *p, void *user_data)
{
struct probe_data *d = user_data;
- GSList *probe_uuids;
struct btd_service *service;
int err;

@@ -2402,21 +2401,17 @@ static void dev_probe(struct btd_profile *p, void *user_data)
if (!device_match_profile(d->dev, p, d->uuids))
return;

- probe_uuids = g_slist_append(NULL, (char *) p->remote_uuid);
-
service = service_create(d->dev, p);

- err = p->device_probe(p, d->dev, probe_uuids);
+ err = p->device_probe(service);
if (err < 0) {
error("%s profile probe failed for %s", p->name, d->addr);
btd_service_unref(service);
- g_slist_free(probe_uuids);
return;
}

btd_service_probed(service);
d->dev->services = g_slist_append(d->dev->services, service);
- g_slist_free(probe_uuids);
}

void device_probe_profile(gpointer a, gpointer b)
@@ -2440,7 +2435,7 @@ void device_probe_profile(gpointer a, gpointer b)

service = service_create(device, profile);

- err = profile->device_probe(profile, device, probe_uuids);
+ err = profile->device_probe(service);
if (err < 0) {
error("%s profile probe failed for %s", profile->name, addr);
btd_service_unref(service);
diff --git a/src/profile.c b/src/profile.c
index 29f9ee6..d0aa332 100644
--- a/src/profile.c
+++ b/src/profile.c
@@ -50,6 +50,7 @@
#include "adapter.h"
#include "device.h"
#include "profile.h"
+#include "service.h"

#define DUN_DEFAULT_CHANNEL 1
#define SPP_DEFAULT_CHANNEL 3
@@ -1359,16 +1360,16 @@ static void ext_adapter_remove(struct btd_profile *p,
}
}

-static int ext_device_probe(struct btd_profile *p, struct btd_device *dev,
- GSList *uuids)
+static int ext_device_probe(struct btd_service *service)
{
+ struct btd_profile *p = btd_service_get_profile(service);
struct ext_profile *ext;

ext = find_ext(p);
if (!ext)
return -ENOENT;

- DBG("%s probed with %u UUIDs", ext->name, g_slist_length(uuids));
+ DBG("%s probed with UUID %s", ext->name, p->remote_uuid);

return 0;
}
@@ -1388,8 +1389,10 @@ static struct ext_io *find_connection(struct ext_profile *ext,
return NULL;
}

-static void ext_device_remove(struct btd_profile *p, struct btd_device *dev)
+static void ext_device_remove(struct btd_service *service)
{
+ struct btd_profile *p = btd_service_get_profile(service);
+ struct btd_device *dev = btd_service_get_device(service);
struct ext_profile *ext;
struct ext_io *conn;

diff --git a/src/profile.h b/src/profile.h
index 5d78b37..8daa358 100644
--- a/src/profile.h
+++ b/src/profile.h
@@ -25,6 +25,8 @@
#define BTD_PROFILE_PRIORITY_MEDIUM 1
#define BTD_PROFILE_PRIORITY_HIGH 2

+struct btd_service;
+
struct btd_profile {
const char *name;
int priority;
@@ -34,10 +36,8 @@ struct btd_profile {

bool auto_connect;

- int (*device_probe) (struct btd_profile *p, struct btd_device *device,
- GSList *uuids);
- void (*device_remove) (struct btd_profile *p,
- struct btd_device *device);
+ int (*device_probe) (struct btd_service *service);
+ void (*device_remove) (struct btd_service *service);

int (*connect) (struct btd_device *device,
struct btd_profile *profile);
--
1.8.1.4


2013-04-05 11:45:44

by Mikel Astiz

[permalink] [raw]
Subject: [RFC v2 07/11] audio: Hold a reference to btd_service

From: Mikel Astiz <[email protected]>

Profile implementations are expected to hold a reference to probed
services, so update the audio profiles accordingly.
---
profiles/audio/control.c | 28 ++++++++++++++++++++++------
profiles/audio/control.h | 7 +++++--
profiles/audio/manager.c | 9 ++++-----
profiles/audio/sink.c | 6 +++++-
profiles/audio/sink.h | 4 +++-
profiles/audio/source.c | 7 ++++++-
profiles/audio/source.h | 5 ++++-
7 files changed, 49 insertions(+), 17 deletions(-)

diff --git a/profiles/audio/control.c b/profiles/audio/control.c
index fd5ff92..10cd1de 100644
--- a/profiles/audio/control.c
+++ b/profiles/audio/control.c
@@ -48,6 +48,8 @@
#include "lib/uuid.h"
#include "../src/adapter.h"
#include "../src/device.h"
+#include "../src/profile.h"
+#include "../src/service.h"

#include "log.h"
#include "error.h"
@@ -61,7 +63,8 @@

struct control {
struct avctp *session;
- gboolean target;
+ struct btd_service *target;
+ struct btd_service *remote;
unsigned int avctp_id;
};

@@ -242,6 +245,12 @@ static void path_unregister(void *data)

avctp_remove_state_cb(control->avctp_id);

+ if (control->target)
+ btd_service_unref(control->target);
+
+ if (control->remote)
+ btd_service_unref(control->remote);
+
g_free(control);
dev->control = NULL;
}
@@ -253,13 +262,20 @@ void control_unregister(struct audio_device *dev)
AUDIO_CONTROL_INTERFACE);
}

-void control_update(struct control *control, const char *uuid)
+void control_update(struct control *control, struct btd_service *service)
{
- if (bt_uuid_strcmp(uuid, AVRCP_TARGET_UUID) == 0)
- control->target = TRUE;
+ struct btd_profile *p = btd_service_get_profile(service);
+ const char *uuid = p->remote_uuid;
+
+ if (!control->target && bt_uuid_strcmp(uuid, AVRCP_TARGET_UUID) == 0)
+ control->target = btd_service_ref(service);
+ else if (!control->remote &&
+ bt_uuid_strcmp(uuid, AVRCP_REMOTE_UUID) == 0)
+ control->remote = btd_service_ref(service);
}

-struct control *control_init(struct audio_device *dev, const char *uuid)
+struct control *control_init(struct audio_device *dev,
+ struct btd_service *service)
{
struct control *control;

@@ -276,7 +292,7 @@ struct control *control_init(struct audio_device *dev, const char *uuid)

control = g_new0(struct control, 1);

- control_update(control, uuid);
+ control_update(control, service);

control->avctp_id = avctp_add_state_cb(dev, state_changed);

diff --git a/profiles/audio/control.h b/profiles/audio/control.h
index 82ad0d2..0176b54 100644
--- a/profiles/audio/control.h
+++ b/profiles/audio/control.h
@@ -24,8 +24,11 @@

#define AUDIO_CONTROL_INTERFACE "org.bluez.MediaControl1"

-struct control *control_init(struct audio_device *dev, const char *uuid);
-void control_update(struct control *control, const char *uuid);
+struct btd_service;
+
+struct control *control_init(struct audio_device *dev,
+ struct btd_service *service);
+void control_update(struct control *control, struct btd_service *service);
void control_unregister(struct audio_device *dev);
gboolean control_is_active(struct audio_device *dev);

diff --git a/profiles/audio/manager.c b/profiles/audio/manager.c
index ff4590e..e886e12 100644
--- a/profiles/audio/manager.c
+++ b/profiles/audio/manager.c
@@ -114,7 +114,7 @@ static int a2dp_source_probe(struct btd_service *service)
return -1;
}

- audio_dev->source = source_init(audio_dev);
+ audio_dev->source = source_init(audio_dev, service);

return 0;
}
@@ -130,7 +130,7 @@ static int a2dp_sink_probe(struct btd_service *service)
return -1;
}

- audio_dev->sink = sink_init(audio_dev);
+ audio_dev->sink = sink_init(audio_dev, service);

return 0;
}
@@ -138,7 +138,6 @@ static int a2dp_sink_probe(struct btd_service *service)
static int avrcp_probe(struct btd_service *service)
{
struct btd_device *device = btd_service_get_device(service);
- struct btd_profile *p = btd_service_get_profile(service);
struct audio_device *audio_dev;

audio_dev = get_audio_dev(device);
@@ -148,9 +147,9 @@ static int avrcp_probe(struct btd_service *service)
}

if (audio_dev->control)
- control_update(audio_dev->control, p->remote_uuid);
+ control_update(audio_dev->control, service);
else
- audio_dev->control = control_init(audio_dev, p->remote_uuid);
+ audio_dev->control = control_init(audio_dev, service);

if (audio_dev->sink && sink_is_active(audio_dev))
avrcp_connect(audio_dev);
diff --git a/profiles/audio/sink.c b/profiles/audio/sink.c
index f023307..9f1a2d9 100644
--- a/profiles/audio/sink.c
+++ b/profiles/audio/sink.c
@@ -41,6 +41,7 @@

#include "../src/adapter.h"
#include "../src/device.h"
+#include "../src/service.h"

#include "device.h"
#include "avdtp.h"
@@ -55,6 +56,7 @@

struct sink {
struct audio_device *dev;
+ struct btd_service *service;
struct avdtp *session;
struct avdtp_stream *stream;
unsigned int cb_id;
@@ -361,6 +363,7 @@ static void sink_free(struct audio_device *dev)
g_source_remove(sink->retry_id);

avdtp_remove_state_cb(sink->avdtp_callback_id);
+ btd_service_unref(sink->service);

g_free(sink);
dev->sink = NULL;
@@ -372,7 +375,7 @@ void sink_unregister(struct audio_device *dev)
sink_free(dev);
}

-struct sink *sink_init(struct audio_device *dev)
+struct sink *sink_init(struct audio_device *dev, struct btd_service *service)
{
struct sink *sink;

@@ -381,6 +384,7 @@ struct sink *sink_init(struct audio_device *dev)
sink = g_new0(struct sink, 1);

sink->dev = dev;
+ sink->service = btd_service_ref(service);

sink->avdtp_callback_id = avdtp_add_state_cb(dev, avdtp_state_callback);

diff --git a/profiles/audio/sink.h b/profiles/audio/sink.h
index ba0dde8..1f20545 100644
--- a/profiles/audio/sink.h
+++ b/profiles/audio/sink.h
@@ -36,11 +36,13 @@ typedef void (*sink_state_cb) (struct audio_device *dev,
sink_state_t new_state,
void *user_data);

+struct btd_service;
+
unsigned int sink_add_state_cb(struct audio_device *dev, sink_state_cb cb,
void *user_data);
gboolean sink_remove_state_cb(unsigned int id);

-struct sink *sink_init(struct audio_device *dev);
+struct sink *sink_init(struct audio_device *dev, struct btd_service *service);
void sink_unregister(struct audio_device *dev);
gboolean sink_is_active(struct audio_device *dev);
int sink_connect(struct audio_device *dev);
diff --git a/profiles/audio/source.c b/profiles/audio/source.c
index 5d9e237..20fd412 100644
--- a/profiles/audio/source.c
+++ b/profiles/audio/source.c
@@ -42,6 +42,7 @@

#include "../src/adapter.h"
#include "../src/device.h"
+#include "../src/service.h"

#include "device.h"
#include "avdtp.h"
@@ -56,6 +57,7 @@

struct source {
struct audio_device *dev;
+ struct btd_service *service;
struct avdtp *session;
struct avdtp_stream *stream;
unsigned int cb_id;
@@ -365,6 +367,7 @@ static void source_free(struct audio_device *dev)
g_source_remove(source->retry_id);

avdtp_remove_state_cb(source->avdtp_callback_id);
+ btd_service_unref(source->service);

g_free(source);
dev->source = NULL;
@@ -377,7 +380,8 @@ void source_unregister(struct audio_device *dev)
source_free(dev);
}

-struct source *source_init(struct audio_device *dev)
+struct source *source_init(struct audio_device *dev,
+ struct btd_service *service)
{
struct source *source;

@@ -386,6 +390,7 @@ struct source *source_init(struct audio_device *dev)
source = g_new0(struct source, 1);

source->dev = dev;
+ source->service = btd_service_ref(service);

source->avdtp_callback_id = avdtp_add_state_cb(dev,
avdtp_state_callback);
diff --git a/profiles/audio/source.h b/profiles/audio/source.h
index 61afd94..0156423 100644
--- a/profiles/audio/source.h
+++ b/profiles/audio/source.h
@@ -37,11 +37,14 @@ typedef void (*source_state_cb) (struct audio_device *dev,
source_state_t new_state,
void *user_data);

+struct btd_service;
+
unsigned int source_add_state_cb(struct audio_device *dev, source_state_cb cb,
void *user_data);
gboolean source_remove_state_cb(unsigned int id);

-struct source *source_init(struct audio_device *dev);
+struct source *source_init(struct audio_device *dev,
+ struct btd_service *service);
void source_unregister(struct audio_device *dev);
int source_connect(struct audio_device *dev);
gboolean source_new_stream(struct audio_device *dev, struct avdtp *session,
--
1.8.1.4


2013-04-05 11:45:42

by Mikel Astiz

[permalink] [raw]
Subject: [RFC v2 05/11] device: Replace pending profile list with services

From: Mikel Astiz <[email protected]>

Use btd_service pointers to represent the list of services pending for
connection.

This list doesn't reference count the btd_service instances, since the
pending services should be a subset of the available services, and thus
they should already be referenced by device->services. This means
special care must be taken to make sure any removed service is also
removed from the pending list, as addressed in service_remove().
---
src/device.c | 50 +++++++++++++++++++++++++++++++-------------------
1 file changed, 31 insertions(+), 19 deletions(-)

diff --git a/src/device.c b/src/device.c
index c24c82b..dd2b7af 100644
--- a/src/device.c
+++ b/src/device.c
@@ -169,7 +169,7 @@ struct btd_device {
GSList *uuids;
GSList *primaries; /* List of primary services */
GSList *services; /* List of btd_service */
- GSList *pending; /* Pending profiles */
+ GSList *pending; /* Pending services */
GSList *watches; /* List of disconnect_data */
gboolean temporary;
guint disconn_timer;
@@ -906,6 +906,7 @@ static void service_remove(struct btd_service *service)

btd_service_unavailable(service);
profile->device_remove(profile, device);
+ device->pending = g_slist_remove(device->pending, service);
btd_service_unref(service);
}

@@ -1090,28 +1091,35 @@ static DBusMessage *disconnect(DBusConnection *conn, DBusMessage *msg,

static int connect_next(struct btd_device *dev)
{
+ struct btd_service *service;
struct btd_profile *profile;
int err = -ENOENT;

while (dev->pending) {
int err;
- GSList *l;

- profile = dev->pending->data;
+ service = dev->pending->data;
+ profile = btd_service_get_profile(service);
+
+ if (btd_service_get_state(service) !=
+ BTD_SERVICE_STATE_DISCONNECTED) {
+ dev->pending = g_slist_delete_link(dev->pending,
+ dev->pending);
+ continue;
+ }

- l = g_slist_find_custom(dev->services, profile,
- service_profile_cmp);
- btd_service_connecting(l->data);
+ btd_service_connecting(service);

err = profile->connect(dev, profile);
if (err == 0)
return 0;

- btd_service_connecting_complete(l->data, err);
+ btd_service_connecting_complete(service, err);

error("Failed to connect %s: %s", profile->name,
strerror(-err));
- dev->pending = g_slist_remove(dev->pending, profile);
+
+ dev->pending = g_slist_delete_link(dev->pending, dev->pending);
}

return err;
@@ -1120,7 +1128,7 @@ static int connect_next(struct btd_device *dev)
void device_profile_connected(struct btd_device *dev,
struct btd_profile *profile, int err)
{
- struct btd_profile *pending;
+ struct btd_service *pending;
GSList *l;

DBG("%s %s (%d)", profile->name, strerror(-err), -err);
@@ -1129,7 +1137,9 @@ void device_profile_connected(struct btd_device *dev,
return;

pending = dev->pending->data;
- dev->pending = g_slist_remove(dev->pending, profile);
+ l = g_slist_find_custom(dev->pending, profile, service_profile_cmp);
+ if (l != NULL)
+ dev->pending = g_slist_delete_link(dev->pending, l);

l = g_slist_find_custom(dev->services, profile, service_profile_cmp);
if (l != NULL)
@@ -1139,7 +1149,7 @@ void device_profile_connected(struct btd_device *dev,
* pending, otherwise it will trigger another connect to the same
* profile
*/
- if (profile != pending)
+ if (profile != btd_service_get_profile(pending))
return;

if (connect_next(dev) == 0)
@@ -1217,9 +1227,12 @@ static struct btd_service *find_connectable_service(struct btd_device *dev,
return NULL;
}

-static gint profile_prio_cmp(gconstpointer a, gconstpointer b)
+static gint service_prio_cmp(gconstpointer a, gconstpointer b)
{
- const struct btd_profile *p1 = a, *p2 = b;
+ const struct btd_service *s1 = a;
+ const struct btd_service *s2 = b;
+ struct btd_profile *p1 = btd_service_get_profile(s1);
+ struct btd_profile *p2 = btd_service_get_profile(s2);

return p2->priority - p1->priority;
}
@@ -1252,8 +1265,7 @@ static DBusMessage *connect_profiles(struct btd_device *dev, DBusMessage *msg,
if (!service)
return btd_error_invalid_args(msg);

- p = btd_service_get_profile(service);
- dev->pending = g_slist_prepend(dev->pending, p);
+ dev->pending = g_slist_prepend(dev->pending, service);

goto start_connect;
}
@@ -1265,15 +1277,15 @@ static DBusMessage *connect_profiles(struct btd_device *dev, DBusMessage *msg,
if (!p->auto_connect)
continue;

- if (g_slist_find(dev->pending, p))
+ if (g_slist_find(dev->pending, service))
continue;

if (btd_service_get_state(service) !=
BTD_SERVICE_STATE_DISCONNECTED)
continue;

- dev->pending = g_slist_insert_sorted(dev->pending, p,
- profile_prio_cmp);
+ dev->pending = g_slist_insert_sorted(dev->pending, service,
+ service_prio_cmp);
}

if (!dev->pending)
@@ -2443,7 +2455,7 @@ void device_probe_profile(gpointer a, gpointer b)
if (!profile->auto_connect || !device->general_connect)
return;

- device->pending = g_slist_append(device->pending, profile);
+ device->pending = g_slist_append(device->pending, service);

if (g_slist_length(device->pending) == 1)
connect_next(device);
--
1.8.1.4


2013-04-05 11:45:41

by Mikel Astiz

[permalink] [raw]
Subject: [RFC v2 04/11] device: Find services instead of profiles

From: Mikel Astiz <[email protected]>

Trivially replace the former find_connectable_profile() with
find_connectable_service().
---
src/device.c | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/src/device.c b/src/device.c
index 0d73ce2..c24c82b 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1198,7 +1198,7 @@ static int device_resolve_svc(struct btd_device *dev, DBusMessage *msg)
return device_browse_primary(dev, msg, FALSE);
}

-static struct btd_profile *find_connectable_profile(struct btd_device *dev,
+static struct btd_service *find_connectable_service(struct btd_device *dev,
const char *uuid)
{
GSList *l;
@@ -1211,7 +1211,7 @@ static struct btd_profile *find_connectable_profile(struct btd_device *dev,
continue;

if (strcasecmp(uuid, p->remote_uuid) == 0)
- return p;
+ return service;
}

return NULL;
@@ -1248,10 +1248,11 @@ static DBusMessage *connect_profiles(struct btd_device *dev, DBusMessage *msg,
}

if (uuid) {
- p = find_connectable_profile(dev, uuid);
- if (!p)
+ service = find_connectable_service(dev, uuid);
+ if (!service)
return btd_error_invalid_args(msg);

+ p = btd_service_get_profile(service);
dev->pending = g_slist_prepend(dev->pending, p);

goto start_connect;
@@ -1367,7 +1368,6 @@ static DBusMessage *disconnect_profile(DBusConnection *conn, DBusMessage *msg,
const char *pattern;
char *uuid;
int err;
- GSList *l;

if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
DBUS_TYPE_INVALID))
@@ -1377,14 +1377,13 @@ static DBusMessage *disconnect_profile(DBusConnection *conn, DBusMessage *msg,
if (uuid == NULL)
return btd_error_invalid_args(msg);

- p = find_connectable_profile(dev, uuid);
+ service = find_connectable_service(dev, uuid);
g_free(uuid);

- if (!p)
+ if (!service)
return btd_error_invalid_args(msg);

- l = g_slist_find_custom(dev->services, p, service_profile_cmp);
- service = l->data;
+ p = btd_service_get_profile(service);

if (!p->disconnect)
return btd_error_not_supported(msg);
--
1.8.1.4


2013-04-05 11:45:39

by Mikel Astiz

[permalink] [raw]
Subject: [RFC v2 02/11] device: Use btd_service to represent profiles

From: Mikel Astiz <[email protected]>

Maintain a list of btd_service pointers instead of btd_profile pointers,
for services that have been probed for this device.

This list will reference count the btd_service instances.
---
src/device.c | 76 ++++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 53 insertions(+), 23 deletions(-)

diff --git a/src/device.c b/src/device.c
index ee17514..fd65cb6 100644
--- a/src/device.c
+++ b/src/device.c
@@ -56,6 +56,7 @@
#include "attio.h"
#include "device.h"
#include "profile.h"
+#include "service.h"
#include "dbus-common.h"
#include "error.h"
#include "glib-helper.h"
@@ -167,7 +168,7 @@ struct btd_device {
struct btd_adapter *adapter;
GSList *uuids;
GSList *primaries; /* List of primary services */
- GSList *profiles; /* Probed profiles */
+ GSList *services; /* List of btd_service */
GSList *pending; /* Pending profiles */
GSList *watches; /* List of disconnect_data */
gboolean temporary;
@@ -217,6 +218,17 @@ static int device_browse_primary(struct btd_device *device, DBusMessage *msg,
static int device_browse_sdp(struct btd_device *device, DBusMessage *msg,
gboolean reverse);

+static gint service_profile_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct btd_service *service = a;
+ const struct btd_profile *profile = b;
+
+ if (btd_service_get_profile(service) == profile)
+ return 0;
+ else
+ return 1;
+}
+
static gboolean store_device_info_cb(gpointer user_data)
{
struct btd_device *device = user_data;
@@ -873,12 +885,14 @@ static gboolean dev_property_get_adapter(const GDBusPropertyTable *property,
return TRUE;
}

-static void profile_remove(gpointer data, gpointer user_data)
+static void service_remove(struct btd_service *service)
{
- struct btd_profile *profile = data;
- struct btd_device *device = user_data;
+ struct btd_profile *profile = btd_service_get_profile(service);
+ struct btd_device *device = btd_service_get_device(service);

+ btd_service_unavailable(service);
profile->device_remove(profile, device);
+ btd_service_unref(service);
}

static gboolean do_disconnect(gpointer user_data)
@@ -903,9 +917,8 @@ int device_block(struct btd_device *device, gboolean update_only)
if (device->connected)
do_disconnect(device);

- g_slist_foreach(device->profiles, profile_remove, device);
- g_slist_free(device->profiles);
- device->profiles = NULL;
+ g_slist_free_full(device->services, (GDestroyNotify) service_remove);
+ device->services = NULL;

if (!update_only)
err = btd_adapter_block_address(device->adapter,
@@ -1159,8 +1172,9 @@ static struct btd_profile *find_connectable_profile(struct btd_device *dev,
{
GSList *l;

- for (l = dev->profiles; l != NULL; l = g_slist_next(l)) {
- struct btd_profile *p = l->data;
+ for (l = dev->services; l != NULL; l = g_slist_next(l)) {
+ struct btd_service *service = l->data;
+ struct btd_profile *p = btd_service_get_profile(service);

if (!p->connect || !p->remote_uuid)
continue;
@@ -1182,6 +1196,7 @@ static gint profile_prio_cmp(gconstpointer a, gconstpointer b)
static DBusMessage *connect_profiles(struct btd_device *dev, DBusMessage *msg,
const char *uuid)
{
+ struct btd_service *service;
struct btd_profile *p;
GSList *l;
int err;
@@ -1211,8 +1226,9 @@ static DBusMessage *connect_profiles(struct btd_device *dev, DBusMessage *msg,
goto start_connect;
}

- for (l = dev->profiles; l != NULL; l = g_slist_next(l)) {
- p = l->data;
+ for (l = dev->services; l != NULL; l = g_slist_next(l)) {
+ service = l->data;
+ p = btd_service_get_profile(service);

if (!p->auto_connect)
continue;
@@ -2248,9 +2264,8 @@ void device_remove(struct btd_device *device, gboolean remove_stored)
if (remove_stored)
device_remove_stored(device);

- g_slist_foreach(device->profiles, profile_remove, device);
- g_slist_free(device->profiles);
- device->profiles = NULL;
+ g_slist_free_full(device->services, (GDestroyNotify) service_remove);
+ device->services = NULL;

btd_device_unref(device);
}
@@ -2326,6 +2341,7 @@ static void dev_probe(struct btd_profile *p, void *user_data)
{
struct probe_data *d = user_data;
GSList *probe_uuids;
+ struct btd_service *service;
int err;

if (p->device_probe == NULL)
@@ -2336,14 +2352,18 @@ static void dev_probe(struct btd_profile *p, void *user_data)

probe_uuids = g_slist_append(NULL, (char *) p->remote_uuid);

+ service = service_create(d->dev, p);
+
err = p->device_probe(p, d->dev, probe_uuids);
if (err < 0) {
error("%s profile probe failed for %s", p->name, d->addr);
+ btd_service_unref(service);
g_slist_free(probe_uuids);
return;
}

- d->dev->profiles = g_slist_append(d->dev->profiles, p);
+ btd_service_probed(service);
+ d->dev->services = g_slist_append(d->dev->services, service);
g_slist_free(probe_uuids);
}

@@ -2351,6 +2371,7 @@ void device_probe_profile(gpointer a, gpointer b)
{
struct btd_device *device = a;
struct btd_profile *profile = b;
+ struct btd_service *service;
GSList *probe_uuids;
char addr[18];
int err;
@@ -2365,14 +2386,18 @@ void device_probe_profile(gpointer a, gpointer b)

ba2str(&device->bdaddr, addr);

+ service = service_create(device, profile);
+
err = profile->device_probe(profile, device, probe_uuids);
if (err < 0) {
error("%s profile probe failed for %s", profile->name, addr);
+ btd_service_unref(service);
g_slist_free(probe_uuids);
return;
}

- device->profiles = g_slist_append(device->profiles, profile);
+ btd_service_probed(service);
+ device->services = g_slist_append(device->services, service);
g_slist_free(probe_uuids);

if (!profile->auto_connect || !device->general_connect)
@@ -2388,15 +2413,19 @@ void device_remove_profile(gpointer a, gpointer b)
{
struct btd_device *device = a;
struct btd_profile *profile = b;
+ struct btd_service *service;
+ GSList *l;

- if (!g_slist_find(device->profiles, profile))
+ l = g_slist_find_custom(device->services, profile, service_profile_cmp);
+ if (l == NULL)
return;

device->connected_profiles = g_slist_remove(device->connected_profiles,
profile);
- device->profiles = g_slist_remove(device->profiles, profile);

- profile->device_remove(profile, device);
+ service = l->data;
+ device->services = g_slist_delete_link(device->services, l);
+ service_remove(service);
}

void device_probe_profiles(struct btd_device *device, GSList *uuids)
@@ -2445,15 +2474,16 @@ static void device_remove_profiles(struct btd_device *device, GSList *uuids)
device->uuids = NULL;
store_device_info(device);

- for (l = device->profiles; l != NULL; l = next) {
- struct btd_profile *profile = l->data;
+ for (l = device->services; l != NULL; l = next) {
+ struct btd_service *service = l->data;
+ struct btd_profile *profile = btd_service_get_profile(service);

next = l->next;
if (device_match_profile(device, profile, device->uuids))
continue;

- profile->device_remove(profile, device);
- device->profiles = g_slist_remove(device->profiles, profile);
+ device->services = g_slist_delete_link(device->services, l);
+ service_remove(service);
}
}

--
1.8.1.4


2013-04-05 11:45:40

by Mikel Astiz

[permalink] [raw]
Subject: [RFC v2 03/11] device: Replace connected_profiles with btd_service

From: Mikel Astiz <[email protected]>

The service state can provide enough information not to maintain such
a connected_profiles list. Therefore, avoid duplicated information and
remove the list.
---
src/device.c | 88 +++++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 63 insertions(+), 25 deletions(-)

diff --git a/src/device.c b/src/device.c
index fd65cb6..0d73ce2 100644
--- a/src/device.c
+++ b/src/device.c
@@ -186,7 +186,6 @@ struct btd_device {
guint attachid; /* Attrib server attach */

gboolean connected;
- GSList *connected_profiles;

sdp_list_t *tmp_records;

@@ -229,6 +228,21 @@ static gint service_profile_cmp(gconstpointer a, gconstpointer b)
return 1;
}

+static GSList *find_service_with_state(GSList *list,
+ btd_service_state_t state)
+{
+ GSList *l;
+
+ for (l = list; l != NULL; l = g_slist_next(l)) {
+ struct btd_service *service = l->data;
+
+ if (btd_service_get_state(service) == state)
+ return l;
+ }
+
+ return NULL;
+}
+
static gboolean store_device_info_cb(gpointer user_data)
{
struct btd_device *device = user_data;
@@ -984,15 +998,26 @@ static void bonding_request_cancel(struct bonding_req *bonding)
adapter_cancel_bonding(adapter, &device->bdaddr, device->bdaddr_type);
}

-static void dev_disconn_profile(gpointer a, gpointer b)
+static void dev_disconn_service(gpointer a, gpointer b)
{
- struct btd_profile *profile = a;
- struct btd_device *dev = b;
+ struct btd_service *service = a;
+ struct btd_profile *profile = btd_service_get_profile(service);
+ struct btd_device *dev = btd_service_get_device(service);
+ btd_service_state_t state = btd_service_get_state(service);
+ int err;

if (!profile->disconnect)
return;

- profile->disconnect(dev, profile);
+ if (state != BTD_SERVICE_STATE_CONNECTING &&
+ state != BTD_SERVICE_STATE_CONNECTED)
+ return;
+
+ btd_service_disconnecting(service);
+
+ err = profile->disconnect(dev, profile);
+ if (err != 0)
+ btd_service_disconnecting_complete(service, err);
}

void device_request_disconnect(struct btd_device *device, DBusMessage *msg)
@@ -1018,10 +1043,7 @@ void device_request_disconnect(struct btd_device *device, DBusMessage *msg)
if (device->disconn_timer)
return;

- g_slist_foreach(device->connected_profiles, dev_disconn_profile,
- device);
- g_slist_free(device->connected_profiles);
- device->connected_profiles = NULL;
+ g_slist_foreach(device->services, dev_disconn_service, NULL);

g_slist_free(device->pending);
device->pending = NULL;
@@ -1073,13 +1095,20 @@ static int connect_next(struct btd_device *dev)

while (dev->pending) {
int err;
+ GSList *l;

profile = dev->pending->data;

+ l = g_slist_find_custom(dev->services, profile,
+ service_profile_cmp);
+ btd_service_connecting(l->data);
+
err = profile->connect(dev, profile);
if (err == 0)
return 0;

+ btd_service_connecting_complete(l->data, err);
+
error("Failed to connect %s: %s", profile->name,
strerror(-err));
dev->pending = g_slist_remove(dev->pending, profile);
@@ -1092,6 +1121,7 @@ void device_profile_connected(struct btd_device *dev,
struct btd_profile *profile, int err)
{
struct btd_profile *pending;
+ GSList *l;

DBG("%s %s (%d)", profile->name, strerror(-err), -err);

@@ -1101,10 +1131,9 @@ void device_profile_connected(struct btd_device *dev,
pending = dev->pending->data;
dev->pending = g_slist_remove(dev->pending, profile);

- if (!err)
- dev->connected_profiles =
- g_slist_append(dev->connected_profiles,
- profile);
+ l = g_slist_find_custom(dev->services, profile, service_profile_cmp);
+ if (l != NULL)
+ btd_service_connecting_complete(l->data, err);

/* Only continue connecting the next profile if it matches the first
* pending, otherwise it will trigger another connect to the same
@@ -1125,7 +1154,9 @@ void device_profile_connected(struct btd_device *dev,

DBG("returning response to %s", dbus_message_get_sender(dev->connect));

- if (err && dev->connected_profiles == NULL)
+ l = find_service_with_state(dev->services, BTD_SERVICE_STATE_CONNECTED);
+
+ if (err && l == NULL)
g_dbus_send_message(dbus_conn,
btd_error_failed(dev->connect, strerror(-err)));
else
@@ -1236,7 +1267,8 @@ static DBusMessage *connect_profiles(struct btd_device *dev, DBusMessage *msg,
if (g_slist_find(dev->pending, p))
continue;

- if (g_slist_find(dev->connected_profiles, p))
+ if (btd_service_get_state(service) !=
+ BTD_SERVICE_STATE_DISCONNECTED)
continue;

dev->pending = g_slist_insert_sorted(dev->pending, p,
@@ -1305,8 +1337,11 @@ static DBusMessage *connect_profile(DBusConnection *conn, DBusMessage *msg,
void device_profile_disconnected(struct btd_device *dev,
struct btd_profile *profile, int err)
{
- dev->connected_profiles = g_slist_remove(dev->connected_profiles,
- profile);
+ GSList *l;
+
+ l = g_slist_find_custom(dev->services, profile, service_profile_cmp);
+ if (l != NULL)
+ btd_service_disconnecting_complete(l->data, err);

if (!dev->disconnect)
return;
@@ -1327,10 +1362,12 @@ static DBusMessage *disconnect_profile(DBusConnection *conn, DBusMessage *msg,
void *user_data)
{
struct btd_device *dev = user_data;
+ struct btd_service *service;
struct btd_profile *p;
const char *pattern;
char *uuid;
int err;
+ GSList *l;

if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
DBUS_TYPE_INVALID))
@@ -1346,12 +1383,19 @@ static DBusMessage *disconnect_profile(DBusConnection *conn, DBusMessage *msg,
if (!p)
return btd_error_invalid_args(msg);

+ l = g_slist_find_custom(dev->services, p, service_profile_cmp);
+ service = l->data;
+
if (!p->disconnect)
return btd_error_not_supported(msg);

+ btd_service_disconnecting(service);
+
err = p->disconnect(dev, p);
- if (err < 0)
+ if (err < 0) {
+ btd_service_disconnecting_complete(service, err);
return btd_error_failed(msg, strerror(-err));
+ }

dev->disconnect = dbus_message_ref(msg);

@@ -2242,10 +2286,7 @@ void device_remove(struct btd_device *device, gboolean remove_stored)
if (device->browse)
browse_request_cancel(device->browse);

- g_slist_foreach(device->connected_profiles, dev_disconn_profile,
- device);
- g_slist_free(device->connected_profiles);
- device->connected_profiles = NULL;
+ g_slist_foreach(device->services, dev_disconn_service, NULL);

g_slist_free(device->pending);
device->pending = NULL;
@@ -2420,9 +2461,6 @@ void device_remove_profile(gpointer a, gpointer b)
if (l == NULL)
return;

- device->connected_profiles = g_slist_remove(device->connected_profiles,
- profile);
-
service = l->data;
device->services = g_slist_delete_link(device->services, l);
service_remove(service);
--
1.8.1.4


2013-04-05 11:45:38

by Mikel Astiz

[permalink] [raw]
Subject: [RFC v2 01/11] core: Add btd_service to represent device services

From: Mikel Astiz <[email protected]>

Add object to centralize all data corresponding to a service provided by
a remote device as well as the possible states for such a service.
---
Makefile.am | 1 +
src/service.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/service.h | 53 +++++++++++++++
3 files changed, 266 insertions(+)
create mode 100644 src/service.c
create mode 100644 src/service.h

diff --git a/Makefile.am b/Makefile.am
index f75b8d6..c30ab69 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -142,6 +142,7 @@ src_bluetoothd_SOURCES = $(gdbus_sources) $(builtin_sources) \
src/error.h src/error.c \
src/adapter.h src/adapter.c \
src/profile.h src/profile.c \
+ src/service.h src/service.c \
src/device.h src/device.c src/attio.h \
src/dbus-common.c src/dbus-common.h \
src/eir.h src/eir.c \
diff --git a/src/service.c b/src/service.c
new file mode 100644
index 0000000..abbee08
--- /dev/null
+++ b/src/service.c
@@ -0,0 +1,212 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012-2013 BMW Car IT GmbH. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include <bluetooth/bluetooth.h>
+
+#include <glib.h>
+
+#include "log.h"
+
+#include "adapter.h"
+#include "device.h"
+#include "profile.h"
+#include "service.h"
+
+struct btd_service {
+ gint ref;
+ struct btd_device *device;
+ struct btd_profile *profile;
+ void *user_data;
+ btd_service_state_t state;
+ int err;
+};
+
+static const char *state2str(btd_service_state_t state)
+{
+ switch (state) {
+ case BTD_SERVICE_STATE_UNAVAILABLE:
+ return "unavailable";
+ case BTD_SERVICE_STATE_DISCONNECTED:
+ return "disconnected";
+ case BTD_SERVICE_STATE_CONNECTING:
+ return "connecting";
+ case BTD_SERVICE_STATE_CONNECTED:
+ return "connected";
+ case BTD_SERVICE_STATE_DISCONNECTING:
+ return "disconnecting";
+ }
+
+ return NULL;
+}
+
+struct btd_device *btd_service_get_device(const struct btd_service *service)
+{
+ return service->device;
+}
+
+struct btd_profile *btd_service_get_profile(const struct btd_service *service)
+{
+ return service->profile;
+}
+
+void btd_service_set_user_data(struct btd_service *service, void *user_data)
+{
+ assert(service->state == BTD_SERVICE_STATE_UNAVAILABLE);
+ service->user_data = user_data;
+}
+
+void *btd_service_get_user_data(const struct btd_service *service)
+{
+ return service->user_data;
+}
+
+int btd_service_get_error(const struct btd_service *service)
+{
+ return service->err;
+}
+
+btd_service_state_t btd_service_get_state(const struct btd_service *service)
+{
+ return service->state;
+}
+
+static void service_set_state(struct btd_service *service,
+ btd_service_state_t state)
+{
+ btd_service_state_t old = service->state;
+
+ if (state == old)
+ return;
+
+ service->state = state;
+
+ DBG("State changed %p: %s -> %s", service, state2str(old),
+ state2str(state));
+}
+
+struct btd_service *service_create(struct btd_device *device,
+ struct btd_profile *profile)
+{
+ struct btd_service *service;
+
+ service = g_try_new0(struct btd_service, 1);
+ if (!service) {
+ error("service_create: failed to alloc memory");
+ return NULL;
+ }
+
+ service->ref = 1;
+ service->device = btd_device_ref(device);
+ service->profile = profile;
+ service->state = BTD_SERVICE_STATE_UNAVAILABLE;
+
+ return service;
+}
+
+struct btd_service *btd_service_ref(struct btd_service *service)
+{
+ service->ref++;
+
+ DBG("%p: ref=%d", service, service->ref);
+
+ return service;
+}
+
+void btd_service_unref(struct btd_service *service)
+{
+ service->ref--;
+
+ DBG("%p: ref=%d", service, service->ref);
+
+ if (service->ref > 0)
+ return;
+
+ btd_device_unref(service->device);
+ g_free(service);
+}
+
+void btd_service_probed(struct btd_service *service)
+{
+ assert(service->state == BTD_SERVICE_STATE_UNAVAILABLE);
+ service_set_state(service, BTD_SERVICE_STATE_DISCONNECTED);
+}
+
+void btd_service_connecting(struct btd_service *service)
+{
+ assert(service->state == BTD_SERVICE_STATE_DISCONNECTED);
+ service->err = 0;
+ service_set_state(service, BTD_SERVICE_STATE_CONNECTING);
+}
+
+void btd_service_connecting_complete(struct btd_service *service, int err)
+{
+ if (service->state != BTD_SERVICE_STATE_DISCONNECTED &&
+ service->state != BTD_SERVICE_STATE_CONNECTING)
+ return;
+
+ service->err = err;
+
+ if (err == 0)
+ service_set_state(service, BTD_SERVICE_STATE_CONNECTED);
+ else
+ service_set_state(service, BTD_SERVICE_STATE_DISCONNECTED);
+}
+
+void btd_service_disconnecting(struct btd_service *service)
+{
+ assert(service->state == BTD_SERVICE_STATE_CONNECTING ||
+ service->state == BTD_SERVICE_STATE_CONNECTED);
+ service->err = 0;
+ service_set_state(service, BTD_SERVICE_STATE_DISCONNECTING);
+}
+
+void btd_service_disconnecting_complete(struct btd_service *service, int err)
+{
+ if (service->state != BTD_SERVICE_STATE_CONNECTED &&
+ service->state != BTD_SERVICE_STATE_DISCONNECTING)
+ return;
+
+ service->err = err;
+ service_set_state(service, BTD_SERVICE_STATE_DISCONNECTED);
+}
+
+void btd_service_unavailable(struct btd_service *service)
+{
+ service->profile = NULL;
+ service->err = 0;
+ service_set_state(service, BTD_SERVICE_STATE_UNAVAILABLE);
+}
diff --git a/src/service.h b/src/service.h
new file mode 100644
index 0000000..596898b
--- /dev/null
+++ b/src/service.h
@@ -0,0 +1,53 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012-2013 BMW Car IT GmbH. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+typedef enum {
+ BTD_SERVICE_STATE_UNAVAILABLE, /* Not probed */
+ BTD_SERVICE_STATE_DISCONNECTED,
+ BTD_SERVICE_STATE_CONNECTING,
+ BTD_SERVICE_STATE_CONNECTED,
+ BTD_SERVICE_STATE_DISCONNECTING,
+} btd_service_state_t;
+
+struct btd_service;
+
+struct btd_service *service_create(struct btd_device *device,
+ struct btd_profile *profile);
+
+struct btd_service *btd_service_ref(struct btd_service *service);
+void btd_service_unref(struct btd_service *service);
+
+struct btd_device *btd_service_get_device(const struct btd_service *service);
+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);
+
+void btd_service_set_user_data(struct btd_service *service, void *user_data);
+void *btd_service_get_user_data(const struct btd_service *service);
+int btd_service_get_error(const struct btd_service *service);
+
+void btd_service_probed(struct btd_service *service);
+void btd_service_connecting(struct btd_service *service);
+void btd_service_connecting_complete(struct btd_service *service, int err);
+void btd_service_disconnecting(struct btd_service *service);
+void btd_service_disconnecting_complete(struct btd_service *service, int err);
+void btd_service_unavailable(struct btd_service *service);
--
1.8.1.4