From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH BlueZ 03/11] AVRCP: Don't respond with errors when no player is registered
Date: Thu, 25 Oct 2012 16:59:06 +0300 [thread overview]
Message-ID: <1351173554-28039-3-git-send-email-luiz.dentz@gmail.com> (raw)
In-Reply-To: <1351173554-28039-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Some devices w.g. Sony MW600 will stop using certain commands if an
error happen, so the code now just fake a player and once a real
player is registered it takes place of the fake one.
---
audio/avrcp.c | 117 +++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 84 insertions(+), 33 deletions(-)
diff --git a/audio/avrcp.c b/audio/avrcp.c
index fe304d1..a14833a 100644
--- a/audio/avrcp.c
+++ b/audio/avrcp.c
@@ -493,6 +493,17 @@ void avrcp_player_event(struct avrcp_player *player, uint8_t id, void *data)
return;
}
+static const char *player_get_metadata(struct avrcp_player *player, uint32_t attr)
+{
+ if (player != NULL)
+ return player->cb->get_metadata(attr, player->user_data);
+
+ if (attr == AVRCP_MEDIA_ATTRIBUTE_TITLE)
+ return "";
+
+ return NULL;
+}
+
static uint16_t player_write_media_attribute(struct avrcp_player *player,
uint32_t id, uint8_t *buf,
uint16_t *pos,
@@ -504,7 +515,7 @@ static uint16_t player_write_media_attribute(struct avrcp_player *player,
DBG("%u", id);
- value = player->cb->get_metadata(id, player->user_data);
+ value = player_get_metadata(player, id);
if (value == NULL) {
*offset = 0;
return 0;
@@ -589,25 +600,21 @@ static gboolean session_abort_pending_pdu(struct avrcp *session)
return TRUE;
}
-static int player_set_attribute(struct avrcp_player *player,
- uint8_t attr, uint8_t val)
+static int player_set_setting(struct avrcp_player *player, uint8_t id,
+ uint8_t val)
{
- DBG("Change attribute: %u %u", attr, val);
+ if (player == NULL)
+ return -ENOENT;
- return player->cb->set_setting(attr, val, player->user_data);
+ return player->cb->set_setting(id, val, player->user_data);
}
-static int player_get_attribute(struct avrcp_player *player, uint8_t attr)
+static int player_get_setting(struct avrcp_player *player, uint8_t id)
{
- int value;
-
- DBG("attr %u", attr);
-
- value = player->cb->get_setting(attr, player->user_data);
- if (value < 0)
- DBG("attr %u not supported by player", attr);
+ if (player == NULL)
+ return -ENOENT;
- return value;
+ return player->cb->get_setting(id, player->user_data);
}
static uint8_t avrcp_handle_get_capabilities(struct avrcp *session,
@@ -659,7 +666,7 @@ static uint8_t avrcp_handle_list_player_attributes(struct avrcp *session,
uint16_t len = ntohs(pdu->params_len);
unsigned int i;
- if (len != 0 || player == NULL) {
+ if (len != 0) {
pdu->params_len = htons(1);
pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
return AVC_CTYPE_REJECTED;
@@ -669,7 +676,7 @@ static uint8_t avrcp_handle_list_player_attributes(struct avrcp *session,
goto done;
for (i = 1; i <= AVRCP_ATTRIBUTE_SCAN; i++) {
- if (player_get_attribute(player, i) < 0)
+ if (player_get_setting(player, i) < 0)
continue;
len++;
@@ -691,10 +698,10 @@ static uint8_t avrcp_handle_list_player_values(struct avrcp *session,
uint16_t len = ntohs(pdu->params_len);
unsigned int i;
- if (len != 1 || player == NULL)
+ if (len != 1)
goto err;
- if (player_get_attribute(player, pdu->params[0]) < 0)
+ if (player_get_setting(player, pdu->params[0]) < 0)
goto err;
len = attr_get_max_val(pdu->params[0]);
@@ -713,6 +720,15 @@ err:
return AVC_CTYPE_REJECTED;
}
+static GList *player_list_metadata(struct avrcp_player *player)
+{
+ if (player != NULL)
+ return player->cb->list_metadata(player->user_data);
+
+ return g_list_prepend(NULL,
+ GUINT_TO_POINTER(AVRCP_MEDIA_ATTRIBUTE_TITLE));
+}
+
static uint8_t avrcp_handle_get_element_attributes(struct avrcp *session,
struct avrcp_header *pdu,
uint8_t transaction)
@@ -725,7 +741,7 @@ static uint8_t avrcp_handle_get_element_attributes(struct avrcp *session,
GList *attr_ids;
uint16_t offset;
- if (len < 9 || identifier != 0 || player == NULL)
+ if (len < 9 || identifier != 0)
goto err;
nattr = pdu->params[8];
@@ -738,7 +754,7 @@ static uint8_t avrcp_handle_get_element_attributes(struct avrcp *session,
* Return all available information, at least
* title must be returned if there's a track selected.
*/
- attr_ids = player->cb->list_metadata(player->user_data);
+ attr_ids = player_list_metadata(player);
len = g_list_length(attr_ids);
} else {
unsigned int i;
@@ -794,8 +810,7 @@ static uint8_t avrcp_handle_get_current_player_value(struct avrcp *session,
uint8_t *settings;
unsigned int i;
- if (player == NULL || len <= 1 || pdu->params[0] != len - 1 ||
- player == NULL)
+ if (len <= 1 || pdu->params[0] != len - 1)
goto err;
/*
@@ -819,7 +834,7 @@ static uint8_t avrcp_handle_get_current_player_value(struct avrcp *session,
continue;
}
- val = player_get_attribute(player, settings[i]);
+ val = player_get_setting(player, settings[i]);
if (val < 0)
continue;
@@ -866,7 +881,7 @@ static uint8_t avrcp_handle_set_player_value(struct avrcp *session,
*/
for (len = 0, i = 0, param = &pdu->params[1]; i < pdu->params[0];
i++, param += 2) {
- if (player_set_attribute(player, param[0], param[1]) < 0)
+ if (player_set_setting(player, param[0], param[1]) < 0)
continue;
len++;
@@ -928,6 +943,36 @@ err:
return AVC_CTYPE_REJECTED;
}
+static uint32_t player_get_position(struct avrcp_player *player)
+{
+ if (player == NULL)
+ return 0;
+
+ return player->cb->get_position(player->user_data);
+}
+
+static uint32_t player_get_duration(struct avrcp_player *player)
+{
+ uint32_t num;
+
+ if (player == NULL)
+ return UINT32_MAX;
+
+ num = player->cb->get_duration(player->user_data);
+ if (num == 0)
+ return UINT32_MAX;
+
+ return num;
+}
+
+static uint8_t player_get_status(struct avrcp_player *player)
+{
+ if (player == NULL)
+ return AVRCP_PLAY_STATUS_STOPPED;
+
+ return player->cb->get_status(player->user_data);
+}
+
static uint8_t avrcp_handle_get_play_status(struct avrcp *session,
struct avrcp_header *pdu,
uint8_t transaction)
@@ -937,29 +982,35 @@ static uint8_t avrcp_handle_get_play_status(struct avrcp *session,
uint32_t position;
uint32_t duration;
- if (len != 0 || player == NULL) {
+ if (len != 0) {
pdu->params_len = htons(1);
pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
return AVC_CTYPE_REJECTED;
}
- position = player->cb->get_position(player->user_data);
- duration = player->cb->get_duration(player->user_data);
- if (duration == 0)
- duration = UINT32_MAX;
+ position = player_get_position(player);
+ duration = player_get_duration(player);
position = htonl(position);
duration = htonl(duration);
memcpy(&pdu->params[0], &duration, 4);
memcpy(&pdu->params[4], &position, 4);
- pdu->params[8] = player->cb->get_status(player->user_data);;
+ pdu->params[8] = player_get_status(player);;
pdu->params_len = htons(9);
return AVC_CTYPE_STABLE;
}
+static uint64_t player_get_uid(struct avrcp_player *player)
+{
+ if (player == NULL)
+ return UINT64_MAX;
+
+ return player->cb->get_uid(player->user_data);
+}
+
static uint8_t avrcp_handle_register_notification(struct avrcp *session,
struct avrcp_header *pdu,
uint8_t transaction)
@@ -973,18 +1024,18 @@ static uint8_t avrcp_handle_register_notification(struct avrcp *session,
* one is applicable only for EVENT_PLAYBACK_POS_CHANGED. See AVRCP
* 1.3 spec, section 5.4.2.
*/
- if (len != 5 || player == NULL)
+ if (len != 5)
goto err;
switch (pdu->params[0]) {
case AVRCP_EVENT_STATUS_CHANGED:
len = 2;
- pdu->params[1] = player->cb->get_status(player->user_data);
+ pdu->params[1] = player_get_status(player);
break;
case AVRCP_EVENT_TRACK_CHANGED:
len = 9;
- uid = player->cb->get_uid(player->user_data);
+ uid = player_get_uid(player);
memcpy(&pdu->params[1], &uid, sizeof(uint64_t));
break;
--
1.7.11.7
next prev parent reply other threads:[~2012-10-25 13:59 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-10-25 13:59 [PATCH BlueZ 01/11] control: Fix Control.Disconnect not generating any reply Luiz Augusto von Dentz
2012-10-25 13:59 ` [PATCH BlueZ 02/11] AVRCP: Fix using void * for metadata values Luiz Augusto von Dentz
2012-10-25 13:59 ` Luiz Augusto von Dentz [this message]
2012-10-25 13:59 ` [PATCH BlueZ 04/11] AVRCP: Fix not adding session to player's list of sessions Luiz Augusto von Dentz
2012-10-25 13:59 ` [PATCH BlueZ 05/11] AVCTP: Reduce verbosity of PDU parsing Luiz Augusto von Dentz
2012-10-25 13:59 ` [PATCH BlueZ 06/11] AVRCP: Add support for settings changed event Luiz Augusto von Dentz
2012-10-25 13:59 ` [PATCH BlueZ 07/11] AVRCP: Add initial support for controller player Luiz Augusto von Dentz
2012-10-26 7:44 ` Johan Hedberg
2012-10-25 13:59 ` [PATCH BlueZ 08/11] AVRCP: Remove conversions inside media.c Luiz Augusto von Dentz
2012-10-25 13:59 ` [PATCH BlueZ 09/11] test: Fix using Number instead of Track in simple-player Luiz Augusto von Dentz
2012-10-25 13:59 ` [PATCH BlueZ 10/11] test: Fix using Number instead of Track in mpris-player Luiz Augusto von Dentz
2012-10-25 13:59 ` [PATCH BlueZ 11/11] test: Add support for using external player Luiz Augusto von Dentz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1351173554-28039-3-git-send-email-luiz.dentz@gmail.com \
--to=luiz.dentz@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).