From: Andrei Emeltchenko <[email protected]>
---
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 9760420..fe7009a 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -578,7 +578,7 @@ static void test_server(gconstpointer data)
avrcp_set_passthrough_handlers(context->session, passthrough_handlers,
context);
- avrcp_set_control_handlers(context->session, control_handlers, NULL);
+ avrcp_set_control_handlers(context->session, control_handlers, context);
g_idle_add(send_pdu, context);
--
1.8.3.2
Hi Andrei,
On Wed, Mar 12, 2014 at 4:40 PM, Andrei Emeltchenko
<[email protected]> wrote:
> From: Andrei Emeltchenko <[email protected]>
>
> This allows to use vendor unique commands
> ---
> android/avctp.c | 74 ++++++++++++++++++++++++++++++++++++++++++++-------------
> android/avctp.h | 8 ++++++-
> 2 files changed, 65 insertions(+), 17 deletions(-)
>
> diff --git a/android/avctp.c b/android/avctp.c
> index d970250..e9ba6db 100644
> --- a/android/avctp.c
> +++ b/android/avctp.c
> @@ -159,6 +159,8 @@ struct avctp_channel {
>
> struct key_pressed {
> uint8_t op;
> + uint8_t *params;
> + size_t params_len;
> guint timer;
> };
>
> @@ -1172,25 +1174,38 @@ static const char *op2str(uint8_t op)
> return "UNKNOWN";
> }
>
> -static int avctp_passthrough_press(struct avctp *session, uint8_t op)
> +static int avctp_passthrough_press(struct avctp *session, uint8_t op,
> + uint8_t *params, size_t params_len)
> {
> - uint8_t operands[2];
> + uint8_t operands[7];
> + size_t len;
>
> - DBG("%s", op2str(op));
> + DBG("op 0x%02x %s params_len %zd", op, op2str(op), params_len);
>
> /* Button pressed */
> operands[0] = op & 0x7f;
> - operands[1] = 0;
> +
> + if (op == AVC_VENDOR_UNIQUE && params &&
> + params_len == 5) {
> + memcpy(&operands[2], params, params_len);
> + len = params_len + 2;
> + operands[1] = params_len;
> + } else {
> + len = 2;
> + operands[1] = 0;
> + }
>
> return avctp_send_req(session, AVC_CTYPE_CONTROL,
> AVC_SUBUNIT_PANEL, AVC_OP_PASSTHROUGH,
> - operands, sizeof(operands),
> + operands, len,
> avctp_passthrough_rsp, NULL);
> }
>
> -static int avctp_passthrough_release(struct avctp *session, uint8_t op)
> +static int avctp_passthrough_release(struct avctp *session, uint8_t op,
> + uint8_t *params, size_t params_len)
> {
> - uint8_t operands[2];
> + uint8_t operands[7];
> + size_t len;
>
> DBG("%s", op2str(op));
>
> @@ -1198,9 +1213,16 @@ static int avctp_passthrough_release(struct avctp *session, uint8_t op)
> operands[0] = op | 0x80;
> operands[1] = 0;
>
> + if (op == AVC_VENDOR_UNIQUE && params &&
> + params_len > sizeof(operands) - 2) {
> + memcpy(&operands[2], params, params_len);
> + len = params_len;
> + } else
> + len = 2;
> +
> return avctp_send_req(session, AVC_CTYPE_CONTROL,
> AVC_SUBUNIT_PANEL, AVC_OP_PASSTHROUGH,
> - operands, sizeof(operands),
> + operands, len,
> NULL, NULL);
> }
>
> @@ -1208,15 +1230,18 @@ static gboolean repeat_timeout(gpointer user_data)
> {
> struct avctp *session = user_data;
>
> - avctp_passthrough_release(session, session->key.op);
> - avctp_passthrough_press(session, session->key.op);
> + avctp_passthrough_release(session, session->key.op, session->key.params,
> + session->key.params_len);
> + avctp_passthrough_press(session, session->key.op, session->key.params,
> + session->key.params_len);
>
> return TRUE;
> }
>
> static void release_pressed(struct avctp *session)
> {
> - avctp_passthrough_release(session, session->key.op);
> + avctp_passthrough_release(session, session->key.op, session->key.params,
> + session->key.params_len);
>
> if (session->key.timer > 0)
> g_source_remove(session->key.timer);
> @@ -1224,7 +1249,8 @@ static void release_pressed(struct avctp *session)
> session->key.timer = 0;
> }
>
> -static bool set_pressed(struct avctp *session, uint8_t op)
> +static bool set_pressed(struct avctp *session, uint8_t op, uint8_t *params,
> + size_t params_len)
> {
> if (session->key.timer > 0) {
> if (session->key.op == op)
> @@ -1236,6 +1262,8 @@ static bool set_pressed(struct avctp *session, uint8_t op)
> return FALSE;
>
> session->key.op = op;
> + session->key.params = params;
> + session->key.params_len = params_len;
> session->key.timer = g_timeout_add_seconds(AVC_PRESS_TIMEOUT,
> repeat_timeout,
> session);
> @@ -1247,24 +1275,38 @@ static gboolean avctp_passthrough_rsp(struct avctp *session, uint8_t code,
> uint8_t subunit, uint8_t *operands,
> size_t operand_count, void *user_data)
> {
> + uint8_t *params;
> + size_t params_len;
> +
> + DBG("code 0x%02x operand_count %zd", code, operand_count);
> +
> if (code != AVC_CTYPE_ACCEPTED)
> return FALSE;
>
> - if (set_pressed(session, operands[0]))
> + if (operands[0] == AVC_VENDOR_UNIQUE) {
> + params = &operands[2];
> + params_len = operand_count - 2;
> + } else {
> + params = NULL;
> + params_len = 0;
> + }
> +
> + if (set_pressed(session, operands[0], params, params_len))
> return FALSE;
>
> - avctp_passthrough_release(session, operands[0]);
> + avctp_passthrough_release(session, operands[0], params, params_len);
>
> return FALSE;
> }
>
> -int avctp_send_passthrough(struct avctp *session, uint8_t op)
> +int avctp_send_passthrough(struct avctp *session, uint8_t op, uint8_t *params,
> + size_t params_len)
> {
> /* Auto release if key pressed */
> if (session->key.timer > 0)
> release_pressed(session);
>
> - return avctp_passthrough_press(session, op);
> + return avctp_passthrough_press(session, op, params, params_len);
> }
>
> int avctp_send_vendordep(struct avctp *session, uint8_t transaction,
> diff --git a/android/avctp.h b/android/avctp.h
> index 2f419a2..98c1142 100644
> --- a/android/avctp.h
> +++ b/android/avctp.h
> @@ -108,6 +108,11 @@
> #define AVC_BLUE 0x7c
> #define AVC_YELLOW 0x7c
>
> +#define AVC_VENDOR_UNIQUE 0x7e
> +
> +#define AVC_VENDOR_NEXT_GROUP 0x00
> +#define AVC_VENDOR_PREV_GROUP 0x01
> +
> struct avctp;
>
> typedef bool (*avctp_passthrough_cb) (struct avctp *session,
> @@ -159,7 +164,8 @@ unsigned int avctp_register_browsing_pdu_handler(struct avctp *session,
> bool avctp_unregister_browsing_pdu_handler(struct avctp *session,
> unsigned int id);
>
> -int avctp_send_passthrough(struct avctp *session, uint8_t op);
> +int avctp_send_passthrough(struct avctp *session, uint8_t op, uint8_t *params,
> + size_t params_len);
> int avctp_send_vendordep(struct avctp *session, uint8_t transaction,
> uint8_t code, uint8_t subunit,
> uint8_t *operands, size_t operand_count);
> --
> 1.8.3.2
Pushed with changes to avrcp_send_passthrough and avrcp_set_addressed_player.
--
Luiz Augusto von Dentz
From: Andrei Emeltchenko <[email protected]>
This allows to use vendor unique commands
---
android/avctp.c | 74 ++++++++++++++++++++++++++++++++++++++++++++-------------
android/avctp.h | 8 ++++++-
2 files changed, 65 insertions(+), 17 deletions(-)
diff --git a/android/avctp.c b/android/avctp.c
index d970250..e9ba6db 100644
--- a/android/avctp.c
+++ b/android/avctp.c
@@ -159,6 +159,8 @@ struct avctp_channel {
struct key_pressed {
uint8_t op;
+ uint8_t *params;
+ size_t params_len;
guint timer;
};
@@ -1172,25 +1174,38 @@ static const char *op2str(uint8_t op)
return "UNKNOWN";
}
-static int avctp_passthrough_press(struct avctp *session, uint8_t op)
+static int avctp_passthrough_press(struct avctp *session, uint8_t op,
+ uint8_t *params, size_t params_len)
{
- uint8_t operands[2];
+ uint8_t operands[7];
+ size_t len;
- DBG("%s", op2str(op));
+ DBG("op 0x%02x %s params_len %zd", op, op2str(op), params_len);
/* Button pressed */
operands[0] = op & 0x7f;
- operands[1] = 0;
+
+ if (op == AVC_VENDOR_UNIQUE && params &&
+ params_len == 5) {
+ memcpy(&operands[2], params, params_len);
+ len = params_len + 2;
+ operands[1] = params_len;
+ } else {
+ len = 2;
+ operands[1] = 0;
+ }
return avctp_send_req(session, AVC_CTYPE_CONTROL,
AVC_SUBUNIT_PANEL, AVC_OP_PASSTHROUGH,
- operands, sizeof(operands),
+ operands, len,
avctp_passthrough_rsp, NULL);
}
-static int avctp_passthrough_release(struct avctp *session, uint8_t op)
+static int avctp_passthrough_release(struct avctp *session, uint8_t op,
+ uint8_t *params, size_t params_len)
{
- uint8_t operands[2];
+ uint8_t operands[7];
+ size_t len;
DBG("%s", op2str(op));
@@ -1198,9 +1213,16 @@ static int avctp_passthrough_release(struct avctp *session, uint8_t op)
operands[0] = op | 0x80;
operands[1] = 0;
+ if (op == AVC_VENDOR_UNIQUE && params &&
+ params_len > sizeof(operands) - 2) {
+ memcpy(&operands[2], params, params_len);
+ len = params_len;
+ } else
+ len = 2;
+
return avctp_send_req(session, AVC_CTYPE_CONTROL,
AVC_SUBUNIT_PANEL, AVC_OP_PASSTHROUGH,
- operands, sizeof(operands),
+ operands, len,
NULL, NULL);
}
@@ -1208,15 +1230,18 @@ static gboolean repeat_timeout(gpointer user_data)
{
struct avctp *session = user_data;
- avctp_passthrough_release(session, session->key.op);
- avctp_passthrough_press(session, session->key.op);
+ avctp_passthrough_release(session, session->key.op, session->key.params,
+ session->key.params_len);
+ avctp_passthrough_press(session, session->key.op, session->key.params,
+ session->key.params_len);
return TRUE;
}
static void release_pressed(struct avctp *session)
{
- avctp_passthrough_release(session, session->key.op);
+ avctp_passthrough_release(session, session->key.op, session->key.params,
+ session->key.params_len);
if (session->key.timer > 0)
g_source_remove(session->key.timer);
@@ -1224,7 +1249,8 @@ static void release_pressed(struct avctp *session)
session->key.timer = 0;
}
-static bool set_pressed(struct avctp *session, uint8_t op)
+static bool set_pressed(struct avctp *session, uint8_t op, uint8_t *params,
+ size_t params_len)
{
if (session->key.timer > 0) {
if (session->key.op == op)
@@ -1236,6 +1262,8 @@ static bool set_pressed(struct avctp *session, uint8_t op)
return FALSE;
session->key.op = op;
+ session->key.params = params;
+ session->key.params_len = params_len;
session->key.timer = g_timeout_add_seconds(AVC_PRESS_TIMEOUT,
repeat_timeout,
session);
@@ -1247,24 +1275,38 @@ static gboolean avctp_passthrough_rsp(struct avctp *session, uint8_t code,
uint8_t subunit, uint8_t *operands,
size_t operand_count, void *user_data)
{
+ uint8_t *params;
+ size_t params_len;
+
+ DBG("code 0x%02x operand_count %zd", code, operand_count);
+
if (code != AVC_CTYPE_ACCEPTED)
return FALSE;
- if (set_pressed(session, operands[0]))
+ if (operands[0] == AVC_VENDOR_UNIQUE) {
+ params = &operands[2];
+ params_len = operand_count - 2;
+ } else {
+ params = NULL;
+ params_len = 0;
+ }
+
+ if (set_pressed(session, operands[0], params, params_len))
return FALSE;
- avctp_passthrough_release(session, operands[0]);
+ avctp_passthrough_release(session, operands[0], params, params_len);
return FALSE;
}
-int avctp_send_passthrough(struct avctp *session, uint8_t op)
+int avctp_send_passthrough(struct avctp *session, uint8_t op, uint8_t *params,
+ size_t params_len)
{
/* Auto release if key pressed */
if (session->key.timer > 0)
release_pressed(session);
- return avctp_passthrough_press(session, op);
+ return avctp_passthrough_press(session, op, params, params_len);
}
int avctp_send_vendordep(struct avctp *session, uint8_t transaction,
diff --git a/android/avctp.h b/android/avctp.h
index 2f419a2..98c1142 100644
--- a/android/avctp.h
+++ b/android/avctp.h
@@ -108,6 +108,11 @@
#define AVC_BLUE 0x7c
#define AVC_YELLOW 0x7c
+#define AVC_VENDOR_UNIQUE 0x7e
+
+#define AVC_VENDOR_NEXT_GROUP 0x00
+#define AVC_VENDOR_PREV_GROUP 0x01
+
struct avctp;
typedef bool (*avctp_passthrough_cb) (struct avctp *session,
@@ -159,7 +164,8 @@ unsigned int avctp_register_browsing_pdu_handler(struct avctp *session,
bool avctp_unregister_browsing_pdu_handler(struct avctp *session,
unsigned int id);
-int avctp_send_passthrough(struct avctp *session, uint8_t op);
+int avctp_send_passthrough(struct avctp *session, uint8_t op, uint8_t *params,
+ size_t params_len);
int avctp_send_vendordep(struct avctp *session, uint8_t transaction,
uint8_t code, uint8_t subunit,
uint8_t *operands, size_t operand_count);
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that the Target responds to Next Group command.
---
unit/test-avrcp.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 3714c1a..7351a34 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -280,11 +280,20 @@ static bool handle_select(struct avrcp *session, bool pressed, void *user_data)
return true;
}
+static bool handle_vendor_uniq(struct avrcp *session, bool pressed,
+ void *user_data)
+{
+ DBG("");
+
+ return true;
+}
+
static const struct avrcp_passthrough_handler passthrough_handlers[] = {
{ AVC_PLAY, handle_play },
{ AVC_VOLUME_UP, handle_volume_up },
{ AVC_CHANNEL_UP, handle_channel_up },
{ AVC_SELECT, handle_select },
+ { AVC_VENDOR_UNIQUE, handle_vendor_uniq },
{ },
};
@@ -1045,6 +1054,17 @@ int main(int argc, char *argv[])
AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
0x58, 0x00, AVC_VENDOR_NEXT_GROUP));
+ /* Next Group command transfer - TG */
+ define_test("/TP/BGN/BV-01-I", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48,
+ AVC_OP_PASSTHROUGH,
+ AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
+ 0x58, 0x00, AVC_VENDOR_NEXT_GROUP),
+ raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_ACCEPTED,
+ 0x48, AVC_OP_PASSTHROUGH,
+ AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
+ 0x58, 0x00, AVC_VENDOR_NEXT_GROUP));
+
/* Previous Group command transfer - CT */
define_test("/TP/BGN/BV-02-I", test_client,
raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48,
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
This function allows to send AVRCP vendor unique commands.
---
android/avrcp-lib.c | 11 +++++++++++
android/avrcp-lib.h | 1 +
2 files changed, 12 insertions(+)
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 5400f80..f719a00 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -471,3 +471,14 @@ int avrcp_register_notification_rsp(struct avrcp *session, uint8_t transaction,
AVC_SUBUNIT_PANEL, AVRCP_REGISTER_NOTIFICATION,
params, params_len);
}
+
+int avrcp_send_passthrough(struct avrcp *session, uint32_t vendor, uint8_t op)
+{
+ uint8_t params[5];
+
+ hton24(params, vendor);
+ bt_put_be16(op, ¶ms[3]);
+
+ return avctp_send_passthrough(session->conn, AVC_VENDOR_UNIQUE, params,
+ sizeof(params));
+}
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 91a7d47..cc6c2ee 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -164,3 +164,4 @@ 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_send_passthrough(struct avrcp *session, uint32_t vendor, uint8_t op);
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that the Target responds to Prev Group command.
---
unit/test-avrcp.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 7351a34..82c18b5 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -1072,5 +1072,16 @@ int main(int argc, char *argv[])
AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
0x58, 0x00, AVC_VENDOR_PREV_GROUP));
+ /* Previous Group command transfer - TG */
+ define_test("/TP/BGN/BV-02-I", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48,
+ AVC_OP_PASSTHROUGH,
+ AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
+ 0x58, 0x00, AVC_VENDOR_PREV_GROUP),
+ raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_ACCEPTED,
+ 0x48, AVC_OP_PASSTHROUGH,
+ AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
+ 0x58, 0x00, AVC_VENDOR_PREV_GROUP));
+
return g_test_run();
}
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that the Controller can send Prev Group command to the
Target.
---
unit/test-avrcp.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index f0f36dd..3714c1a 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -639,6 +639,11 @@ static void test_client(gconstpointer data)
if (g_str_equal(context->data->test_name, "/TP/BGN/BV-01-I"))
avrcp_send_passthrough(context->session, IEEEID_BTSIG,
AVC_VENDOR_NEXT_GROUP);
+
+ if (g_str_equal(context->data->test_name, "/TP/BGN/BV-02-I"))
+ avrcp_send_passthrough(context->session, IEEEID_BTSIG,
+ AVC_VENDOR_PREV_GROUP);
+
execute_context(context);
}
@@ -1040,5 +1045,12 @@ int main(int argc, char *argv[])
AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
0x58, 0x00, AVC_VENDOR_NEXT_GROUP));
+ /* Previous Group command transfer - CT */
+ define_test("/TP/BGN/BV-02-I", test_client,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48,
+ AVC_OP_PASSTHROUGH,
+ AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
+ 0x58, 0x00, AVC_VENDOR_PREV_GROUP));
+
return g_test_run();
}
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
---
android/avrcp-lib.c | 12 ++++++++++++
android/avrcp-lib.h | 3 +++
2 files changed, 15 insertions(+)
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index f719a00..68c2df4 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -440,6 +440,18 @@ int avrcp_get_element_attributes(struct avrcp *session, avctp_rsp_cb func,
func, user_data);
}
+int avrcp_set_addr_player(struct avrcp *session, uint16_t player_id,
+ avctp_rsp_cb func, void *user_data)
+{
+ uint8_t params[2];
+
+ bt_put_be16(player_id, params);
+
+ return avrcp_send_req(session, AVC_CTYPE_CONTROL, AVC_SUBUNIT_PANEL,
+ AVRCP_SET_ADDRESSED_PLAYER, params,
+ sizeof(params), func, user_data);
+}
+
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 cc6c2ee..17072fb 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -37,6 +37,7 @@
#define AVRCP_REQUEST_CONTINUING 0x40
#define AVRCP_ABORT_CONTINUING 0x41
#define AVRCP_SET_ABSOLUTE_VOLUME 0x50
+#define AVRCP_SET_ADDRESSED_PLAYER 0x60
#define AVRCP_SET_BROWSED_PLAYER 0x70
#define AVRCP_GET_FOLDER_ITEMS 0x71
#define AVRCP_CHANGE_PATH 0x72
@@ -155,6 +156,8 @@ int avrcp_set_volume(struct avrcp *session, uint8_t volume, avctp_rsp_cb func,
void *user_data);
int avrcp_get_element_attributes(struct avrcp *session, avctp_rsp_cb func,
void *user_data);
+int avrcp_set_addr_player(struct avrcp *session, uint16_t player_id,
+ avctp_rsp_cb func, void *user_data);
int avrcp_get_play_status_rsp(struct avrcp *session, uint8_t transaction,
uint32_t position, uint32_t duration,
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that SetAddressedPlayer command issued by Controller.
---
unit/test-avrcp.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 82c18b5..56f73b4 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -605,6 +605,9 @@ static void test_client(gconstpointer data)
{
struct context *context = create_context(0x0100, data);
+ if (g_str_equal(context->data->test_name, "/TP/MPS/BV-01-C"))
+ avrcp_set_addr_player(context->session, 0xabcd, NULL, NULL);
+
if (g_str_equal(context->data->test_name, "/TP/CFG/BV-01-C"))
avrcp_get_capabilities(context->session, CAP_EVENTS_SUPPORTED,
NULL, NULL);
@@ -663,6 +666,14 @@ int main(int argc, char *argv[])
if (g_test_verbose())
__btd_log_init("*", 0);
+ /* Media Player Selection Commands and Notifications */
+
+ /* SetAddressedPlayer - CT */
+ define_test("/TP/MPS/BV-01-C", test_client,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48, 0x00,
+ 0x00, 0x19, 0x58, 0x60, 0x00, 0x00,
+ 0x02, 0xab, 0xcd));
+
/* Connection Establishment for Control tests */
/*
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that SetAddressedPlayer response issued by the Target.
---
unit/test-avrcp.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 56f73b4..75e8036 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -468,6 +468,19 @@ static ssize_t avrcp_handle_set_player_value(struct avrcp *session,
return 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)
+{
+ DBG("");
+
+ params[0] = 0;
+
+ return 1;
+}
+
static ssize_t avrcp_handle_get_play_status(struct avrcp *session,
uint8_t transaction,
uint16_t params_len,
@@ -585,6 +598,9 @@ static const struct avrcp_control_handler control_handlers[] = {
{ 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 },
{ },
};
@@ -674,6 +690,16 @@ int main(int argc, char *argv[])
0x00, 0x19, 0x58, 0x60, 0x00, 0x00,
0x02, 0xab, 0xcd));
+ /* SetAddressedPlayer - TG */
+ define_test("/TP/MPS/BV-02-C", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48, 0x00,
+ 0x00, 0x19, 0x58, AVRCP_SET_ADDRESSED_PLAYER,
+ 0x00, 0x00, 0x02, 0xab, 0xcd),
+ raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_STABLE,
+ 0x48, 0x00, 0x00, 0x19, 0x58,
+ AVRCP_SET_ADDRESSED_PLAYER,
+ 0x00, 0x00, 0x01, 0x00));
+
/* Connection Establishment for Control tests */
/*
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that the Controller can send Next Group command to the
Target.
---
unit/test-avrcp.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 3702d39..f0f36dd 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -636,6 +636,9 @@ static void test_client(gconstpointer data)
AVRCP_EVENT_STATUS_CHANGED, 0,
NULL, NULL);
+ if (g_str_equal(context->data->test_name, "/TP/BGN/BV-01-I"))
+ avrcp_send_passthrough(context->session, IEEEID_BTSIG,
+ AVC_VENDOR_NEXT_GROUP);
execute_context(context);
}
@@ -1030,5 +1033,12 @@ int main(int argc, char *argv[])
0xff, 0x00, 0x00, 0x01,
AVRCP_STATUS_INVALID_COMMAND));
+ /* Next Group command transfer - CT */
+ define_test("/TP/BGN/BV-01-I", test_client,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48,
+ AVC_OP_PASSTHROUGH,
+ AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
+ 0x58, 0x00, AVC_VENDOR_NEXT_GROUP));
+
return g_test_run();
}
--
1.8.3.2
Hi Andrei,
On Wed, Mar 12, 2014 at 12:54 PM, Andrei Emeltchenko
<[email protected]> wrote:
> From: Andrei Emeltchenko <[email protected]>
>
> ---
> android/avctp.c | 74 +++++++++++++++++++++++++++++++++++++++++------------
> android/avctp.h | 8 +++++-
> android/avrcp-lib.c | 12 +++++++++
> android/avrcp-lib.h | 2 ++
> 4 files changed, 79 insertions(+), 17 deletions(-)
>
> diff --git a/android/avctp.c b/android/avctp.c
> index d970250..e9ba6db 100644
> --- a/android/avctp.c
> +++ b/android/avctp.c
> @@ -159,6 +159,8 @@ struct avctp_channel {
>
> struct key_pressed {
> uint8_t op;
> + uint8_t *params;
> + size_t params_len;
> guint timer;
> };
>
> @@ -1172,25 +1174,38 @@ static const char *op2str(uint8_t op)
> return "UNKNOWN";
> }
>
> -static int avctp_passthrough_press(struct avctp *session, uint8_t op)
> +static int avctp_passthrough_press(struct avctp *session, uint8_t op,
> + uint8_t *params, size_t params_len)
> {
> - uint8_t operands[2];
> + uint8_t operands[7];
> + size_t len;
>
> - DBG("%s", op2str(op));
> + DBG("op 0x%02x %s params_len %zd", op, op2str(op), params_len);
>
> /* Button pressed */
> operands[0] = op & 0x7f;
> - operands[1] = 0;
> +
> + if (op == AVC_VENDOR_UNIQUE && params &&
> + params_len == 5) {
> + memcpy(&operands[2], params, params_len);
> + len = params_len + 2;
> + operands[1] = params_len;
> + } else {
> + len = 2;
> + operands[1] = 0;
> + }
>
> return avctp_send_req(session, AVC_CTYPE_CONTROL,
> AVC_SUBUNIT_PANEL, AVC_OP_PASSTHROUGH,
> - operands, sizeof(operands),
> + operands, len,
> avctp_passthrough_rsp, NULL);
> }
>
> -static int avctp_passthrough_release(struct avctp *session, uint8_t op)
> +static int avctp_passthrough_release(struct avctp *session, uint8_t op,
> + uint8_t *params, size_t params_len)
> {
> - uint8_t operands[2];
> + uint8_t operands[7];
> + size_t len;
>
> DBG("%s", op2str(op));
>
> @@ -1198,9 +1213,16 @@ static int avctp_passthrough_release(struct avctp *session, uint8_t op)
> operands[0] = op | 0x80;
> operands[1] = 0;
>
> + if (op == AVC_VENDOR_UNIQUE && params &&
> + params_len > sizeof(operands) - 2) {
> + memcpy(&operands[2], params, params_len);
> + len = params_len;
> + } else
> + len = 2;
> +
> return avctp_send_req(session, AVC_CTYPE_CONTROL,
> AVC_SUBUNIT_PANEL, AVC_OP_PASSTHROUGH,
> - operands, sizeof(operands),
> + operands, len,
> NULL, NULL);
> }
>
> @@ -1208,15 +1230,18 @@ static gboolean repeat_timeout(gpointer user_data)
> {
> struct avctp *session = user_data;
>
> - avctp_passthrough_release(session, session->key.op);
> - avctp_passthrough_press(session, session->key.op);
> + avctp_passthrough_release(session, session->key.op, session->key.params,
> + session->key.params_len);
> + avctp_passthrough_press(session, session->key.op, session->key.params,
> + session->key.params_len);
>
> return TRUE;
> }
>
> static void release_pressed(struct avctp *session)
> {
> - avctp_passthrough_release(session, session->key.op);
> + avctp_passthrough_release(session, session->key.op, session->key.params,
> + session->key.params_len);
>
> if (session->key.timer > 0)
> g_source_remove(session->key.timer);
> @@ -1224,7 +1249,8 @@ static void release_pressed(struct avctp *session)
> session->key.timer = 0;
> }
>
> -static bool set_pressed(struct avctp *session, uint8_t op)
> +static bool set_pressed(struct avctp *session, uint8_t op, uint8_t *params,
> + size_t params_len)
> {
> if (session->key.timer > 0) {
> if (session->key.op == op)
> @@ -1236,6 +1262,8 @@ static bool set_pressed(struct avctp *session, uint8_t op)
> return FALSE;
>
> session->key.op = op;
> + session->key.params = params;
> + session->key.params_len = params_len;
> session->key.timer = g_timeout_add_seconds(AVC_PRESS_TIMEOUT,
> repeat_timeout,
> session);
> @@ -1247,24 +1275,38 @@ static gboolean avctp_passthrough_rsp(struct avctp *session, uint8_t code,
> uint8_t subunit, uint8_t *operands,
> size_t operand_count, void *user_data)
> {
> + uint8_t *params;
> + size_t params_len;
> +
> + DBG("code 0x%02x operand_count %zd", code, operand_count);
> +
> if (code != AVC_CTYPE_ACCEPTED)
> return FALSE;
>
> - if (set_pressed(session, operands[0]))
> + if (operands[0] == AVC_VENDOR_UNIQUE) {
> + params = &operands[2];
> + params_len = operand_count - 2;
> + } else {
> + params = NULL;
> + params_len = 0;
> + }
> +
> + if (set_pressed(session, operands[0], params, params_len))
> return FALSE;
>
> - avctp_passthrough_release(session, operands[0]);
> + avctp_passthrough_release(session, operands[0], params, params_len);
>
> return FALSE;
> }
>
> -int avctp_send_passthrough(struct avctp *session, uint8_t op)
> +int avctp_send_passthrough(struct avctp *session, uint8_t op, uint8_t *params,
> + size_t params_len)
> {
> /* Auto release if key pressed */
> if (session->key.timer > 0)
> release_pressed(session);
>
> - return avctp_passthrough_press(session, op);
> + return avctp_passthrough_press(session, op, params, params_len);
> }
>
> int avctp_send_vendordep(struct avctp *session, uint8_t transaction,
> diff --git a/android/avctp.h b/android/avctp.h
> index 2f419a2..98c1142 100644
> --- a/android/avctp.h
> +++ b/android/avctp.h
> @@ -108,6 +108,11 @@
> #define AVC_BLUE 0x7c
> #define AVC_YELLOW 0x7c
>
> +#define AVC_VENDOR_UNIQUE 0x7e
> +
> +#define AVC_VENDOR_NEXT_GROUP 0x00
> +#define AVC_VENDOR_PREV_GROUP 0x01
> +
> struct avctp;
>
> typedef bool (*avctp_passthrough_cb) (struct avctp *session,
> @@ -159,7 +164,8 @@ unsigned int avctp_register_browsing_pdu_handler(struct avctp *session,
> bool avctp_unregister_browsing_pdu_handler(struct avctp *session,
> unsigned int id);
>
> -int avctp_send_passthrough(struct avctp *session, uint8_t op);
> +int avctp_send_passthrough(struct avctp *session, uint8_t op, uint8_t *params,
> + size_t params_len);
> int avctp_send_vendordep(struct avctp *session, uint8_t transaction,
> uint8_t code, uint8_t subunit,
> uint8_t *operands, size_t operand_count);
> diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
> index 5400f80..2cdd1e0 100644
> --- a/android/avrcp-lib.c
> +++ b/android/avrcp-lib.c
> @@ -471,3 +471,15 @@ int avrcp_register_notification_rsp(struct avrcp *session, uint8_t transaction,
> AVC_SUBUNIT_PANEL, AVRCP_REGISTER_NOTIFICATION,
> params, params_len);
> }
> +
> +int avrcp_send_passthrough_vendor(struct avrcp *session, uint8_t vendor_op,
> + uint16_t vendor_id)
> +{
> + uint8_t params[5];
> +
> + hton24(params, vendor_id);
> + bt_put_be16(vendor_op, ¶ms[3]);
> +
> + return avctp_send_passthrough(session->conn, AVC_VENDOR_UNIQUE, params,
> + sizeof(params));
> +}
Looks like this the type of vendor_id should uint32 to be used with
hton24, also I would turn this into a generic avrcp_send_passthrough
which from AV/C perspective is a vendor unique anyway so the function
would look like this:
int avrcp_send_passthrough(struct avrcp *session, uint32_t vendor, uint8_t op);
If vendor is not set e.g. 0 then we can probably treat as a regular
passthrough operation otherwise send it as AVC_VENDOR_UNIQUE. Btw make
this into 2 patches, one introducing the changes to
avctp_send_passthrough and another for adding avrcp_send_passthrough.
> diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
> index 91a7d47..3a2012a 100644
> --- a/android/avrcp-lib.h
> +++ b/android/avrcp-lib.h
> @@ -164,3 +164,5 @@ 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_send_passthrough_vendor(struct avrcp *session, uint8_t vendor_op,
> + uint16_t vendor_id);
> --
> 1.8.3.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Luiz Augusto von Dentz
From: Andrei Emeltchenko <[email protected]>
---
android/avctp.c | 74 +++++++++++++++++++++++++++++++++++++++++------------
android/avctp.h | 8 +++++-
android/avrcp-lib.c | 12 +++++++++
android/avrcp-lib.h | 2 ++
4 files changed, 79 insertions(+), 17 deletions(-)
diff --git a/android/avctp.c b/android/avctp.c
index d970250..e9ba6db 100644
--- a/android/avctp.c
+++ b/android/avctp.c
@@ -159,6 +159,8 @@ struct avctp_channel {
struct key_pressed {
uint8_t op;
+ uint8_t *params;
+ size_t params_len;
guint timer;
};
@@ -1172,25 +1174,38 @@ static const char *op2str(uint8_t op)
return "UNKNOWN";
}
-static int avctp_passthrough_press(struct avctp *session, uint8_t op)
+static int avctp_passthrough_press(struct avctp *session, uint8_t op,
+ uint8_t *params, size_t params_len)
{
- uint8_t operands[2];
+ uint8_t operands[7];
+ size_t len;
- DBG("%s", op2str(op));
+ DBG("op 0x%02x %s params_len %zd", op, op2str(op), params_len);
/* Button pressed */
operands[0] = op & 0x7f;
- operands[1] = 0;
+
+ if (op == AVC_VENDOR_UNIQUE && params &&
+ params_len == 5) {
+ memcpy(&operands[2], params, params_len);
+ len = params_len + 2;
+ operands[1] = params_len;
+ } else {
+ len = 2;
+ operands[1] = 0;
+ }
return avctp_send_req(session, AVC_CTYPE_CONTROL,
AVC_SUBUNIT_PANEL, AVC_OP_PASSTHROUGH,
- operands, sizeof(operands),
+ operands, len,
avctp_passthrough_rsp, NULL);
}
-static int avctp_passthrough_release(struct avctp *session, uint8_t op)
+static int avctp_passthrough_release(struct avctp *session, uint8_t op,
+ uint8_t *params, size_t params_len)
{
- uint8_t operands[2];
+ uint8_t operands[7];
+ size_t len;
DBG("%s", op2str(op));
@@ -1198,9 +1213,16 @@ static int avctp_passthrough_release(struct avctp *session, uint8_t op)
operands[0] = op | 0x80;
operands[1] = 0;
+ if (op == AVC_VENDOR_UNIQUE && params &&
+ params_len > sizeof(operands) - 2) {
+ memcpy(&operands[2], params, params_len);
+ len = params_len;
+ } else
+ len = 2;
+
return avctp_send_req(session, AVC_CTYPE_CONTROL,
AVC_SUBUNIT_PANEL, AVC_OP_PASSTHROUGH,
- operands, sizeof(operands),
+ operands, len,
NULL, NULL);
}
@@ -1208,15 +1230,18 @@ static gboolean repeat_timeout(gpointer user_data)
{
struct avctp *session = user_data;
- avctp_passthrough_release(session, session->key.op);
- avctp_passthrough_press(session, session->key.op);
+ avctp_passthrough_release(session, session->key.op, session->key.params,
+ session->key.params_len);
+ avctp_passthrough_press(session, session->key.op, session->key.params,
+ session->key.params_len);
return TRUE;
}
static void release_pressed(struct avctp *session)
{
- avctp_passthrough_release(session, session->key.op);
+ avctp_passthrough_release(session, session->key.op, session->key.params,
+ session->key.params_len);
if (session->key.timer > 0)
g_source_remove(session->key.timer);
@@ -1224,7 +1249,8 @@ static void release_pressed(struct avctp *session)
session->key.timer = 0;
}
-static bool set_pressed(struct avctp *session, uint8_t op)
+static bool set_pressed(struct avctp *session, uint8_t op, uint8_t *params,
+ size_t params_len)
{
if (session->key.timer > 0) {
if (session->key.op == op)
@@ -1236,6 +1262,8 @@ static bool set_pressed(struct avctp *session, uint8_t op)
return FALSE;
session->key.op = op;
+ session->key.params = params;
+ session->key.params_len = params_len;
session->key.timer = g_timeout_add_seconds(AVC_PRESS_TIMEOUT,
repeat_timeout,
session);
@@ -1247,24 +1275,38 @@ static gboolean avctp_passthrough_rsp(struct avctp *session, uint8_t code,
uint8_t subunit, uint8_t *operands,
size_t operand_count, void *user_data)
{
+ uint8_t *params;
+ size_t params_len;
+
+ DBG("code 0x%02x operand_count %zd", code, operand_count);
+
if (code != AVC_CTYPE_ACCEPTED)
return FALSE;
- if (set_pressed(session, operands[0]))
+ if (operands[0] == AVC_VENDOR_UNIQUE) {
+ params = &operands[2];
+ params_len = operand_count - 2;
+ } else {
+ params = NULL;
+ params_len = 0;
+ }
+
+ if (set_pressed(session, operands[0], params, params_len))
return FALSE;
- avctp_passthrough_release(session, operands[0]);
+ avctp_passthrough_release(session, operands[0], params, params_len);
return FALSE;
}
-int avctp_send_passthrough(struct avctp *session, uint8_t op)
+int avctp_send_passthrough(struct avctp *session, uint8_t op, uint8_t *params,
+ size_t params_len)
{
/* Auto release if key pressed */
if (session->key.timer > 0)
release_pressed(session);
- return avctp_passthrough_press(session, op);
+ return avctp_passthrough_press(session, op, params, params_len);
}
int avctp_send_vendordep(struct avctp *session, uint8_t transaction,
diff --git a/android/avctp.h b/android/avctp.h
index 2f419a2..98c1142 100644
--- a/android/avctp.h
+++ b/android/avctp.h
@@ -108,6 +108,11 @@
#define AVC_BLUE 0x7c
#define AVC_YELLOW 0x7c
+#define AVC_VENDOR_UNIQUE 0x7e
+
+#define AVC_VENDOR_NEXT_GROUP 0x00
+#define AVC_VENDOR_PREV_GROUP 0x01
+
struct avctp;
typedef bool (*avctp_passthrough_cb) (struct avctp *session,
@@ -159,7 +164,8 @@ unsigned int avctp_register_browsing_pdu_handler(struct avctp *session,
bool avctp_unregister_browsing_pdu_handler(struct avctp *session,
unsigned int id);
-int avctp_send_passthrough(struct avctp *session, uint8_t op);
+int avctp_send_passthrough(struct avctp *session, uint8_t op, uint8_t *params,
+ size_t params_len);
int avctp_send_vendordep(struct avctp *session, uint8_t transaction,
uint8_t code, uint8_t subunit,
uint8_t *operands, size_t operand_count);
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 5400f80..2cdd1e0 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -471,3 +471,15 @@ int avrcp_register_notification_rsp(struct avrcp *session, uint8_t transaction,
AVC_SUBUNIT_PANEL, AVRCP_REGISTER_NOTIFICATION,
params, params_len);
}
+
+int avrcp_send_passthrough_vendor(struct avrcp *session, uint8_t vendor_op,
+ uint16_t vendor_id)
+{
+ uint8_t params[5];
+
+ hton24(params, vendor_id);
+ bt_put_be16(vendor_op, ¶ms[3]);
+
+ return avctp_send_passthrough(session->conn, AVC_VENDOR_UNIQUE, params,
+ sizeof(params));
+}
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 91a7d47..3a2012a 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -164,3 +164,5 @@ 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_send_passthrough_vendor(struct avrcp *session, uint8_t vendor_op,
+ uint16_t vendor_id);
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that the Controller can send Prev Group command to the
Target.
---
unit/test-avrcp.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index a5a7a38..fd95a7d 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -640,6 +640,12 @@ static void test_client(gconstpointer data)
avrcp_send_passthrough_vendor(context->session,
AVC_VENDOR_NEXT_GROUP,
IEEEID_BTSIG);
+
+ if (g_str_equal(context->data->test_name, "/TP/BGN/BV-02-I"))
+ avrcp_send_passthrough_vendor(context->session,
+ AVC_VENDOR_PREV_GROUP,
+ IEEEID_BTSIG);
+
execute_context(context);
}
@@ -1041,5 +1047,12 @@ int main(int argc, char *argv[])
AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
0x58, 0x00, AVC_VENDOR_NEXT_GROUP));
+ /* Previous Group command transfer - CT */
+ define_test("/TP/BGN/BV-02-I", test_client,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48,
+ AVC_OP_PASSTHROUGH,
+ AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
+ 0x58, 0x00, AVC_VENDOR_PREV_GROUP));
+
return g_test_run();
}
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that the Target responds to Next Group command.
---
unit/test-avrcp.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index fd95a7d..ea421b0 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -280,11 +280,20 @@ static bool handle_select(struct avrcp *session, bool pressed, void *user_data)
return true;
}
+static bool handle_vendor_uniq(struct avrcp *session, bool pressed,
+ void *user_data)
+{
+ DBG("");
+
+ return true;
+}
+
static const struct avrcp_passthrough_handler passthrough_handlers[] = {
{ AVC_PLAY, handle_play },
{ AVC_VOLUME_UP, handle_volume_up },
{ AVC_CHANNEL_UP, handle_channel_up },
{ AVC_SELECT, handle_select },
+ { AVC_VENDOR_UNIQUE, handle_vendor_uniq },
{ },
};
@@ -1047,6 +1056,17 @@ int main(int argc, char *argv[])
AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
0x58, 0x00, AVC_VENDOR_NEXT_GROUP));
+ /* Next Group command transfer - TG */
+ define_test("/TP/BGN/BV-01-I", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48,
+ AVC_OP_PASSTHROUGH,
+ AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
+ 0x58, 0x00, AVC_VENDOR_NEXT_GROUP),
+ raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_ACCEPTED,
+ 0x48, AVC_OP_PASSTHROUGH,
+ AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
+ 0x58, 0x00, AVC_VENDOR_NEXT_GROUP));
+
/* Previous Group command transfer - CT */
define_test("/TP/BGN/BV-02-I", test_client,
raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48,
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that the Target responds to Prev Group command.
---
unit/test-avrcp.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index ea421b0..31d17b9 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -1074,5 +1074,16 @@ int main(int argc, char *argv[])
AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
0x58, 0x00, AVC_VENDOR_PREV_GROUP));
+ /* Previous Group command transfer - TG */
+ define_test("/TP/BGN/BV-02-I", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48,
+ AVC_OP_PASSTHROUGH,
+ AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
+ 0x58, 0x00, AVC_VENDOR_PREV_GROUP),
+ raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_ACCEPTED,
+ 0x48, AVC_OP_PASSTHROUGH,
+ AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
+ 0x58, 0x00, AVC_VENDOR_PREV_GROUP));
+
return g_test_run();
}
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that the Controller can send Next Group command to the
Target.
---
unit/test-avrcp.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 3702d39..a5a7a38 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -636,6 +636,10 @@ static void test_client(gconstpointer data)
AVRCP_EVENT_STATUS_CHANGED, 0,
NULL, NULL);
+ if (g_str_equal(context->data->test_name, "/TP/BGN/BV-01-I"))
+ avrcp_send_passthrough_vendor(context->session,
+ AVC_VENDOR_NEXT_GROUP,
+ IEEEID_BTSIG);
execute_context(context);
}
@@ -1030,5 +1034,12 @@ int main(int argc, char *argv[])
0xff, 0x00, 0x00, 0x01,
AVRCP_STATUS_INVALID_COMMAND));
+ /* Next Group command transfer - CT */
+ define_test("/TP/BGN/BV-01-I", test_client,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48,
+ AVC_OP_PASSTHROUGH,
+ AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
+ 0x58, 0x00, AVC_VENDOR_NEXT_GROUP));
+
return g_test_run();
}
--
1.8.3.2
Hi Andrei,
On Tue, Mar 11, 2014 at 3:05 PM, Andrei Emeltchenko
<[email protected]> wrote:
> From: Andrei Emeltchenko <[email protected]>
>
> ---
> 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 9760420..fe7009a 100644
> --- a/unit/test-avrcp.c
> +++ b/unit/test-avrcp.c
> @@ -578,7 +578,7 @@ static void test_server(gconstpointer data)
>
> avrcp_set_passthrough_handlers(context->session, passthrough_handlers,
> context);
> - avrcp_set_control_handlers(context->session, control_handlers, NULL);
> + avrcp_set_control_handlers(context->session, control_handlers, context);
>
> g_idle_add(send_pdu, context);
>
> --
> 1.8.3.2
Patches 1-5 are now applied, please rework the patch 6/10 so it
doesn't include avrcp-lib.h in avctp.c.
--
Luiz Augusto von Dentz
From: Andrei Emeltchenko <[email protected]>
Test verifies that the Controller can send Next Group command to the
Target.
---
unit/test-avrcp.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 5d78a9a..d33c69d 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -636,6 +636,9 @@ static void test_client(gconstpointer data)
AVRCP_EVENT_STATUS_CHANGED, 0,
NULL, NULL);
+ if (g_str_equal(context->data->test_name, "/TP/BGN/BV-01-I"))
+ avrcp_passthrough_vendor_req(context->session,
+ AVC_VENDOR_NEXT_GROUP, true);
execute_context(context);
}
@@ -1030,5 +1033,12 @@ int main(int argc, char *argv[])
0xff, 0x00, 0x00, 0x01,
AVRCP_STATUS_INVALID_COMMAND));
+ /* Next Group command transfer - CT */
+ define_test("/TP/BGN/BV-01-I", test_client,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48,
+ AVC_OP_PASSTHROUGH,
+ AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
+ 0x58, 0x00, AVC_VENDOR_NEXT_GROUP));
+
return g_test_run();
}
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that the Target responds to Next Group command.
---
unit/test-avrcp.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 923fd9f..5179c7b 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -280,11 +280,20 @@ static bool handle_select(struct avrcp *session, bool pressed, void *user_data)
return true;
}
+static bool handle_vendor_uniq(struct avrcp *session, bool pressed,
+ void *user_data)
+{
+ DBG("");
+
+ return true;
+}
+
static const struct avrcp_passthrough_handler passthrough_handlers[] = {
{ AVC_PLAY, handle_play },
{ AVC_VOLUME_UP, handle_volume_up },
{ AVC_CHANNEL_UP, handle_channel_up },
{ AVC_SELECT, handle_select },
+ { AVC_VENDOR_UNIQUE, handle_vendor_uniq },
{ },
};
@@ -1045,6 +1054,17 @@ int main(int argc, char *argv[])
AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
0x58, 0x00, AVC_VENDOR_NEXT_GROUP));
+ /* Next Group command transfer - TG */
+ define_test("/TP/BGN/BV-01-I", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48,
+ AVC_OP_PASSTHROUGH,
+ AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
+ 0x58, 0x00, AVC_VENDOR_NEXT_GROUP),
+ raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_ACCEPTED,
+ 0x48, AVC_OP_PASSTHROUGH,
+ AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
+ 0x58, 0x00, AVC_VENDOR_NEXT_GROUP));
+
/* Previous Group command transfer - CT */
define_test("/TP/BGN/BV-02-I", test_client,
raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48,
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies Register notification - Track Changed - Track Playing.
---
unit/test-avrcp.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index fe7009a..fa93b25 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -501,6 +501,7 @@ static ssize_t avrcp_handle_register_notification(struct avrcp *session,
uint8_t *params,
void *user_data)
{
+ struct context *context = user_data;
uint8_t event;
uint8_t pdu[9];
size_t pdu_len;
@@ -516,7 +517,11 @@ static ssize_t avrcp_handle_register_notification(struct avrcp *session,
switch (event) {
case AVRCP_EVENT_TRACK_CHANGED:
- memset(&pdu[1], 0xff, 8);
+ if (g_str_equal(context->data->test_name, "/TP/NFY/BV-05-C"))
+ memset(&pdu[1], 0, 8);
+ else
+ memset(&pdu[1], 0xff, 8);
+
pdu_len += 8;
break;
case AVRCP_EVENT_SETTINGS_CHANGED:
@@ -972,5 +977,17 @@ int main(int argc, char *argv[])
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff));
+ /* Register notification - Track Changed - Track Playing - TG */
+ define_test("/TP/NFY/BV-05-C", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x03, 0x48, 0x00,
+ 0x00, 0x19, 0x58, AVRCP_REGISTER_NOTIFICATION,
+ 0x00, 0x00, 0x05, AVRCP_EVENT_TRACK_CHANGED,
+ 0x00, 0x00, 0x00, 0x00),
+ raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_INTERIM, 0x48, 0x00,
+ 0x00, 0x19, 0x58, AVRCP_REGISTER_NOTIFICATION,
+ 0x00, 0x00, 0x09, AVRCP_EVENT_TRACK_CHANGED,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00));
+
return g_test_run();
}
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
---
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 9760420..fe7009a 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -578,7 +578,7 @@ static void test_server(gconstpointer data)
avrcp_set_passthrough_handlers(context->session, passthrough_handlers,
context);
- avrcp_set_control_handlers(context->session, control_handlers, NULL);
+ avrcp_set_control_handlers(context->session, control_handlers, context);
g_idle_add(send_pdu, context);
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that Target returns error on register for invalid event.
---
unit/test-avrcp.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 0e65789..09d7689 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -1003,5 +1003,18 @@ int main(int argc, char *argv[])
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00));
+ /* Register notification - Register for events invalid behavior - TG */
+ define_test("/TP/NFY/BI-01-C", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x03, 0x48, 0x00,
+ 0x00, 0x19, 0x58, AVRCP_REGISTER_NOTIFICATION,
+ 0x00, 0x00, 0x05,
+ /* Invalid event id */
+ 0xff,
+ 0x00, 0x00, 0x00, 0x00),
+ raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_REJECTED,
+ 0x48, 0x00, 0x00, 0x19, 0x58,
+ AVRCP_REGISTER_NOTIFICATION,
+ 0x00, 0x00, 0x01, AVRCP_STATUS_INVALID_PARAM));
+
return g_test_run();
}
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that the Controller can send Prev Group command to the
Target.
---
unit/test-avrcp.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index d33c69d..923fd9f 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -639,6 +639,11 @@ static void test_client(gconstpointer data)
if (g_str_equal(context->data->test_name, "/TP/BGN/BV-01-I"))
avrcp_passthrough_vendor_req(context->session,
AVC_VENDOR_NEXT_GROUP, true);
+
+ if (g_str_equal(context->data->test_name, "/TP/BGN/BV-02-I"))
+ avrcp_passthrough_vendor_req(context->session,
+ AVC_VENDOR_PREV_GROUP, true);
+
execute_context(context);
}
@@ -1040,5 +1045,12 @@ int main(int argc, char *argv[])
AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
0x58, 0x00, AVC_VENDOR_NEXT_GROUP));
+ /* Previous Group command transfer - CT */
+ define_test("/TP/BGN/BV-02-I", test_client,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48,
+ AVC_OP_PASSTHROUGH,
+ AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
+ 0x58, 0x00, AVC_VENDOR_PREV_GROUP));
+
return g_test_run();
}
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that Target issued Track Changed INTERIM response when
the track is SELECTED.
---
unit/test-avrcp.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index fa93b25..0e65789 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -517,7 +517,9 @@ static ssize_t avrcp_handle_register_notification(struct avrcp *session,
switch (event) {
case AVRCP_EVENT_TRACK_CHANGED:
- if (g_str_equal(context->data->test_name, "/TP/NFY/BV-05-C"))
+ if (g_str_equal(context->data->test_name, "/TP/NFY/BV-05-C") ||
+ g_str_equal(context->data->test_name,
+ "/TP/NFY/BV-08-C"))
memset(&pdu[1], 0, 8);
else
memset(&pdu[1], 0xff, 8);
@@ -989,5 +991,17 @@ int main(int argc, char *argv[])
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00));
+ /* Register notification - Track Changed - Selected Track - TG */
+ define_test("/TP/NFY/BV-08-C", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x03, 0x48, 0x00,
+ 0x00, 0x19, 0x58, AVRCP_REGISTER_NOTIFICATION,
+ 0x00, 0x00, 0x05, AVRCP_EVENT_TRACK_CHANGED,
+ 0x00, 0x00, 0x00, 0x00),
+ raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_INTERIM, 0x48, 0x00,
+ 0x00, 0x19, 0x58, AVRCP_REGISTER_NOTIFICATION,
+ 0x00, 0x00, 0x09, AVRCP_EVENT_TRACK_CHANGED,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00));
+
return g_test_run();
}
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that the Target responds to Prev Group command.
---
unit/test-avrcp.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 5179c7b..08e07ac 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -1072,5 +1072,16 @@ int main(int argc, char *argv[])
AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
0x58, 0x00, AVC_VENDOR_PREV_GROUP));
+ /* Previous Group command transfer - TG */
+ define_test("/TP/BGN/BV-02-I", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48,
+ AVC_OP_PASSTHROUGH,
+ AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
+ 0x58, 0x00, AVC_VENDOR_PREV_GROUP),
+ raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_ACCEPTED,
+ 0x48, AVC_OP_PASSTHROUGH,
+ AVC_VENDOR_UNIQUE, 0x05, 0x00, 0x19,
+ 0x58, 0x00, AVC_VENDOR_PREV_GROUP));
+
return g_test_run();
}
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
---
android/avctp.c | 22 ++++++++++++++++++++++
android/avctp.h | 7 +++++++
android/avrcp-lib.c | 5 +++++
android/avrcp-lib.h | 2 ++
4 files changed, 36 insertions(+)
diff --git a/android/avctp.c b/android/avctp.c
index d970250..33729f0 100644
--- a/android/avctp.c
+++ b/android/avctp.c
@@ -48,6 +48,7 @@
#include "src/uinput.h"
#include "avctp.h"
+#include "avrcp-lib.h"
/* AV/C Panel 1.23, page 76:
* command with the pressed value is valid for two seconds
@@ -1214,6 +1215,27 @@ static gboolean repeat_timeout(gpointer user_data)
return TRUE;
}
+int avctp_passthrough_vendor_req(struct avctp *session, uint8_t op, bool press)
+{
+ uint8_t operands[7];
+
+ DBG("op %d press %d", op, press);
+
+ if (press)
+ operands[0] = AVC_VENDOR_UNIQUE;
+ else
+ operands[0] = AVC_VENDOR_UNIQUE | 0x80;
+
+ operands[1] = 5;
+ hton24(&operands[2], IEEEID_BTSIG);
+ bt_put_be16(op, &operands[5]);
+
+ return avctp_send_req(session, AVC_CTYPE_CONTROL,
+ AVC_SUBUNIT_PANEL, AVC_OP_PASSTHROUGH,
+ operands, sizeof(operands),
+ avctp_passthrough_rsp, NULL);
+}
+
static void release_pressed(struct avctp *session)
{
avctp_passthrough_release(session, session->key.op);
diff --git a/android/avctp.h b/android/avctp.h
index 2f419a2..4f65869 100644
--- a/android/avctp.h
+++ b/android/avctp.h
@@ -108,6 +108,11 @@
#define AVC_BLUE 0x7c
#define AVC_YELLOW 0x7c
+#define AVC_VENDOR_UNIQUE 0x7e
+
+#define AVC_VENDOR_NEXT_GROUP 0x00
+#define AVC_VENDOR_PREV_GROUP 0x01
+
struct avctp;
typedef bool (*avctp_passthrough_cb) (struct avctp *session,
@@ -170,3 +175,5 @@ int avctp_send_vendordep_req(struct avctp *session, uint8_t code,
int avctp_send_browsing_req(struct avctp *session,
uint8_t *operands, size_t operand_count,
avctp_browsing_rsp_cb func, void *user_data);
+int avctp_passthrough_vendor_req(struct avctp *session, uint8_t op,
+ bool press);
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 5400f80..a9bd438 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -471,3 +471,8 @@ int avrcp_register_notification_rsp(struct avrcp *session, uint8_t transaction,
AVC_SUBUNIT_PANEL, AVRCP_REGISTER_NOTIFICATION,
params, params_len);
}
+
+int avrcp_passthrough_vendor_req(struct avrcp *session, uint8_t op, bool press)
+{
+ return avctp_passthrough_vendor_req(session->conn, op, press);
+}
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 91a7d47..2acf0fb 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -164,3 +164,5 @@ 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_passthrough_vendor_req(struct avrcp *session, uint8_t op,
+ bool press);
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that AVRCP_STATUS_INVALID_COMMAND returned when received
command with Invalid PDU ID.
---
unit/test-avrcp.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 09d7689..5d78a9a 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -1016,5 +1016,19 @@ int main(int argc, char *argv[])
AVRCP_REGISTER_NOTIFICATION,
0x00, 0x00, 0x01, AVRCP_STATUS_INVALID_PARAM));
+ /* Invalid commands */
+
+ /* Invalid PDU ID - TG */
+ define_test("/TP/INV/BI-01-C", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x03, 0x48, 0x00,
+ 0x00, 0x19, 0x58,
+ /* Invalid PDU ID */
+ 0xff,
+ 0x00, 0x00, 0x00),
+ raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_REJECTED,
+ 0x48, 0x00, 0x00, 0x19, 0x58,
+ 0xff, 0x00, 0x00, 0x01,
+ AVRCP_STATUS_INVALID_COMMAND));
+
return g_test_run();
}
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies Register notification - Track Changed - Track Playing.
---
unit/test-avrcp.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index fe7009a..fa93b25 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -501,6 +501,7 @@ static ssize_t avrcp_handle_register_notification(struct avrcp *session,
uint8_t *params,
void *user_data)
{
+ struct context *context = user_data;
uint8_t event;
uint8_t pdu[9];
size_t pdu_len;
@@ -516,7 +517,11 @@ static ssize_t avrcp_handle_register_notification(struct avrcp *session,
switch (event) {
case AVRCP_EVENT_TRACK_CHANGED:
- memset(&pdu[1], 0xff, 8);
+ if (g_str_equal(context->data->test_name, "/TP/NFY/BV-05-C"))
+ memset(&pdu[1], 0, 8);
+ else
+ memset(&pdu[1], 0xff, 8);
+
pdu_len += 8;
break;
case AVRCP_EVENT_SETTINGS_CHANGED:
@@ -972,5 +977,17 @@ int main(int argc, char *argv[])
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff));
+ /* Register notification - Track Changed - Track Playing - TG */
+ define_test("/TP/NFY/BV-05-C", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x03, 0x48, 0x00,
+ 0x00, 0x19, 0x58, AVRCP_REGISTER_NOTIFICATION,
+ 0x00, 0x00, 0x05, AVRCP_EVENT_TRACK_CHANGED,
+ 0x00, 0x00, 0x00, 0x00),
+ raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_INTERIM, 0x48, 0x00,
+ 0x00, 0x19, 0x58, AVRCP_REGISTER_NOTIFICATION,
+ 0x00, 0x00, 0x09, AVRCP_EVENT_TRACK_CHANGED,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00));
+
return g_test_run();
}
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that AVRCP_STATUS_INVALID_COMMAND returned when received
command with Invalid PDU ID.
---
unit/test-avrcp.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 09d7689..5d78a9a 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -1016,5 +1016,19 @@ int main(int argc, char *argv[])
AVRCP_REGISTER_NOTIFICATION,
0x00, 0x00, 0x01, AVRCP_STATUS_INVALID_PARAM));
+ /* Invalid commands */
+
+ /* Invalid PDU ID - TG */
+ define_test("/TP/INV/BI-01-C", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x03, 0x48, 0x00,
+ 0x00, 0x19, 0x58,
+ /* Invalid PDU ID */
+ 0xff,
+ 0x00, 0x00, 0x00),
+ raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_REJECTED,
+ 0x48, 0x00, 0x00, 0x19, 0x58,
+ 0xff, 0x00, 0x00, 0x01,
+ AVRCP_STATUS_INVALID_COMMAND));
+
return g_test_run();
}
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that Target issued Track Changed INTERIM response when
the track is SELECTED.
---
unit/test-avrcp.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index fa93b25..0e65789 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -517,7 +517,9 @@ static ssize_t avrcp_handle_register_notification(struct avrcp *session,
switch (event) {
case AVRCP_EVENT_TRACK_CHANGED:
- if (g_str_equal(context->data->test_name, "/TP/NFY/BV-05-C"))
+ if (g_str_equal(context->data->test_name, "/TP/NFY/BV-05-C") ||
+ g_str_equal(context->data->test_name,
+ "/TP/NFY/BV-08-C"))
memset(&pdu[1], 0, 8);
else
memset(&pdu[1], 0xff, 8);
@@ -989,5 +991,17 @@ int main(int argc, char *argv[])
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00));
+ /* Register notification - Track Changed - Selected Track - TG */
+ define_test("/TP/NFY/BV-08-C", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x03, 0x48, 0x00,
+ 0x00, 0x19, 0x58, AVRCP_REGISTER_NOTIFICATION,
+ 0x00, 0x00, 0x05, AVRCP_EVENT_TRACK_CHANGED,
+ 0x00, 0x00, 0x00, 0x00),
+ raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_INTERIM, 0x48, 0x00,
+ 0x00, 0x19, 0x58, AVRCP_REGISTER_NOTIFICATION,
+ 0x00, 0x00, 0x09, AVRCP_EVENT_TRACK_CHANGED,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00));
+
return g_test_run();
}
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that Target returns error on register for invalid event.
---
unit/test-avrcp.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 0e65789..09d7689 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -1003,5 +1003,18 @@ int main(int argc, char *argv[])
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00));
+ /* Register notification - Register for events invalid behavior - TG */
+ define_test("/TP/NFY/BI-01-C", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x03, 0x48, 0x00,
+ 0x00, 0x19, 0x58, AVRCP_REGISTER_NOTIFICATION,
+ 0x00, 0x00, 0x05,
+ /* Invalid event id */
+ 0xff,
+ 0x00, 0x00, 0x00, 0x00),
+ raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_REJECTED,
+ 0x48, 0x00, 0x00, 0x19, 0x58,
+ AVRCP_REGISTER_NOTIFICATION,
+ 0x00, 0x00, 0x01, AVRCP_STATUS_INVALID_PARAM));
+
return g_test_run();
}
--
1.8.3.2