From: Andrei Emeltchenko <[email protected]>
Set of unapplied test cases and code so far.
Changes:
* v3: Rebased against new interface
Andrei Emeltchenko (16):
android/avrcp: Add avrcp_connect_browsing()
android/avrcp: Add avrcp_set_browsed_player() function
unit/avrcp: Add browsing channel support in unit testing
unit/avrcp: Add /TP/MPS/BV-03-C test
android/avrcp: Use defined constant instead of magic number
android/avrcp: Add avrcp_get_folder_items() function
unit/avrcp: Add /TP/MPS/BV-08-C test
unit/avrcp: Add /TP/MPS/BV-01-I test
unit/avrcp: Add Connection establishment and release tests
unit/avrcp: Add /TP/MCN/CB/BV-01-C test
android/avrcp: Add avrcp_change_path() function
unit/avrcp: Add /TP/MCN/CB/BV-04-C test
android/avrcp: Add avrcp_get_item_attributes() function
unit/avrcp: Add /TP/MCN/CB/BV-07-C test
android/avrcp: Add avrcp_search() function
unit/avrcp: Add /TP/MCN/SRC/BV-01-C test
.gitignore | 2 +
android/avrcp-lib.c | 126 ++++++++++++++++++++++++++++++++-
android/avrcp-lib.h | 32 +++++++++
unit/test-avrcp.c | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 352 insertions(+), 5 deletions(-)
--
1.8.3.2
Hi Luiz,
On Wed, Mar 19, 2014 at 01:32:53PM +0200, Luiz Augusto von Dentz wrote:
> Hi Andrei,
>
> On Wed, Mar 19, 2014 at 11:13 AM, Andrei Emeltchenko
> <[email protected]> wrote:
> > On Tue, Mar 18, 2014 at 11:20:31AM +0200, Andrei Emeltchenko wrote:
> >> From: Andrei Emeltchenko <[email protected]>
> >>
> >> Set of unapplied test cases and code so far.
> >
> > ping
> >
> >
> >>
> >>
> >> Changes:
> >> * v3: Rebased against new interface
> >>
> >> Andrei Emeltchenko (16):
> >> android/avrcp: Add avrcp_connect_browsing()
> >> android/avrcp: Add avrcp_set_browsed_player() function
> >> unit/avrcp: Add browsing channel support in unit testing
> >> unit/avrcp: Add /TP/MPS/BV-03-C test
> >> android/avrcp: Use defined constant instead of magic number
> >> android/avrcp: Add avrcp_get_folder_items() function
> >> unit/avrcp: Add /TP/MPS/BV-08-C test
> >> unit/avrcp: Add /TP/MPS/BV-01-I test
> >> unit/avrcp: Add Connection establishment and release tests
> >> unit/avrcp: Add /TP/MCN/CB/BV-01-C test
> >> android/avrcp: Add avrcp_change_path() function
> >> unit/avrcp: Add /TP/MCN/CB/BV-04-C test
> >> android/avrcp: Add avrcp_get_item_attributes() function
> >> unit/avrcp: Add /TP/MCN/CB/BV-07-C test
> >> android/avrcp: Add avrcp_search() function
> >> unit/avrcp: Add /TP/MCN/SRC/BV-01-C test
> >>
> >> .gitignore | 2 +
> >> android/avrcp-lib.c | 126 ++++++++++++++++++++++++++++++++-
> >> android/avrcp-lib.h | 32 +++++++++
> >> unit/test-avrcp.c | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++-
> >> 4 files changed, 352 insertions(+), 5 deletions(-)
> >>
> >> --
> >> 1.8.3.2
>
> The idea was that we start using cfm callbacks for commands, so
> instead of using avctp_rsp_cb or avctp_browsing_rsp_cb directly which
> leads to receive raw PDU as response we would internally parse then
> and only then call the respective cfm callback with the parameter in
> host order.
So will you create skeleton or example how you want interface to change?
Best regards
Andrei Emeltchenko
Hi Andrei,
On Wed, Mar 19, 2014 at 11:13 AM, Andrei Emeltchenko
<[email protected]> wrote:
> On Tue, Mar 18, 2014 at 11:20:31AM +0200, Andrei Emeltchenko wrote:
>> From: Andrei Emeltchenko <[email protected]>
>>
>> Set of unapplied test cases and code so far.
>
> ping
>
>
>>
>>
>> Changes:
>> * v3: Rebased against new interface
>>
>> Andrei Emeltchenko (16):
>> android/avrcp: Add avrcp_connect_browsing()
>> android/avrcp: Add avrcp_set_browsed_player() function
>> unit/avrcp: Add browsing channel support in unit testing
>> unit/avrcp: Add /TP/MPS/BV-03-C test
>> android/avrcp: Use defined constant instead of magic number
>> android/avrcp: Add avrcp_get_folder_items() function
>> unit/avrcp: Add /TP/MPS/BV-08-C test
>> unit/avrcp: Add /TP/MPS/BV-01-I test
>> unit/avrcp: Add Connection establishment and release tests
>> unit/avrcp: Add /TP/MCN/CB/BV-01-C test
>> android/avrcp: Add avrcp_change_path() function
>> unit/avrcp: Add /TP/MCN/CB/BV-04-C test
>> android/avrcp: Add avrcp_get_item_attributes() function
>> unit/avrcp: Add /TP/MCN/CB/BV-07-C test
>> android/avrcp: Add avrcp_search() function
>> unit/avrcp: Add /TP/MCN/SRC/BV-01-C test
>>
>> .gitignore | 2 +
>> android/avrcp-lib.c | 126 ++++++++++++++++++++++++++++++++-
>> android/avrcp-lib.h | 32 +++++++++
>> unit/test-avrcp.c | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++-
>> 4 files changed, 352 insertions(+), 5 deletions(-)
>>
>> --
>> 1.8.3.2
The idea was that we start using cfm callbacks for commands, so
instead of using avctp_rsp_cb or avctp_browsing_rsp_cb directly which
leads to receive raw PDU as response we would internally parse then
and only then call the respective cfm callback with the parameter in
host order.
--
Luiz Augusto von Dentz
On Tue, Mar 18, 2014 at 11:20:31AM +0200, Andrei Emeltchenko wrote:
> From: Andrei Emeltchenko <[email protected]>
>
> Set of unapplied test cases and code so far.
ping
>
>
> Changes:
> * v3: Rebased against new interface
>
> Andrei Emeltchenko (16):
> android/avrcp: Add avrcp_connect_browsing()
> android/avrcp: Add avrcp_set_browsed_player() function
> unit/avrcp: Add browsing channel support in unit testing
> unit/avrcp: Add /TP/MPS/BV-03-C test
> android/avrcp: Use defined constant instead of magic number
> android/avrcp: Add avrcp_get_folder_items() function
> unit/avrcp: Add /TP/MPS/BV-08-C test
> unit/avrcp: Add /TP/MPS/BV-01-I test
> unit/avrcp: Add Connection establishment and release tests
> unit/avrcp: Add /TP/MCN/CB/BV-01-C test
> android/avrcp: Add avrcp_change_path() function
> unit/avrcp: Add /TP/MCN/CB/BV-04-C test
> android/avrcp: Add avrcp_get_item_attributes() function
> unit/avrcp: Add /TP/MCN/CB/BV-07-C test
> android/avrcp: Add avrcp_search() function
> unit/avrcp: Add /TP/MCN/SRC/BV-01-C test
>
> .gitignore | 2 +
> android/avrcp-lib.c | 126 ++++++++++++++++++++++++++++++++-
> android/avrcp-lib.h | 32 +++++++++
> unit/test-avrcp.c | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++-
> 4 files changed, 352 insertions(+), 5 deletions(-)
>
> --
> 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
From: Andrei Emeltchenko <[email protected]>
---
android/avrcp-lib.c | 20 ++++++++++++++++++++
android/avrcp-lib.h | 3 +++
2 files changed, 23 insertions(+)
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index db2057b..284ed10 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -1075,3 +1075,23 @@ int avrcp_get_folder_items(struct avrcp *session, uint8_t scope,
return avctp_send_browsing_req(session->conn, buf, sizeof(buf),
func, user_data);
}
+
+int avrcp_change_path(struct avrcp *session, uint8_t direction, uint64_t uid,
+ uint16_t counter, avctp_browsing_rsp_cb func,
+ void *user_data)
+{
+ uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 11];
+ struct avrcp_browsing_header *pdu = (void *) buf;
+
+ memset(buf, 0, sizeof(buf));
+
+ pdu->pdu_id = AVRCP_CHANGE_PATH;
+ pdu->param_len = htons(11);
+
+ bt_put_be16(counter, &pdu->params[0]);
+ pdu->params[2] = direction;
+ bt_put_be64(uid, &pdu->params[3]);
+
+ return avctp_send_browsing_req(session->conn, buf, sizeof(buf),
+ func, user_data);
+}
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index b84f61c..40e571a 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -262,3 +262,6 @@ int avrcp_get_folder_items(struct avrcp *session, uint8_t scope,
uint32_t start, uint32_t end, uint32_t *attr,
size_t attr_count, avctp_browsing_rsp_cb func,
void *user_data);
+int avrcp_change_path(struct avrcp *session, uint8_t direction, uint64_t uid,
+ uint16_t counter, avctp_browsing_rsp_cb func,
+ void *user_data);
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that Search command issued by the Controller.
---
unit/test-avrcp.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 860deaf..a06d068 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -590,6 +590,10 @@ static void test_client(gconstpointer data)
AVRCP_MEDIA_PLAYER_VFS, 0x01, 0xaabb,
NULL, 0, NULL, NULL);
+ if (g_str_equal(context->data->test_name, "/TP/MCN/SRC/BV-01-C"))
+ avrcp_search(context->session, AVRCP_CHARSET_UTF8, "Country",
+ 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);
@@ -710,6 +714,16 @@ int main(int argc, char *argv[])
0xaa, 0xbb, /* counter */
0x00)); /* num attr */
+ /* Media Content Navigation Commands and Notifications for Search */
+
+ /* Search - CT */
+ define_test("/TP/MCN/SRC/BV-01-C", test_client,
+ raw_pdu(0x00, 0x11, 0x0e, AVRCP_SEARCH,
+ 0x00, 0x0b, 0x00, AVRCP_CHARSET_UTF8,
+ 0x00, 0x07,
+ 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79));
+
+
/* Media Player Selection IOP tests */
/* Listing of available media players */
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that SetBrowsedPlayer command issued by the Controller.
---
unit/test-avrcp.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index bd65637..401a50d 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -563,6 +563,9 @@ static void test_client(gconstpointer data)
avrcp_set_addressed_player(context->session, 0xabcd, NULL,
NULL);
+ if (g_str_equal(context->data->test_name, "/TP/MPS/BV-03-C"))
+ avrcp_set_browsed_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);
@@ -639,6 +642,11 @@ int main(int argc, char *argv[])
AVRCP_SET_ADDRESSED_PLAYER,
0x00, 0x00, 0x01, 0x04));
+ /* SetBrowsedPlayer - CT */
+ define_test("/TP/MPS/BV-03-C", test_client,
+ raw_pdu(0x00, 0x11, 0x0e, 0x70, 0x00, 0x02,
+ 0xab, 0xcd));
+
/* Connection Establishment for Control tests */
/*
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
---
android/avrcp-lib.c | 18 ++++++++++++++++++
android/avrcp-lib.h | 9 +++++++++
2 files changed, 27 insertions(+)
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 13acae9..75af49b 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -1028,3 +1028,21 @@ int avrcp_send_passthrough(struct avrcp *session, uint32_t vendor, uint8_t op)
return avctp_send_passthrough(session->conn, AVC_VENDOR_UNIQUE, params,
sizeof(params));
}
+
+int avrcp_set_browsed_player(struct avrcp *session, uint16_t player_id,
+ avctp_browsing_rsp_cb func, void *user_data)
+{
+ uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 2];
+ struct avrcp_browsing_header *pdu = (void *) buf;
+
+ DBG("");
+
+ memset(buf, 0, sizeof(buf));
+
+ pdu->pdu_id = AVRCP_SET_BROWSED_PLAYER;
+ bt_put_be16(player_id, pdu->params);
+ pdu->param_len = htons(2);
+
+ return avctp_send_browsing_req(session->conn, buf, sizeof(buf),
+ func, user_data);
+}
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 8d9782b..3f557fc 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -121,6 +121,13 @@
/* Parameters legths */
#define AVRCP_REGISTER_NOTIFICATION_PARAM_LENGTH 5
+struct avrcp_browsing_header {
+ uint8_t pdu_id;
+ uint16_t param_len;
+ uint8_t params[0];
+} __attribute__ ((packed));
+#define AVRCP_BROWSING_HEADER_LENGTH 3
+
struct avrcp;
struct avrcp_control_handler {
@@ -243,3 +250,5 @@ int avrcp_register_notification_rsp(struct avrcp *session, uint8_t transaction,
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);
+int avrcp_set_browsed_player(struct avrcp *session, uint16_t player_id,
+ avctp_browsing_rsp_cb func, void *user_data);
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that the GetFolderItems command issued by the Controller
with VFS parameter.
---
unit/test-avrcp.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 602e4bb..b69674b 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -576,6 +576,11 @@ static void test_client(gconstpointer data)
AVRCP_MEDIA_PLAYER_LIST, 0, 2, NULL, 0,
NULL, NULL);
+ if (g_str_equal(context->data->test_name, "/TP/MCN/CB/BV-01-C"))
+ avrcp_get_folder_items(context->session,
+ AVRCP_MEDIA_PLAYER_VFS, 0, 2, NULL, 0,
+ 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);
@@ -665,6 +670,19 @@ int main(int argc, char *argv[])
0x00, 0x00, 0x00, 0x02, /* end */
0x00));
+ /*
+ * Media Content Navigation Commands and Notifications for Content
+ * Browsing.
+ */
+
+ /* GetFolderItems - Virtual FS - CT */
+ define_test("/TP/MCN/CB/BV-01-C", test_client,
+ raw_pdu(0x00, 0x11, 0x0e, AVRCP_GET_FOLDER_ITEMS,
+ 0x00, 0x0a, AVRCP_MEDIA_PLAYER_VFS,
+ 0x00, 0x00, 0x00, 0x00, /* start */
+ 0x00, 0x00, 0x00, 0x02, /* end */
+ 0x00));
+
/* Media Player Selection IOP tests */
/* Listing of available media players */
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
---
android/avrcp-lib.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 75af49b..a075809 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -717,7 +717,7 @@ int avrcp_register_notification(struct avrcp *session, uint8_t event,
uint32_t interval, avctp_rsp_cb func,
void *user_data)
{
- uint8_t params[5];
+ uint8_t params[AVRCP_REGISTER_NOTIFICATION_PARAM_LENGTH];
params[0] = event;
bt_put_be32(interval, ¶ms[1]);
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
---
android/avrcp-lib.c | 29 +++++++++++++++++++++++++++++
android/avrcp-lib.h | 10 ++++++++++
2 files changed, 39 insertions(+)
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index a075809..db2057b 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -1046,3 +1046,32 @@ int avrcp_set_browsed_player(struct avrcp *session, uint16_t player_id,
return avctp_send_browsing_req(session->conn, buf, sizeof(buf),
func, user_data);
}
+
+int avrcp_get_folder_items(struct avrcp *session, uint8_t scope,
+ uint32_t start, uint32_t end, uint32_t *attr,
+ size_t attr_count, avctp_browsing_rsp_cb func,
+ void *user_data)
+{
+ uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 10 +
+ attr_count * sizeof(uint32_t)];
+ struct avrcp_browsing_header *pdu = (void *) buf;
+
+ memset(buf, 0, sizeof(buf));
+
+ pdu->pdu_id = AVRCP_GET_FOLDER_ITEMS;
+ pdu->param_len = htons(10 + attr_count * sizeof(uint32_t));
+
+ /* Scope */
+ pdu->params[0] = scope;
+
+ bt_put_be32(start, &pdu->params[1]);
+ bt_put_be32(end, &pdu->params[5]);
+
+ /* attr count */
+ pdu->params[9] = attr_count;
+
+ memcpy(&pdu->params[10], attr, attr_count);
+
+ return avctp_send_browsing_req(session->conn, buf, sizeof(buf),
+ func, user_data);
+}
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 3f557fc..b84f61c 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -115,6 +115,12 @@
#define AVRCP_MEDIA_ATTRIBUTE_DURATION 0x07
#define AVRCP_MEDIA_ATTRIBUTE_LAST AVRCP_MEDIA_ATTRIBUTE_DURATION
+/* Media Scope */
+#define AVRCP_MEDIA_PLAYER_LIST 0x00
+#define AVRCP_MEDIA_PLAYER_VFS 0x01
+#define AVRCP_MEDIA_SEARCH 0x02
+#define AVRCP_MEDIA_NOW_PLAYING 0x03
+
/* Company IDs for vendor dependent commands */
#define IEEEID_BTSIG 0x001958
@@ -252,3 +258,7 @@ int avrcp_set_addressed_player_rsp(struct avrcp *session, uint8_t transaction,
int avrcp_send_passthrough(struct avrcp *session, uint32_t vendor, uint8_t op);
int avrcp_set_browsed_player(struct avrcp *session, uint16_t player_id,
avctp_browsing_rsp_cb func, void *user_data);
+int avrcp_get_folder_items(struct avrcp *session, uint8_t scope,
+ uint32_t start, uint32_t end, uint32_t *attr,
+ size_t attr_count, avctp_browsing_rsp_cb func,
+ void *user_data);
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that the ChangePath command issued by the Controller.
---
unit/test-avrcp.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index b69674b..2905380 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -581,6 +581,10 @@ static void test_client(gconstpointer data)
AVRCP_MEDIA_PLAYER_VFS, 0, 2, NULL, 0,
NULL, NULL);
+ if (g_str_equal(context->data->test_name, "/TP/MCN/CB/BV-04-C"))
+ avrcp_change_path(context->session, 0x01, 0x01, 0xaabb,
+ 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);
@@ -683,6 +687,15 @@ int main(int argc, char *argv[])
0x00, 0x00, 0x00, 0x02, /* end */
0x00));
+ /* ChangePath - CT */
+ define_test("/TP/MCN/CB/BV-04-C", test_client,
+ raw_pdu(0x00, 0x11, 0x0e, AVRCP_CHANGE_PATH,
+ 0x00, 0x0b,
+ 0xaa, 0xbb, /* counter */
+ 0x01, /* direction */
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01 /* Folder UID */));
+
/* Media Player Selection IOP tests */
/* Listing of available media players */
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
---
android/avrcp-lib.c | 23 +++++++++++++++++++++--
android/avrcp-lib.h | 4 ++++
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 7304b11..5bbc407 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -28,6 +28,7 @@
#include <stdbool.h>
#include <glib.h>
#include <errno.h>
+#include <string.h>
#include "lib/bluetooth.h"
@@ -43,8 +44,6 @@
#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 {
@@ -1123,3 +1122,23 @@ int avrcp_get_item_attributes(struct avrcp *session, uint8_t scope,
return avctp_send_browsing_req(session->conn, buf, sizeof(buf),
func, user_data);
}
+
+int avrcp_search(struct avrcp *session, uint16_t charset, const char *string,
+ avctp_browsing_rsp_cb func, void *user_data)
+{
+ size_t str_len = strnlen(string, 255 - 4);
+ uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + str_len + 4];
+ struct avrcp_browsing_header *pdu = (void *) buf;
+
+ memset(buf, 0, sizeof(buf));
+
+ pdu->pdu_id = AVRCP_SEARCH;
+ pdu->param_len = htons(str_len + 4);
+
+ bt_put_be16(charset, &pdu->params[0]);
+ bt_put_be16(str_len, &pdu->params[2]);
+ memcpy(&pdu->params[4], string, str_len);
+
+ return avctp_send_browsing_req(session->conn, buf, sizeof(buf),
+ func, user_data);
+}
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 653a98e..3a452d5 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -124,6 +124,8 @@
/* Company IDs for vendor dependent commands */
#define IEEEID_BTSIG 0x001958
+#define AVRCP_CHARSET_UTF8 0x006a
+
/* Parameters legths */
#define AVRCP_REGISTER_NOTIFICATION_PARAM_LENGTH 5
@@ -269,3 +271,5 @@ int avrcp_get_item_attributes(struct avrcp *session, uint8_t scope,
uint64_t uid, uint16_t counter, uint32_t *attr,
size_t attr_count, avctp_browsing_rsp_cb func,
void *user_data);
+int avrcp_search(struct avrcp *session, uint16_t charset, const char *string,
+ avctp_browsing_rsp_cb func, void *user_data);
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
---
.gitignore | 2 ++
unit/test-avrcp.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 89 insertions(+), 2 deletions(-)
diff --git a/.gitignore b/.gitignore
index 7a2af5a..0a66fec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -127,3 +127,5 @@ android/bluetoothd-snoop
android/test-ipc
android/test-*.log
android/test-*.trs
+
+patches/
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 3235e48..bd65637 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -46,6 +46,7 @@
struct test_pdu {
bool valid;
bool fragmented;
+ bool browse;
const uint8_t *data;
size_t size;
};
@@ -59,8 +60,10 @@ struct context {
GMainLoop *main_loop;
struct avrcp *session;
guint source;
+ guint browse_source;
guint process;
int fd;
+ int browse_fd;
unsigned int pdu_offset;
const struct test_data *data;
};
@@ -74,6 +77,14 @@ struct context {
.size = sizeof(data(args)), \
}
+#define brs_pdu(args...) \
+ { \
+ .valid = true, \
+ .browse = true, \
+ .data = data(args), \
+ .size = sizeof(data(args)), \
+ }
+
#define frg_pdu(args...) \
{ \
.valid = true, \
@@ -129,7 +140,10 @@ static gboolean send_pdu(gpointer user_data)
pdu = &context->data->pdu_list[context->pdu_offset++];
- len = write(context->fd, pdu->data, pdu->size);
+ if (pdu->browse)
+ len = write(context->browse_fd, pdu->data, pdu->size);
+ else
+ len = write(context->fd, pdu->data, pdu->size);
if (g_test_verbose())
util_hexdump('<', pdu->data, len, test_debug, "AVRCP: ");
@@ -162,6 +176,8 @@ static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
ssize_t len;
int fd;
+ DBG("");
+
pdu = &context->data->pdu_list[context->pdu_offset++];
if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
@@ -189,17 +205,59 @@ static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
return TRUE;
}
+static gboolean browse_test_handler(GIOChannel *channel, GIOCondition cond,
+ gpointer user_data)
+{
+ struct context *context = user_data;
+ const struct test_pdu *pdu;
+ unsigned char buf[512];
+ ssize_t len;
+ int fd;
+
+ DBG("");
+
+ pdu = &context->data->pdu_list[context->pdu_offset++];
+
+ if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+ context->browse_source = 0;
+ g_print("%s: cond %x\n", __func__, cond);
+ return FALSE;
+ }
+
+ fd = g_io_channel_unix_get_fd(channel);
+
+ len = read(fd, buf, sizeof(buf));
+
+ g_assert(len > 0);
+
+ if (g_test_verbose())
+ util_hexdump('>', buf, len, test_debug, "AVCTP: ");
+
+ g_assert_cmpint(len, ==, pdu->size);
+
+ g_assert(memcmp(buf, pdu->data, pdu->size) == 0);
+
+ if (!pdu->fragmented)
+ context_process(context);
+
+ return TRUE;
+}
+
static struct context *create_context(uint16_t version, gconstpointer data)
{
struct context *context = g_new0(struct context, 1);
GIOChannel *channel;
int err, sv[2];
+ DBG("");
+
context->main_loop = g_main_loop_new(NULL, FALSE);
g_assert(context->main_loop);
+ /* Control channel setup */
+
err = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sv);
- g_assert(err == 0);
+ g_assert(!err);
context->session = avrcp_new(sv[0], 672, 672, version);
g_assert(context->session != NULL);
@@ -218,6 +276,30 @@ static struct context *create_context(uint16_t version, gconstpointer data)
g_io_channel_unref(channel);
context->fd = sv[1];
+
+ /* Browsing channel setup */
+
+ err = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sv);
+ g_assert(!err);
+
+ err = avrcp_connect_browsing(context->session, sv[0], 672, 672);
+ g_assert(!err);
+
+ channel = g_io_channel_unix_new(sv[1]);
+
+ g_io_channel_set_close_on_unref(channel, TRUE);
+ g_io_channel_set_encoding(channel, NULL, NULL);
+ g_io_channel_set_buffered(channel, FALSE);
+
+ context->browse_source = g_io_add_watch(channel,
+ G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ browse_test_handler, context);
+ g_assert(context->browse_source > 0);
+
+ g_io_channel_unref(channel);
+
+ context->browse_fd = sv[1];
+
context->data = data;
return context;
@@ -230,6 +312,9 @@ static void destroy_context(struct context *context)
avrcp_shutdown(context->session);
+ if (context->browse_source > 0)
+ g_source_remove(context->browse_source);
+
g_main_loop_unref(context->main_loop);
test_free(context->data);
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Tests are checking connection establishment and release for browsing
channel. Since we are connected through socketpair the tests are dummy.
---
unit/test-avrcp.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 46c10a3..602e4bb 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -675,6 +675,19 @@ int main(int argc, char *argv[])
0x00, 0x00, 0x00, 0x02, /* end */
0x00));
+ /* Connection Establishment for Browsing tests */
+
+ /*
+ * Tests are checking connection establishment and release
+ * for browsing channel. Since we are connected through socketpair
+ * the tests are dummy
+ */
+ define_test("/TP/CON/BV-01-C", test_dummy, raw_pdu(0x00));
+ define_test("/TP/CON/BV-02-C", test_dummy, raw_pdu(0x00));
+ define_test("/TP/CON/BV-03-C", test_dummy, raw_pdu(0x00));
+ define_test("/TP/CON/BV-04-C", test_dummy, raw_pdu(0x00));
+ define_test("/TP/CON/BV-05-C", test_dummy, raw_pdu(0x00));
+
/* Connection Establishment for Control tests */
/*
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that GetFolderItems cmd for the Media Player List
issued by the Controller.
---
unit/test-avrcp.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 401a50d..4336668 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -566,6 +566,11 @@ static void test_client(gconstpointer data)
if (g_str_equal(context->data->test_name, "/TP/MPS/BV-03-C"))
avrcp_set_browsed_player(context->session, 0xabcd, NULL, NULL);
+ if (g_str_equal(context->data->test_name, "/TP/MPS/BV-08-C"))
+ avrcp_get_folder_items(context->session,
+ AVRCP_MEDIA_PLAYER_LIST, 0, 2, NULL, 0,
+ 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);
@@ -647,6 +652,14 @@ int main(int argc, char *argv[])
raw_pdu(0x00, 0x11, 0x0e, 0x70, 0x00, 0x02,
0xab, 0xcd));
+ /* GetFolderItems - CT */
+ define_test("/TP/MPS/BV-08-C", test_client,
+ raw_pdu(0x00, 0x11, 0x0e, AVRCP_GET_FOLDER_ITEMS,
+ 0x00, 0x0a, AVRCP_MEDIA_PLAYER_LIST,
+ 0x00, 0x00, 0x00, 0x00, /* start */
+ 0x00, 0x00, 0x00, 0x02, /* end */
+ 0x00));
+
/* Connection Establishment for Control tests */
/*
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that Controller is able to request the list of available
Media Players.
---
unit/test-avrcp.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 4336668..46c10a3 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -571,6 +571,11 @@ static void test_client(gconstpointer data)
AVRCP_MEDIA_PLAYER_LIST, 0, 2, NULL, 0,
NULL, NULL);
+ if (g_str_equal(context->data->test_name, "/TP/MPS/BV-01-I"))
+ avrcp_get_folder_items(context->session,
+ AVRCP_MEDIA_PLAYER_LIST, 0, 2, NULL, 0,
+ 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);
@@ -660,6 +665,16 @@ int main(int argc, char *argv[])
0x00, 0x00, 0x00, 0x02, /* end */
0x00));
+ /* Media Player Selection IOP tests */
+
+ /* Listing of available media players */
+ define_test("/TP/MPS/BV-01-I", test_client,
+ raw_pdu(0x00, 0x11, 0x0e, AVRCP_GET_FOLDER_ITEMS,
+ 0x00, 0x0a, AVRCP_MEDIA_PLAYER_LIST,
+ 0x00, 0x00, 0x00, 0x00, /* start */
+ 0x00, 0x00, 0x00, 0x02, /* end */
+ 0x00));
+
/* Connection Establishment for Control tests */
/*
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Test verifies that GetItemAttributes command issued by the Controller.
---
unit/test-avrcp.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 2905380..860deaf 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -585,6 +585,11 @@ static void test_client(gconstpointer data)
avrcp_change_path(context->session, 0x01, 0x01, 0xaabb,
NULL, NULL);
+ if (g_str_equal(context->data->test_name, "/TP/MCN/CB/BV-07-C"))
+ avrcp_get_item_attributes(context->session,
+ AVRCP_MEDIA_PLAYER_VFS, 0x01, 0xaabb,
+ NULL, 0, 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);
@@ -696,6 +701,15 @@ int main(int argc, char *argv[])
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01 /* Folder UID */));
+ /* GetItemAttributes - CT */
+ define_test("/TP/MCN/CB/BV-07-C", test_client,
+ raw_pdu(0x00, 0x11, 0x0e, AVRCP_GET_ITEM_ATTRIBUTES,
+ 0x00, 0x0c, AVRCP_MEDIA_PLAYER_VFS,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, /* uuid */
+ 0xaa, 0xbb, /* counter */
+ 0x00)); /* num attr */
+
/* Media Player Selection IOP tests */
/* Listing of available media players */
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
---
android/avrcp-lib.c | 28 ++++++++++++++++++++++++++++
android/avrcp-lib.h | 4 ++++
2 files changed, 32 insertions(+)
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 284ed10..7304b11 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -1095,3 +1095,31 @@ int avrcp_change_path(struct avrcp *session, uint8_t direction, uint64_t uid,
return avctp_send_browsing_req(session->conn, buf, sizeof(buf),
func, user_data);
}
+
+int avrcp_get_item_attributes(struct avrcp *session, uint8_t scope,
+ uint64_t uid, uint16_t counter, uint32_t *attr,
+ size_t attr_count, avctp_browsing_rsp_cb func,
+ void *user_data)
+{
+ uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 12 +
+ attr_count * sizeof(uint32_t)];
+ struct avrcp_browsing_header *pdu = (void *) buf;
+
+ memset(buf, 0, sizeof(buf));
+
+ pdu->pdu_id = AVRCP_GET_ITEM_ATTRIBUTES;
+ pdu->param_len = htons(12 + attr_count * sizeof(uint32_t));
+
+ /* Scope */
+ pdu->params[0] = scope;
+
+ bt_put_be64(uid, &pdu->params[1]);
+ bt_put_be16(counter, &pdu->params[9]);
+
+ pdu->params[11] = attr_count;
+
+ memcpy(&pdu->params[12], attr, attr_count * sizeof(uint32_t));
+
+ return avctp_send_browsing_req(session->conn, buf, sizeof(buf),
+ func, user_data);
+}
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 40e571a..653a98e 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -265,3 +265,7 @@ int avrcp_get_folder_items(struct avrcp *session, uint8_t scope,
int avrcp_change_path(struct avrcp *session, uint8_t direction, uint64_t uid,
uint16_t counter, avctp_browsing_rsp_cb func,
void *user_data);
+int avrcp_get_item_attributes(struct avrcp *session, uint8_t scope,
+ uint64_t uid, uint16_t counter, uint32_t *attr,
+ size_t attr_count, avctp_browsing_rsp_cb func,
+ void *user_data);
--
1.8.3.2
From: Andrei Emeltchenko <[email protected]>
Add support for browsing channel
---
android/avrcp-lib.c | 6 ++++++
android/avrcp-lib.h | 2 ++
2 files changed, 8 insertions(+)
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 689c536..13acae9 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -270,6 +270,12 @@ struct avrcp *avrcp_new(int fd, size_t imtu, size_t omtu, uint16_t version)
return session;
}
+int avrcp_connect_browsing(struct avrcp *session, int fd, size_t imtu,
+ size_t omtu)
+{
+ return avctp_connect_browsing(session->conn, fd, imtu, omtu);
+}
+
void avrcp_set_destroy_cb(struct avrcp *session, avrcp_destroy_cb_t cb,
void *user_data)
{
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index d9acb7d..8d9782b 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -177,6 +177,8 @@ 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,
void *user_data);
+int avrcp_connect_browsing(struct avrcp *session, int fd, size_t imtu,
+ size_t omtu);
void avrcp_register_player(struct avrcp *session,
const struct avrcp_control_ind *ind,
--
1.8.3.2