* [PATCH BlueZ 4/6] AVRCP: Get player list if supported
From: Luiz Augusto von Dentz @ 2013-02-01 3:58 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1359691117-13847-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
If addressed player changed is supported get the list of players
---
profiles/audio/avrcp.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++
profiles/audio/player.c | 119 +++++++++++++++++++++++++++++++++++++++
profiles/audio/player.h | 4 ++
3 files changed, 270 insertions(+)
diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 8187ddf..793b5cf 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -99,6 +99,7 @@
#define AVRCP_REQUEST_CONTINUING 0x40
#define AVRCP_ABORT_CONTINUING 0x41
#define AVRCP_SET_ABSOLUTE_VOLUME 0x50
+#define AVRCP_GET_FOLDER_ITEMS 0x71
#define AVRCP_GENERAL_REJECT 0xA0
/* Capabilities for AVRCP_GET_CAPABILITIES pdu */
@@ -1859,6 +1860,151 @@ static void avrcp_get_element_attributes(struct avrcp *session)
session);
}
+static const char *type_to_string(uint8_t type)
+{
+ switch (type & 0x0F) {
+ case 0x01:
+ return "Audio";
+ case 0x02:
+ return "Video";
+ case 0x03:
+ return "Audio, Video";
+ case 0x04:
+ return "Audio Broadcasting";
+ case 0x05:
+ return "Audio, Audio Broadcasting";
+ case 0x06:
+ return "Video, Audio Broadcasting";
+ case 0x07:
+ return "Audio, Video, Audio Broadcasting";
+ case 0x08:
+ return "Video Broadcasting";
+ case 0x09:
+ return "Audio, Video Broadcasting";
+ case 0x0A:
+ return "Video, Video Broadcasting";
+ case 0x0B:
+ return "Audio, Video, Video Broadcasting";
+ case 0x0C:
+ return "Audio Broadcasting, Video Broadcasting";
+ case 0x0D:
+ return "Audio, Audio Broadcasting, Video Broadcasting";
+ case 0x0E:
+ return "Video, Audio Broadcasting, Video Broadcasting";
+ case 0x0F:
+ return "Audio, Video, Audio Broadcasting, Video Broadcasting";
+ }
+
+ return "None";
+}
+
+static const char *subtype_to_string(uint32_t subtype)
+{
+ switch (subtype & 0x03) {
+ case 0x01:
+ return "Audio Book";
+ case 0x02:
+ return "Podcast";
+ case 0x03:
+ return "Audio Book, Podcast";
+ }
+
+ return "None";
+}
+
+static void avrcp_parse_media_player_item(struct avrcp *session,
+ uint8_t *operands, uint16_t len)
+{
+ struct avrcp_player *player = session->player;
+ struct media_player *mp = player->user_data;
+ uint16_t id;
+ uint32_t subtype;
+ const char *curval, *strval;
+ uint64_t features[2];
+ char name[255];
+
+ if (len < 28)
+ return;
+
+ id = bt_get_be16(&operands[0]);
+
+ if (player->id != id)
+ return;
+
+ media_player_set_type(mp, type_to_string(operands[2]));
+
+ subtype = bt_get_be32(&operands[3]);
+
+ media_player_set_subtype(mp, subtype_to_string(subtype));
+
+ curval = media_player_get_status(mp);
+ strval = status_to_string(operands[7]);
+
+ if (g_strcmp0(curval, strval) != 0) {
+ media_player_set_status(mp, strval);
+ avrcp_get_play_status(session);
+ }
+
+ features[0] = bt_get_be64(&operands[8]);
+ features[1] = bt_get_be64(&operands[16]);
+
+ media_player_set_features(mp, features);
+
+ if (operands[26] == 0)
+ return;
+
+ memcpy(name, &operands[27], operands[26]);
+
+ media_player_set_name(mp, name);
+}
+
+static gboolean avrcp_get_media_player_list_rsp(struct avctp *conn,
+ uint8_t *operands,
+ size_t operand_count,
+ void *user_data)
+{
+ struct avrcp *session = user_data;
+ uint16_t count;
+ int i;
+
+ if (operands[3] != AVRCP_STATUS_SUCCESS || operand_count < 5)
+ return FALSE;
+
+ count = bt_get_be16(&operands[6]);
+
+ for (i = 8; count; count--) {
+ uint8_t type;
+ uint16_t len;
+
+ type = operands[i++];
+ len = bt_get_be16(&operands[i]);
+ i += 2;
+
+ if (type != 0x01) {
+ i += len;
+ continue;
+ }
+
+ avrcp_parse_media_player_item(session, &operands[i], len);
+ }
+
+ return FALSE;
+}
+
+static void avrcp_get_media_player_list(struct avrcp *session)
+{
+ uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 10];
+ struct avrcp_browsing_header *pdu = (void *) buf;
+
+ memset(buf, 0, sizeof(buf));
+
+ pdu->pdu_id = AVRCP_GET_FOLDER_ITEMS;
+ pdu->param_len = htons(10);
+
+ avctp_send_browsing_req(session->conn, buf, sizeof(buf),
+ avrcp_get_media_player_list_rsp, session);
+}
+
static gboolean avrcp_handle_event(struct avctp *conn,
uint8_t code, uint8_t subunit,
uint8_t *operands, size_t operand_count,
@@ -1944,6 +2090,7 @@ static gboolean avrcp_handle_event(struct avctp *conn,
player->id = id;
player->uid_counter = bt_get_be16(&pdu->params[3]);
+ avrcp_get_media_player_list(session);
break;
}
diff --git a/profiles/audio/player.c b/profiles/audio/player.c
index fb750fd..b4efa70 100644
--- a/profiles/audio/player.c
+++ b/profiles/audio/player.c
@@ -57,6 +57,10 @@ struct pending_req {
struct media_player {
char *device; /* Device path */
+ char *name; /* Player name */
+ char *type; /* Player type */
+ char *subtype; /* Player subtype */
+ uint64_t features[2]; /* Player features */
char *path; /* Player object path */
GHashTable *settings; /* Player settings */
GHashTable *track; /* Player current track */
@@ -272,6 +276,72 @@ static gboolean get_device(const GDBusPropertyTable *property,
return TRUE;
}
+static gboolean name_exists(const GDBusPropertyTable *property, void *data)
+{
+ struct media_player *mp = data;
+
+ return mp->name != NULL;
+}
+
+static gboolean get_name(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct media_player *mp = data;
+
+ if (mp->name == NULL)
+ return FALSE;
+
+ DBG("%s", mp->name);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &mp->name);
+
+ return TRUE;
+}
+
+static gboolean type_exists(const GDBusPropertyTable *property, void *data)
+{
+ struct media_player *mp = data;
+
+ return mp->type != NULL;
+}
+
+static gboolean get_type(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct media_player *mp = data;
+
+ if (mp->type == NULL)
+ return FALSE;
+
+ DBG("%s", mp->type);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &mp->type);
+
+ return TRUE;
+}
+
+static gboolean subtype_exists(const GDBusPropertyTable *property, void *data)
+{
+ struct media_player *mp = data;
+
+ return mp->subtype != NULL;
+}
+
+static gboolean get_subtype(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct media_player *mp = data;
+
+ if (mp->subtype == NULL)
+ return FALSE;
+
+ DBG("%s", mp->subtype);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &mp->subtype);
+
+ return TRUE;
+}
+
static DBusMessage *media_player_play(DBusConnection *conn, DBusMessage *msg,
void *data)
{
@@ -410,6 +480,12 @@ static const GDBusSignalTable media_player_signals[] = {
};
static const GDBusPropertyTable media_player_properties[] = {
+ { "Name", "s", get_name, NULL, name_exists,
+ G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+ { "Type", "s", get_type, NULL, type_exists,
+ G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+ { "Subtype", "s", get_subtype, NULL, subtype_exists,
+ G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
{ "Position", "u", get_position, NULL, NULL,
G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
{ "Status", "s", get_status, NULL, status_exists,
@@ -452,6 +528,9 @@ void media_player_destroy(struct media_player *mp)
g_free(mp->status);
g_free(mp->path);
g_free(mp->device);
+ g_free(mp->subtype);
+ g_free(mp->type);
+ g_free(mp->name);
g_free(mp);
}
@@ -618,6 +697,46 @@ void media_player_set_metadata(struct media_player *mp, const char *key,
g_hash_table_replace(mp->track, g_strdup(key), value);
}
+void media_player_set_type(struct media_player *mp, const char *type)
+{
+ DBG("%s", type);
+
+ mp->type = g_strdup(type);
+
+ g_dbus_emit_property_changed(btd_get_dbus_connection(),
+ mp->path, MEDIA_PLAYER_INTERFACE,
+ "Type");
+}
+
+void media_player_set_subtype(struct media_player *mp, const char *subtype)
+{
+ DBG("%s", subtype);
+
+ mp->subtype = g_strdup(subtype);
+
+ g_dbus_emit_property_changed(btd_get_dbus_connection(),
+ mp->path, MEDIA_PLAYER_INTERFACE,
+ "Subtype");
+}
+
+void media_player_set_name(struct media_player *mp, const char *name)
+{
+ DBG("%s", name);
+
+ mp->name = g_strdup(name);
+
+ g_dbus_emit_property_changed(btd_get_dbus_connection(),
+ mp->path, MEDIA_PLAYER_INTERFACE,
+ "Name");
+}
+
+void media_player_set_features(struct media_player *mp, uint64_t *features)
+{
+ DBG("0x%08zx %08zx", features[0], features[1]);
+
+ memcpy(features, mp->features, sizeof(mp->features));
+}
+
void media_player_set_callbacks(struct media_player *mp,
const struct media_player_callback *cbs,
void *user_data)
diff --git a/profiles/audio/player.h b/profiles/audio/player.h
index fec1d06..b546ba7 100644
--- a/profiles/audio/player.h
+++ b/profiles/audio/player.h
@@ -47,6 +47,10 @@ const char *media_player_get_status(struct media_player *mp);
void media_player_set_status(struct media_player *mp, const char *status);
void media_player_set_metadata(struct media_player *mp, const char *key,
void *data, size_t len);
+void media_player_set_type(struct media_player *mp, const char *type);
+void media_player_set_subtype(struct media_player *mp, const char *subtype);
+void media_player_set_features(struct media_player *mp, uint64_t *features);
+void media_player_set_name(struct media_player *mp, const char *name);
void media_player_set_callbacks(struct media_player *mp,
const struct media_player_callback *cbs,
--
1.8.1
^ permalink raw reply related
* [PATCH BlueZ 5/6] AVRCP: Split event handing to its own functions
From: Luiz Augusto von Dentz @ 2013-02-01 3:58 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1359691117-13847-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
profiles/audio/avrcp.c | 141 +++++++++++++++++++++++++++++--------------------
1 file changed, 85 insertions(+), 56 deletions(-)
diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 793b5cf..d1eb8ce 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -2005,21 +2005,94 @@ static void avrcp_get_media_player_list(struct avrcp *session)
avrcp_get_media_player_list_rsp, session);
}
+static void avrcp_volume_changed(struct avrcp *session,
+ struct avrcp_header *pdu)
+{
+ struct avrcp_player *player = session->player;
+ uint8_t volume;
+
+ if (player == NULL)
+ return;
+
+ volume = pdu->params[1] & 0x7F;
+
+ player->cb->set_volume(volume, session->dev, player->user_data);
+}
+
+static void avrcp_status_changed(struct avrcp *session,
+ struct avrcp_header *pdu)
+{
+ struct avrcp_player *player = session->player;
+ struct media_player *mp = player->user_data;
+ uint8_t value;
+ const char *curval, *strval;
+
+ value = pdu->params[1];
+
+ curval = media_player_get_status(mp);
+ strval = status_to_string(value);
+
+ if (g_strcmp0(curval, strval) == 0)
+ return;
+
+ media_player_set_status(mp, strval);
+ avrcp_get_play_status(session);
+}
+
+static void avrcp_track_changed(struct avrcp *session,
+ struct avrcp_header *pdu)
+{
+ avrcp_get_element_attributes(session);
+ avrcp_get_play_status(session);
+
+}
+
+static void avrcp_setting_changed(struct avrcp *session,
+ struct avrcp_header *pdu)
+{
+ struct avrcp_player *player = session->player;
+ struct media_player *mp = player->user_data;
+ uint8_t count = pdu->params[1];
+ int i;
+
+ for (i = 2; count > 0; count--, i += 2) {
+ const char *key;
+ const char *value;
+
+ key = attr_to_str(pdu->params[i]);
+ if (key == NULL)
+ continue;
+
+ value = attrval_to_str(pdu->params[i], pdu->params[i + 1]);
+ if (value == NULL)
+ continue;
+
+ media_player_set_setting(mp, key, value);
+ }
+}
+
+static void avrcp_addressed_player_changed(struct avrcp *session,
+ struct avrcp_header *pdu)
+{
+ struct avrcp_player *player = session->player;
+ uint16_t id = bt_get_be16(&pdu->params[1]);
+
+ if (player->id == id)
+ return;
+
+ player->id = id;
+ player->uid_counter = bt_get_le16(&pdu->params[3]);
+ avrcp_get_media_player_list(session);
+}
+
static gboolean avrcp_handle_event(struct avctp *conn,
uint8_t code, uint8_t subunit,
uint8_t *operands, size_t operand_count,
void *user_data)
{
struct avrcp *session = user_data;
- struct avrcp_player *player = session->player;
struct avrcp_header *pdu = (void *) operands;
- struct media_player *mp;
uint8_t event;
- uint8_t value;
- uint8_t count;
- uint16_t id;
- const char *curval, *strval;
- int i;
if (code != AVC_CTYPE_INTERIM && code != AVC_CTYPE_CHANGED)
return FALSE;
@@ -2034,63 +2107,19 @@ static gboolean avrcp_handle_event(struct avctp *conn,
switch (event) {
case AVRCP_EVENT_VOLUME_CHANGED:
- value = pdu->params[1] & 0x7F;
-
- if (player)
- player->cb->set_volume(value, session->dev,
- player->user_data);
-
+ avrcp_volume_changed(session, pdu);
break;
case AVRCP_EVENT_STATUS_CHANGED:
- mp = player->user_data;
- value = pdu->params[1];
-
- curval = media_player_get_status(mp);
- strval = status_to_string(value);
-
- if (g_strcmp0(curval, strval) != 0) {
- media_player_set_status(mp, strval);
- avrcp_get_play_status(session);
- }
-
+ avrcp_status_changed(session, pdu);
break;
case AVRCP_EVENT_TRACK_CHANGED:
- avrcp_get_element_attributes(session);
- avrcp_get_play_status(session);
-
+ avrcp_track_changed(session, pdu);
break;
-
case AVRCP_EVENT_SETTINGS_CHANGED:
- mp = player->user_data;
- count = pdu->params[1];
-
- for (i = 2; count > 0; count--, i += 2) {
- const char *key;
- const char *value;
-
- key = attr_to_str(pdu->params[i]);
- if (key == NULL)
- continue;
-
- value = attrval_to_str(pdu->params[i],
- pdu->params[i + 1]);
- if (value == NULL)
- continue;
-
- media_player_set_setting(mp, key, value);
- }
-
+ avrcp_setting_changed(session, pdu);
break;
-
case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
- id = bt_get_be16(&pdu->params[1]);
-
- if (player->id == id)
- break;
-
- player->id = id;
- player->uid_counter = bt_get_be16(&pdu->params[3]);
- avrcp_get_media_player_list(session);
+ avrcp_addressed_player_changed(session, pdu);
break;
}
--
1.8.1
^ permalink raw reply related
* [PATCH BlueZ 6/6] AVRCP: Set addressed player as browsed player
From: Luiz Augusto von Dentz @ 2013-02-01 3:58 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1359691117-13847-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This send SetBrowsedPlayer after getting the player details.
---
profiles/audio/avrcp.c | 73 +++++++++++++++++++++++--
profiles/audio/player.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++
profiles/audio/player.h | 2 +
3 files changed, 209 insertions(+), 5 deletions(-)
diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index d1eb8ce..00eeea1 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -99,6 +99,7 @@
#define AVRCP_REQUEST_CONTINUING 0x40
#define AVRCP_ABORT_CONTINUING 0x41
#define AVRCP_SET_ABSOLUTE_VOLUME 0x50
+#define AVRCP_SET_BROWSED_PLAYER 0x70
#define AVRCP_GET_FOLDER_ITEMS 0x71
#define AVRCP_GENERAL_REJECT 0xA0
@@ -1912,6 +1913,68 @@ static const char *subtype_to_string(uint32_t subtype)
return "None";
}
+static gboolean avrcp_set_browsed_player_rsp(struct avctp *conn,
+ uint8_t *operands,
+ size_t operand_count,
+ void *user_data)
+{
+ struct avrcp *session = user_data;
+ struct avrcp_player *player = session->player;
+ struct media_player *mp = player->user_data;
+ uint32_t items;
+ char **folders, *path;
+ uint8_t depth, count;
+ int i;
+
+ if (operands[3] != AVRCP_STATUS_SUCCESS || operand_count < 13)
+ return FALSE;
+
+ player->uid_counter = bt_get_be16(&operands[4]);
+
+ items = bt_get_be32(&operands[6]);
+
+ depth = operands[13];
+
+ folders = g_new0(char *, depth + 1);
+
+ for (i = 14, count = 0; count < depth; count++) {
+ char *part;
+ uint8_t len;
+
+ len = operands[i++];
+ part = g_memdup(&operands[i], len);
+ i += len;
+ folders[count] = part;
+ }
+
+ path = g_build_pathv("/", folders);
+ g_strfreev(folders);
+
+ media_player_set_folder(mp, path, items);
+
+ g_free(path);
+
+ return FALSE;
+}
+
+static void avrcp_set_browsed_player(struct avrcp *session,
+ struct avrcp_player *player)
+{
+ uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 2];
+ struct avrcp_browsing_header *pdu = (void *) buf;
+ uint16_t id;
+
+ memset(buf, 0, sizeof(buf));
+
+ pdu->pdu_id = AVRCP_SET_BROWSED_PLAYER;
+ id = htons(player->id);
+ memcpy(pdu->params, &id, 2);
+ pdu->param_len = htons(2);
+
+ avctp_send_browsing_req(session->conn, buf, sizeof(buf),
+ avrcp_set_browsed_player_rsp, session);
+}
+
static void avrcp_parse_media_player_item(struct avrcp *session,
uint8_t *operands, uint16_t len)
{
@@ -1950,12 +2013,12 @@ static void avrcp_parse_media_player_item(struct avrcp *session,
media_player_set_features(mp, features);
- if (operands[26] == 0)
- return;
-
- memcpy(name, &operands[27], operands[26]);
+ if (operands[26] != 0) {
+ memcpy(name, &operands[27], operands[26]);
+ media_player_set_name(mp, name);
+ }
- media_player_set_name(mp, name);
+ avrcp_set_browsed_player(session, player);
}
static gboolean avrcp_get_media_player_list_rsp(struct avctp *conn,
diff --git a/profiles/audio/player.c b/profiles/audio/player.c
index b4efa70..2f4ea83 100644
--- a/profiles/audio/player.c
+++ b/profiles/audio/player.c
@@ -43,6 +43,7 @@
#include "error.h"
#define MEDIA_PLAYER_INTERFACE "org.bluez.MediaPlayer1"
+#define MEDIA_FOLDER_INTERFACE "org.bluez.MediaFolder1"
struct player_callback {
const struct media_player_callback *cbs;
@@ -55,12 +56,18 @@ struct pending_req {
const char *value;
};
+struct media_folder {
+ char *name; /* Folder name */
+ uint32_t items; /* Number of items */
+};
+
struct media_player {
char *device; /* Device path */
char *name; /* Player name */
char *type; /* Player type */
char *subtype; /* Player subtype */
uint64_t features[2]; /* Player features */
+ struct media_folder *folder; /* Player currenct folder */
char *path; /* Player object path */
GHashTable *settings; /* Player settings */
GHashTable *track; /* Player current track */
@@ -505,6 +512,104 @@ static const GDBusPropertyTable media_player_properties[] = {
{ }
};
+static DBusMessage *media_folder_search(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ return btd_error_failed(msg, strerror(ENOTSUP));
+}
+
+static DBusMessage *media_folder_list_items(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ return btd_error_failed(msg, strerror(ENOTSUP));
+}
+
+
+static DBusMessage *media_folder_change_folder(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ return btd_error_failed(msg, strerror(ENOTSUP));
+}
+
+static gboolean folder_name_exists(const GDBusPropertyTable *property,
+ void *data)
+{
+ struct media_player *mp = data;
+
+ if (mp->folder == NULL)
+ return FALSE;
+
+ return mp->folder->name != NULL;
+}
+
+static gboolean get_folder_name(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct media_player *mp = data;
+
+ if (mp->folder == NULL || mp->folder->name == NULL)
+ return FALSE;
+
+ DBG("%s", mp->folder->name);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+ &mp->folder->name);
+
+ return TRUE;
+}
+
+static gboolean items_exists(const GDBusPropertyTable *property, void *data)
+{
+ struct media_player *mp = data;
+
+ return mp->folder != NULL;
+}
+
+static gboolean get_items(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct media_player *mp = data;
+
+ if (mp->folder == NULL)
+ return FALSE;
+
+ DBG("%u", mp->folder->items);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32,
+ &mp->folder->items);
+
+ return TRUE;
+}
+
+static const GDBusMethodTable media_folder_methods[] = {
+ { GDBUS_EXPERIMENTAL_METHOD("Search",
+ GDBUS_ARGS({ "string", "s" }, { "filter", "a{sv}" }),
+ GDBUS_ARGS({ "folder", "o" }),
+ media_folder_search) },
+ { GDBUS_EXPERIMENTAL_METHOD("ListItems",
+ GDBUS_ARGS({ "filter", "a{sv}" }),
+ GDBUS_ARGS({ "items", "a{oa{sv}}" }),
+ media_folder_list_items) },
+ { GDBUS_EXPERIMENTAL_METHOD("ChangeFolder",
+ GDBUS_ARGS({ "folder", "o" }), NULL,
+ media_folder_change_folder) },
+ { }
+};
+
+static const GDBusPropertyTable media_folder_properties[] = {
+ { "Name", "s", get_folder_name, NULL, folder_name_exists,
+ G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+ { "NumberOfItems", "u", get_items, NULL, items_exists,
+ G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+ { }
+};
+
+static void media_folder_destroy(struct media_folder *folder)
+{
+ g_free(folder->name);
+ g_free(folder);
+}
+
void media_player_destroy(struct media_player *mp)
{
DBG("%s", mp->path);
@@ -521,6 +626,13 @@ void media_player_destroy(struct media_player *mp)
if (mp->process_id > 0)
g_source_remove(mp->process_id);
+ if (mp->folder) {
+ g_dbus_unregister_interface(btd_get_dbus_connection(),
+ mp->path,
+ MEDIA_FOLDER_INTERFACE);
+ media_folder_destroy(mp->folder);
+ }
+
g_slist_free_full(mp->pending, g_free);
g_timer_destroy(mp->progress);
@@ -730,6 +842,33 @@ void media_player_set_name(struct media_player *mp, const char *name)
"Name");
}
+void media_player_set_folder(struct media_player *mp, const char *path,
+ uint32_t items)
+{
+ struct media_folder *folder;
+
+ DBG("%s items %u", path, items);
+
+ if (mp->folder != NULL)
+ media_folder_destroy(mp->folder);
+
+ folder = g_new0(struct media_folder, 1);
+ folder->name = g_strdup(path);
+ folder->items = items;
+ mp->folder = folder;
+
+ if (!g_dbus_register_interface(btd_get_dbus_connection(),
+ mp->path, MEDIA_FOLDER_INTERFACE,
+ media_folder_methods,
+ NULL,
+ media_folder_properties, mp, NULL)) {
+ error("D-Bus failed to register %s on %s path",
+ MEDIA_FOLDER_INTERFACE, mp->path);
+ media_folder_destroy(mp->folder);
+ mp->folder = NULL;
+ }
+}
+
void media_player_set_features(struct media_player *mp, uint64_t *features)
{
DBG("0x%08zx %08zx", features[0], features[1]);
diff --git a/profiles/audio/player.h b/profiles/audio/player.h
index b546ba7..1ac9800 100644
--- a/profiles/audio/player.h
+++ b/profiles/audio/player.h
@@ -51,6 +51,8 @@ void media_player_set_type(struct media_player *mp, const char *type);
void media_player_set_subtype(struct media_player *mp, const char *subtype);
void media_player_set_features(struct media_player *mp, uint64_t *features);
void media_player_set_name(struct media_player *mp, const char *name);
+void media_player_set_folder(struct media_player *mp, const char *path,
+ uint32_t items);
void media_player_set_callbacks(struct media_player *mp,
const struct media_player_callback *cbs,
--
1.8.1
^ permalink raw reply related
* Accepting RFCOMM connections without pairing?
From: Tim Connolly @ 2013-02-01 9:20 UTC (permalink / raw)
To: linux-bluetooth
Can anybody point me to sample code for an RFCOMM server that can accept
connections without the need for pairing?
I am trying to get this working under Debian Squeeze, which has Bluez
4.66. Both ends of the connection are using Bluetooth v2.0 hardware.
I found this discussion:
http://permalink.gmane.org/gmane.linux.bluez.kernel/13828
indicating that with my hardware, adjusting the security level on the
server socket will disable pairing. However, I have not been able to
make this work - bluetoothd triggers a link_key_request and
pin_code_request on every connection attempt.
Any advice you can offer would be greatly appreciated.
--
Current test server:
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
int main(int argc, char **argv)
{
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
int s, client, bytes_read;
unsigned int opt = sizeof(rem_addr);
// allocate socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
struct bt_security sec = { BT_SECURITY_LOW };
if (setsockopt(s, SOL_BLUETOOTH, BT_SECURITY, &sec, sizeof(sec)) < 0) {
fprintf(stderr, "failed to set security level");
return 2;
}
// bind socket to port 1 of the first available bluetooth adapter
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = *BDADDR_ANY;
loc_addr.rc_channel = 1;
bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
// put socket into listening mode
listen(s, 1);
// accept one connection
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf(stderr, "accepted connection from %s\n", buf);
memset(buf, 0, sizeof(buf));
// read data from the client
bytes_read = recv(client, buf, sizeof(buf), 0);
if( bytes_read > 0 ) {
printf("received [%s]\n", buf);
}
// close connection
close(client);
close(s);
return 0;
}
^ permalink raw reply
* [PATCH] network: Fix user data handling on unregister
From: patrik.flykt @ 2013-02-01 11:19 UTC (permalink / raw)
To: linux-bluetooth
From: Patrik Flykt <patrik.flykt@linux.intel.com>
User data in unregister_server() is a network_adapter struct. Unregistering
using full UUID will now also work.
---
profiles/network/server.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/profiles/network/server.c b/profiles/network/server.c
index 864b49c..c8bfed5 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -676,7 +676,8 @@ static DBusMessage *register_server(DBusConnection *conn,
static DBusMessage *unregister_server(DBusConnection *conn,
DBusMessage *msg, void *data)
{
- struct network_server *ns = data;
+ struct network_adapter *na = data;
+ struct network_server *ns;
DBusMessage *reply;
const char *uuid;
@@ -684,7 +685,9 @@ static DBusMessage *unregister_server(DBusConnection *conn,
DBUS_TYPE_INVALID))
return btd_error_invalid_args(msg);
- if (g_strcmp0(uuid, "nap"))
+ ns = find_server_by_uuid(na->servers, uuid);
+
+ if (ns == NULL)
return btd_error_failed(msg, "Invalid UUID");
reply = dbus_message_new_method_return(msg);
--
1.7.10.4
^ permalink raw reply related
* RE: [PATCH] Add heartrate monitoring LE device to auto connect list.
From: Damjan Cvetko @ 2013-02-01 13:39 UTC (permalink / raw)
To: Johan Hedberg; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <20130129233606.GA16365@x220>
> This patch isn't needed anymore since btd_device_add_attio_callback was fixed to enable the auto connecting. Please verify that latest git works for you.
Hi Johan.
Sorry, could not get back earlier.
Generally the latest code works, but not always. Every so often the reconnect would not happen. Here a snip from output when the reconnection does not happen (or fails somehow):
bluetoothd[4628]: src/attrib-server.c:channel_handler() op 0x1b
bluetoothd[4628]: src/adapter.c:dev_disconnected() Device 00:22:D0:00:00:64 disconnected, reason 0
bluetoothd[4628]: src/adapter.c:adapter_remove_connection()
bluetoothd[4628]: src/device.c:device_bonding_complete() bonding (nil) status 0x0e
bluetoothd[4628]: src/device.c:device_bonding_failed() status 14
bluetoothd[4628]: src/adapter.c:resume_discovery()
bluetoothd[4628]: attrib/gattrib.c:g_attrib_unref() 0x1f9eda8: ref=4
bluetoothd[4628]: profiles/heartrate/heartrate.c:attio_disconnected_cb()
bluetoothd[4628]: attrib/gattrib.c:g_attrib_unref() 0x1f9eda8: ref=3
bluetoothd[4628]: attrib/gattrib.c:g_attrib_unref() 0x1f9eda8: ref=2
bluetoothd[4628]: g_attrib_unregister: invalid id
bluetoothd[4628]: attrib/gattrib.c:g_attrib_unref() 0x1f9eda8: ref=1
bluetoothd[4628]: src/adapter.c:adapter_connect_list_add() /org/bluez/hci0/dev_00_22_D0_00_00_64 added to BlueZ 5.1's connect_list
bluetoothd[4628]: src/adapter.c:trigger_passive_scanning()
bluetoothd[4628]: attrib/gattrib.c:g_attrib_unref() 0x1f9eda8: ref=0
bluetoothd[4628]: src/adapter.c:passive_scanning_complete() status 0x00
bluetoothd[4628]: src/adapter.c:discovering_callback() hci0 type 6 discovering 1
bluetoothd[4628]: src/adapter.c:device_found_callback() hci0 addr 00:22:D0:00:00:64, rssi -91 flags 0x0000 eir_len 17
bluetoothd[4628]: src/device.c:device_set_legacy() legacy 0
bluetoothd[4628]: src/adapter.c:stop_passive_scanning()
bluetoothd[4628]: src/device.c:device_connect_le() Connection attempt to: 00:22:D0:00:00:64
bluetoothd[4628]: src/adapter.c:discovering_callback() hci0 type 6 discovering 0
bluetoothd[4628]: src/adapter.c:connected_callback() hci0 device 00:22:D0:00:00:64 connected eir_len 0
bluetoothd[4628]: src/adapter.c:dev_disconnected() Device 00:22:D0:00:00:64 disconnected, reason 0
bluetoothd[4628]: src/adapter.c:adapter_remove_connection()
bluetoothd[4628]: src/device.c:device_bonding_complete() bonding (nil) status 0x0e
bluetoothd[4628]: src/device.c:device_bonding_failed() status 14
bluetoothd[4628]: src/adapter.c:resume_discovery()
bluetoothd[4628]: src/device.c:att_connect_cb() connect error: Function not implemented (38)
bluetoothd[4628]: src/device.c:att_error_cb() Enabling automatic connections
bluetoothd[4628]: src/adapter.c:adapter_connect_list_add() ignoring already added device /org/bluez/hci0/dev_00_22_D0_00_00_64
(end)
And for reference a situation where reconnection works:
bluetoothd[4628]: src/attrib-server.c:channel_handler() op 0x1b
bluetoothd[4628]: src/adapter.c:dev_disconnected() Device 00:22:D0:00:00:64 disconnected, reason 0
bluetoothd[4628]: src/adapter.c:adapter_remove_connection()
bluetoothd[4628]: src/device.c:device_bonding_complete() bonding (nil) status 0x0e
bluetoothd[4628]: src/device.c:device_bonding_failed() status 14
bluetoothd[4628]: src/adapter.c:resume_discovery()
bluetoothd[4628]: attrib/gattrib.c:g_attrib_unref() 0x1fa33e8: ref=4
bluetoothd[4628]: profiles/heartrate/heartrate.c:attio_disconnected_cb()
bluetoothd[4628]: attrib/gattrib.c:g_attrib_unref() 0x1fa33e8: ref=3
bluetoothd[4628]: attrib/gattrib.c:g_attrib_unref() 0x1fa33e8: ref=2
bluetoothd[4628]: g_attrib_unregister: invalid id
bluetoothd[4628]: attrib/gattrib.c:g_attrib_unref() 0x1fa33e8: ref=1
bluetoothd[4628]: src/adapter.c:adapter_connect_list_add() /org/bluez/hci0/dev_00_22_D0_00_00_64 added to BlueZ 5.1's connect_list
bluetoothd[4628]: src/adapter.c:trigger_passive_scanning()
bluetoothd[4628]: attrib/gattrib.c:g_attrib_unref() 0x1fa33e8: ref=0
bluetoothd[4628]: src/adapter.c:passive_scanning_complete() status 0x00
bluetoothd[4628]: src/adapter.c:discovering_callback() hci0 type 6 discovering 1
bluetoothd[4628]: src/adapter.c:device_found_callback() hci0 addr 00:22:D0:00:00:64, rssi -87 flags 0x0000 eir_len 17
bluetoothd[4628]: src/device.c:device_set_legacy() legacy 0
bluetoothd[4628]: src/device.c:device_set_rssi() rssi -87 delta 10
bluetoothd[4628]: src/adapter.c:stop_passive_scanning()
bluetoothd[4628]: src/adapter.c:device_found_callback() hci0 addr 00:22:D0:00:00:64, rssi -87 flags 0x0000 eir_len 17
bluetoothd[4628]: src/device.c:device_set_legacy() legacy 0
bluetoothd[4628]: src/adapter.c:stop_passive_scanning()
bluetoothd[4628]: src/device.c:device_connect_le() Connection attempt to: 00:22:D0:00:00:64
bluetoothd[4628]: src/adapter.c:discovering_callback() hci0 type 6 discovering 0
bluetoothd[4628]: Stopping passive scanning failed: Rejected
bluetoothd[4628]: src/adapter.c:connected_callback() hci0 device 00:22:D0:00:00:64 connected eir_len 0
bluetoothd[4628]: attrib/gattrib.c:g_attrib_ref() 0x1f9eda8: ref=1
bluetoothd[4628]: attrib/gattrib.c:g_attrib_ref() 0x1f9eda8: ref=2
bluetoothd[4628]: src/adapter.c:adapter_connect_list_remove() /org/bluez/hci0/dev_00_22_D0_00_00_64 removed from BlueZ 5.1's connect_list
bluetoothd[4628]: src/adapter.c:stop_passive_scanning()
bluetoothd[4628]: profiles/heartrate/heartrate.c:attio_connected_cb()
bluetoothd[4628]: attrib/gattrib.c:g_attrib_ref() 0x1f9eda8: ref=3
bluetoothd[4628]: attrib/gattrib.c:g_attrib_ref() 0x1f9eda8: ref=4
bluetoothd[4628]: attrib/gattrib.c:g_attrib_ref() 0x1f9eda8: ref=5
(goes on)
I did not have time yet to look into this, will try to do it next week. With the old solution this did not happen in the window of one week when constantly testing this.
Best regards,
Damjan
^ permalink raw reply
* [PATCH] Bluetooth: Refactor mgmt_pending_foreach
From: Andre Guedes @ 2013-02-01 14:21 UTC (permalink / raw)
To: linux-bluetooth
This patch does a trivial refactor in mgmt_pending_foreach function.
It replaces list_for_each_safe by list_for_each_entry_safe, simplifying
the function.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
net/bluetooth/mgmt.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 3bd4c41..39395c7 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -760,13 +760,9 @@ static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
void *data),
void *data)
{
- struct list_head *p, *n;
-
- list_for_each_safe(p, n, &hdev->mgmt_pending) {
- struct pending_cmd *cmd;
-
- cmd = list_entry(p, struct pending_cmd, list);
+ struct pending_cmd *cmd, *tmp;
+ list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
if (opcode > 0 && cmd->opcode != opcode)
continue;
--
1.8.1.1
^ permalink raw reply related
* Re: [PATCH] network: Fix user data handling on unregister
From: Johan Hedberg @ 2013-02-01 15:57 UTC (permalink / raw)
To: patrik.flykt; +Cc: linux-bluetooth
In-Reply-To: <1359717591-32532-1-git-send-email-patrik.flykt@linux.intel.com>
Hi Patrik,
On Fri, Feb 01, 2013, patrik.flykt@linux.intel.com wrote:
> User data in unregister_server() is a network_adapter struct. Unregistering
> using full UUID will now also work.
> ---
> profiles/network/server.c | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
Applied. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH] Add heartrate monitoring LE device to auto connect list.
From: Johan Hedberg @ 2013-02-01 16:11 UTC (permalink / raw)
To: Damjan Cvetko; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CEE0DF8E7B2727428D202DA3F3FBC4DD8C756889@PULWAR.mtk.lan>
Hi Damjan,
On Fri, Feb 01, 2013, Damjan Cvetko wrote:
> Generally the latest code works, but not always. Every so often the
> reconnect would not happen. Here a snip from output when the
> reconnection does not happen (or fails somehow):
>
> bluetoothd[4628]: src/attrib-server.c:channel_handler() op 0x1b
> bluetoothd[4628]: src/adapter.c:dev_disconnected() Device 00:22:D0:00:00:64 disconnected, reason 0
> bluetoothd[4628]: src/adapter.c:adapter_remove_connection()
> bluetoothd[4628]: src/device.c:device_bonding_complete() bonding (nil) status 0x0e
> bluetoothd[4628]: src/device.c:device_bonding_failed() status 14
> bluetoothd[4628]: src/adapter.c:resume_discovery()
> bluetoothd[4628]: attrib/gattrib.c:g_attrib_unref() 0x1f9eda8: ref=4
> bluetoothd[4628]: profiles/heartrate/heartrate.c:attio_disconnected_cb()
> bluetoothd[4628]: attrib/gattrib.c:g_attrib_unref() 0x1f9eda8: ref=3
> bluetoothd[4628]: attrib/gattrib.c:g_attrib_unref() 0x1f9eda8: ref=2
> bluetoothd[4628]: g_attrib_unregister: invalid id
> bluetoothd[4628]: attrib/gattrib.c:g_attrib_unref() 0x1f9eda8: ref=1
> bluetoothd[4628]: src/adapter.c:adapter_connect_list_add() /org/bluez/hci0/dev_00_22_D0_00_00_64 added to BlueZ 5.1's connect_list
> bluetoothd[4628]: src/adapter.c:trigger_passive_scanning()
> bluetoothd[4628]: attrib/gattrib.c:g_attrib_unref() 0x1f9eda8: ref=0
> bluetoothd[4628]: src/adapter.c:passive_scanning_complete() status 0x00
> bluetoothd[4628]: src/adapter.c:discovering_callback() hci0 type 6 discovering 1
> bluetoothd[4628]: src/adapter.c:device_found_callback() hci0 addr 00:22:D0:00:00:64, rssi -91 flags 0x0000 eir_len 17
> bluetoothd[4628]: src/device.c:device_set_legacy() legacy 0
> bluetoothd[4628]: src/adapter.c:stop_passive_scanning()
> bluetoothd[4628]: src/device.c:device_connect_le() Connection attempt to: 00:22:D0:00:00:64
> bluetoothd[4628]: src/adapter.c:discovering_callback() hci0 type 6 discovering 0
> bluetoothd[4628]: src/adapter.c:connected_callback() hci0 device 00:22:D0:00:00:64 connected eir_len 0
> bluetoothd[4628]: src/adapter.c:dev_disconnected() Device 00:22:D0:00:00:64 disconnected, reason 0
> bluetoothd[4628]: src/adapter.c:adapter_remove_connection()
> bluetoothd[4628]: src/device.c:device_bonding_complete() bonding (nil) status 0x0e
> bluetoothd[4628]: src/device.c:device_bonding_failed() status 14
> bluetoothd[4628]: src/adapter.c:resume_discovery()
> bluetoothd[4628]: src/device.c:att_connect_cb() connect error: Function not implemented (38)
It's hard to say exactly why the connection is failing here without the
HCI logs. Could you run btmon simultaneously and let me know the output.
Also please update to latest bluez.git since there might be some fixes
that you have missed.
Johan
^ permalink raw reply
* Re: [PATCH v2 1/4] Bluetooth: Add option for SCO socket mode
From: Johan Hedberg @ 2013-02-01 16:26 UTC (permalink / raw)
To: Frédéric Dalleau; +Cc: linux-bluetooth
In-Reply-To: <1359561800-12870-2-git-send-email-frederic.dalleau@linux.intel.com>
Hi Frédéric,
On Wed, Jan 30, 2013, Frédéric Dalleau wrote:
> +#define SCO_MODE_CVSD 0x00
> +#define SCO_MODE_TRANSPARENT 0x01
> +#define SCO_MODE_MAX 0x02
If you're going to have a MAX define better make it the real maximum
instead of max + 1.
> + if (opts.mode >= SCO_MODE_MAX) {
> + err = -EINVAL;
> + break;
> + }
It makes this check also look a bit nicer since you use > instead of >=
Johan
^ permalink raw reply
* Re: [PATCH v2 2/4] Bluetooth: Use mode to create SCO connection
From: Johan Hedberg @ 2013-02-01 16:29 UTC (permalink / raw)
To: Frédéric Dalleau; +Cc: linux-bluetooth
In-Reply-To: <1359561800-12870-3-git-send-email-frederic.dalleau@linux.intel.com>
Hi Frédéric,
On Wed, Jan 30, 2013, Frédéric Dalleau wrote:
> + switch (mode) {
> + case 0:
> + cp.max_latency = __constant_cpu_to_le16(0xffff);
> + cp.content_format = cpu_to_le16(hdev->voice_setting);
> + cp.retrans_effort = 0xff;
> + break;
> + case 1:
> + if (conn->pkt_type & ESCO_2EV3)
> + cp.max_latency = __constant_cpu_to_le16(0x0008);
> + else
> + cp.max_latency = __constant_cpu_to_le16(0x000D);
> + cp.content_format = __constant_cpu_to_le16(0x0003);
> + cp.retrans_effort = 0x02;
> + break;
> + }
Why are you using 0 and 1 here instead of your nice defines?
Johan
^ permalink raw reply
* Re: [PATCH] Bluetooth: Remove unneeded locking
From: Gustavo Padovan @ 2013-02-01 17:23 UTC (permalink / raw)
To: Andre Guedes; +Cc: linux-bluetooth
In-Reply-To: <1359673930-18226-1-git-send-email-andre.guedes@openbossa.org>
Hi Andre,
* Andre Guedes <andre.guedes@openbossa.org> [2013-01-31 20:12:10 -0300]:
> This patch removes unneeded locking in hci_le_adv_report_evt. There
> is no need to lock hdev before calling mgmt_device_found.
>
> Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> ---
> net/bluetooth/hci_event.c | 4 ----
> 1 file changed, 4 deletions(-)
Patch has been applied to bluetooth-next. Thanks.
Gustavo
^ permalink raw reply
* Re: [PATCH] Bluetooth: Refactor mgmt_pending_foreach
From: Gustavo Padovan @ 2013-02-01 17:27 UTC (permalink / raw)
To: Andre Guedes; +Cc: linux-bluetooth
In-Reply-To: <1359728490-26097-1-git-send-email-andre.guedes@openbossa.org>
Hi Andre,
* Andre Guedes <andre.guedes@openbossa.org> [2013-02-01 11:21:30 -0300]:
> This patch does a trivial refactor in mgmt_pending_foreach function.
> It replaces list_for_each_safe by list_for_each_entry_safe, simplifying
> the function.
>
> Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> ---
> net/bluetooth/mgmt.c | 8 ++------
> 1 file changed, 2 insertions(+), 6 deletions(-)
Patch has been applied to bluetooth-next. Thanks.
Gustavo
^ permalink raw reply
* pull request: bluetooth 2013-02-01
From: Gustavo Padovan @ 2013-02-01 17:33 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, linux-bluetooth, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 1091 bytes --]
Hi John,
Two simple fixes for 3.8. One of the patches fixes a situation where the
connection wasn't terminated if a timeout ocurrs for LE an SCO connections.
The other fixes prevent NULL dereference in the SMP code, it is a security fix
as well.
Please pull, or let me know of any problems!
Gustavo
---
The following changes since commit b7e98b5100aad9290d7f06fcb9d1e80f7f62f05f:
Bluetooth: Check if the hci connection exists in SCO shutdown (2013-01-10 03:53:32 -0200)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth for-upstream
for you to fetch changes up to 4c02e2d444595200d0b18b889994aac3611cd288:
Bluetooth: Fix hci_conn timeout routine (2013-01-31 15:38:02 -0200)
----------------------------------------------------------------
Andre Guedes (1):
Bluetooth: Fix hci_conn timeout routine
Johan Hedberg (1):
Bluetooth: Fix handling of unexpected SMP PDUs
net/bluetooth/hci_conn.c | 6 +++---
net/bluetooth/smp.c | 13 +++++++++++++
2 files changed, 16 insertions(+), 3 deletions(-)
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* [PATCH BlueZ] device: Fix not marking svc_resolved when loaded from storage
From: Vinicius Costa Gomes @ 2013-02-01 17:37 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
When the device is loaded from storage, we should mark it as it
services were resolved.
---
src/device.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/device.c b/src/device.c
index 452ccfe..49f8957 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1849,6 +1849,9 @@ next:
bt_uuid_strcmp);
}
g_strfreev(uuids);
+
+ /* Discovered services restored from storage */
+ device->svc_resolved = true;
}
/* Load device id */
--
1.8.1.1
^ permalink raw reply related
* pull request: bluetooth-next 2013-02-01
From: Gustavo Padovan @ 2013-02-01 17:40 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, linux-bluetooth, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 4833 bytes --]
Hi John,
Here goes another batch intended for 3.9, the majority of the patch here are
from Johan who is fixing many issues in the management interface that have
appeared lately. The rest of the patches are just small improvements, fixes
and clean ups.
Please pull! Thanks a lot!
Gustavo
---
wing changes since commit e7f767a7d9f809c494bfffffeda2bbdbfec110b4:
mwifiex: use map/unmap APIs in TX and RX to reduce memcpy (2013-01-07 15:18:30 -0500)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next master
for you to fetch changes up to 6f02fc91b645ac909bec2d55ee1f345177282f37:
Bluetooth: Refactor mgmt_pending_foreach (2013-02-01 14:49:24 -0200)
----------------------------------------------------------------
Andre Guedes (3):
Bluetooth: Reduce critical section in sco_conn_ready
Bluetooth: Remove unneeded locking
Bluetooth: Refactor mgmt_pending_foreach
Andrei Emeltchenko (4):
Bluetooth: AMP: Send A2MP Create Phylink Rsp after Assoc write
Bluetooth: AMP: Clean up logical link create / accept
Bluetooth: AMP: Remove dead code
Bluetooth: AMP: Use set_bit / test_bit for amp_mgr state
Gustavo Padovan (1):
Bluetooth: Fix uuid output in debugfs
Johan Hedberg (36):
Bluetooth: Fix missing command complete event for mgmt_confirm_name
Bluetooth: Fix missing command complete for mgmt_load_long_term_keys
Bluetooth: Fix checking for valid device class values
Bluetooth: Fix accepting set_dev_class for non-BR/EDR controllers
Bluetooth: Move non-critical sections outside of the dev lock
Bluetooth: Fix checking for exact values of boolean mgmt parameters
Bluetooth: Fix returning proper command status for start_discovery
Bluetooth: Fix sending incorrect new_settings for mgmt_set_powered
Bluetooth: Add a new workqueue for hci_request operations
Bluetooth: Use req_workqueue for hci_request operations
Bluetooth: Fix using system-global workqueue when not necessary
Bluetooth: Fix Class of Device indication when powering off
Bluetooth: Fix checking for correct mgmt_load_link_keys parameters
Bluetooth: Fix returning proper mgmt status for Load LTKs
Bluetooth: Fix checking for proper key->master value in Load LTKs
Bluetooth: Refactor valid LTK data testing into its own function
Bluetooth: Check for valid key->authenticated value for LTKs
Bluetooth: Add helper functions for testing bdaddr types
Bluetooth: Fix checking for valid address type values in mgmt commands
Bluetooth: Fix checking for valid disconnect parameters in unpair_device
Bluetooth: Fix returning proper cmd_complete for mgmt_disconnect
Bluetooth: Fix returning proper cmd_complete for mgmt_block/unblock
Bluetooth: Add LE Local Features reading support
Bluetooth: Add support for reading LE White List Size
Bluetooth: Add support for reading LE supported states
Bluetooth: Store UUIDs in the same order that they were added
Bluetooth: Simplify UUIDs clearing code
Bluetooth: Keep track of UUID type upon addition
Bluetooth: Simplify UUID removal code
Bluetooth: Simplify UUID16 list generation for EIR
Bluetooth: Remove useless eir_len variable from EIR creation
Bluetooth: Refactor UUID-16 list generation into its own function
Bluetooth: Add support for 32-bit UUIDs in EIR data
Bluetooth: Add support for 128-bit UUIDs in EIR data
Bluetooth: Fix link security setting when powering on
Bluetooth: Increment Management interface revision
Rami Rosen (2):
Bluetooth: Remove unnecessary include l2cap.h
Bluetooth: remove an unused variable in a header file
Szymon Janc (3):
Bluetooth: mgmt: Remove not needed restriction on add/remove OOB data
Bluetooth: mgmt: Avoid using magic number in status code
Bluetooth: Fix pair device command reply if adapter is powered off
include/net/bluetooth/a2mp.h | 4 +-
include/net/bluetooth/bluetooth.h | 23 ++
include/net/bluetooth/hci.h | 18 ++
include/net/bluetooth/hci_core.h | 5 +
include/net/bluetooth/l2cap.h | 1 -
net/bluetooth/a2mp.c | 42 +++-
net/bluetooth/amp.c | 25 +-
net/bluetooth/bnep/core.c | 1 -
net/bluetooth/hci_core.c | 30 ++-
net/bluetooth/hci_event.c | 64 +++++-
net/bluetooth/hci_sysfs.c | 22 +-
net/bluetooth/l2cap_core.c | 5 -
net/bluetooth/mgmt.c | 489 +++++++++++++++++++++++++++-------------
net/bluetooth/sco.c | 18 +-
14 files changed, 525 insertions(+), 222 deletions(-)
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH BlueZ] device: Fix not marking svc_resolved when loaded from storage
From: Johan Hedberg @ 2013-02-01 17:45 UTC (permalink / raw)
To: Vinicius Costa Gomes; +Cc: linux-bluetooth
In-Reply-To: <1359740236-16095-1-git-send-email-vinicius.gomes@openbossa.org>
Hi Vinicius,
On Fri, Feb 01, 2013, Vinicius Costa Gomes wrote:
> When the device is loaded from storage, we should mark it as it
> services were resolved.
> ---
> src/device.c | 3 +++
> 1 file changed, 3 insertions(+)
Applied. Thanks.
Johan
^ permalink raw reply
* Re: pull request: bluetooth-next 2013-02-01
From: Gustavo Padovan @ 2013-02-01 17:54 UTC (permalink / raw)
To: linville, linux-wireless, linux-bluetooth, linux-kernel
In-Reply-To: <20130201174019.GD4733@joana>
[-- Attachment #1: Type: text/plain, Size: 2175 bytes --]
Hi John,
* Gustavo Padovan <gustavo@padovan.org> [2013-02-01 15:40:19 -0200]:
> Hi John,
>
> Here goes another batch intended for 3.9, the majority of the patch here are
> from Johan who is fixing many issues in the management interface that have
> appeared lately. The rest of the patches are just small improvements, fixes
> and clean ups.
I had a brain shutdown moment and forgot to rebase against wireless-next.
SO the pull request is actually much smaller.
Please pull!
Gustavo
---
The following changes since commit c331997b6c9ad7f4b8075e6e60d3caa6e36f5938:
wil6210: fix wil_vring_init_tx status (2013-01-30 15:07:19 -0500)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next for-upstream
for you to fetch changes up to a3d09356491d637548dbe815ddb966f52ec9e53a:
Bluetooth: Refactor mgmt_pending_foreach (2013-02-01 15:50:18 -0200)
----------------------------------------------------------------
Andre Guedes (3):
Bluetooth: Reduce critical section in sco_conn_ready
Bluetooth: Remove unneeded locking
Bluetooth: Refactor mgmt_pending_foreach
Johan Hedberg (11):
Bluetooth: Store UUIDs in the same order that they were added
Bluetooth: Simplify UUIDs clearing code
Bluetooth: Keep track of UUID type upon addition
Bluetooth: Simplify UUID removal code
Bluetooth: Simplify UUID16 list generation for EIR
Bluetooth: Remove useless eir_len variable from EIR creation
Bluetooth: Refactor UUID-16 list generation into its own function
Bluetooth: Add support for 32-bit UUIDs in EIR data
Bluetooth: Add support for 128-bit UUIDs in EIR data
Bluetooth: Fix link security setting when powering on
Bluetooth: Increment Management interface revision
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/hci_core.c | 10 +-
net/bluetooth/hci_event.c | 4 -
net/bluetooth/mgmt.c | 219 +++++++++++++++++++++++++----------------
net/bluetooth/sco.c | 18 ++--
5 files changed, 150 insertions(+), 102 deletions(-)
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* [PATCH BlueZ] AVDTP: Fix memory leak
From: Luiz Augusto von Dentz @ 2013-02-01 18:20 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
56 (16 direct, 40 indirect) bytes in 1 blocks are definitely lost in loss record 173 of 263
at 0x4A0883C: malloc (vg_replace_malloc.c:270)
by 0x4C8568E: g_malloc (in /usr/lib64/libglib-2.0.so.0.3400.2)
by 0x4C9A7F1: g_slice_alloc (in /usr/lib64/libglib-2.0.so.0.3400.2)
by 0x4C9BB92: g_slist_append (in /usr/lib64/libglib-2.0.so.0.3400.2)
by 0x422072: send_req (avdtp.c:2569)
by 0x422D0B: avdtp_discover (avdtp.c:3380)
by 0x41D16C: source_setup_stream (source.c:307)
by 0x41D1EF: source_connect (source.c:331)
by 0x465411: connect_next (device.c:1073)
by 0x466C92: device_profile_connected (device.c:1097)
by 0x4629EB: ext_connect (profile.c:950)
by 0x44AECB: connect_cb (btio.c:230)
---
profiles/audio/avdtp.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c
index 0187691..403a22b 100644
--- a/profiles/audio/avdtp.c
+++ b/profiles/audio/avdtp.c
@@ -599,8 +599,10 @@ static gboolean avdtp_send(struct avdtp *session, uint8_t transaction,
return TRUE;
}
-static void pending_req_free(struct pending_req *req)
+static void pending_req_free(void *data)
{
+ struct pending_req *req = data;
+
if (req->timeout)
g_source_remove(req->timeout);
g_free(req->data);
@@ -1137,6 +1139,8 @@ static void avdtp_free(void *data)
if (session->req)
pending_req_free(session->req);
+ g_slist_free_full(session->req_queue, pending_req_free);
+ g_slist_free_full(session->prio_queue, pending_req_free);
g_slist_free_full(session->seps, sep_free);
g_free(session->buf);
--
1.8.1
^ permalink raw reply related
* Re: pull request: bluetooth-next 2013-02-01
From: John W. Linville @ 2013-02-01 19:22 UTC (permalink / raw)
To: Gustavo Padovan, linux-wireless, linux-bluetooth, linux-kernel
In-Reply-To: <20130201175445.GE4733@joana>
On Fri, Feb 01, 2013 at 03:54:45PM -0200, Gustavo Padovan wrote:
> Hi John,
>
> * Gustavo Padovan <gustavo@padovan.org> [2013-02-01 15:40:19 -0200]:
>
> > Hi John,
> >
> > Here goes another batch intended for 3.9, the majority of the patch here are
> > from Johan who is fixing many issues in the management interface that have
> > appeared lately. The rest of the patches are just small improvements, fixes
> > and clean ups.
>
> I had a brain shutdown moment and forgot to rebase against wireless-next.
> SO the pull request is actually much smaller.
>
> Please pull!
>
> Gustavo
>
> ---
> The following changes since commit c331997b6c9ad7f4b8075e6e60d3caa6e36f5938:
>
> wil6210: fix wil_vring_init_tx status (2013-01-30 15:07:19 -0500)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next for-upstream
>
> for you to fetch changes up to a3d09356491d637548dbe815ddb966f52ec9e53a:
>
> Bluetooth: Refactor mgmt_pending_foreach (2013-02-01 15:50:18 -0200)
Pulling now...
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply
* Re: [PATCH BlueZ] AVDTP: Fix memory leak
From: Johan Hedberg @ 2013-02-01 21:23 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1359742844-4612-1-git-send-email-luiz.dentz@gmail.com>
Hi Luiz,
On Fri, Feb 01, 2013, Luiz Augusto von Dentz wrote:
> 56 (16 direct, 40 indirect) bytes in 1 blocks are definitely lost in loss record 173 of 263
> at 0x4A0883C: malloc (vg_replace_malloc.c:270)
> by 0x4C8568E: g_malloc (in /usr/lib64/libglib-2.0.so.0.3400.2)
> by 0x4C9A7F1: g_slice_alloc (in /usr/lib64/libglib-2.0.so.0.3400.2)
> by 0x4C9BB92: g_slist_append (in /usr/lib64/libglib-2.0.so.0.3400.2)
> by 0x422072: send_req (avdtp.c:2569)
> by 0x422D0B: avdtp_discover (avdtp.c:3380)
> by 0x41D16C: source_setup_stream (source.c:307)
> by 0x41D1EF: source_connect (source.c:331)
> by 0x465411: connect_next (device.c:1073)
> by 0x466C92: device_profile_connected (device.c:1097)
> by 0x4629EB: ext_connect (profile.c:950)
> by 0x44AECB: connect_cb (btio.c:230)
> ---
> profiles/audio/avdtp.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
Applied. Thanks.
Johan
^ permalink raw reply
* [PATCH BlueZ 1/6 v2] media-api: Add org.bluez.MediaFolder1
From: Luiz Augusto von Dentz @ 2013-02-01 21:28 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This interface adds support for browsing and searching in the player's
storage using AVRCP 1.4/1.5.
Some remarks about the design:
- Exposing UIDCounter and UIDs was considered, but the spec seems to have
missed to define the player's id persistency. There are also the fact that
UIDCounter alone does not guarantee persistency across sessions and do not
provide what exact items have changed, so in the end exposing these
details will bring almost no value.
- Indexing or caching the whole media library is not recommended, Bluetooth
is too slow for that and even vendors such as Apple do not recommend doing
it, so the only items keep in cache are the current listed ones.
- Addressed vs Browsed player is done implicitly when accessed, this was done
to simplify the API and avoid confusions between applications and players.
---
v2: Remove Buttons property for now
doc/media-api.txt | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 171 insertions(+)
diff --git a/doc/media-api.txt b/doc/media-api.txt
index 972716e..db1575f 100644
--- a/doc/media-api.txt
+++ b/doc/media-api.txt
@@ -226,6 +226,177 @@ Properties string Equalizer [readwrite]
Device object path.
+ string Name [readonly]
+
+ Player name
+
+ boolean Browsable [readonly]
+
+ If present indicates the player can be browsed using
+ MediaLibrary interface.
+
+ Possible values:
+
+ True: Supported and active
+ False: Supported but inactive
+
+ Note: If supported but inactive clients can enable it
+ by using MediaLibrary interface but it might interfere
+ in the playback of other players.
+
+
+ boolean Searchable [readonly]
+
+ If present indicates the player can be searched using
+ MediaLibrary interface.
+
+ Possible values:
+
+ True: Supported and active
+ False: Supported but inactive
+
+ Note: If supported but inactive clients can enable it
+ by using MediaLibrary interface but it might interfere
+ in the playback of other players.
+
+MediaFolder1 hierarchy
+======================
+
+Service unique name (Target role)
+ org.bluez (Controller role)
+Interface org.bluez.MediaFolder1 [Experimental]
+Object path freely definable (Target role)
+ [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/playerX
+ (Controller role)
+
+Methods object Search(string value, dict filter)
+
+ Return a folder object containing the search result.
+
+ To list the items found use the folder object returned
+ and pass to ChangeFolder.
+
+ array{objects, properties} ListItems(dict filter)
+
+ Return a list of items found
+
+ void ChangeFolder(object folder)
+
+ Change current folder.
+
+ Note: By changing folder the items of previous folder
+ might be destroyed and have to be listed again, the
+ exception is NowPlaying folder which should be always
+ present while the player is active.
+
+Properties uint32 NumberOfItems:
+
+ Number of items in the folder
+
+ string Name:
+
+ Folder name:
+
+ Possible values:
+ "/Filesystem/...": Filesystem scope
+ "/NowPlaying/...": NowPlaying scope
+
+ Note: /NowPlaying folder might not be listed if player
+ is stopped, folders created by Search are virtual so
+ once another Search is perform or the folder is
+ changed using ChangeFolder it will no longer be listed.
+
+Filters uint32 Start:
+
+ Offset of the first item.
+
+ Default value: 0
+
+ uint32 End:
+
+ Offset of the last item.
+
+ Default value: NumbeOfItems
+
+ array{string} Attributes
+
+ Item properties that should be included in the list.
+
+ Possible Values:
+
+ "title", "artist", "album", "genre",
+ "number-of-tracks", "number", "duration"
+
+ Default Value: All
+
+MediaItem1 hierarchy
+====================
+
+Service unique name (Target role)
+ org.bluez (Controller role)
+Interface org.bluez.MediaItem1 [Experimental]
+Object path freely definable (Target role)
+ [variable
+ prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/playerX/itemX
+ (Controller role)
+
+Methods void Play()
+
+ Play item
+
+ void AddtoNowPlaying()
+
+ Add item to now playing list
+
+Properties string Name [readonly]
+
+ Item displayable name
+
+ boolean Folder [readonly]
+
+ Indicates whether the item is a folder
+
+ string Type [readonly]
+
+ Item type
+
+ Possible values:
+
+ Folder: "Mixed", "Titles", "Albums", "Artists"
+ Other Items: "Video", "Audio"
+
+ boolean Playable [readonly]
+
+ Indicates if the item can be played
+
+ string Title:
+
+ Item title name
+
+ string Artist:
+
+ Item artist name
+
+ string Album:
+
+ Item album name
+
+ string Genre:
+
+ Item genre name
+
+ uint32 NumberOfTracks:
+
+ Item album number of tracks in total
+
+ uint32 Number:
+
+ Item album number
+
+ uint32 Duration:
+
+ Item duration in milliseconds
+
MediaEndpoint1 hierarchy
========================
--
1.8.1
^ permalink raw reply related
* [PATCH BlueZ 2/6 v2] AVRCP: Avoid repeating command due to changed event
From: Luiz Augusto von Dentz @ 2013-02-01 21:28 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1359754105-8185-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Currently we are repeating the same command twice for notification, first
for changed and then latter for interim response.
To avoid this the code now just do it for interim responses, changed
responses just trigger another registration.
---
profiles/audio/avrcp.c | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 728ba91..0a173bc 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -1877,6 +1877,12 @@ static gboolean avrcp_handle_event(struct avctp *conn,
event = pdu->params[0];
+ if (code == AVC_CTYPE_CHANGED) {
+ session->registered_events ^= (1 << event);
+ avrcp_register_notification(session, event);
+ return FALSE;
+ }
+
switch (event) {
case AVRCP_EVENT_VOLUME_CHANGED:
value = pdu->params[1] & 0x7F;
@@ -1900,12 +1906,8 @@ static gboolean avrcp_handle_event(struct avctp *conn,
break;
case AVRCP_EVENT_TRACK_CHANGED:
- mp = player->user_data;
-
avrcp_get_element_attributes(session);
-
- if (code == AVC_CTYPE_CHANGED)
- avrcp_get_play_status(session);
+ avrcp_get_play_status(session);
break;
@@ -1932,12 +1934,6 @@ static gboolean avrcp_handle_event(struct avctp *conn,
break;
}
- if (code == AVC_CTYPE_CHANGED) {
- session->registered_events ^= (1 << event);
- avrcp_register_notification(session, event);
- return FALSE;
- }
-
session->registered_events |= (1 << event);
return TRUE;
--
1.8.1
^ permalink raw reply related
* [PATCH BlueZ 3/6 v2] AVRCP: Register to addressed player changed event if supported
From: Luiz Augusto von Dentz @ 2013-02-01 21:28 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1359754105-8185-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This enables registering for addressed player changed event and handle
the interim response setting the player id and uid counter to the current
player.
---
profiles/audio/avrcp.c | 14 ++++++++++++++
profiles/audio/avrcp.h | 15 ++++++++-------
2 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 0a173bc..8187ddf 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -176,6 +176,8 @@ struct pending_pdu {
struct avrcp_player {
struct avrcp_server *server;
GSList *sessions;
+ uint16_t id;
+ uint16_t uid_counter;
struct avrcp_player_cb *cb;
void *user_data;
@@ -1869,6 +1871,7 @@ static gboolean avrcp_handle_event(struct avctp *conn,
uint8_t event;
uint8_t value;
uint8_t count;
+ uint16_t id;
const char *curval, *strval;
int i;
@@ -1932,6 +1935,16 @@ static gboolean avrcp_handle_event(struct avctp *conn,
}
break;
+
+ case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
+ id = bt_get_be16(&pdu->params[1]);
+
+ if (player->id == id)
+ break;
+
+ player->id = id;
+ player->uid_counter = bt_get_be16(&pdu->params[3]);
+ break;
}
session->registered_events |= (1 << event);
@@ -2112,6 +2125,7 @@ static gboolean avrcp_get_capabilities_resp(struct avctp *conn,
case AVRCP_EVENT_STATUS_CHANGED:
case AVRCP_EVENT_TRACK_CHANGED:
case AVRCP_EVENT_SETTINGS_CHANGED:
+ case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
avrcp_register_notification(session, event);
break;
}
diff --git a/profiles/audio/avrcp.h b/profiles/audio/avrcp.h
index b2c0d61..3799da1 100644
--- a/profiles/audio/avrcp.h
+++ b/profiles/audio/avrcp.h
@@ -69,13 +69,14 @@
#define AVRCP_PLAY_STATUS_ERROR 0xFF
/* Notification events */
-#define AVRCP_EVENT_STATUS_CHANGED 0x01
-#define AVRCP_EVENT_TRACK_CHANGED 0x02
-#define AVRCP_EVENT_TRACK_REACHED_END 0x03
-#define AVRCP_EVENT_TRACK_REACHED_START 0x04
-#define AVRCP_EVENT_SETTINGS_CHANGED 0x08
-#define AVRCP_EVENT_VOLUME_CHANGED 0x0d
-#define AVRCP_EVENT_LAST AVRCP_EVENT_VOLUME_CHANGED
+#define AVRCP_EVENT_STATUS_CHANGED 0x01
+#define AVRCP_EVENT_TRACK_CHANGED 0x02
+#define AVRCP_EVENT_TRACK_REACHED_END 0x03
+#define AVRCP_EVENT_TRACK_REACHED_START 0x04
+#define AVRCP_EVENT_SETTINGS_CHANGED 0x08
+#define AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED 0x0b
+#define AVRCP_EVENT_VOLUME_CHANGED 0x0d
+#define AVRCP_EVENT_LAST AVRCP_EVENT_VOLUME_CHANGED
struct avrcp_player_cb {
GList *(*list_settings) (void *user_data);
--
1.8.1
^ permalink raw reply related
* [PATCH BlueZ 4/6 v2] AVRCP: Get player list if supported
From: Luiz Augusto von Dentz @ 2013-02-01 21:28 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1359754105-8185-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
If addressed player changed is supported get the list of players
---
profiles/audio/avrcp.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++
profiles/audio/player.c | 119 +++++++++++++++++++++++++++++++++++++++
profiles/audio/player.h | 4 ++
3 files changed, 270 insertions(+)
diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 8187ddf..793b5cf 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -99,6 +99,7 @@
#define AVRCP_REQUEST_CONTINUING 0x40
#define AVRCP_ABORT_CONTINUING 0x41
#define AVRCP_SET_ABSOLUTE_VOLUME 0x50
+#define AVRCP_GET_FOLDER_ITEMS 0x71
#define AVRCP_GENERAL_REJECT 0xA0
/* Capabilities for AVRCP_GET_CAPABILITIES pdu */
@@ -1859,6 +1860,151 @@ static void avrcp_get_element_attributes(struct avrcp *session)
session);
}
+static const char *type_to_string(uint8_t type)
+{
+ switch (type & 0x0F) {
+ case 0x01:
+ return "Audio";
+ case 0x02:
+ return "Video";
+ case 0x03:
+ return "Audio, Video";
+ case 0x04:
+ return "Audio Broadcasting";
+ case 0x05:
+ return "Audio, Audio Broadcasting";
+ case 0x06:
+ return "Video, Audio Broadcasting";
+ case 0x07:
+ return "Audio, Video, Audio Broadcasting";
+ case 0x08:
+ return "Video Broadcasting";
+ case 0x09:
+ return "Audio, Video Broadcasting";
+ case 0x0A:
+ return "Video, Video Broadcasting";
+ case 0x0B:
+ return "Audio, Video, Video Broadcasting";
+ case 0x0C:
+ return "Audio Broadcasting, Video Broadcasting";
+ case 0x0D:
+ return "Audio, Audio Broadcasting, Video Broadcasting";
+ case 0x0E:
+ return "Video, Audio Broadcasting, Video Broadcasting";
+ case 0x0F:
+ return "Audio, Video, Audio Broadcasting, Video Broadcasting";
+ }
+
+ return "None";
+}
+
+static const char *subtype_to_string(uint32_t subtype)
+{
+ switch (subtype & 0x03) {
+ case 0x01:
+ return "Audio Book";
+ case 0x02:
+ return "Podcast";
+ case 0x03:
+ return "Audio Book, Podcast";
+ }
+
+ return "None";
+}
+
+static void avrcp_parse_media_player_item(struct avrcp *session,
+ uint8_t *operands, uint16_t len)
+{
+ struct avrcp_player *player = session->player;
+ struct media_player *mp = player->user_data;
+ uint16_t id;
+ uint32_t subtype;
+ const char *curval, *strval;
+ uint64_t features[2];
+ char name[255];
+
+ if (len < 28)
+ return;
+
+ id = bt_get_be16(&operands[0]);
+
+ if (player->id != id)
+ return;
+
+ media_player_set_type(mp, type_to_string(operands[2]));
+
+ subtype = bt_get_be32(&operands[3]);
+
+ media_player_set_subtype(mp, subtype_to_string(subtype));
+
+ curval = media_player_get_status(mp);
+ strval = status_to_string(operands[7]);
+
+ if (g_strcmp0(curval, strval) != 0) {
+ media_player_set_status(mp, strval);
+ avrcp_get_play_status(session);
+ }
+
+ features[0] = bt_get_be64(&operands[8]);
+ features[1] = bt_get_be64(&operands[16]);
+
+ media_player_set_features(mp, features);
+
+ if (operands[26] == 0)
+ return;
+
+ memcpy(name, &operands[27], operands[26]);
+
+ media_player_set_name(mp, name);
+}
+
+static gboolean avrcp_get_media_player_list_rsp(struct avctp *conn,
+ uint8_t *operands,
+ size_t operand_count,
+ void *user_data)
+{
+ struct avrcp *session = user_data;
+ uint16_t count;
+ int i;
+
+ if (operands[3] != AVRCP_STATUS_SUCCESS || operand_count < 5)
+ return FALSE;
+
+ count = bt_get_be16(&operands[6]);
+
+ for (i = 8; count; count--) {
+ uint8_t type;
+ uint16_t len;
+
+ type = operands[i++];
+ len = bt_get_be16(&operands[i]);
+ i += 2;
+
+ if (type != 0x01) {
+ i += len;
+ continue;
+ }
+
+ avrcp_parse_media_player_item(session, &operands[i], len);
+ }
+
+ return FALSE;
+}
+
+static void avrcp_get_media_player_list(struct avrcp *session)
+{
+ uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 10];
+ struct avrcp_browsing_header *pdu = (void *) buf;
+
+ memset(buf, 0, sizeof(buf));
+
+ pdu->pdu_id = AVRCP_GET_FOLDER_ITEMS;
+ pdu->param_len = htons(10);
+
+ avctp_send_browsing_req(session->conn, buf, sizeof(buf),
+ avrcp_get_media_player_list_rsp, session);
+}
+
static gboolean avrcp_handle_event(struct avctp *conn,
uint8_t code, uint8_t subunit,
uint8_t *operands, size_t operand_count,
@@ -1944,6 +2090,7 @@ static gboolean avrcp_handle_event(struct avctp *conn,
player->id = id;
player->uid_counter = bt_get_be16(&pdu->params[3]);
+ avrcp_get_media_player_list(session);
break;
}
diff --git a/profiles/audio/player.c b/profiles/audio/player.c
index fb750fd..b4efa70 100644
--- a/profiles/audio/player.c
+++ b/profiles/audio/player.c
@@ -57,6 +57,10 @@ struct pending_req {
struct media_player {
char *device; /* Device path */
+ char *name; /* Player name */
+ char *type; /* Player type */
+ char *subtype; /* Player subtype */
+ uint64_t features[2]; /* Player features */
char *path; /* Player object path */
GHashTable *settings; /* Player settings */
GHashTable *track; /* Player current track */
@@ -272,6 +276,72 @@ static gboolean get_device(const GDBusPropertyTable *property,
return TRUE;
}
+static gboolean name_exists(const GDBusPropertyTable *property, void *data)
+{
+ struct media_player *mp = data;
+
+ return mp->name != NULL;
+}
+
+static gboolean get_name(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct media_player *mp = data;
+
+ if (mp->name == NULL)
+ return FALSE;
+
+ DBG("%s", mp->name);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &mp->name);
+
+ return TRUE;
+}
+
+static gboolean type_exists(const GDBusPropertyTable *property, void *data)
+{
+ struct media_player *mp = data;
+
+ return mp->type != NULL;
+}
+
+static gboolean get_type(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct media_player *mp = data;
+
+ if (mp->type == NULL)
+ return FALSE;
+
+ DBG("%s", mp->type);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &mp->type);
+
+ return TRUE;
+}
+
+static gboolean subtype_exists(const GDBusPropertyTable *property, void *data)
+{
+ struct media_player *mp = data;
+
+ return mp->subtype != NULL;
+}
+
+static gboolean get_subtype(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct media_player *mp = data;
+
+ if (mp->subtype == NULL)
+ return FALSE;
+
+ DBG("%s", mp->subtype);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &mp->subtype);
+
+ return TRUE;
+}
+
static DBusMessage *media_player_play(DBusConnection *conn, DBusMessage *msg,
void *data)
{
@@ -410,6 +480,12 @@ static const GDBusSignalTable media_player_signals[] = {
};
static const GDBusPropertyTable media_player_properties[] = {
+ { "Name", "s", get_name, NULL, name_exists,
+ G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+ { "Type", "s", get_type, NULL, type_exists,
+ G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+ { "Subtype", "s", get_subtype, NULL, subtype_exists,
+ G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
{ "Position", "u", get_position, NULL, NULL,
G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
{ "Status", "s", get_status, NULL, status_exists,
@@ -452,6 +528,9 @@ void media_player_destroy(struct media_player *mp)
g_free(mp->status);
g_free(mp->path);
g_free(mp->device);
+ g_free(mp->subtype);
+ g_free(mp->type);
+ g_free(mp->name);
g_free(mp);
}
@@ -618,6 +697,46 @@ void media_player_set_metadata(struct media_player *mp, const char *key,
g_hash_table_replace(mp->track, g_strdup(key), value);
}
+void media_player_set_type(struct media_player *mp, const char *type)
+{
+ DBG("%s", type);
+
+ mp->type = g_strdup(type);
+
+ g_dbus_emit_property_changed(btd_get_dbus_connection(),
+ mp->path, MEDIA_PLAYER_INTERFACE,
+ "Type");
+}
+
+void media_player_set_subtype(struct media_player *mp, const char *subtype)
+{
+ DBG("%s", subtype);
+
+ mp->subtype = g_strdup(subtype);
+
+ g_dbus_emit_property_changed(btd_get_dbus_connection(),
+ mp->path, MEDIA_PLAYER_INTERFACE,
+ "Subtype");
+}
+
+void media_player_set_name(struct media_player *mp, const char *name)
+{
+ DBG("%s", name);
+
+ mp->name = g_strdup(name);
+
+ g_dbus_emit_property_changed(btd_get_dbus_connection(),
+ mp->path, MEDIA_PLAYER_INTERFACE,
+ "Name");
+}
+
+void media_player_set_features(struct media_player *mp, uint64_t *features)
+{
+ DBG("0x%08zx %08zx", features[0], features[1]);
+
+ memcpy(features, mp->features, sizeof(mp->features));
+}
+
void media_player_set_callbacks(struct media_player *mp,
const struct media_player_callback *cbs,
void *user_data)
diff --git a/profiles/audio/player.h b/profiles/audio/player.h
index fec1d06..b546ba7 100644
--- a/profiles/audio/player.h
+++ b/profiles/audio/player.h
@@ -47,6 +47,10 @@ const char *media_player_get_status(struct media_player *mp);
void media_player_set_status(struct media_player *mp, const char *status);
void media_player_set_metadata(struct media_player *mp, const char *key,
void *data, size_t len);
+void media_player_set_type(struct media_player *mp, const char *type);
+void media_player_set_subtype(struct media_player *mp, const char *subtype);
+void media_player_set_features(struct media_player *mp, uint64_t *features);
+void media_player_set_name(struct media_player *mp, const char *name);
void media_player_set_callbacks(struct media_player *mp,
const struct media_player_callback *cbs,
--
1.8.1
^ permalink raw reply related
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