From: Luiz Augusto von Dentz <[email protected]>
This replaces the use of avrcp_set_control_handlers which is now
deprecated in favor of avrcp_register_player.
---
unit/test-avrcp.c | 264 ++++++++++++------------------------------------------
1 file changed, 56 insertions(+), 208 deletions(-)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index b86d572..9fdbe6d 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -297,243 +297,106 @@ static const struct avrcp_passthrough_handler passthrough_handlers[] = {
{ },
};
-static bool check_attributes(const uint8_t *params)
-{
- int i;
-
- for (i = 1; i <= params[0]; i++) {
- DBG("params[%d] = 0x%02x", i, params[i]);
- if (params[i] > AVRCP_ATTRIBUTE_LAST ||
- params[i] == AVRCP_ATTRIBUTE_ILEGAL)
- return false;
- }
-
- return true;
-}
-
-static ssize_t avrcp_handle_get_capabilities(struct avrcp *session,
- uint8_t transaction,
- uint16_t params_len,
- uint8_t *params,
- void *user_data)
+static int get_capabilities(struct avrcp *session, uint8_t transaction,
+ void *user_data)
{
- if (params_len != 1)
- return -EINVAL;
-
- switch (params[0]) {
- case CAP_COMPANY_ID:
- params[1] = 1;
- hton24(¶ms[2], IEEEID_BTSIG);
- return 5;
- }
-
return -EINVAL;
}
-static ssize_t avrcp_handle_list_attributes(struct avrcp *session,
- uint8_t transaction,
- uint16_t params_len,
- uint8_t *params,
- void *user_data)
+static int list_attributes(struct avrcp *session, uint8_t transaction,
+ void *user_data)
{
DBG("");
- params[0] = 0;
-
return 1;
}
-static ssize_t avrcp_handle_get_player_attr_text(struct avrcp *session,
- uint8_t transaction,
- uint16_t params_len,
- uint8_t *params,
- void *user_data)
+static int get_attribute_text(struct avrcp *session, uint8_t transaction,
+ uint8_t number, uint8_t *attrs,
+ void *user_data)
{
- DBG("params[0] %d params_len %d", params[0], params_len);
-
- if (!check_attributes(params))
- return -EINVAL;
-
- params[0] = 0;
+ DBG("");
return 1;
}
-static ssize_t avrcp_handle_list_player_values(struct avrcp *session,
- uint8_t transaction,
- uint16_t params_len,
- uint8_t *params,
- void *user_data)
+static int list_values(struct avrcp *session, uint8_t transaction,
+ uint8_t attr, void *user_data)
{
- DBG("params[0] 0x%02x params_len %d", params[0], params_len);
-
- if (params_len != 1)
- return -EINVAL;
-
- if (params[0] > AVRCP_ATTRIBUTE_LAST ||
- params[0] == AVRCP_ATTRIBUTE_ILEGAL)
- return -EINVAL;
-
- params[0] = 0;
+ DBG("");
return 1;
}
-static ssize_t avrcp_handle_get_player_value_text(struct avrcp *session,
- uint8_t transaction,
- uint16_t params_len,
- uint8_t *params,
- void *user_data)
+static int get_value_text(struct avrcp *session, uint8_t transaction,
+ uint8_t attr, uint8_t number, uint8_t *values,
+ void *user_data)
{
- int i;
-
- DBG("attr_id %d num_vals %d len %d", params[0], params[1], params_len);
-
- if (params_len != 2 + params[1])
- return -EINVAL;
-
- if (params[0] > AVRCP_ATTRIBUTE_LAST ||
- params[0] == AVRCP_ATTRIBUTE_ILEGAL)
- return -EINVAL;
-
- for (i = 2; i < 2 + params[1]; i++) {
- DBG("Value 0x%02x", params[i]);
-
- /* Check for invalid value */
- switch (params[0]) {
- case AVRCP_ATTRIBUTE_EQUALIZER:
- if (params[i] < 0x01 || params[i] > 0x02)
- return -EINVAL;
- }
- }
-
- params[0] = 0;
+ DBG("");
return 1;
}
-static ssize_t avrcp_handle_get_current_player_value(struct avrcp *session,
- uint8_t transaction,
- uint16_t params_len,
- uint8_t *params,
- void *user_data)
+static int get_value(struct avrcp *session, uint8_t transaction,
+ uint8_t number, uint8_t *attrs, void *user_data)
{
uint8_t *attributes;
int i;
- DBG("params[0] %d params_len %d", params[0], params_len);
-
- if (!check_attributes(params))
- return -EINVAL;
+ DBG("");
- attributes = g_memdup(¶ms[1], params[0]);
+ attributes = g_memdup(attrs, number);
- for (i = 0; i < params[0]; i++) {
- params[i * 2 + 1] = attributes[i];
- params[i * 2 + 2] = 0; /* value */
+ for (i = 0; i < number; i++) {
+ attrs[i * 2 + 1] = attributes[i];
+ attrs[i * 2 + 2] = 0; /* value */
}
g_free(attributes);
- params[0] = i;
-
- return params[0] * 2 + 1;
-}
-
-static ssize_t avrcp_handle_set_player_value(struct avrcp *session,
- uint8_t transaction,
- uint16_t params_len,
- uint8_t *params,
- void *user_data)
-{
- int i;
-
- DBG("params[0] %d params_len %d", params[0], params_len);
-
- if (params_len != params[0] * 2 + 1)
- return -EINVAL;
-
- for (i = 0; i < params[0]; i++) {
- uint8_t attr = params[i * 2 + 1];
- uint8_t val = params[i * 2 + 2];
-
- DBG("attr 0x%02x val 0x%02x", attr, val);
- switch (attr) {
- case AVRCP_ATTRIBUTE_REPEAT_MODE:
- if (val < 0x01 || val > 0x05)
- return -EINVAL;
- }
- }
-
- return 1;
+ return number * 2 + 1;
}
-static ssize_t avrcp_handle_set_addr_player(struct avrcp *session,
- uint8_t transaction,
- uint16_t params_len,
- uint8_t *params,
- void *user_data)
+static int set_value(struct avrcp *session, uint8_t transaction,
+ uint8_t number, uint8_t *attrs, void *user_data)
{
DBG("");
- params[0] = 0;
-
- return 1;
+ return 0;
}
-static ssize_t avrcp_handle_get_play_status(struct avrcp *session,
- uint8_t transaction,
- uint16_t params_len,
- uint8_t *params,
- void *user_data)
+static int get_play_status(struct avrcp *session, uint8_t transaction,
+ void *user_data)
{
DBG("");
- if (params_len)
- return -EINVAL;
-
avrcp_get_play_status_rsp(session, transaction, 0xaaaaaaaa, 0xbbbbbbbb,
0x00);
return -EAGAIN;
}
-static ssize_t avrcp_handle_get_element_attrs(struct avrcp *session,
- uint8_t transaction,
- uint16_t params_len,
- uint8_t *params,
- void *user_data)
+static int get_element_attributes(struct avrcp *session, uint8_t transaction,
+ uint64_t uid, uint8_t number,
+ uint32_t *attrs, void *user_data)
{
- DBG("params_len %d params[8] %d", params_len, params[8]);
-
- if (params_len < 9)
- return -EINVAL;
-
- if (params_len != 9 + params[8] * 4)
- return -EINVAL;
+ DBG("");
avrcp_get_element_attrs_rsp(session, transaction, NULL, 0);
return -EAGAIN;
}
-static ssize_t avrcp_handle_register_notification(struct avrcp *session,
- uint8_t transaction,
- uint16_t params_len,
- uint8_t *params,
- void *user_data)
+static int register_notification(struct avrcp *session, uint8_t transaction,
+ uint8_t event, uint32_t interval,
+ void *user_data)
{
struct context *context = user_data;
- uint8_t event;
uint8_t pdu[9];
size_t pdu_len;
DBG("");
- if (params_len != AVRCP_REGISTER_NOTIFICATION_PARAM_LENGTH)
- return -EINVAL;
-
- event = params[0];
pdu[0] = event;
pdu_len = 1;
@@ -567,41 +430,26 @@ static ssize_t avrcp_handle_register_notification(struct avrcp *session,
return -EAGAIN;
}
-static const struct avrcp_control_handler control_handlers[] = {
- { AVRCP_GET_CAPABILITIES,
- AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
- avrcp_handle_get_capabilities },
- { AVRCP_LIST_PLAYER_ATTRIBUTES,
- AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
- avrcp_handle_list_attributes },
- { AVRCP_GET_PLAYER_ATTRIBUTE_TEXT,
- AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
- avrcp_handle_get_player_attr_text },
- { AVRCP_LIST_PLAYER_VALUES,
- AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
- avrcp_handle_list_player_values },
- { AVRCP_GET_PLAYER_VALUE_TEXT,
- AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
- avrcp_handle_get_player_value_text },
- { AVRCP_GET_CURRENT_PLAYER_VALUE,
- AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
- avrcp_handle_get_current_player_value },
- { AVRCP_SET_PLAYER_VALUE,
- AVC_CTYPE_CONTROL, AVC_CTYPE_STABLE,
- avrcp_handle_set_player_value },
- { AVRCP_GET_PLAY_STATUS,
- AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
- avrcp_handle_get_play_status },
- { AVRCP_GET_ELEMENT_ATTRIBUTES,
- AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
- avrcp_handle_get_element_attrs },
- { AVRCP_REGISTER_NOTIFICATION,
- AVC_CTYPE_NOTIFY, AVC_CTYPE_INTERIM,
- avrcp_handle_register_notification },
- { AVRCP_SET_ADDRESSED_PLAYER,
- AVC_CTYPE_CONTROL, AVC_CTYPE_STABLE,
- avrcp_handle_set_addr_player },
- { },
+static int set_addressed(struct avrcp *session, uint8_t transaction,
+ uint16_t id, void *user_data)
+{
+ DBG("");
+
+ return 1;
+}
+
+static const struct avrcp_control_ind control_ind = {
+ .get_capabilities = get_capabilities,
+ .list_attributes = list_attributes,
+ .get_attribute_text = get_attribute_text,
+ .list_values = list_values,
+ .get_value_text = get_value_text,
+ .get_value = get_value,
+ .set_value = set_value,
+ .get_play_status = get_play_status,
+ .get_element_attributes = get_element_attributes,
+ .register_notification = register_notification,
+ .set_addressed = set_addressed,
};
static void test_server(gconstpointer data)
@@ -610,7 +458,7 @@ static void test_server(gconstpointer data)
avrcp_set_passthrough_handlers(context->session, passthrough_handlers,
context);
- avrcp_set_control_handlers(context->session, control_handlers, context);
+ avrcp_register_player(context->session, &control_ind, NULL, context);
g_idle_add(send_pdu, context);
--
1.8.5.3
Hi,
On Mon, Mar 17, 2014 at 3:07 PM, Luiz Augusto von Dentz
<[email protected]> wrote:
> From: Luiz Augusto von Dentz <[email protected]>
>
> This replaces the use of avrcp_set_control_handlers which is now
> deprecated in favor of avrcp_register_player.
> ---
> unit/test-avrcp.c | 264 ++++++++++++------------------------------------------
> 1 file changed, 56 insertions(+), 208 deletions(-)
>
> diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
> index b86d572..9fdbe6d 100644
> --- a/unit/test-avrcp.c
> +++ b/unit/test-avrcp.c
> @@ -297,243 +297,106 @@ static const struct avrcp_passthrough_handler passthrough_handlers[] = {
> { },
> };
>
> -static bool check_attributes(const uint8_t *params)
> -{
> - int i;
> -
> - for (i = 1; i <= params[0]; i++) {
> - DBG("params[%d] = 0x%02x", i, params[i]);
> - if (params[i] > AVRCP_ATTRIBUTE_LAST ||
> - params[i] == AVRCP_ATTRIBUTE_ILEGAL)
> - return false;
> - }
> -
> - return true;
> -}
> -
> -static ssize_t avrcp_handle_get_capabilities(struct avrcp *session,
> - uint8_t transaction,
> - uint16_t params_len,
> - uint8_t *params,
> - void *user_data)
> +static int get_capabilities(struct avrcp *session, uint8_t transaction,
> + void *user_data)
> {
> - if (params_len != 1)
> - return -EINVAL;
> -
> - switch (params[0]) {
> - case CAP_COMPANY_ID:
> - params[1] = 1;
> - hton24(¶ms[2], IEEEID_BTSIG);
> - return 5;
> - }
> -
> return -EINVAL;
> }
>
> -static ssize_t avrcp_handle_list_attributes(struct avrcp *session,
> - uint8_t transaction,
> - uint16_t params_len,
> - uint8_t *params,
> - void *user_data)
> +static int list_attributes(struct avrcp *session, uint8_t transaction,
> + void *user_data)
> {
> DBG("");
>
> - params[0] = 0;
> -
> return 1;
> }
>
> -static ssize_t avrcp_handle_get_player_attr_text(struct avrcp *session,
> - uint8_t transaction,
> - uint16_t params_len,
> - uint8_t *params,
> - void *user_data)
> +static int get_attribute_text(struct avrcp *session, uint8_t transaction,
> + uint8_t number, uint8_t *attrs,
> + void *user_data)
> {
> - DBG("params[0] %d params_len %d", params[0], params_len);
> -
> - if (!check_attributes(params))
> - return -EINVAL;
> -
> - params[0] = 0;
> + DBG("");
>
> return 1;
> }
>
> -static ssize_t avrcp_handle_list_player_values(struct avrcp *session,
> - uint8_t transaction,
> - uint16_t params_len,
> - uint8_t *params,
> - void *user_data)
> +static int list_values(struct avrcp *session, uint8_t transaction,
> + uint8_t attr, void *user_data)
> {
> - DBG("params[0] 0x%02x params_len %d", params[0], params_len);
> -
> - if (params_len != 1)
> - return -EINVAL;
> -
> - if (params[0] > AVRCP_ATTRIBUTE_LAST ||
> - params[0] == AVRCP_ATTRIBUTE_ILEGAL)
> - return -EINVAL;
> -
> - params[0] = 0;
> + DBG("");
>
> return 1;
> }
>
> -static ssize_t avrcp_handle_get_player_value_text(struct avrcp *session,
> - uint8_t transaction,
> - uint16_t params_len,
> - uint8_t *params,
> - void *user_data)
> +static int get_value_text(struct avrcp *session, uint8_t transaction,
> + uint8_t attr, uint8_t number, uint8_t *values,
> + void *user_data)
> {
> - int i;
> -
> - DBG("attr_id %d num_vals %d len %d", params[0], params[1], params_len);
> -
> - if (params_len != 2 + params[1])
> - return -EINVAL;
> -
> - if (params[0] > AVRCP_ATTRIBUTE_LAST ||
> - params[0] == AVRCP_ATTRIBUTE_ILEGAL)
> - return -EINVAL;
> -
> - for (i = 2; i < 2 + params[1]; i++) {
> - DBG("Value 0x%02x", params[i]);
> -
> - /* Check for invalid value */
> - switch (params[0]) {
> - case AVRCP_ATTRIBUTE_EQUALIZER:
> - if (params[i] < 0x01 || params[i] > 0x02)
> - return -EINVAL;
> - }
> - }
> -
> - params[0] = 0;
> + DBG("");
>
> return 1;
> }
>
> -static ssize_t avrcp_handle_get_current_player_value(struct avrcp *session,
> - uint8_t transaction,
> - uint16_t params_len,
> - uint8_t *params,
> - void *user_data)
> +static int get_value(struct avrcp *session, uint8_t transaction,
> + uint8_t number, uint8_t *attrs, void *user_data)
> {
> uint8_t *attributes;
> int i;
>
> - DBG("params[0] %d params_len %d", params[0], params_len);
> -
> - if (!check_attributes(params))
> - return -EINVAL;
> + DBG("");
>
> - attributes = g_memdup(¶ms[1], params[0]);
> + attributes = g_memdup(attrs, number);
>
> - for (i = 0; i < params[0]; i++) {
> - params[i * 2 + 1] = attributes[i];
> - params[i * 2 + 2] = 0; /* value */
> + for (i = 0; i < number; i++) {
> + attrs[i * 2 + 1] = attributes[i];
> + attrs[i * 2 + 2] = 0; /* value */
> }
>
> g_free(attributes);
>
> - params[0] = i;
> -
> - return params[0] * 2 + 1;
> -}
> -
> -static ssize_t avrcp_handle_set_player_value(struct avrcp *session,
> - uint8_t transaction,
> - uint16_t params_len,
> - uint8_t *params,
> - void *user_data)
> -{
> - int i;
> -
> - DBG("params[0] %d params_len %d", params[0], params_len);
> -
> - if (params_len != params[0] * 2 + 1)
> - return -EINVAL;
> -
> - for (i = 0; i < params[0]; i++) {
> - uint8_t attr = params[i * 2 + 1];
> - uint8_t val = params[i * 2 + 2];
> -
> - DBG("attr 0x%02x val 0x%02x", attr, val);
> - switch (attr) {
> - case AVRCP_ATTRIBUTE_REPEAT_MODE:
> - if (val < 0x01 || val > 0x05)
> - return -EINVAL;
> - }
> - }
> -
> - return 1;
> + return number * 2 + 1;
> }
>
> -static ssize_t avrcp_handle_set_addr_player(struct avrcp *session,
> - uint8_t transaction,
> - uint16_t params_len,
> - uint8_t *params,
> - void *user_data)
> +static int set_value(struct avrcp *session, uint8_t transaction,
> + uint8_t number, uint8_t *attrs, void *user_data)
> {
> DBG("");
>
> - params[0] = 0;
> -
> - return 1;
> + return 0;
> }
>
> -static ssize_t avrcp_handle_get_play_status(struct avrcp *session,
> - uint8_t transaction,
> - uint16_t params_len,
> - uint8_t *params,
> - void *user_data)
> +static int get_play_status(struct avrcp *session, uint8_t transaction,
> + void *user_data)
> {
> DBG("");
>
> - if (params_len)
> - return -EINVAL;
> -
> avrcp_get_play_status_rsp(session, transaction, 0xaaaaaaaa, 0xbbbbbbbb,
> 0x00);
>
> return -EAGAIN;
> }
>
> -static ssize_t avrcp_handle_get_element_attrs(struct avrcp *session,
> - uint8_t transaction,
> - uint16_t params_len,
> - uint8_t *params,
> - void *user_data)
> +static int get_element_attributes(struct avrcp *session, uint8_t transaction,
> + uint64_t uid, uint8_t number,
> + uint32_t *attrs, void *user_data)
> {
> - DBG("params_len %d params[8] %d", params_len, params[8]);
> -
> - if (params_len < 9)
> - return -EINVAL;
> -
> - if (params_len != 9 + params[8] * 4)
> - return -EINVAL;
> + DBG("");
>
> avrcp_get_element_attrs_rsp(session, transaction, NULL, 0);
>
> return -EAGAIN;
> }
>
> -static ssize_t avrcp_handle_register_notification(struct avrcp *session,
> - uint8_t transaction,
> - uint16_t params_len,
> - uint8_t *params,
> - void *user_data)
> +static int register_notification(struct avrcp *session, uint8_t transaction,
> + uint8_t event, uint32_t interval,
> + void *user_data)
> {
> struct context *context = user_data;
> - uint8_t event;
> uint8_t pdu[9];
> size_t pdu_len;
>
> DBG("");
>
> - if (params_len != AVRCP_REGISTER_NOTIFICATION_PARAM_LENGTH)
> - return -EINVAL;
> -
> - event = params[0];
> pdu[0] = event;
> pdu_len = 1;
>
> @@ -567,41 +430,26 @@ static ssize_t avrcp_handle_register_notification(struct avrcp *session,
> return -EAGAIN;
> }
>
> -static const struct avrcp_control_handler control_handlers[] = {
> - { AVRCP_GET_CAPABILITIES,
> - AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
> - avrcp_handle_get_capabilities },
> - { AVRCP_LIST_PLAYER_ATTRIBUTES,
> - AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
> - avrcp_handle_list_attributes },
> - { AVRCP_GET_PLAYER_ATTRIBUTE_TEXT,
> - AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
> - avrcp_handle_get_player_attr_text },
> - { AVRCP_LIST_PLAYER_VALUES,
> - AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
> - avrcp_handle_list_player_values },
> - { AVRCP_GET_PLAYER_VALUE_TEXT,
> - AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
> - avrcp_handle_get_player_value_text },
> - { AVRCP_GET_CURRENT_PLAYER_VALUE,
> - AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
> - avrcp_handle_get_current_player_value },
> - { AVRCP_SET_PLAYER_VALUE,
> - AVC_CTYPE_CONTROL, AVC_CTYPE_STABLE,
> - avrcp_handle_set_player_value },
> - { AVRCP_GET_PLAY_STATUS,
> - AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
> - avrcp_handle_get_play_status },
> - { AVRCP_GET_ELEMENT_ATTRIBUTES,
> - AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
> - avrcp_handle_get_element_attrs },
> - { AVRCP_REGISTER_NOTIFICATION,
> - AVC_CTYPE_NOTIFY, AVC_CTYPE_INTERIM,
> - avrcp_handle_register_notification },
> - { AVRCP_SET_ADDRESSED_PLAYER,
> - AVC_CTYPE_CONTROL, AVC_CTYPE_STABLE,
> - avrcp_handle_set_addr_player },
> - { },
> +static int set_addressed(struct avrcp *session, uint8_t transaction,
> + uint16_t id, void *user_data)
> +{
> + DBG("");
> +
> + return 1;
> +}
> +
> +static const struct avrcp_control_ind control_ind = {
> + .get_capabilities = get_capabilities,
> + .list_attributes = list_attributes,
> + .get_attribute_text = get_attribute_text,
> + .list_values = list_values,
> + .get_value_text = get_value_text,
> + .get_value = get_value,
> + .set_value = set_value,
> + .get_play_status = get_play_status,
> + .get_element_attributes = get_element_attributes,
> + .register_notification = register_notification,
> + .set_addressed = set_addressed,
> };
>
> static void test_server(gconstpointer data)
> @@ -610,7 +458,7 @@ static void test_server(gconstpointer data)
>
> avrcp_set_passthrough_handlers(context->session, passthrough_handlers,
> context);
> - avrcp_set_control_handlers(context->session, control_handlers, context);
> + avrcp_register_player(context->session, &control_ind, NULL, context);
>
> g_idle_add(send_pdu, context);
>
> --
> 1.8.5.3
Pushed.
--
Luiz Augusto von Dentz
Hi Andrei,
On Tue, Mar 18, 2014 at 10:25 AM, Andrei Emeltchenko
<[email protected]> wrote:
> Hi Luiz,
>
> On Mon, Mar 17, 2014 at 03:07:49PM +0200, Luiz Augusto von Dentz wrote:
>> From: Luiz Augusto von Dentz <[email protected]>
>>
>> The correct status should 0x04 not 0x00.
>> ---
>> unit/test-avrcp.c | 7 +++++--
>> 1 file changed, 5 insertions(+), 2 deletions(-)
>>
>> diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
>> index 9fdbe6d..ed0c3fc 100644
>> --- a/unit/test-avrcp.c
>> +++ b/unit/test-avrcp.c
>> @@ -435,7 +435,10 @@ static int set_addressed(struct avrcp *session, uint8_t transaction,
>> {
>> DBG("");
>>
>> - return 1;
>> + avrcp_set_addressed_player_rsp(session, transaction,
>> + AVRCP_STATUS_SUCCESS);
>> +
>> + return -EAGAIN;
>> }
>>
>> static const struct avrcp_control_ind control_ind = {
>> @@ -547,7 +550,7 @@ int main(int argc, char *argv[])
>> raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_STABLE,
>> 0x48, 0x00, 0x00, 0x19, 0x58,
>> AVRCP_SET_ADDRESSED_PLAYER,
>> - 0x00, 0x00, 0x01, 0x00));
>> + 0x00, 0x00, 0x01, 0x04));
>
> I would put it 0x00, 0x00, 0x01, AVRCP_STATUS_SUCCESS));
I prefer not to input defines in the raw PDU, the reason is that it
just gets in your way to debug what values are wrong when using
hexdump, also some defines that you are using such as PDU ids should
probably not be exposed now that we have proper functions mapping to
them.
--
Luiz Augusto von Dentz
Hi Luiz,
On Mon, Mar 17, 2014 at 03:07:49PM +0200, Luiz Augusto von Dentz wrote:
> From: Luiz Augusto von Dentz <[email protected]>
>
> The correct status should 0x04 not 0x00.
> ---
> unit/test-avrcp.c | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
> index 9fdbe6d..ed0c3fc 100644
> --- a/unit/test-avrcp.c
> +++ b/unit/test-avrcp.c
> @@ -435,7 +435,10 @@ static int set_addressed(struct avrcp *session, uint8_t transaction,
> {
> DBG("");
>
> - return 1;
> + avrcp_set_addressed_player_rsp(session, transaction,
> + AVRCP_STATUS_SUCCESS);
> +
> + return -EAGAIN;
> }
>
> static const struct avrcp_control_ind control_ind = {
> @@ -547,7 +550,7 @@ int main(int argc, char *argv[])
> raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_STABLE,
> 0x48, 0x00, 0x00, 0x19, 0x58,
> AVRCP_SET_ADDRESSED_PLAYER,
> - 0x00, 0x00, 0x01, 0x00));
> + 0x00, 0x00, 0x01, 0x04));
I would put it 0x00, 0x00, 0x01, AVRCP_STATUS_SUCCESS));
Best regards
Andrei Emeltchenko
From: Luiz Augusto von Dentz <[email protected]>
This makes get_values_text callback to use
avrcp_get_player_values_text_rsp
---
unit/test-avrcp.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 4bf9e47..b443a40 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -341,7 +341,9 @@ static int get_value_text(struct avrcp *session, uint8_t transaction,
{
DBG("");
- return 1;
+ avrcp_get_player_values_text_rsp(session, transaction, 0, NULL, NULL);
+
+ return -EINVAL;
}
static int get_value(struct avrcp *session, uint8_t transaction,
--
1.8.5.3
From: Luiz Augusto von Dentz <[email protected]>
This function can be used to generate GetCapabilities response PDUs.
---
android/avrcp-lib.c | 16 ++++++++++++++++
android/avrcp-lib.h | 2 ++
2 files changed, 18 insertions(+)
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index cb3e61e..360da10 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -809,6 +809,22 @@ int avrcp_set_addressed_player(struct avrcp *session, uint16_t player_id,
sizeof(params), func, user_data);
}
+int avrcp_get_capabilities_rsp(struct avrcp *session, uint8_t transaction,
+ uint8_t number, uint8_t *events)
+{
+ uint8_t pdu[AVRCP_EVENT_LAST];
+
+ if (number > AVRCP_EVENT_LAST)
+ return -EINVAL;
+
+ pdu[0] = number;
+ memcpy(&pdu[1], events, number);
+
+ return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
+ AVC_SUBUNIT_PANEL, AVRCP_GET_CAPABILITIES,
+ pdu, number + 1);
+}
+
int avrcp_list_player_attributes_rsp(struct avrcp *session, uint8_t transaction,
uint8_t number, uint8_t *attrs)
{
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 8fb7152..30c7184 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -230,6 +230,8 @@ int avrcp_get_element_attributes(struct avrcp *session, avctp_rsp_cb func,
int avrcp_set_addressed_player(struct avrcp *session, uint16_t player_id,
avctp_rsp_cb func, void *user_data);
+int avrcp_get_capabilities_rsp(struct avrcp *session, uint8_t transaction,
+ uint8_t number, uint8_t *events);
int avrcp_list_player_attributes_rsp(struct avrcp *session, uint8_t transaction,
uint8_t number, uint8_t *attrs);
int avrcp_get_player_attribute_text_rsp(struct avrcp *session,
--
1.8.5.3
From: Luiz Augusto von Dentz <[email protected]>
---
android/avrcp-lib.c | 28 ++++++++++++++++++++--------
android/avrcp-lib.h | 15 ---------------
2 files changed, 20 insertions(+), 23 deletions(-)
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 360da10..83ff96a 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -99,6 +99,18 @@ struct avrcp_player {
void *user_data;
};
+static inline uint32_t ntoh24(const uint8_t src[3])
+{
+ return src[0] << 16 | src[1] << 8 | src[2];
+}
+
+static inline void hton24(uint8_t dst[3], uint32_t src)
+{
+ dst[0] = (src & 0xff0000) >> 16;
+ dst[1] = (src & 0x00ff00) >> 8;
+ dst[2] = (src & 0x0000ff);
+}
+
void avrcp_shutdown(struct avrcp *session)
{
if (session->conn) {
@@ -592,6 +604,14 @@ static const struct avrcp_control_handler player_handlers[] = {
{ },
};
+static void avrcp_set_control_handlers(struct avrcp *session,
+ const struct avrcp_control_handler *handlers,
+ void *user_data)
+{
+ session->control_handlers = handlers;
+ session->control_data = user_data;
+}
+
void avrcp_register_player(struct avrcp *session,
const struct avrcp_control_ind *ind,
const struct avrcp_control_cfm *cfm,
@@ -608,14 +628,6 @@ void avrcp_register_player(struct avrcp *session,
session->player = player;
}
-void avrcp_set_control_handlers(struct avrcp *session,
- const struct avrcp_control_handler *handlers,
- void *user_data)
-{
- session->control_handlers = handlers;
- session->control_data = user_data;
-}
-
void avrcp_set_passthrough_handlers(struct avrcp *session,
const struct avrcp_passthrough_handler *handlers,
void *user_data)
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 30c7184..d9acb7d 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -173,18 +173,6 @@ struct avrcp_passthrough_handler {
typedef void (*avrcp_destroy_cb_t) (void *user_data);
-static inline uint32_t ntoh24(const uint8_t src[3])
-{
- return src[0] << 16 | src[1] << 8 | src[2];
-}
-
-static inline void hton24(uint8_t dst[3], uint32_t src)
-{
- dst[0] = (src & 0xff0000) >> 16;
- dst[1] = (src & 0x00ff00) >> 8;
- dst[2] = (src & 0x0000ff);
-}
-
struct avrcp *avrcp_new(int fd, size_t imtu, size_t omtu, uint16_t version);
void avrcp_shutdown(struct avrcp *session);
void avrcp_set_destroy_cb(struct avrcp *session, avrcp_destroy_cb_t cb,
@@ -194,9 +182,6 @@ void avrcp_register_player(struct avrcp *session,
const struct avrcp_control_ind *ind,
const struct avrcp_control_cfm *cfm,
void *user_data);
-void avrcp_set_control_handlers(struct avrcp *session,
- const struct avrcp_control_handler *handlers,
- void *user_data);
void avrcp_set_passthrough_handlers(struct avrcp *session,
const struct avrcp_passthrough_handler *handlers,
void *user_data);
--
1.8.5.3
From: Luiz Augusto von Dentz <[email protected]>
This makes android daemon to start using avrcp_register_player instead
of now deprecated avrcp_set_control_handlers.
---
android/avrcp.c | 113 +++++++++++++++++---------------------------------------
1 file changed, 34 insertions(+), 79 deletions(-)
diff --git a/android/avrcp.c b/android/avrcp.c
index f0a6d59..437164e 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -599,34 +599,22 @@ static const struct avrcp_passthrough_handler passthrough_handlers[] = {
{ },
};
-static ssize_t handle_get_capabilities_cmd(struct avrcp *session,
- uint8_t transaction,
- uint16_t params_len,
- uint8_t *params,
- void *user_data)
+static int handle_get_capabilities_cmd(struct avrcp *session,
+ uint8_t transaction, void *user_data)
{
- DBG("");
+ uint8_t events[] = { AVRCP_EVENT_STATUS_CHANGED,
+ AVRCP_EVENT_TRACK_CHANGED,
+ AVRCP_EVENT_PLAYBACK_POS_CHANGED };
- if (params_len != 1)
- return -EINVAL;
+ DBG("");
- switch (params[0]) {
- case CAP_COMPANY_ID:
- params[params_len++] = 1;
- hton24(¶ms[params_len], IEEEID_BTSIG);
- return params_len + 3;
- case CAP_EVENTS_SUPPORTED:
- /* Android do not provide this info via HAL so the list most
- * be hardcoded according to what RegisterNotification can
- * actually handle */
- params[params_len++] = 3;
- params[params_len++] = AVRCP_EVENT_STATUS_CHANGED;
- params[params_len++] = AVRCP_EVENT_TRACK_CHANGED;
- params[params_len++] = AVRCP_EVENT_PLAYBACK_POS_CHANGED;
- return params_len;
- }
+ /* Android do not provide this info via HAL so the list most
+ * be hardcoded according to what RegisterNotification can
+ * actually handle */
+ avrcp_get_capabilities_rsp(session, transaction, sizeof(events),
+ events);
- return -EINVAL;
+ return -EAGAIN;
}
static void push_request(struct avrcp_device *dev, uint8_t pdu_id,
@@ -643,19 +631,13 @@ static void push_request(struct avrcp_device *dev, uint8_t pdu_id,
g_queue_push_tail(dev->queue, req);
}
-static ssize_t handle_get_play_status_cmd(struct avrcp *session,
- uint8_t transaction,
- uint16_t params_len,
- uint8_t *params,
- void *user_data)
+static int handle_get_play_status_cmd(struct avrcp *session,
+ uint8_t transaction, void *user_data)
{
struct avrcp_device *dev = user_data;
DBG("");
- if (params_len != 0)
- return -EINVAL;
-
ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
HAL_EV_AVRCP_GET_PLAY_STATUS, 0, NULL);
@@ -664,11 +646,10 @@ static ssize_t handle_get_play_status_cmd(struct avrcp *session,
return -EAGAIN;
}
-static ssize_t handle_get_element_attrs_cmd(struct avrcp *session,
- uint8_t transaction,
- uint16_t params_len,
- uint8_t *params,
- void *user_data)
+static int handle_get_element_attrs_cmd(struct avrcp *session,
+ uint8_t transaction, uint64_t uid,
+ uint8_t number, uint32_t *attrs,
+ void *user_data)
{
struct avrcp_device *dev = user_data;
uint8_t buf[IPC_MTU];
@@ -677,16 +658,7 @@ static ssize_t handle_get_element_attrs_cmd(struct avrcp *session,
DBG("");
- if (params_len < 9)
- return -EINVAL;
-
- ev->number = params[8];
-
- if (params_len < ev->number * sizeof(uint32_t) + 1)
- return -EINVAL;
-
- params += 9;
-
+ ev->number = number;
/* Set everything in case of empty list */
if (ev->number == 0) {
for (i = 0; i < HAL_AVRCP_MEDIA_ATTR_DURATION; i++) {
@@ -697,10 +669,8 @@ static ssize_t handle_get_element_attrs_cmd(struct avrcp *session,
goto done;
}
- for (i = 0; i < ev->number; i++) {
- ev->attrs[i] = bt_get_be32(params);
- params += 4;
- }
+ for (i = 0; i < number; i++)
+ ev->attrs[i] = attrs[i];
done:
ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
@@ -713,25 +683,19 @@ done:
}
-static ssize_t handle_register_notification_cmd(struct avrcp *session,
+static int handle_register_notification_cmd(struct avrcp *session,
uint8_t transaction,
- uint16_t params_len,
- uint8_t *params,
+ uint8_t event,
+ uint32_t interval,
void *user_data)
{
struct avrcp_device *dev = user_data;
struct hal_ev_avrcp_register_notification ev;
- uint8_t event_id;
DBG("");
- if (params_len != 5)
- return -EINVAL;
-
- event_id = params[0];
-
/* TODO: Add any missing events supported by Android */
- switch (event_id) {
+ switch (event) {
case AVRCP_EVENT_STATUS_CHANGED:
case AVRCP_EVENT_TRACK_CHANGED:
case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
@@ -740,32 +704,23 @@ static ssize_t handle_register_notification_cmd(struct avrcp *session,
return -EINVAL;
}
- ev.event = event_id;
- ev.param = bt_get_be32(¶ms[1]);
+ ev.event = event;
+ ev.param = interval;
ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
HAL_EV_AVRCP_REGISTER_NOTIFICATION,
sizeof(ev), &ev);
- push_request(dev, AVRCP_REGISTER_NOTIFICATION, event_id, transaction);
+ push_request(dev, AVRCP_REGISTER_NOTIFICATION, event, transaction);
return -EAGAIN;
}
-static const struct avrcp_control_handler control_handlers[] = {
- { AVRCP_GET_CAPABILITIES,
- AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
- handle_get_capabilities_cmd },
- { AVRCP_GET_PLAY_STATUS,
- AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
- handle_get_play_status_cmd },
- { AVRCP_GET_ELEMENT_ATTRIBUTES,
- AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
- handle_get_element_attrs_cmd },
- { AVRCP_REGISTER_NOTIFICATION,
- AVC_CTYPE_NOTIFY, AVC_CTYPE_INTERIM,
- handle_register_notification_cmd },
- { },
+static const struct avrcp_control_ind control_ind = {
+ .get_capabilities = handle_get_capabilities_cmd,
+ .get_play_status = handle_get_play_status_cmd,
+ .get_element_attributes = handle_get_element_attrs_cmd,
+ .register_notification = handle_register_notification_cmd,
};
static gboolean register_notification_rsp(struct avctp *conn,
@@ -848,7 +803,7 @@ static int avrcp_device_add_session(struct avrcp_device *dev, int fd,
avrcp_set_destroy_cb(dev->session, disconnect_cb, dev);
avrcp_set_passthrough_handlers(dev->session, passthrough_handlers,
dev);
- avrcp_set_control_handlers(dev->session, control_handlers, dev);
+ avrcp_register_player(dev->session, &control_ind, NULL, dev);
dev->queue = g_queue_new();
--
1.8.5.3
From: Luiz Augusto von Dentz <[email protected]>
This makes get_value callback to use avrcp_get_current_player_value_rsp
---
unit/test-avrcp.c | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index a49a0a2..3235e48 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -349,21 +349,14 @@ static int get_value_text(struct avrcp *session, uint8_t transaction,
static int get_value(struct avrcp *session, uint8_t transaction,
uint8_t number, uint8_t *attrs, void *user_data)
{
- uint8_t *attributes;
- int i;
+ uint8_t values[2] = { 0x00, 0x00 };
DBG("");
- attributes = g_memdup(attrs, number);
+ avrcp_get_current_player_value_rsp(session, transaction, number, attrs,
+ values);
- for (i = 0; i < number; i++) {
- attrs[i * 2 + 1] = attributes[i];
- attrs[i * 2 + 2] = 0; /* value */
- }
-
- g_free(attributes);
-
- return number * 2 + 1;
+ return -EAGAIN;
}
static int set_value(struct avrcp *session, uint8_t transaction,
--
1.8.5.3
From: Luiz Augusto von Dentz <[email protected]>
This function can be used to generate GetCurrentPlayerValue response
PDUs.
---
android/avrcp-lib.c | 26 ++++++++++++++++++++++++++
android/avrcp-lib.h | 3 +++
2 files changed, 29 insertions(+)
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 16636e6..cb3e61e 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -928,6 +928,32 @@ int avrcp_get_player_values_text_rsp(struct avrcp *session,
pdu, length);
}
+int avrcp_get_current_player_value_rsp(struct avrcp *session,
+ uint8_t transaction, uint8_t number,
+ uint8_t *attrs, uint8_t *values)
+{
+ uint8_t pdu[AVRCP_ATTRIBUTE_LAST * 2 + 1];
+ uint8_t *ptr;
+ uint16_t length;
+ int i;
+
+ if (number > AVRCP_ATTRIBUTE_LAST)
+ return -EINVAL;
+
+ pdu[0] = number;
+ length = 1;
+ for (i = 0, ptr = &pdu[1]; i < number; i++) {
+ ptr[0] = attrs[i];
+ ptr[1] = values[i];
+ ptr += 2;
+ length += 2;
+ }
+
+ return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
+ AVC_SUBUNIT_PANEL, AVRCP_GET_CURRENT_PLAYER_VALUE,
+ pdu, length);
+}
+
int avrcp_get_element_attrs_rsp(struct avrcp *session, uint8_t transaction,
uint8_t *params, size_t params_len)
{
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 181e7aa..8fb7152 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -243,6 +243,9 @@ int avrcp_get_play_status_rsp(struct avrcp *session, uint8_t transaction,
int avrcp_get_player_values_text_rsp(struct avrcp *session,
uint8_t transaction, uint8_t number,
uint8_t *values, const char **text);
+int avrcp_get_current_player_value_rsp(struct avrcp *session,
+ uint8_t transaction, uint8_t number,
+ uint8_t *attrs, uint8_t *values);
int avrcp_get_element_attrs_rsp(struct avrcp *session, uint8_t transaction,
uint8_t *params, size_t params_len);
int avrcp_register_notification_rsp(struct avrcp *session, uint8_t transaction,
--
1.8.5.3
From: Luiz Augusto von Dentz <[email protected]>
GetPlayerAttributeText needs at least one parameter otherwise it can be
considered invalid.
---
unit/test-avrcp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index b443a40..a49a0a2 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -670,7 +670,7 @@ int main(int argc, char *argv[])
raw_pdu(0x00, 0x11, 0x0e, 0x01, 0x48, 0x00,
0x00, 0x19, 0x58,
AVRCP_GET_PLAYER_ATTRIBUTE_TEXT,
- 0x00, 0x00, 0x00),
+ 0x00, 0x00, 0x01, 0x00),
raw_pdu(0x02, 0x11, 0x0e, 0x0c, 0x48, 0x00,
0x00, 0x19, 0x58,
AVRCP_GET_PLAYER_ATTRIBUTE_TEXT,
--
1.8.5.3
From: Luiz Augusto von Dentz <[email protected]>
This function can be used to generate GetPlayerValuesText response PDUs.
---
android/avrcp-lib.c | 33 +++++++++++++++++++++++++++++++++
android/avrcp-lib.h | 3 +++
2 files changed, 36 insertions(+)
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index fe3205e..16636e6 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -895,6 +895,39 @@ int avrcp_get_play_status_rsp(struct avrcp *session, uint8_t transaction,
pdu, sizeof(pdu));
}
+int avrcp_get_player_values_text_rsp(struct avrcp *session,
+ uint8_t transaction, uint8_t number,
+ uint8_t *values, const char **text)
+{
+ uint8_t pdu[AVRCP_ATTRIBUTE_LAST * (4 + 255)];
+ uint8_t *ptr;
+ uint16_t length;
+ int i;
+
+ if (number > AVRCP_ATTRIBUTE_LAST)
+ return -EINVAL;
+
+ pdu[0] = number;
+ length = 1;
+ for (i = 0, ptr = &pdu[1]; i < number; i++) {
+ uint8_t len = 0;
+
+ if (text[i])
+ len = strlen(text[i]);
+
+ ptr[0] = values[i];
+ bt_put_be16(AVRCP_CHARSET_UTF8, &ptr[1]);
+ ptr[3] = len;
+ memcpy(ptr, text[i], len);
+ ptr += 4 + len;
+ length += 4 + len;
+ }
+
+ return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
+ AVC_SUBUNIT_PANEL, AVRCP_GET_PLAYER_VALUE_TEXT,
+ pdu, length);
+}
+
int avrcp_get_element_attrs_rsp(struct avrcp *session, uint8_t transaction,
uint8_t *params, size_t params_len)
{
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index a9485b2..181e7aa 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -240,6 +240,9 @@ int avrcp_list_player_values_rsp(struct avrcp *session, uint8_t transaction,
int avrcp_get_play_status_rsp(struct avrcp *session, uint8_t transaction,
uint32_t position, uint32_t duration,
uint8_t status);
+int avrcp_get_player_values_text_rsp(struct avrcp *session,
+ uint8_t transaction, uint8_t number,
+ uint8_t *values, const char **text);
int avrcp_get_element_attrs_rsp(struct avrcp *session, uint8_t transaction,
uint8_t *params, size_t params_len);
int avrcp_register_notification_rsp(struct avrcp *session, uint8_t transaction,
--
1.8.5.3
From: Luiz Augusto von Dentz <[email protected]>
This makes list_values callback to use avrcp_list_player_values_rsp.
---
unit/test-avrcp.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 4bca7b4..4bf9e47 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -330,7 +330,9 @@ static int list_values(struct avrcp *session, uint8_t transaction,
{
DBG("");
- return 1;
+ avrcp_list_player_values_rsp(session, transaction, 0, NULL);
+
+ return -EINVAL;
}
static int get_value_text(struct avrcp *session, uint8_t transaction,
--
1.8.5.3
From: Luiz Augusto von Dentz <[email protected]>
This function can be used to generate ListPlayerValues response PDUs.
---
android/avrcp-lib.c | 16 ++++++++++++++++
android/avrcp-lib.h | 2 ++
2 files changed, 18 insertions(+)
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 05ec329..fe3205e 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -864,6 +864,22 @@ int avrcp_get_player_attribute_text_rsp(struct avrcp *session,
pdu, length);
}
+int avrcp_list_player_values_rsp(struct avrcp *session, uint8_t transaction,
+ uint8_t number, uint8_t *values)
+{
+ uint8_t pdu[AVRCP_ATTRIBUTE_LAST + 1];
+
+ if (number > AVRCP_ATTRIBUTE_LAST)
+ return -EINVAL;
+
+ pdu[0] = number;
+ memcpy(&pdu[1], values, number);
+
+ return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
+ AVC_SUBUNIT_PANEL, AVRCP_LIST_PLAYER_VALUES,
+ pdu, number + 1);
+}
+
int avrcp_get_play_status_rsp(struct avrcp *session, uint8_t transaction,
uint32_t position, uint32_t duration,
uint8_t status)
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index b53b916..a9485b2 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -235,6 +235,8 @@ int avrcp_list_player_attributes_rsp(struct avrcp *session, uint8_t transaction,
int avrcp_get_player_attribute_text_rsp(struct avrcp *session,
uint8_t transaction, uint8_t number,
uint8_t *attrs, const char **text);
+int avrcp_list_player_values_rsp(struct avrcp *session, uint8_t transaction,
+ uint8_t number, uint8_t *values);
int avrcp_get_play_status_rsp(struct avrcp *session, uint8_t transaction,
uint32_t position, uint32_t duration,
uint8_t status);
--
1.8.5.3
From: Luiz Augusto von Dentz <[email protected]>
This makes list_attributes callback to use
avrcp_get_player_attribute_text_rsp.
---
unit/test-avrcp.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 204d190..4bca7b4 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -319,7 +319,10 @@ static int get_attribute_text(struct avrcp *session, uint8_t transaction,
{
DBG("");
- return 1;
+ avrcp_get_player_attribute_text_rsp(session, transaction, 0, NULL,
+ NULL);
+
+ return -EAGAIN;
}
static int list_values(struct avrcp *session, uint8_t transaction,
--
1.8.5.3
From: Luiz Augusto von Dentz <[email protected]>
This function can be used to generate GetPlayerAttributeText response
PDUs.
---
android/avrcp-lib.c | 39 +++++++++++++++++++++++++++++++++++++++
android/avrcp-lib.h | 3 +++
2 files changed, 42 insertions(+)
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 97822ac..05ec329 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -43,6 +43,8 @@
#define AVRCP_PACKET_TYPE_CONTINUING 0x02
#define AVRCP_PACKET_TYPE_END 0x03
+#define AVRCP_CHARSET_UTF8 106
+
#if __BYTE_ORDER == __LITTLE_ENDIAN
struct avrcp_header {
@@ -825,6 +827,43 @@ int avrcp_list_player_attributes_rsp(struct avrcp *session, uint8_t transaction,
pdu, number + 1);
}
+int avrcp_get_player_attribute_text_rsp(struct avrcp *session,
+ uint8_t transaction, uint8_t number,
+ uint8_t *attrs, const char **text)
+{
+ uint8_t pdu[AVRCP_ATTRIBUTE_LAST * (4 + 255)];
+ uint8_t *ptr;
+ uint16_t length;
+ int i;
+
+ if (number > AVRCP_ATTRIBUTE_LAST)
+ return -EINVAL;
+
+ pdu[0] = number;
+ length = 1;
+ for (i = 0, ptr = &pdu[1]; i < number; i++) {
+ uint8_t len = 0;
+
+ if (attrs[i] > AVRCP_ATTRIBUTE_LAST ||
+ attrs[i] == AVRCP_ATTRIBUTE_ILEGAL)
+ return -EINVAL;
+
+ if (text[i])
+ len = strlen(text[i]);
+
+ ptr[0] = attrs[i];
+ bt_put_be16(AVRCP_CHARSET_UTF8, &ptr[1]);
+ ptr[3] = len;
+ memcpy(ptr, text[i], len);
+ ptr += 4 + len;
+ length += 4 + len;
+ }
+
+ return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
+ AVC_SUBUNIT_PANEL, AVRCP_GET_PLAYER_ATTRIBUTE_TEXT,
+ pdu, length);
+}
+
int avrcp_get_play_status_rsp(struct avrcp *session, uint8_t transaction,
uint32_t position, uint32_t duration,
uint8_t status)
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 80a6b6a..b53b916 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -232,6 +232,9 @@ int avrcp_set_addressed_player(struct avrcp *session, uint16_t player_id,
int avrcp_list_player_attributes_rsp(struct avrcp *session, uint8_t transaction,
uint8_t number, uint8_t *attrs);
+int avrcp_get_player_attribute_text_rsp(struct avrcp *session,
+ uint8_t transaction, uint8_t number,
+ uint8_t *attrs, const char **text);
int avrcp_get_play_status_rsp(struct avrcp *session, uint8_t transaction,
uint32_t position, uint32_t duration,
uint8_t status);
--
1.8.5.3
From: Luiz Augusto von Dentz <[email protected]>
This makes list_attributes callback to use
avrcp_list_player_attributes_rsp.
---
unit/test-avrcp.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index ed0c3fc..204d190 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -308,7 +308,9 @@ static int list_attributes(struct avrcp *session, uint8_t transaction,
{
DBG("");
- return 1;
+ avrcp_list_player_attributes_rsp(session, transaction, 0, NULL);
+
+ return -EAGAIN;
}
static int get_attribute_text(struct avrcp *session, uint8_t transaction,
--
1.8.5.3
From: Luiz Augusto von Dentz <[email protected]>
This function can be used to generate ListPlayerAttributes response PDUs.
---
android/avrcp-lib.c | 18 ++++++++++++++++++
android/avrcp-lib.h | 2 ++
2 files changed, 20 insertions(+)
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index dc0d516..97822ac 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -807,6 +807,24 @@ int avrcp_set_addressed_player(struct avrcp *session, uint16_t player_id,
sizeof(params), func, user_data);
}
+int avrcp_list_player_attributes_rsp(struct avrcp *session, uint8_t transaction,
+ uint8_t number, uint8_t *attrs)
+{
+ uint8_t pdu[AVRCP_ATTRIBUTE_LAST + 1];
+
+ if (number > AVRCP_ATTRIBUTE_LAST)
+ return -EINVAL;
+
+ pdu[0] = number;
+
+ if (number > 0)
+ memcpy(&pdu[1], attrs, number);
+
+ return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
+ AVC_SUBUNIT_PANEL, AVRCP_LIST_PLAYER_ATTRIBUTES,
+ pdu, number + 1);
+}
+
int avrcp_get_play_status_rsp(struct avrcp *session, uint8_t transaction,
uint32_t position, uint32_t duration,
uint8_t status)
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 2117838..80a6b6a 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -230,6 +230,8 @@ int avrcp_get_element_attributes(struct avrcp *session, avctp_rsp_cb func,
int avrcp_set_addressed_player(struct avrcp *session, uint16_t player_id,
avctp_rsp_cb func, void *user_data);
+int avrcp_list_player_attributes_rsp(struct avrcp *session, uint8_t transaction,
+ uint8_t number, uint8_t *attrs);
int avrcp_get_play_status_rsp(struct avrcp *session, uint8_t transaction,
uint32_t position, uint32_t duration,
uint8_t status);
--
1.8.5.3
From: Luiz Augusto von Dentz <[email protected]>
The correct status should 0x04 not 0x00.
---
unit/test-avrcp.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 9fdbe6d..ed0c3fc 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -435,7 +435,10 @@ static int set_addressed(struct avrcp *session, uint8_t transaction,
{
DBG("");
- return 1;
+ avrcp_set_addressed_player_rsp(session, transaction,
+ AVRCP_STATUS_SUCCESS);
+
+ return -EAGAIN;
}
static const struct avrcp_control_ind control_ind = {
@@ -547,7 +550,7 @@ int main(int argc, char *argv[])
raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_STABLE,
0x48, 0x00, 0x00, 0x19, 0x58,
AVRCP_SET_ADDRESSED_PLAYER,
- 0x00, 0x00, 0x01, 0x00));
+ 0x00, 0x00, 0x01, 0x04));
/* Connection Establishment for Control tests */
--
1.8.5.3
From: Luiz Augusto von Dentz <[email protected]>
This function can be used to generate SetAddressedPlayer response PDUs.
---
android/avrcp-lib.c | 8 ++++++++
android/avrcp-lib.h | 2 ++
2 files changed, 10 insertions(+)
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 60d494f..dc0d516 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -839,6 +839,14 @@ int avrcp_register_notification_rsp(struct avrcp *session, uint8_t transaction,
params, params_len);
}
+int avrcp_set_addressed_player_rsp(struct avrcp *session, uint8_t transaction,
+ uint8_t status)
+{
+ return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
+ AVC_SUBUNIT_PANEL, AVRCP_SET_ADDRESSED_PLAYER,
+ &status, sizeof(status));
+}
+
int avrcp_send_passthrough(struct avrcp *session, uint32_t vendor, uint8_t op)
{
uint8_t params[5];
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 54bdf4f..2117838 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -238,4 +238,6 @@ int avrcp_get_element_attrs_rsp(struct avrcp *session, uint8_t transaction,
int avrcp_register_notification_rsp(struct avrcp *session, uint8_t transaction,
uint8_t code, uint8_t *params,
size_t params_len);
+int avrcp_set_addressed_player_rsp(struct avrcp *session, uint8_t transaction,
+ uint8_t status);
int avrcp_send_passthrough(struct avrcp *session, uint32_t vendor, uint8_t op);
--
1.8.5.3