* [PATCH BlueZ 6/6] tools: Emit Seeked signal if Position changes
From: Luiz Augusto von Dentz @ 2013-01-21 15:21 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1358781718-386-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
MPRIS spec says PropertiesChanged is not emitted for Position, which is
probably to make clear that progress is done using the rate, so instead
Seeked should be emitted.
---
tools/mpris-player.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/tools/mpris-player.c b/tools/mpris-player.c
index 448050d..b8de9a1 100644
--- a/tools/mpris-player.c
+++ b/tools/mpris-player.c
@@ -1646,6 +1646,8 @@ static void player_property_changed(GDBusProxy *proxy, const char *name,
{
struct player *player;
const char *property;
+ uint32_t position;
+ uint64_t value;
player = find_player(proxy);
if (player == NULL)
@@ -1658,6 +1660,18 @@ static void player_property_changed(GDBusProxy *proxy, const char *name,
g_dbus_emit_property_changed(player->conn, MPRIS_PLAYER_PATH,
MPRIS_PLAYER_INTERFACE,
property);
+
+ if (strcasecmp(name, "Position") != 0)
+ return;
+
+ dbus_message_iter_get_basic(iter, &position);
+
+ value = position * 1000;
+
+ g_dbus_emit_signal(player->conn, MPRIS_PLAYER_PATH,
+ MPRIS_PLAYER_INTERFACE, "Seeked",
+ DBUS_TYPE_INT64, &value,
+ DBUS_TYPE_INVALID);
}
static void transport_property_changed(GDBusProxy *proxy, const char *name,
--
1.8.0.2
^ permalink raw reply related
* [PATCH BlueZ 5/6] tools: Add volume support for mpris-player
From: Luiz Augusto von Dentz @ 2013-01-21 15:21 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1358781718-386-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This uses MediaTransport1 to track the Volume changes.
---
tools/mpris-player.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 178 insertions(+), 9 deletions(-)
diff --git a/tools/mpris-player.c b/tools/mpris-player.c
index 232e3c0..448050d 100644
--- a/tools/mpris-player.c
+++ b/tools/mpris-player.c
@@ -43,6 +43,7 @@
#define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter1"
#define BLUEZ_MEDIA_INTERFACE "org.bluez.Media1"
#define BLUEZ_MEDIA_PLAYER_INTERFACE "org.bluez.MediaPlayer1"
+#define BLUEZ_MEDIA_TRANSPORT_INTERFACE "org.bluez.MediaTransport1"
#define MPRIS_BUS_NAME "org.mpris.MediaPlayer2."
#define MPRIS_INTERFACE "org.mpris.MediaPlayer2"
#define MPRIS_PLAYER_INTERFACE "org.mpris.MediaPlayer2.Player"
@@ -55,6 +56,7 @@ static DBusConnection *sys = NULL;
static DBusConnection *session = NULL;
static GDBusClient *client = NULL;
static GSList *players = NULL;
+static GSList *transports = NULL;
struct player {
char *name;
@@ -62,6 +64,7 @@ struct player {
DBusConnection *conn;
GDBusProxy *proxy;
GDBusProxy *device;
+ GDBusProxy *transport;
};
typedef int (* parse_metadata_func) (DBusMessageIter *iter, const char *key,
@@ -793,6 +796,9 @@ static void player_free(void *data)
g_dbus_proxy_unref(player->device);
g_dbus_proxy_unref(player->proxy);
+ if (player->transport)
+ g_dbus_proxy_unref(player->transport);
+
g_free(player->name);
g_free(player->bus_name);
g_free(player);
@@ -1277,6 +1283,30 @@ static gboolean get_enable(const GDBusPropertyTable *property,
}
+static gboolean get_volume(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct player *player = data;
+ double value = 0.0;
+ uint16_t volume;
+ DBusMessageIter var;
+
+ if (player->transport == NULL)
+ goto done;
+
+ if (!g_dbus_proxy_get_property(player->transport, "Volume", &var))
+ goto done;
+
+ dbus_message_iter_get_basic(&var, &volume);
+
+ value = (double) volume / 127;
+
+done:
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_DOUBLE, &value);
+
+ return TRUE;
+}
+
static const GDBusMethodTable player_methods[] = {
{ GDBUS_ASYNC_METHOD("PlayPause", NULL, NULL, player_toggle) },
{ GDBUS_ASYNC_METHOD("Play", NULL, NULL, player_play) },
@@ -1301,7 +1331,7 @@ static const GDBusPropertyTable player_properties[] = {
{ "Shuffle", "b", get_shuffle, set_shuffle, shuffle_exists },
{ "Position", "x", get_position, NULL, position_exists },
{ "Metadata", "a{sv}", get_track, NULL, track_exists },
- { "Volume", "d", get_double, NULL, NULL },
+ { "Volume", "d", get_volume, NULL, NULL },
{ "CanGoNext", "b", get_enable, NULL, NULL },
{ "CanGoPrevious", "b", get_enable, NULL, NULL },
{ "CanPlay", "b", get_enable, NULL, NULL },
@@ -1353,12 +1383,33 @@ static char *mpris_busname(const char *name)
return g_strdelimit(bus_name, " ’", '_');
}
+static GDBusProxy *find_transport_by_path(const char *path)
+{
+ GSList *l;
+
+ for (l = transports; l; l = l->next) {
+ GDBusProxy *transport = l->data;
+ DBusMessageIter iter;
+ const char *value;
+
+ if (!g_dbus_proxy_get_property(transport, "Device", &iter))
+ continue;
+
+ dbus_message_iter_get_basic(&iter, &value);
+
+ if (strcmp(path, value) == 0)
+ return transport;
+ }
+
+ return NULL;
+}
+
static void register_player(GDBusProxy *proxy)
{
struct player *player;
DBusMessageIter iter;
const char *path, *name;
- GDBusProxy *device;
+ GDBusProxy *device, *transport;
if (!g_dbus_proxy_get_property(proxy, "Device", &iter))
return;
@@ -1412,6 +1463,10 @@ static void register_player(GDBusProxy *proxy)
goto fail;
}
+ transport = find_transport_by_path(path);
+ if (transport)
+ player->transport = g_dbus_proxy_ref(transport);
+
return;
fail:
@@ -1419,6 +1474,47 @@ fail:
player_free(player);
}
+static struct player *find_player_by_device(const char *device)
+{
+ GSList *l;
+
+ for (l = players; l; l = l->next) {
+ struct player *player = l->data;
+ const char *path = g_dbus_proxy_get_path(player->device);
+
+ if (g_strcmp0(device, path) == 0)
+ return player;
+ }
+
+ return NULL;
+}
+
+static void register_transport(GDBusProxy *proxy)
+{
+ struct player *player;
+ DBusMessageIter iter;
+ const char *path;
+
+ if (g_slist_find(transports, proxy) != NULL)
+ return;
+
+ if (!g_dbus_proxy_get_property(proxy, "Volume", &iter))
+ return;
+
+ if (!g_dbus_proxy_get_property(proxy, "Device", &iter))
+ return;
+
+ dbus_message_iter_get_basic(&iter, &path);
+
+ transports = g_slist_append(transports, proxy);
+
+ player = find_player_by_device(path);
+ if (player == NULL || player->transport != NULL)
+ return;
+
+ player->transport = g_dbus_proxy_ref(proxy);
+}
+
static void proxy_added(GDBusProxy *proxy, void *user_data)
{
const char *interface;
@@ -1437,6 +1533,10 @@ static void proxy_added(GDBusProxy *proxy, void *user_data)
printf("Bluetooth Player %s found\n",
g_dbus_proxy_get_path(proxy));
register_player(proxy);
+ } else if (!strcmp(interface, BLUEZ_MEDIA_TRANSPORT_INTERFACE)) {
+ printf("Bluetooth Transport %s found\n",
+ g_dbus_proxy_get_path(proxy));
+ register_transport(proxy);
}
}
@@ -1462,6 +1562,37 @@ static struct player *find_player(GDBusProxy *proxy)
return NULL;
}
+static struct player *find_player_by_transport(GDBusProxy *proxy)
+{
+ GSList *l;
+
+ for (l = players; l; l = l->next) {
+ struct player *player = l->data;
+
+ if (player->transport == proxy)
+ return player;
+ }
+
+ return NULL;
+}
+
+static void unregister_transport(GDBusProxy *proxy)
+{
+ struct player *player;
+
+ if (g_slist_find(transports, proxy) == NULL)
+ return;
+
+ transports = g_slist_remove(transports, proxy);
+
+ player = find_player_by_transport(proxy);
+ if (player == NULL)
+ return;
+
+ g_dbus_proxy_unref(player->transport);
+ player->transport = NULL;
+}
+
static void proxy_removed(GDBusProxy *proxy, void *user_data)
{
const char *interface;
@@ -1487,6 +1618,10 @@ static void proxy_removed(GDBusProxy *proxy, void *user_data)
printf("Bluetooth Player %s removed\n",
g_dbus_proxy_get_path(proxy));
unregister_player(player);
+ } else if (strcmp(interface, BLUEZ_MEDIA_TRANSPORT_INTERFACE) == 0) {
+ printf("Bluetooth Transport %s removed\n",
+ g_dbus_proxy_get_path(proxy));
+ unregister_transport(proxy);
}
}
@@ -1506,16 +1641,11 @@ static const char *property_to_mpris(const char *property)
return NULL;
}
-static void property_changed(GDBusProxy *proxy, const char *name,
+static void player_property_changed(GDBusProxy *proxy, const char *name,
DBusMessageIter *iter, void *user_data)
{
struct player *player;
- const char *interface, *property;
-
- interface = g_dbus_proxy_get_interface(proxy);
-
- if (strcmp(interface, BLUEZ_MEDIA_PLAYER_INTERFACE) != 0)
- return;
+ const char *property;
player = find_player(proxy);
if (player == NULL)
@@ -1530,6 +1660,45 @@ static void property_changed(GDBusProxy *proxy, const char *name,
property);
}
+static void transport_property_changed(GDBusProxy *proxy, const char *name,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct player *player;
+ DBusMessageIter var;
+ const char *path;
+
+ if (strcasecmp(name, "Volume") != 0)
+ return;
+
+ if (!g_dbus_proxy_get_property(proxy, "Device", &var))
+ return;
+
+ dbus_message_iter_get_basic(&var, &path);
+
+ player = find_player_by_device(path);
+ if (player == NULL)
+ return;
+
+ g_dbus_emit_property_changed(player->conn, MPRIS_PLAYER_PATH,
+ MPRIS_PLAYER_INTERFACE,
+ name);
+}
+
+static void property_changed(GDBusProxy *proxy, const char *name,
+ DBusMessageIter *iter, void *user_data)
+{
+ const char *interface;
+
+ interface = g_dbus_proxy_get_interface(proxy);
+
+ if (strcmp(interface, BLUEZ_MEDIA_PLAYER_INTERFACE) == 0)
+ return player_property_changed(proxy, name, iter, user_data);
+
+ if (strcmp(interface, BLUEZ_MEDIA_TRANSPORT_INTERFACE) == 0)
+ return transport_property_changed(proxy, name, iter,
+ user_data);
+}
+
int main(int argc, char *argv[])
{
guint owner_watch, properties_watch;
--
1.8.0.2
^ permalink raw reply related
* [PATCH BlueZ 4/6] tools: Make mpris-player to export org.mpris.MediaPlayer2
From: Luiz Augusto von Dentz @ 2013-01-21 15:21 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1358781718-386-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds support for org.mpris.MediaPlayer2 interface whic is also
mandatory accourding to MPRIS spec.
---
tools/mpris-player.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/tools/mpris-player.c b/tools/mpris-player.c
index 31da384..232e3c0 100644
--- a/tools/mpris-player.c
+++ b/tools/mpris-player.c
@@ -44,6 +44,7 @@
#define BLUEZ_MEDIA_INTERFACE "org.bluez.Media1"
#define BLUEZ_MEDIA_PLAYER_INTERFACE "org.bluez.MediaPlayer1"
#define MPRIS_BUS_NAME "org.mpris.MediaPlayer2."
+#define MPRIS_INTERFACE "org.mpris.MediaPlayer2"
#define MPRIS_PLAYER_INTERFACE "org.mpris.MediaPlayer2.Player"
#define MPRIS_PLAYER_PATH "/org/mpris/MediaPlayer2"
#define ERROR_INTERFACE "org.mpris.MediaPlayer2.Error"
@@ -1275,6 +1276,7 @@ static gboolean get_enable(const GDBusPropertyTable *property,
return TRUE;
}
+
static const GDBusMethodTable player_methods[] = {
{ GDBUS_ASYNC_METHOD("PlayPause", NULL, NULL, player_toggle) },
{ GDBUS_ASYNC_METHOD("Play", NULL, NULL, player_play) },
@@ -1309,6 +1311,40 @@ static const GDBusPropertyTable player_properties[] = {
{ }
};
+static gboolean get_disable(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ dbus_bool_t value = FALSE;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &value);
+
+ return TRUE;
+}
+
+static gboolean get_name(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct player *player = data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &player->name);
+
+ return TRUE;
+}
+
+static const GDBusMethodTable mpris_methods[] = {
+ { }
+};
+
+static const GDBusPropertyTable mpris_properties[] = {
+ { "CanQuit", "b", get_disable, NULL, NULL },
+ { "Fullscreen", "b", get_disable, NULL, NULL },
+ { "CanSetFullscreen", "b", get_disable, NULL, NULL },
+ { "CanRaise", "b", get_disable, NULL, NULL },
+ { "HasTrackList", "b", get_disable, NULL, NULL },
+ { "Identity", "s", get_name, NULL, NULL },
+ { }
+};
+
static char *mpris_busname(const char *name)
{
char *bus_name;
@@ -1355,6 +1391,17 @@ static void register_player(GDBusProxy *proxy)
}
if (!g_dbus_register_interface(player->conn, MPRIS_PLAYER_PATH,
+ MPRIS_INTERFACE,
+ mpris_methods,
+ NULL,
+ mpris_properties,
+ player, NULL)) {
+ fprintf(stderr, "Could not register interface %s",
+ MPRIS_INTERFACE);
+ goto fail;
+ }
+
+ if (!g_dbus_register_interface(player->conn, MPRIS_PLAYER_PATH,
MPRIS_PLAYER_INTERFACE,
player_methods,
player_signals,
--
1.8.0.2
^ permalink raw reply related
* [PATCH BlueZ 3/6] tools: Convert player's properties changed signals to MPRIS
From: Luiz Augusto von Dentz @ 2013-01-21 15:21 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1358781718-386-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Thsi convert properties changed signals from org.bluez.MediaPlayer1 to
org.mpris.MediaPlayer2.Player interface.
---
tools/mpris-player.c | 42 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/tools/mpris-player.c b/tools/mpris-player.c
index 8e2d85f..31da384 100644
--- a/tools/mpris-player.c
+++ b/tools/mpris-player.c
@@ -1443,6 +1443,46 @@ static void proxy_removed(GDBusProxy *proxy, void *user_data)
}
}
+static const char *property_to_mpris(const char *property)
+{
+ if (strcasecmp(property, "Repeat") == 0)
+ return "LoopStatus";
+ else if (strcasecmp(property, "Shuffle") == 0)
+ return "Shuffle";
+ else if (strcasecmp(property, "Status") == 0)
+ return "PlaybackStatus";
+ else if (strcasecmp(property, "Position") == 0)
+ return "Position";
+ else if (strcasecmp(property, "Track") == 0)
+ return "Metadata";
+
+ return NULL;
+}
+
+static void property_changed(GDBusProxy *proxy, const char *name,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct player *player;
+ const char *interface, *property;
+
+ interface = g_dbus_proxy_get_interface(proxy);
+
+ if (strcmp(interface, BLUEZ_MEDIA_PLAYER_INTERFACE) != 0)
+ return;
+
+ player = find_player(proxy);
+ if (player == NULL)
+ return;
+
+ property = property_to_mpris(name);
+ if (property == NULL)
+ return;
+
+ g_dbus_emit_property_changed(player->conn, MPRIS_PLAYER_PATH,
+ MPRIS_PLAYER_INTERFACE,
+ property);
+}
+
int main(int argc, char *argv[])
{
guint owner_watch, properties_watch;
@@ -1498,7 +1538,7 @@ int main(int argc, char *argv[])
g_dbus_client_set_disconnect_watch(client, disconnect_handler, NULL);
g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
- NULL, NULL);
+ property_changed, NULL);
g_main_loop_run(main_loop);
--
1.8.0.2
^ permalink raw reply related
* [PATCH BlueZ 2/6] tools: Add support for setting Shuffle and LoopStatus to mpris-player
From: Luiz Augusto von Dentz @ 2013-01-21 15:21 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1358781718-386-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This add write support for Shuffle and LoopStatus properties of
org.mpris.MediaPlayer2.Player interface.
---
tools/mpris-player.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 78 insertions(+), 2 deletions(-)
diff --git a/tools/mpris-player.c b/tools/mpris-player.c
index 1871ae9..8e2d85f 100644
--- a/tools/mpris-player.c
+++ b/tools/mpris-player.c
@@ -992,6 +992,58 @@ static gboolean get_repeat(const GDBusPropertyTable *property,
return TRUE;
}
+static const char *loopstatus_to_repeat(const char *value)
+{
+ if (strcasecmp(value, "None") == 0)
+ return "off";
+ else if (strcasecmp(value, "Track") == 0)
+ return "singletrack";
+ else if (strcasecmp(value, "Playlist") == 0)
+ return "alltracks";
+
+ return NULL;
+}
+
+static void property_result(const DBusError *err, void *user_data)
+{
+ GDBusPendingPropertySet id = GPOINTER_TO_UINT(user_data);
+
+ if (!dbus_error_is_set(err))
+ return g_dbus_pending_property_success(id);
+
+ g_dbus_pending_property_error(id, err->name, err->message);
+}
+
+static void set_repeat(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, GDBusPendingPropertySet id,
+ void *data)
+{
+ struct player *player = data;
+ const char *value;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) {
+ g_dbus_pending_property_error(id,
+ ERROR_INTERFACE ".InvalidArguments",
+ "Invalid arguments in method call");
+ return;
+ }
+
+ dbus_message_iter_get_basic(iter, &value);
+
+ value = loopstatus_to_repeat(value);
+ if (value == NULL) {
+ g_dbus_pending_property_error(id,
+ ERROR_INTERFACE ".InvalidArguments",
+ "Invalid arguments in method call");
+ return;
+ }
+
+ g_dbus_proxy_set_property_basic(player->proxy, "Repeat",
+ DBUS_TYPE_STRING, value,
+ property_result, GUINT_TO_POINTER(id),
+ NULL);
+}
+
static gboolean get_double(const GDBusPropertyTable *property,
DBusMessageIter *iter, void *data)
{
@@ -1030,6 +1082,30 @@ static gboolean get_shuffle(const GDBusPropertyTable *property,
return TRUE;
}
+static void set_shuffle(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, GDBusPendingPropertySet id,
+ void *data)
+{
+ struct player *player = data;
+ dbus_bool_t shuffle;
+ const char *value;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BOOLEAN) {
+ g_dbus_pending_property_error(id,
+ ERROR_INTERFACE ".InvalidArguments",
+ "Invalid arguments in method call");
+ return;
+ }
+
+ dbus_message_iter_get_basic(iter, &shuffle);
+ value = shuffle ? "alltracks" : "off";
+
+ g_dbus_proxy_set_property_basic(player->proxy, "Shuffle",
+ DBUS_TYPE_STRING, value,
+ property_result, GUINT_TO_POINTER(id),
+ NULL);
+}
+
static gboolean position_exists(const GDBusPropertyTable *property, void *data)
{
DBusMessageIter iter;
@@ -1216,11 +1292,11 @@ static const GDBusSignalTable player_signals[] = {
static const GDBusPropertyTable player_properties[] = {
{ "PlaybackStatus", "s", get_status, NULL, status_exists },
- { "LoopStatus", "s", get_repeat, NULL, repeat_exists },
+ { "LoopStatus", "s", get_repeat, set_repeat, repeat_exists },
{ "Rate", "d", get_double, NULL, NULL },
{ "MinimumRate", "d", get_double, NULL, NULL },
{ "MaximumRate", "d", get_double, NULL, NULL },
- { "Shuffle", "b", get_shuffle, NULL, shuffle_exists },
+ { "Shuffle", "b", get_shuffle, set_shuffle, shuffle_exists },
{ "Position", "x", get_position, NULL, position_exists },
{ "Metadata", "a{sv}", get_track, NULL, track_exists },
{ "Volume", "d", get_double, NULL, NULL },
--
1.8.0.2
^ permalink raw reply related
* [PATCH BlueZ 1/6] tools: Make mpris-player to export players using MPRIS interface
From: Luiz Augusto von Dentz @ 2013-01-21 15:21 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Players found are exported in private connections using
org.mpris.MediaPlayer2.<device name> on the session bus.
---
tools/mpris-player.c | 639 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 618 insertions(+), 21 deletions(-)
diff --git a/tools/mpris-player.c b/tools/mpris-player.c
index 246791a..1871ae9 100644
--- a/tools/mpris-player.c
+++ b/tools/mpris-player.c
@@ -32,6 +32,7 @@
#include <signal.h>
#include <getopt.h>
#include <string.h>
+#include <inttypes.h>
#include <dbus/dbus.h>
#include <glib.h>
@@ -41,13 +42,29 @@
#define BLUEZ_PATH "/org/bluez"
#define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter1"
#define BLUEZ_MEDIA_INTERFACE "org.bluez.Media1"
+#define BLUEZ_MEDIA_PLAYER_INTERFACE "org.bluez.MediaPlayer1"
+#define MPRIS_BUS_NAME "org.mpris.MediaPlayer2."
#define MPRIS_PLAYER_INTERFACE "org.mpris.MediaPlayer2.Player"
#define MPRIS_PLAYER_PATH "/org/mpris/MediaPlayer2"
+#define ERROR_INTERFACE "org.mpris.MediaPlayer2.Error"
static GMainLoop *main_loop;
static GDBusProxy *adapter = NULL;
static DBusConnection *sys = NULL;
static DBusConnection *session = NULL;
+static GDBusClient *client = NULL;
+static GSList *players = NULL;
+
+struct player {
+ char *name;
+ char *bus_name;
+ DBusConnection *conn;
+ GDBusProxy *proxy;
+ GDBusProxy *device;
+};
+
+typedef int (* parse_metadata_func) (DBusMessageIter *iter, const char *key,
+ DBusMessageIter *metadata);
static void dict_append_entry(DBusMessageIter *dict, const char *key, int type,
void *val);
@@ -190,7 +207,8 @@ static int parse_metadata_entry(DBusMessageIter *entry, const char *key,
return 0;
}
-static int parse_metadata(DBusMessageIter *args, DBusMessageIter *metadata)
+static int parse_metadata(DBusMessageIter *args, DBusMessageIter *metadata,
+ parse_metadata_func func)
{
DBusMessageIter dict;
int ctype;
@@ -216,7 +234,7 @@ static int parse_metadata(DBusMessageIter *args, DBusMessageIter *metadata)
dbus_message_iter_get_basic(&entry, &key);
dbus_message_iter_next(&entry);
- if (parse_metadata_entry(&entry, key, metadata) < 0)
+ if (func(&entry, key, metadata) < 0)
return -EINVAL;
dbus_message_iter_next(&dict);
@@ -225,7 +243,8 @@ static int parse_metadata(DBusMessageIter *args, DBusMessageIter *metadata)
return 0;
}
-static void append_metadata(DBusMessageIter *iter, DBusMessageIter *dict)
+static void append_metadata(DBusMessageIter *iter, DBusMessageIter *dict,
+ parse_metadata_func func)
{
DBusMessageIter value, metadata;
@@ -237,7 +256,7 @@ static void append_metadata(DBusMessageIter *iter, DBusMessageIter *dict)
DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &metadata);
- parse_metadata(dict, &metadata);
+ parse_metadata(dict, &metadata, func);
dbus_message_iter_close_container(&value, &metadata);
dbus_message_iter_close_container(iter, &value);
@@ -260,7 +279,7 @@ static void dict_append_entry(DBusMessageIter *dict, const char *key, int type,
dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
if (strcasecmp(key, "Metadata") == 0)
- append_metadata(&entry, val);
+ append_metadata(&entry, val, parse_metadata_entry);
else
append_variant(&entry, type, val);
@@ -509,21 +528,29 @@ done:
static void remove_player(DBusConnection *conn, const char *sender)
{
DBusMessage *msg;
- char *path;
+ char *path, *owner;
if (!adapter)
return;
+ path = sender2path(sender);
+ dbus_connection_get_object_path_data(sys, path, (void **) &owner);
+
+ if (owner == NULL) {
+ g_free(path);
+ return;
+ }
+
msg = dbus_message_new_method_call(BLUEZ_BUS_NAME,
g_dbus_proxy_get_path(adapter),
BLUEZ_MEDIA_INTERFACE,
"UnregisterPlayer");
if (!msg) {
fprintf(stderr, "Can't allocate new method call\n");
+ g_free(path);
return;
}
- path = sender2path(sender);
dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_INVALID);
@@ -540,10 +567,16 @@ static gboolean properties_changed(DBusConnection *conn,
{
DBusMessageIter iter;
const char *iface;
- char *path;
+ char *path, *owner;
dbus_message_iter_init(msg, &iter);
+ path = sender2path(dbus_message_get_sender(msg));
+ dbus_connection_get_object_path_data(sys, path, (void **) &owner);
+
+ if (owner == NULL)
+ goto done;
+
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@@ -553,14 +586,28 @@ static gboolean properties_changed(DBusConnection *conn,
dbus_message_iter_next(&iter);
- path = sender2path(dbus_message_get_sender(msg));
parse_properties(conn, path, &iter, NULL);
+done:
g_free(path);
return TRUE;
}
+static struct player *find_player_by_bus_name(const char *name)
+{
+ GSList *l;
+
+ for (l = players; l; l = l->next) {
+ struct player *player = l->data;
+
+ if (strcmp(player->bus_name, name) == 0)
+ return player;
+ }
+
+ return NULL;
+}
+
static gboolean name_owner_changed(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -581,7 +628,7 @@ static gboolean name_owner_changed(DBusConnection *conn,
if (*new == '\0') {
printf("player %s at %s disappear\n", name, old);
remove_player(conn, old);
- } else {
+ } else if (find_player_by_bus_name(name) == NULL) {
printf("player %s at %s found\n", name, new);
add_player(conn, name, new);
}
@@ -733,23 +780,565 @@ static void disconnect_handler(DBusConnection *connection, void *user_data)
printf("org.bluez disappeared\n");
}
-static void proxy_added(GDBusProxy *proxy, void *user_data)
+static void player_free(void *data)
{
- const char *interface;
+ struct player *player = data;
+
+ if (player->conn) {
+ dbus_connection_close(player->conn);
+ dbus_connection_unref(player->conn);
+ }
+
+ g_dbus_proxy_unref(player->device);
+ g_dbus_proxy_unref(player->proxy);
+
+ g_free(player->name);
+ g_free(player->bus_name);
+ g_free(player);
+}
+
+struct pending_call {
+ struct player *player;
+ DBusMessage *msg;
+};
+
+static void pending_call_free(void *data)
+{
+ struct pending_call *p = data;
+
+ if (p->msg)
+ dbus_message_unref(p->msg);
+
+ g_free(p);
+}
+
+static void player_reply(DBusMessage *message, void *user_data)
+{
+ struct pending_call *p = user_data;
+ struct player *player = p->player;
+ DBusMessage *msg = p->msg;
+ DBusMessage *reply;
+ DBusError err;
+
+ dbus_error_init(&err);
+ if (dbus_set_error_from_message(&err, message)) {
+ fprintf(stderr, "error: %s", err.name);
+ reply = g_dbus_create_error(msg, err.name, err.message);
+ dbus_error_free(&err);
+ } else
+ reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+
+ g_dbus_send_message(player->conn, reply);
+}
+
+static void player_control(struct player *player, DBusMessage *msg,
+ const char *name)
+{
+ struct pending_call *p;
+
+ p = g_new0(struct pending_call, 1);
+ p->player = player;
+ p->msg = dbus_message_ref(msg);
+
+ g_dbus_proxy_method_call(player->proxy, name, NULL, player_reply,
+ p, pending_call_free);
+}
+
+static DBusMessage *player_toggle(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct player *player = data;
+ DBusMessageIter value;
+ const char *status;
+
+ if (!g_dbus_proxy_get_property(player->proxy, "Status", &value))
+ return FALSE;
+
+ dbus_message_iter_get_basic(&value, &status);
+
+ if (strcasecmp(status, "Playing") == 0)
+ player_control(player, msg, "Pause");
+ else
+ player_control(player, msg, "Play");
+
+ return NULL;
+}
+
+static DBusMessage *player_play(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct player *player = data;
+
+ player_control(player, msg, "Play");
+
+ return NULL;
+}
+
+static DBusMessage *player_pause(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct player *player = data;
+
+ player_control(player, msg, "Pause");
+
+ return NULL;
+}
+
+static DBusMessage *player_stop(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct player *player = data;
+
+ player_control(player, msg, "Stop");
+
+ return NULL;
+}
+
+static DBusMessage *player_next(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct player *player = data;
+
+ player_control(player, msg, "Next");
+
+ return NULL;
+}
+
+static DBusMessage *player_previous(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct player *player = data;
+
+ player_control(player, msg, "Previous");
+
+ return NULL;
+}
+
+static gboolean status_exists(const GDBusPropertyTable *property, void *data)
+{
+ DBusMessageIter iter;
+ struct player *player = data;
+
+ return g_dbus_proxy_get_property(player->proxy, "Status", &iter);
+}
+
+static const char *status_to_playback(const char *status)
+{
+ if (strcasecmp(status, "playing") == 0)
+ return "Playing";
+ else if (strcasecmp(status, "paused") == 0)
+ return "Paused";
+ else
+ return "Stopped";
+}
+
+static gboolean get_status(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct player *player = data;
+ DBusMessageIter value;
+ const char *status;
+
+ if (!g_dbus_proxy_get_property(player->proxy, "Status", &value))
+ return FALSE;
+
+ dbus_message_iter_get_basic(&value, &status);
+
+ status = status_to_playback(status);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &status);
+
+ return TRUE;
+}
+
+static gboolean repeat_exists(const GDBusPropertyTable *property, void *data)
+{
+ DBusMessageIter iter;
+ struct player *player = data;
+
+ return g_dbus_proxy_get_property(player->proxy, "Repeat", &iter);
+}
+
+static const char *repeat_to_loopstatus(const char *value)
+{
+ if (strcasecmp(value, "off") == 0)
+ return "None";
+ else if (strcasecmp(value, "singletrack") == 0)
+ return "Track";
+ else if (strcasecmp(value, "alltracks") == 0)
+ return "Playlist";
+
+ return NULL;
+}
+
+static gboolean get_repeat(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct player *player = data;
+ DBusMessageIter value;
+ const char *status;
+
+ if (!g_dbus_proxy_get_property(player->proxy, "Repeat", &value))
+ return FALSE;
+
+ dbus_message_iter_get_basic(&value, &status);
+
+ status = repeat_to_loopstatus(status);
+ if (status == NULL)
+ return FALSE;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &status);
+
+ return TRUE;
+}
+
+static gboolean get_double(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ double value = 1.0;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_DOUBLE, &value);
+
+ return TRUE;
+}
+
+static gboolean shuffle_exists(const GDBusPropertyTable *property, void *data)
+{
+ DBusMessageIter iter;
+ struct player *player = data;
+
+ return g_dbus_proxy_get_property(player->proxy, "Shuffle", &iter);
+}
+
+static gboolean get_shuffle(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct player *player = data;
+ DBusMessageIter value;
+ const char *string;
+ dbus_bool_t shuffle;
+
+ if (!g_dbus_proxy_get_property(player->proxy, "Shuffle", &value))
+ return FALSE;
+
+ dbus_message_iter_get_basic(&value, &string);
+
+ shuffle = strcmp(string, "off") != 0;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &shuffle);
+
+ return TRUE;
+}
+
+static gboolean position_exists(const GDBusPropertyTable *property, void *data)
+{
+ DBusMessageIter iter;
+ struct player *player = data;
+
+ return g_dbus_proxy_get_property(player->proxy, "Position", &iter);
+}
+
+static gboolean get_position(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct player *player = data;
+ DBusMessageIter var;
+ uint32_t position;
+ int64_t value;
+
+ if (!g_dbus_proxy_get_property(player->proxy, "Position", &var))
+ return FALSE;
+
+ dbus_message_iter_get_basic(&var, &position);
+
+ value = position * 1000;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_INT64, &value);
+
+ return TRUE;
+}
+
+static gboolean track_exists(const GDBusPropertyTable *property, void *data)
+{
+ DBusMessageIter iter;
+ struct player *player = data;
+
+ return g_dbus_proxy_get_property(player->proxy, "Track", &iter);
+}
+
+static gboolean parse_string_metadata(DBusMessageIter *iter, const char *key,
+ DBusMessageIter *metadata)
+{
+ const char *value;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
+ return FALSE;
+
+ dbus_message_iter_get_basic(iter, &value);
+
+ dict_append_entry(metadata, key, DBUS_TYPE_STRING, &value);
+
+ return TRUE;
+}
+
+static gboolean parse_array_metadata(DBusMessageIter *iter, const char *key,
+ DBusMessageIter *metadata)
+{
+ char **value;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
+ return FALSE;
+
+ value = dbus_malloc0(sizeof(char *));
+
+ dbus_message_iter_get_basic(iter, &(value[0]));
+
+ dict_append_array(metadata, key, DBUS_TYPE_STRING, &value, 1);
+
+ dbus_free(value);
+
+ return TRUE;
+}
+
+static gboolean parse_int64_metadata(DBusMessageIter *iter, const char *key,
+ DBusMessageIter *metadata)
+{
+ uint32_t duration;
+ int64_t value;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT32)
+ return FALSE;
+
+ dbus_message_iter_get_basic(iter, &duration);
+
+ value = duration * 1000;
+
+ dict_append_entry(metadata, key, DBUS_TYPE_INT64, &value);
+
+ return TRUE;
+}
+
+static gboolean parse_int32_metadata(DBusMessageIter *iter, const char *key,
+ DBusMessageIter *metadata)
+{
+ uint32_t value;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT32)
+ return FALSE;
+
+ dbus_message_iter_get_basic(iter, &value);
+
+ dict_append_entry(metadata, key, DBUS_TYPE_INT32, &value);
+
+ return TRUE;
+}
+
+static int parse_track_entry(DBusMessageIter *entry, const char *key,
+ DBusMessageIter *metadata)
+{
+ DBusMessageIter var;
+
+ printf("metadata %s found\n", key);
+
+ if (dbus_message_iter_get_arg_type(entry) != DBUS_TYPE_VARIANT)
+ return -EINVAL;
+
+ dbus_message_iter_recurse(entry, &var);
+
+ if (strcasecmp(key, "Title") == 0) {
+ if (!parse_string_metadata(&var, "xesam:title", metadata))
+ return -EINVAL;
+ } else if (strcasecmp(key, "Artist") == 0) {
+ if (!parse_array_metadata(&var, "xesam:artist", metadata))
+ return -EINVAL;
+ } else if (strcasecmp(key, "Album") == 0) {
+ if (!parse_string_metadata(&var, "xesam:album", metadata))
+ return -EINVAL;
+ } else if (strcasecmp(key, "Genre") == 0) {
+ if (!parse_array_metadata(&var, "xesam:genre", metadata))
+ return -EINVAL;
+ } else if (strcasecmp(key, "Duration") == 0) {
+ if (!parse_int64_metadata(&var, "mpris:length", metadata))
+ return -EINVAL;
+ } else if (strcasecmp(key, "TrackNumber") == 0) {
+ if (!parse_int32_metadata(&var, "xesam:trackNumber", metadata))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static gboolean get_track(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct player *player = data;
+ DBusMessageIter var, metadata;
+
+ if (!g_dbus_proxy_get_property(player->proxy, "Track", &var))
+ return FALSE;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &metadata);
+
+ parse_metadata(&var, &metadata, parse_track_entry);
+
+ dbus_message_iter_close_container(iter, &metadata);
+
+ return TRUE;
+}
+
+static gboolean get_enable(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ dbus_bool_t value = TRUE;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &value);
+
+ return TRUE;
+}
+
+static const GDBusMethodTable player_methods[] = {
+ { GDBUS_ASYNC_METHOD("PlayPause", NULL, NULL, player_toggle) },
+ { GDBUS_ASYNC_METHOD("Play", NULL, NULL, player_play) },
+ { GDBUS_ASYNC_METHOD("Pause", NULL, NULL, player_pause) },
+ { GDBUS_ASYNC_METHOD("Stop", NULL, NULL, player_stop) },
+ { GDBUS_ASYNC_METHOD("Next", NULL, NULL, player_next) },
+ { GDBUS_ASYNC_METHOD("Previous", NULL, NULL, player_previous) },
+ { }
+};
+
+static const GDBusSignalTable player_signals[] = {
+ { GDBUS_SIGNAL("Seeked", GDBUS_ARGS({"Position", "x"})) },
+ { }
+};
+
+static const GDBusPropertyTable player_properties[] = {
+ { "PlaybackStatus", "s", get_status, NULL, status_exists },
+ { "LoopStatus", "s", get_repeat, NULL, repeat_exists },
+ { "Rate", "d", get_double, NULL, NULL },
+ { "MinimumRate", "d", get_double, NULL, NULL },
+ { "MaximumRate", "d", get_double, NULL, NULL },
+ { "Shuffle", "b", get_shuffle, NULL, shuffle_exists },
+ { "Position", "x", get_position, NULL, position_exists },
+ { "Metadata", "a{sv}", get_track, NULL, track_exists },
+ { "Volume", "d", get_double, NULL, NULL },
+ { "CanGoNext", "b", get_enable, NULL, NULL },
+ { "CanGoPrevious", "b", get_enable, NULL, NULL },
+ { "CanPlay", "b", get_enable, NULL, NULL },
+ { "CanPause", "b", get_enable, NULL, NULL },
+ { "CanSeek", "b", get_enable, NULL, NULL },
+ { "CanControl", "b", get_enable, NULL, NULL },
+ { }
+};
+
+static char *mpris_busname(const char *name)
+{
+ char *bus_name;
+
+ bus_name = g_strconcat(MPRIS_BUS_NAME, name, NULL);
+ return g_strdelimit(bus_name, " ’", '_');
+}
+
+static void register_player(GDBusProxy *proxy)
+{
+ struct player *player;
+ DBusMessageIter iter;
+ const char *path, *name;
+ GDBusProxy *device;
+
+ if (!g_dbus_proxy_get_property(proxy, "Device", &iter))
+ return;
+
+ dbus_message_iter_get_basic(&iter, &path);
- if (adapter != NULL)
+ device = g_dbus_proxy_new(client, path, "org.bluez.Device1");
+ if (device == NULL)
return;
+ if (!g_dbus_proxy_get_property(device, "Name", &iter))
+ return;
+
+ dbus_message_iter_get_basic(&iter, &name);
+
+ player = g_new0(struct player, 1);
+ player->name = g_strdup(name);
+ player->bus_name = mpris_busname(name);
+ player->proxy = g_dbus_proxy_ref(proxy);
+ player->device = device;
+
+ players = g_slist_prepend(players, player);
+
+ player->conn = g_dbus_setup_private(DBUS_BUS_SESSION, player->bus_name,
+ NULL);
+ if (!session) {
+ fprintf(stderr, "Could not register bus name %s",
+ player->bus_name);
+ goto fail;
+ }
+
+ if (!g_dbus_register_interface(player->conn, MPRIS_PLAYER_PATH,
+ MPRIS_PLAYER_INTERFACE,
+ player_methods,
+ player_signals,
+ player_properties,
+ player, player_free)) {
+ fprintf(stderr, "Could not register interface %s",
+ MPRIS_PLAYER_INTERFACE);
+ goto fail;
+ }
+
+ return;
+
+fail:
+ players = g_slist_remove(players, player);
+ player_free(player);
+}
+
+static void proxy_added(GDBusProxy *proxy, void *user_data)
+{
+ const char *interface;
+
interface = g_dbus_proxy_get_interface(proxy);
if (!strcmp(interface, BLUEZ_ADAPTER_INTERFACE)) {
+ if (adapter != NULL)
+ return;
+
printf("Bluetooth Adapter %s found\n",
g_dbus_proxy_get_path(proxy));
adapter = proxy;
list_names(session);
+ } else if (!strcmp(interface, BLUEZ_MEDIA_PLAYER_INTERFACE)) {
+ printf("Bluetooth Player %s found\n",
+ g_dbus_proxy_get_path(proxy));
+ register_player(proxy);
}
}
+static void unregister_player(struct player *player)
+{
+ players = g_slist_remove(players, player);
+
+ g_dbus_unregister_interface(player->conn, MPRIS_PLAYER_PATH,
+ MPRIS_PLAYER_INTERFACE);
+}
+
+static struct player *find_player(GDBusProxy *proxy)
+{
+ GSList *l;
+
+ for (l = players; l; l = l->next) {
+ struct player *player = l->data;
+
+ if (player->proxy == proxy)
+ return player;
+ }
+
+ return NULL;
+}
+
static void proxy_removed(GDBusProxy *proxy, void *user_data)
{
const char *interface;
@@ -759,19 +1348,27 @@ static void proxy_removed(GDBusProxy *proxy, void *user_data)
interface = g_dbus_proxy_get_interface(proxy);
- if (strcmp(interface, BLUEZ_ADAPTER_INTERFACE))
- return;
+ if (strcmp(interface, BLUEZ_ADAPTER_INTERFACE) == 0) {
+ if (adapter != proxy)
+ return;
+ printf("Bluetooth Adapter %s removed\n",
+ g_dbus_proxy_get_path(proxy));
+ adapter = NULL;
+ } else if (strcmp(interface, BLUEZ_MEDIA_PLAYER_INTERFACE) == 0) {
+ struct player *player;
- if (adapter != proxy)
- return;
+ player = find_player(proxy);
+ if (player == NULL)
+ return;
- printf("Bluetooth Adapter %s removed\n", g_dbus_proxy_get_path(proxy));
- adapter = NULL;
+ printf("Bluetooth Player %s removed\n",
+ g_dbus_proxy_get_path(proxy));
+ unregister_player(player);
+ }
}
int main(int argc, char *argv[])
{
- GDBusClient *client;
guint owner_watch, properties_watch;
struct sigaction sa;
int opt;
@@ -825,7 +1422,7 @@ int main(int argc, char *argv[])
g_dbus_client_set_disconnect_watch(client, disconnect_handler, NULL);
g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
- NULL, NULL);
+ NULL, NULL);
g_main_loop_run(main_loop);
--
1.8.0.2
^ permalink raw reply related
* [PATCH] monitor: Fix possible crash on unknown command
From: Szymon Janc @ 2013-01-21 15:17 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
If uknown command is received monitor would crash due to dereference
of NULL opcode_data pointer.
---
monitor/packet.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/monitor/packet.c b/monitor/packet.c
index 19139f8..58a5a97 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -4266,7 +4266,7 @@ static void cmd_complete_evt(const void *data, uint8_t size)
print_indent(6, opcode_color, "", opcode_str, COLOR_OFF,
" (0x%2.2x|0x%4.4x) ncmd %d", ogf, ocf, evt->ncmd);
- if (!opcode_data->rsp_func) {
+ if (!opcode_data || !opcode_data->rsp_func) {
packet_hexdump(data + 3, size - 3);
return;
}
--
1.8.0.3
^ permalink raw reply related
* Re: [PATCH BlueZ 5/9 v3] audio: Fix handling of A2DP abort indication
From: Chan-yeol Park @ 2013-01-21 14:53 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth, SYAM SIDHARDHAN
In-Reply-To: <1339771301-24032-5-git-send-email-luiz.dentz@gmail.com>
Hi Luiz.
Regarding your patch that was applied already, I think
finalize_setup_errno() function missed NULL argument.
This is reported by Syam Sidhardhan <s.syam@samsung.com>
On 06/15/2012 11:41 PM, Luiz Augusto von Dentz wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> When an abort is received all setup callbacks should return an error.
> ---
> audio/a2dp.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/audio/a2dp.c b/audio/a2dp.c
> index 5139f61..d9dcead 100644
> --- a/audio/a2dp.c
> +++ b/audio/a2dp.c
> @@ -1182,6 +1182,7 @@ static gboolean abort_ind(struct avdtp *session, struct avdtp_local_sep *sep,
> void *user_data)
> {
> struct a2dp_sep *a2dp_sep = user_data;
> + struct a2dp_setup *setup;
>
> if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
> DBG("Sink %p: Abort_Ind", sep);
> @@ -1190,6 +1191,14 @@ static gboolean abort_ind(struct avdtp *session, struct avdtp_local_sep *sep,
>
> a2dp_sep->stream = NULL;
>
> + setup = find_setup_by_session(session);
> + if (!setup)
> + return TRUE;
> +
> + finalize_setup_errno(setup, -ECONNRESET, finalize_suspend,
> + finalize_resume,
> + finalize_config);
> +
Here.
Could you give us your opinion?
Regards
Chanyeol
^ permalink raw reply
* [PATCH v4 4/4] Bluetooth: Fix stop discovery while in STARTING state
From: Jaganath Kanakkassery @ 2013-01-21 14:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Jaganath Kanakkassery
In-Reply-To: <1358777619-27018-1-git-send-email-jaganath.k@samsung.com>
If stop_discovery() is called when discovery state is STARTING, it
will be failed currently. This patch fixes this.
Signed-off-by: Jaganath Kanakkassery <jaganath.k@samsung.com>
---
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/hci_event.c | 14 ++++++++++++--
net/bluetooth/mgmt.c | 12 +++++++++++-
3 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index f20da05..0a7aa1f 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -64,6 +64,7 @@ struct discovery_state {
DISCOVERY_RESOLVING,
DISCOVERY_STOPPING,
} state;
+ bool discovering;
struct list_head all; /* All devices found during inquiry */
struct list_head unknown; /* Name state not known */
struct list_head resolve; /* Name needs to be resolved */
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 97b4828..c616cbf 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1259,7 +1259,12 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
set_bit(HCI_LE_SCAN, &hdev->dev_flags);
hci_dev_lock(hdev);
- hci_discovery_set_state(hdev, DISCOVERY_FINDING);
+ if (hdev->discovery.state == DISCOVERY_STOPPING) {
+ hci_cancel_le_scan(hdev);
+ mgmt_start_discovery_cancelled(hdev);
+ } else {
+ hci_discovery_set_state(hdev, DISCOVERY_FINDING);
+ }
hci_dev_unlock(hdev);
break;
@@ -1375,7 +1380,12 @@ static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
set_bit(HCI_INQUIRY, &hdev->flags);
hci_dev_lock(hdev);
- hci_discovery_set_state(hdev, DISCOVERY_FINDING);
+ if (hdev->discovery.state == DISCOVERY_STOPPING) {
+ hci_cancel_inquiry(hdev);
+ mgmt_start_discovery_cancelled(hdev);
+ } else {
+ hci_discovery_set_state(hdev, DISCOVERY_FINDING);
+ }
hci_dev_unlock(hdev);
}
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index ba5ca81..d9b1aa1 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2443,7 +2443,8 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
hci_dev_lock(hdev);
- if (!hci_discovery_active(hdev)) {
+ if (hdev->discovery.state != DISCOVERY_STARTING &&
+ !hci_discovery_active(hdev)) {
err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
MGMT_STATUS_REJECTED, &mgmt_cp->type,
sizeof(mgmt_cp->type));
@@ -2491,6 +2492,10 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
break;
+ case DISCOVERY_STARTING:
+ err = 0;
+ break;
+
default:
BT_DBG("unknown discovery state %u", hdev->discovery.state);
err = -EFAULT;
@@ -3777,6 +3782,11 @@ int mgmt_discovering(struct hci_dev *hdev, bool discovering)
mgmt_pending_remove(cmd);
}
+ if (hdev->discovery.discovering == discovering)
+ return 0;
+
+ hdev->discovery.discovering = discovering;
+
memset(&ev, 0, sizeof(ev));
ev.type = hdev->discovery.type;
ev.discovering = discovering;
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 3/4] Bluetooth: Change type of "discovering" from u8 to bool
From: Jaganath Kanakkassery @ 2013-01-21 14:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Jaganath Kanakkassery
In-Reply-To: <1358777619-27018-1-git-send-email-jaganath.k@samsung.com>
Since the only possible values of discovering is 0 and 1, bool is
more appropriate
Signed-off-by: Jaganath Kanakkassery <jaganath.k@samsung.com>
---
include/net/bluetooth/hci_core.h | 2 +-
net/bluetooth/hci_core.c | 4 ++--
net/bluetooth/mgmt.c | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index d8f68c7..f20da05 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1114,7 +1114,7 @@ int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status);
int mgmt_start_discovery_cancelled(struct hci_dev *hdev);
int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status);
-int mgmt_discovering(struct hci_dev *hdev, u8 discovering);
+int mgmt_discovering(struct hci_dev *hdev, bool discovering);
int mgmt_interleaved_discovery(struct hci_dev *hdev);
int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 596660d..ce6a696 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -326,12 +326,12 @@ void hci_discovery_set_state(struct hci_dev *hdev, int state)
switch (state) {
case DISCOVERY_STOPPED:
if (hdev->discovery.state != DISCOVERY_STARTING)
- mgmt_discovering(hdev, 0);
+ mgmt_discovering(hdev, false);
break;
case DISCOVERY_STARTING:
break;
case DISCOVERY_FINDING:
- mgmt_discovering(hdev, 1);
+ mgmt_discovering(hdev, true);
break;
case DISCOVERY_RESOLVING:
break;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 3527095..ba5ca81 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3757,7 +3757,7 @@ int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
return err;
}
-int mgmt_discovering(struct hci_dev *hdev, u8 discovering)
+int mgmt_discovering(struct hci_dev *hdev, bool discovering)
{
struct mgmt_ev_discovering ev;
struct pending_cmd *cmd;
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 2/4] Bluetooth: Add mgmt_start_discovery_cancelled()
From: Jaganath Kanakkassery @ 2013-01-21 14:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Jaganath Kanakkassery
In-Reply-To: <1358777619-27018-1-git-send-email-jaganath.k@samsung.com>
This function can be used to inform userspace that start discovery
is cancelled
Signed-off-by: Jaganath Kanakkassery <jaganath.k@samsung.com>
---
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/mgmt.c | 19 +++++++++++++++++++
2 files changed, 20 insertions(+)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 014a2ea..d8f68c7 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1112,6 +1112,7 @@ int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, s8 rssi, u8 *name, u8 name_len);
int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status);
+int mgmt_start_discovery_cancelled(struct hci_dev *hdev);
int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status);
int mgmt_discovering(struct hci_dev *hdev, u8 discovering);
int mgmt_interleaved_discovery(struct hci_dev *hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index a7865ad..3527095 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3722,6 +3722,25 @@ int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
return err;
}
+int mgmt_start_discovery_cancelled(struct hci_dev *hdev)
+{
+ struct pending_cmd *cmd;
+ u8 type;
+ int err;
+
+ cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
+ if (!cmd)
+ return -ENOENT;
+
+ type = hdev->discovery.type;
+
+ err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, MGMT_STATUS_CANCELLED,
+ &type, sizeof(type));
+ mgmt_pending_remove(cmd);
+
+ return err;
+}
+
int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
{
struct pending_cmd *cmd;
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 1/4] Bluetooth: Move discovery state check inside hci_dev_lock()
From: Jaganath Kanakkassery @ 2013-01-21 14:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Jaganath Kanakkassery
After checking the discovery state, if other thread modifies it
then it will be overwritten by the assignment in the first thread.
Signed-off-by: Jaganath Kanakkassery <jaganath.k@samsung.com>
---
net/bluetooth/hci_event.c | 9 ++++-----
net/bluetooth/mgmt.c | 4 ----
2 files changed, 4 insertions(+), 9 deletions(-)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 705078a..97b4828 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1273,14 +1273,13 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
+ hci_dev_lock(hdev);
if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
- hdev->discovery.state == DISCOVERY_FINDING) {
+ hdev->discovery.state == DISCOVERY_FINDING)
mgmt_interleaved_discovery(hdev);
- } else {
- hci_dev_lock(hdev);
+ else
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
- hci_dev_unlock(hdev);
- }
+ hci_dev_unlock(hdev);
break;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 37add53..a7865ad 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2333,14 +2333,10 @@ int mgmt_interleaved_discovery(struct hci_dev *hdev)
BT_DBG("%s", hdev->name);
- hci_dev_lock(hdev);
-
err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR_LE);
if (err < 0)
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
- hci_dev_unlock(hdev);
-
return err;
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH] avctp: Fix size of read() for browsing channel callbacks
From: Alexandros Antonopoulos @ 2013-01-21 13:44 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1358775868-9963-1-git-send-email-alexandros.antonopoulos@oss.bmw-carit.de>
The read() function should attempt to read browsing->imtu bytes
and not sizeof(browsing->imtu).
---
profiles/audio/avctp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c
index 4309c60..acce507 100644
--- a/profiles/audio/avctp.c
+++ b/profiles/audio/avctp.c
@@ -649,7 +649,7 @@ static gboolean session_browsing_cb(GIOChannel *chan, GIOCondition cond,
sock = g_io_channel_unix_get_fd(chan);
- ret = read(sock, buf, sizeof(browsing->imtu));
+ ret = read(sock, buf, browsing->imtu);
if (ret <= 0)
goto failed;
--
1.8.1
^ permalink raw reply related
* [PATCH] avctp: Fix request timeout after a channel is destroyed
From: Alexandros Antonopoulos @ 2013-01-21 13:44 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1358775868-9963-1-git-send-email-alexandros.antonopoulos@oss.bmw-carit.de>
When the control channel is destroyed if there is a pending request
(chan->p) then the channel queue is deleted in avctp_channel_destroy
but the timer is still alive resulting in a SIGSEGV
---
profiles/audio/avctp.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c
index eb1d35e..e65594d 100644
--- a/profiles/audio/avctp.c
+++ b/profiles/audio/avctp.c
@@ -390,6 +390,9 @@ static void avctp_channel_destroy(struct avctp_channel *chan)
if (chan->watch)
g_source_remove(chan->watch);
+ if (chan->p)
+ pending_destroy(chan->p, NULL);
+
if (chan->process_id > 0)
g_source_remove(chan->process_id);
--
1.8.1
^ permalink raw reply related
* [PATCH] avctp: Fix avctp_unregister_browsing_pdu_handler inner loop
From: Alexandros Antonopoulos @ 2013-01-21 13:44 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1358775868-9963-1-git-send-email-alexandros.antonopoulos@oss.bmw-carit.de>
Inner loop should access the sessions data and not the servers
data
---
profiles/audio/avctp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c
index acce507..eb1d35e 100644
--- a/profiles/audio/avctp.c
+++ b/profiles/audio/avctp.c
@@ -1572,7 +1572,7 @@ gboolean avctp_unregister_browsing_pdu_handler(unsigned int id)
GSList *s;
for (s = server->sessions; s; s = s->next) {
- struct avctp *session = l->data;
+ struct avctp *session = s->data;
struct avctp_channel *browsing = session->browsing;
GSList *h;
--
1.8.1
^ permalink raw reply related
* [PATCH] Check uuid in disconnect profile.
From: Alexandros Antonopoulos @ 2013-01-21 13:44 UTC (permalink / raw)
To: linux-bluetooth
If the user calls Device1.DisconnectProfile with an invalid profile
uuid disconnect_profile still tries to parse the uuid resulting in
a SIGSEGV
---
src/device.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/device.c b/src/device.c
index 3675616..1771c0f 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1270,6 +1270,9 @@ static DBusMessage *disconnect_profile(DBusConnection *conn, DBusMessage *msg,
uuid = bt_name2string(pattern);
+ if (uuid == NULL)
+ return btd_error_invalid_args(msg);
+
p = find_connectable_profile(dev, uuid);
g_free(uuid);
--
1.8.1
^ permalink raw reply related
* [PATCH BlueZ] media: Fix custom property registration for multiple adapters
From: Luiz Augusto von Dentz @ 2013-01-21 13:34 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
The function btd_profile_add_custom_prop register a custom property for
an UUID which is valid for every adapter so its user_data cannot be tied
to a single adapter.
To fix this now NULL is passed as user_data and the callbacks checks if
the adapter passed has been registered and if there is an endpoint for
the UUID requested.
---
profiles/audio/media.c | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index 15dab8c..0ae9932 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -607,13 +607,28 @@ static gboolean endpoint_init_a2dp_sink(struct media_endpoint *endpoint,
return TRUE;
}
+static struct media_adapter *find_adapter(struct btd_device *device)
+{
+ GSList *l;
+
+ for (l = adapters; l; l = l->next) {
+ struct media_adapter *adapter = l->data;
+
+ if (adapter->btd_adapter == device_get_adapter(device))
+ return adapter;
+ }
+
+ return NULL;
+}
+
static bool endpoint_properties_exists(const char *uuid,
struct btd_device *dev,
void *user_data)
{
- struct media_adapter *adapter = user_data;
+ struct media_adapter *adapter;
- if (adapter->btd_adapter != device_get_adapter(dev))
+ adapter = find_adapter(dev);
+ if (adapter == NULL)
return false;
if (media_adapter_find_endpoint(adapter, NULL, NULL, uuid) == NULL)
@@ -659,10 +674,14 @@ static bool endpoint_properties_get(const char *uuid,
DBusMessageIter *iter,
void *user_data)
{
- struct media_adapter *adapter = user_data;
+ struct media_adapter *adapter;
DBusMessageIter dict;
GSList *l;
+ adapter = find_adapter(dev);
+ if (adapter == NULL)
+ return false;
+
dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
DBUS_TYPE_STRING_AS_STRING
@@ -743,7 +762,7 @@ static struct media_endpoint *media_endpoint_create(struct media_adapter *adapte
btd_profile_add_custom_prop(uuid, "a{sv}", "MediaEndpoints",
endpoint_properties_exists,
endpoint_properties_get,
- adapter);
+ NULL);
}
adapter->endpoints = g_slist_append(adapter->endpoints, endpoint);
--
1.8.0.2
^ permalink raw reply related
* [PATCH 3/3] a2dp: Fix invalid memory access during abort_ind()
From: Syam Sidhardhan @ 2013-01-21 13:33 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Syam Sidhardhan
In-Reply-To: <1358775211-31005-1-git-send-email-s.syam@samsung.com>
There is an invalid memory access w.r.t to the callback
during the Abort_Ind finalize_setup_errno().
We should terminate the variable arguments with NULL.
Log:
bluetoothd[3353]: audio/avdtp.c:avdtp_parse_cmd() Received ABORT_CMD
bluetoothd[3353]: audio/a2dp.c:abort_ind() Source 0xb6f5ecc8: Abort_Ind
bluetoothd[3353]: audio/a2dp.c:setup_ref() 0xb6f63200: ref=2
bluetoothd[3353]: audio/transport.c:media_transport_remove() Transport
/org/bluez/3353/hci0/dev_BC_47_60_F5_88_89/fd1 Owner :1.0
bluetoothd[3353]: audio/transport.c:media_transport_release() Transport
/org/bluez/3353/hci0/dev_BC_47_60_F5_88_89/fd1: read lock released
bluetoothd[3353]: audio/transport.c:media_transport_release() Transport
/org/bluez/3353/hci0/dev_BC_47_60_F5_88_89/fd1: write lock released
bluetoothd[3353]: audio/transport.c:media_request_reply() Request
Acquire Reply Input/output error
bluetoothd[3353]: audio/transport.c:media_owner_free() Owner :1.0
bluetoothd[3353]: audio/transport.c:media_owner_remove() Owner :1.0 Request Acquire
bluetoothd[3353]: audio/a2dp.c:a2dp_sep_unlock() SEP 0xb6f5ecc8 unlocked
bluetoothd[3353]: audio/a2dp.c:setup_unref() 0xb6f63200: ref=1
[sys_assert]START of sighandler
[sys-assert]exepath = bluetoothd
[sys-assert]processname = bluetoothd
[sys_assert]this thread is main thread. pid=3353
[sys-assert]cs timestr 1358524835
bluetoothd[3353]: crashed [1358524835] processname=bluetoothd, pid=3353, tid=3353, signal=11
[sys-assert]start print_node_to_file
sighandler = 0xb6e8cfc9, g_sig_oldact[i] = (nil)
[sys_assert]END of sighandler
Segmentation fault (core dumped)
---
profiles/audio/a2dp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index 3c546d9..efb4178 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -957,7 +957,7 @@ static void abort_ind(struct avdtp *session, struct avdtp_local_sep *sep,
finalize_setup_errno(setup, -ECONNRESET, finalize_suspend,
finalize_resume,
- finalize_config);
+ finalize_config, NULL);
return;
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH 2/3] a2dp: Fix invalid memory access during suspend_ind()
From: Syam Sidhardhan @ 2013-01-21 13:33 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Syam Sidhardhan
In-Reply-To: <1358775211-31005-1-git-send-email-s.syam@samsung.com>
There is a possible invalid memory access during suspend_ind().
We should terminate the variable arguments with NULL.
---
profiles/audio/a2dp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index 46f41a6..3c546d9 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -801,7 +801,7 @@ static gboolean suspend_ind(struct avdtp *session, struct avdtp_local_sep *sep,
if (start_err < 0 && start_err != -EINPROGRESS) {
error("avdtp_start: %s (%d)", strerror(-start_err),
-start_err);
- finalize_setup_errno(setup, start_err, finalize_resume);
+ finalize_setup_errno(setup, start_err, finalize_resume, NULL);
}
return TRUE;
--
1.7.9.5
^ permalink raw reply related
* [PATCH 1/3] health: Fix possible use after free
From: Syam Sidhardhan @ 2013-01-21 13:33 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Syam Sidhardhan
A pointer to freed memory is dereferenced if we call function
hdp_get_dcpsm_cb() with out any earlier reference.
---
profiles/health/hdp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/profiles/health/hdp.c b/profiles/health/hdp.c
index c15f06a..a42ca48 100644
--- a/profiles/health/hdp.c
+++ b/profiles/health/hdp.c
@@ -542,9 +542,9 @@ static void hdp_get_dcpsm_cb(uint16_t dcpsm, gpointer user_data, GError *err)
hdp_tmp_dc_data_destroy, &gerr))
return;
- hdp_tmp_dc_data_unref(hdp_conn);
hdp_conn->cb(hdp_chann->mdl, err, hdp_conn);
g_error_free(gerr);
+ hdp_tmp_dc_data_unref(hdp_conn);
}
static void device_reconnect_mdl_cb(struct mcap_mdl *mdl, GError *err,
--
1.7.9.5
^ permalink raw reply related
* Re: Object manager properties on Network1 Connect method call reply
From: Luiz Augusto von Dentz @ 2013-01-21 9:25 UTC (permalink / raw)
To: Patrik Flykt; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1358757002.7854.27.camel@pflykt-mobl1>
Hi Patrick,
On Mon, Jan 21, 2013 at 10:30 AM, Patrik Flykt
<patrik.flykt@linux.intel.com> wrote:
>
> Hi,
>
> While implementing ConnMan Bluez 5 plugin using GDBusProxy from ./gdbus
> I noticed the following things.
>
> On org.bluez.Network1.Connect method call return the object properties
> 'Connected', 'Interface' and 'UUID' have not yet been updated. It is of
> course obvious that if no error occurs, the network is connected. And
> the interface is provided as an argument to the method call return
> function so that's fine as well.
>
> If the method call signals an error, then the network is of course not
> connected. Except if the error is 'AlreadyConnected', which means it is.
> Since it is not possible to send arguments in an error reply, the only
> way to figure out the interface is via the 'Interface' GDBusProxy
> property. 'Connected' and 'UUID' properties are also set properly in
> this case.
I suppose you also have a callback to properties changed signal so in
case of AlreadyConnected error I guess you should not even call it if
you happen to detect it is already connected.
> From the above it would be more consistent if the properties were
> already set to their intended values when the Connect method call
> returns independent of success or failure. Thus one set of logic would
> suffice on ConnMan side to handle both cases.
>
> Maybe the org.bluez.Network1 object properties could be updated only for
> the Network1 object in question before sending the method call return?
> Of course the devil may be in the details of the Bluez 5 API why the
> object property update should not or can not be done this way.
Yep, we discussed this before an came to a conclusion that we probably
need a way to propagate changes immediately in certain situations to
avoid swallow changes, one idea was to modify
g_dbus_emit_property_changed to take a flag or create another property
flag e.g. G_DBUS_PROPERTY_FLAG_CHANGE_IMMEDIATELY or
G_DBUS_PROPERTY_FLAG_NO_WAIT.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re[2]: multiboot sync bluetooth pair key
From: Ilya Basin @ 2013-01-21 8:50 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <20130121082906.GC18141@aemeltch-MOBL1>
AE> Hi,
AE> On Sun, Jan 20, 2013 at 01:24:30PM +0400, Ilya Basin wrote:
>> Hi. Is there any software to sync the bluetooth pair key over Linux
>> and Windows, so one won't need to pair the device again?
AE> Why do you need to pair again? Do you mean your keys get lost?
For example, I boot Linux, pair the device and use it.
Then I boot Windows and I have to pair it too.
Then I boot Linux again: although I paired it already on this OS, the
phone doesn't think so. It refuses to work until I pair it again.
>> Where is the key stored on Linux?
AE> /var/lib/bluetooth/...
AE> Best regards
AE> Andrei Emeltchenko
>> Is it DE-specific?
>> Where is it stored on Windows?
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
^ permalink raw reply
* Object manager properties on Network1 Connect method call reply
From: Patrik Flykt @ 2013-01-21 8:30 UTC (permalink / raw)
To: linux-bluetooth
Hi,
While implementing ConnMan Bluez 5 plugin using GDBusProxy from ./gdbus
I noticed the following things.
On org.bluez.Network1.Connect method call return the object properties
'Connected', 'Interface' and 'UUID' have not yet been updated. It is of
course obvious that if no error occurs, the network is connected. And
the interface is provided as an argument to the method call return
function so that's fine as well.
If the method call signals an error, then the network is of course not
connected. Except if the error is 'AlreadyConnected', which means it is.
Since it is not possible to send arguments in an error reply, the only
way to figure out the interface is via the 'Interface' GDBusProxy
property. 'Connected' and 'UUID' properties are also set properly in
this case.
>From the above it would be more consistent if the properties were
already set to their intended values when the Connect method call
returns independent of success or failure. Thus one set of logic would
suffice on ConnMan side to handle both cases.
Maybe the org.bluez.Network1 object properties could be updated only for
the Network1 object in question before sending the method call return?
Of course the devil may be in the details of the Bluez 5 API why the
object property update should not or can not be done this way.
Just my €0.02 on this.
Cheers,
Patrik
^ permalink raw reply
* Re: multiboot sync bluetooth pair key
From: Andrei Emeltchenko @ 2013-01-21 8:29 UTC (permalink / raw)
To: Ilya Basin; +Cc: linux-bluetooth
In-Reply-To: <892087990.20130120132430@gmail.com>
Hi,
On Sun, Jan 20, 2013 at 01:24:30PM +0400, Ilya Basin wrote:
> Hi. Is there any software to sync the bluetooth pair key over Linux
> and Windows, so one won't need to pair the device again?
Why do you need to pair again? Do you mean your keys get lost?
> Where is the key stored on Linux?
/var/lib/bluetooth/...
Best regards
Andrei Emeltchenko
> Is it DE-specific?
> Where is it stored on Windows?
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: sd8688 firmware location
From: Ben Hutchings @ 2013-01-21 1:13 UTC (permalink / raw)
To: Dan Williams
Cc: Lubomir Rintel, David Woodhouse, libertas-dev, linux-bluetooth,
Gustavo Padovan, Marcel Holtmann, Johan Hedberg, linux-kernel
In-Reply-To: <1357771504.12030.59.camel@dcbw.foobar.com>
[-- Attachment #1: Type: text/plain, Size: 2093 bytes --]
On Wed, 2013-01-09 at 16:45 -0600, Dan Williams wrote:
> On Wed, 2013-01-09 at 00:56 +0100, Lubomir Rintel wrote:
> > Hi!
> >
> > btmrvl_sdio and libertas_sdio both use firmware files sd8688.bin and
> > sd8688_helper.bin. In linux-firmware, they're present in libertas/ tree and
> > (since 3d32a58b) libertas_sdio perfers loading it from there, while it is able
> > to fallback to load it from linux-firmware root. btmrvl_sdio, on the other hand
> > only looks in the root and ends up not being successful.
> >
> > Obviously, there are two solutions to the problem -- either teach btmrvl_sdio
> > to look into libertas/, or move the files in linux-firmware tree. I don't
> > really have a strong preference, though it probably makes less sense to keep in
> > in libertas/, since the bluetooth hardware is not really marketed as "Libertas."
> >
> > I'm following up with patches to linux and linux-firmware and I'd be very
> > thankful if you could pick one (not both of them).
>
> So the BT part and the wifi part have different SDIO IDs; are they
> actually connected separately to the SDIO bus? Or is the chip only in
> one mode at one time or something like that? Is there a problem with
> having both libertas and btmrvl loaded at the same time since they're
> essentially the same chip?
>
> I don't really mind moving stuff to mrvl/ out of libertas/ for these
> devices, but I do want some backwards compat code in libertas for that.
> Unless, of course, Marcel was talking about symlinks in the
> linux-firmware git tree, which would be fine with me. The important
> point is that simply updating your linux-firmware package or install or
> whatever *should not* result in a failed firmware load.
The general policy for linux-firmware.git has been that all filenames
required by all mainline kernel releases will be supported indefinitely.
There is already precedent for compatibility symlinks.
Ben.
--
Ben Hutchings
Q. Which is the greater problem in the world today, ignorance or apathy?
A. I don't know and I couldn't care less.
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox