diff mbox series

[Bluez,v3] audio/avrcp: Fix media player passthrough bitmask

Message ID 20200529133023.Bluez.v3.1.I804fb280949e4ce5cd9d0fce544a6f1a0592d11b@changeid (mailing list archive)
State Accepted
Delegated to: Luiz Von Dentz
Headers show
Series [Bluez,v3] audio/avrcp: Fix media player passthrough bitmask | expand

Commit Message

Archie Pusaka May 29, 2020, 5:31 a.m. UTC
From: Archie Pusaka <apusaka@chromium.org>

Adjust the values of the passthrough bitmask with the declared
keys in avctp.c:key_map, according to section 6.10.2.1 of the
AVRCP specification.

Signed-off-by: Archie Pusaka <apusaka@chromium.org>
---

Changes in v3:
- Use table to map the passthrough bitmask instead of hardcoding

Changes in v2:
- Fix the mix-up between the first 4 and the last 4 bits of each
octet

 profiles/audio/avctp.c | 11 +++++
 profiles/audio/avctp.h | 11 +++++
 profiles/audio/avrcp.c | 93 ++++++++++++++++++++++++++++++++++++++----
 3 files changed, 108 insertions(+), 7 deletions(-)

Comments

Luiz Augusto von Dentz June 4, 2020, 9:26 p.m. UTC | #1
Hi Archie,

On Thu, May 28, 2020 at 10:31 PM Archie Pusaka <apusaka@google.com> wrote:
>
> From: Archie Pusaka <apusaka@chromium.org>
>
> Adjust the values of the passthrough bitmask with the declared
> keys in avctp.c:key_map, according to section 6.10.2.1 of the
> AVRCP specification.
>
> Signed-off-by: Archie Pusaka <apusaka@chromium.org>
> ---
>
> Changes in v3:
> - Use table to map the passthrough bitmask instead of hardcoding
>
> Changes in v2:
> - Fix the mix-up between the first 4 and the last 4 bits of each
> octet
>
>  profiles/audio/avctp.c | 11 +++++
>  profiles/audio/avctp.h | 11 +++++
>  profiles/audio/avrcp.c | 93 ++++++++++++++++++++++++++++++++++++++----
>  3 files changed, 108 insertions(+), 7 deletions(-)
>
> diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c
> index 058b44a8b..7307eaa9e 100644
> --- a/profiles/audio/avctp.c
> +++ b/profiles/audio/avctp.c
> @@ -2222,3 +2222,14 @@ bool avctp_is_initiator(struct avctp *session)
>  {
>         return session->initiator;
>  }
> +
> +bool avctp_supports_avc(uint8_t avc)
> +{
> +       int i;
> +
> +       for (i = 0; key_map[i].name != NULL; i++) {
> +               if (key_map[i].avc == avc)
> +                       return true;
> +       }
> +       return false;
> +}
> diff --git a/profiles/audio/avctp.h b/profiles/audio/avctp.h
> index 68a273561..c3cd49d88 100644
> --- a/profiles/audio/avctp.h
> +++ b/profiles/audio/avctp.h
> @@ -54,7 +54,12 @@
>  #define AVC_DOWN                       0x02
>  #define AVC_LEFT                       0x03
>  #define AVC_RIGHT                      0x04
> +#define AVC_RIGHT_UP                   0x05
> +#define AVC_RIGHT_DOWN                 0x06
> +#define AVC_LEFT_UP                    0x07
> +#define AVC_LEFT_DOWN                  0x08
>  #define AVC_ROOT_MENU                  0x09
> +#define AVC_SETUP_MENU                 0x0a
>  #define AVC_CONTENTS_MENU              0x0b
>  #define AVC_FAVORITE_MENU              0x0c
>  #define AVC_EXIT                       0x0d
> @@ -72,9 +77,11 @@
>  #define AVC_9                          0x29
>  #define AVC_DOT                                0x2a
>  #define AVC_ENTER                      0x2b
> +#define AVC_CLEAR                      0x2c
>  #define AVC_CHANNEL_UP                 0x30
>  #define AVC_CHANNEL_DOWN               0x31
>  #define AVC_CHANNEL_PREVIOUS           0x32
> +#define AVC_SOUND_SELECT               0x33
>  #define AVC_INPUT_SELECT               0x34
>  #define AVC_INFO                       0x35
>  #define AVC_HELP                       0x36
> @@ -95,6 +102,8 @@
>  #define AVC_FORWARD                    0x4b
>  #define AVC_BACKWARD                   0x4c
>  #define AVC_LIST                       0x4d
> +#define AVC_ANGLE                      0x50
> +#define AVC_SUBPICTURE                 0x51
>  #define AVC_F1                         0x71
>  #define AVC_F2                         0x72
>  #define AVC_F3                         0x73
> @@ -108,6 +117,7 @@
>  #define AVC_GREEN                      0x7b
>  #define AVC_BLUE                       0x7c
>  #define AVC_YELLOW                     0x7c
> +#define AVC_VENDOR_UNIQUE              0x7e
>
>  struct avctp;
>
> @@ -183,3 +193,4 @@ 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);
> +bool avctp_supports_avc(uint8_t avc);
> diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
> index 773ccdb60..fa97a3a89 100644
> --- a/profiles/audio/avrcp.c
> +++ b/profiles/audio/avrcp.c
> @@ -293,15 +293,75 @@ struct control_pdu_handler {
>                                                         uint8_t transaction);
>  };
>
> +static struct {
> +       uint8_t feature_bit;
> +       uint8_t avc;
> +} passthrough_map[] = {
> +       { 0, AVC_SELECT },
> +       { 1, AVC_UP },
> +       { 2, AVC_DOWN },
> +       { 3, AVC_LEFT },
> +       { 4, AVC_RIGHT },
> +       { 5, AVC_RIGHT_UP },
> +       { 6, AVC_RIGHT_DOWN },
> +       { 7, AVC_LEFT_UP },
> +       { 8, AVC_LEFT_DOWN },
> +       { 9, AVC_ROOT_MENU },
> +       { 10, AVC_SETUP_MENU },
> +       { 11, AVC_CONTENTS_MENU },
> +       { 12, AVC_FAVORITE_MENU },
> +       { 13, AVC_EXIT },
> +       { 14, AVC_0 },
> +       { 15, AVC_1 },
> +       { 16, AVC_2 },
> +       { 17, AVC_3 },
> +       { 18, AVC_4 },
> +       { 19, AVC_5 },
> +       { 20, AVC_6 },
> +       { 21, AVC_7 },
> +       { 22, AVC_8 },
> +       { 23, AVC_9 },
> +       { 24, AVC_DOT },
> +       { 25, AVC_ENTER },
> +       { 26, AVC_CLEAR },
> +       { 27, AVC_CHANNEL_UP },
> +       { 28, AVC_CHANNEL_DOWN },
> +       { 29, AVC_CHANNEL_PREVIOUS },
> +       { 30, AVC_SOUND_SELECT },
> +       { 31, AVC_INPUT_SELECT },
> +       { 32, AVC_INFO },
> +       { 33, AVC_HELP },
> +       { 34, AVC_PAGE_UP },
> +       { 35, AVC_PAGE_DOWN },
> +       { 36, AVC_POWER },
> +       { 37, AVC_VOLUME_UP },
> +       { 38, AVC_VOLUME_DOWN },
> +       { 39, AVC_MUTE },
> +       { 40, AVC_PLAY },
> +       { 41, AVC_STOP },
> +       { 42, AVC_PAUSE },
> +       { 43, AVC_RECORD },
> +       { 44, AVC_REWIND },
> +       { 45, AVC_FAST_FORWARD },
> +       { 46, AVC_EJECT },
> +       { 47, AVC_FORWARD },
> +       { 48, AVC_BACKWARD },
> +       { 49, AVC_ANGLE },
> +       { 50, AVC_SUBPICTURE },
> +       { 51, AVC_F1 },
> +       { 52, AVC_F2 },
> +       { 53, AVC_F3 },
> +       { 54, AVC_F4 },
> +       { 55, AVC_F5 },
> +       { 56, AVC_VENDOR_UNIQUE },
> +       { 0xff, 0xff }
> +};
> +
>  static GSList *servers = NULL;
>  static unsigned int avctp_id = 0;
>
> -/* Default feature bit mask for media player as per avctp.c:key_map */
> -static const uint8_t features[16] = {
> -                               0xF8, 0xBF, 0xFF, 0xBF, 0x1F,
> -                               0xFB, 0x3F, 0x60, 0x00, 0x00,
> -                               0x00, 0x00, 0x00, 0x00, 0x00,
> -                               0x00 };
> +/* Default feature bit mask for media player */
> +static uint8_t default_features[16];
>
>  /* Company IDs supported by this device */
>  static uint32_t company_ids[] = {
> @@ -490,6 +550,22 @@ static sdp_record_t *avrcp_tg_record(void)
>         return record;
>  }
>
> +static void populate_default_features(void)
> +{
> +       int i;
> +
> +       for (i = 0; passthrough_map[i].feature_bit != 0xff; i++) {
> +               if (avctp_supports_avc(passthrough_map[i].avc)) {
> +                       uint8_t bit = passthrough_map[i].feature_bit;
> +
> +                       default_features[bit >> 3] |= (1 << (bit & 7));
> +               }
> +       }
> +
> +       /* supports at least AVRCP 1.4 */
> +       default_features[7] |= (1 << 2);
> +}
> +
>  static unsigned int attr_get_max_val(uint8_t attr)
>  {
>         switch (attr) {
> @@ -1913,7 +1989,8 @@ static void avrcp_handle_media_player_list(struct avrcp *session,
>                 item->subtype = htonl(0x01); /* Audio Book */
>                 item->status = player_get_status(player);
>                 /* Assign Default Feature Bit Mask */
> -               memcpy(&item->features, &features, sizeof(features));
> +               memcpy(&item->features, &default_features,
> +                                       sizeof(default_features));
>
>                 item->charset = htons(AVRCP_CHARSET_UTF8);
>
> @@ -4578,6 +4655,8 @@ static int avrcp_init(void)
>         btd_profile_register(&avrcp_controller_profile);
>         btd_profile_register(&avrcp_target_profile);
>
> +       populate_default_features();
> +
>         return 0;
>  }
>
> --
> 2.27.0.rc2.251.g90737beb825-goog

Applied, thanks.
diff mbox series

Patch

diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c
index 058b44a8b..7307eaa9e 100644
--- a/profiles/audio/avctp.c
+++ b/profiles/audio/avctp.c
@@ -2222,3 +2222,14 @@  bool avctp_is_initiator(struct avctp *session)
 {
 	return session->initiator;
 }
+
+bool avctp_supports_avc(uint8_t avc)
+{
+	int i;
+
+	for (i = 0; key_map[i].name != NULL; i++) {
+		if (key_map[i].avc == avc)
+			return true;
+	}
+	return false;
+}
diff --git a/profiles/audio/avctp.h b/profiles/audio/avctp.h
index 68a273561..c3cd49d88 100644
--- a/profiles/audio/avctp.h
+++ b/profiles/audio/avctp.h
@@ -54,7 +54,12 @@ 
 #define AVC_DOWN			0x02
 #define AVC_LEFT			0x03
 #define AVC_RIGHT			0x04
+#define AVC_RIGHT_UP			0x05
+#define AVC_RIGHT_DOWN			0x06
+#define AVC_LEFT_UP			0x07
+#define AVC_LEFT_DOWN			0x08
 #define AVC_ROOT_MENU			0x09
+#define AVC_SETUP_MENU			0x0a
 #define AVC_CONTENTS_MENU		0x0b
 #define AVC_FAVORITE_MENU		0x0c
 #define AVC_EXIT			0x0d
@@ -72,9 +77,11 @@ 
 #define AVC_9				0x29
 #define AVC_DOT				0x2a
 #define AVC_ENTER			0x2b
+#define AVC_CLEAR			0x2c
 #define AVC_CHANNEL_UP			0x30
 #define AVC_CHANNEL_DOWN		0x31
 #define AVC_CHANNEL_PREVIOUS		0x32
+#define AVC_SOUND_SELECT		0x33
 #define AVC_INPUT_SELECT		0x34
 #define AVC_INFO			0x35
 #define AVC_HELP			0x36
@@ -95,6 +102,8 @@ 
 #define AVC_FORWARD			0x4b
 #define AVC_BACKWARD			0x4c
 #define AVC_LIST			0x4d
+#define AVC_ANGLE			0x50
+#define AVC_SUBPICTURE			0x51
 #define AVC_F1				0x71
 #define AVC_F2				0x72
 #define AVC_F3				0x73
@@ -108,6 +117,7 @@ 
 #define AVC_GREEN			0x7b
 #define AVC_BLUE			0x7c
 #define AVC_YELLOW			0x7c
+#define AVC_VENDOR_UNIQUE		0x7e
 
 struct avctp;
 
@@ -183,3 +193,4 @@  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);
+bool avctp_supports_avc(uint8_t avc);
diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 773ccdb60..fa97a3a89 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -293,15 +293,75 @@  struct control_pdu_handler {
 							uint8_t transaction);
 };
 
+static struct {
+	uint8_t feature_bit;
+	uint8_t avc;
+} passthrough_map[] = {
+	{ 0, AVC_SELECT },
+	{ 1, AVC_UP },
+	{ 2, AVC_DOWN },
+	{ 3, AVC_LEFT },
+	{ 4, AVC_RIGHT },
+	{ 5, AVC_RIGHT_UP },
+	{ 6, AVC_RIGHT_DOWN },
+	{ 7, AVC_LEFT_UP },
+	{ 8, AVC_LEFT_DOWN },
+	{ 9, AVC_ROOT_MENU },
+	{ 10, AVC_SETUP_MENU },
+	{ 11, AVC_CONTENTS_MENU },
+	{ 12, AVC_FAVORITE_MENU },
+	{ 13, AVC_EXIT },
+	{ 14, AVC_0 },
+	{ 15, AVC_1 },
+	{ 16, AVC_2 },
+	{ 17, AVC_3 },
+	{ 18, AVC_4 },
+	{ 19, AVC_5 },
+	{ 20, AVC_6 },
+	{ 21, AVC_7 },
+	{ 22, AVC_8 },
+	{ 23, AVC_9 },
+	{ 24, AVC_DOT },
+	{ 25, AVC_ENTER },
+	{ 26, AVC_CLEAR },
+	{ 27, AVC_CHANNEL_UP },
+	{ 28, AVC_CHANNEL_DOWN },
+	{ 29, AVC_CHANNEL_PREVIOUS },
+	{ 30, AVC_SOUND_SELECT },
+	{ 31, AVC_INPUT_SELECT },
+	{ 32, AVC_INFO },
+	{ 33, AVC_HELP },
+	{ 34, AVC_PAGE_UP },
+	{ 35, AVC_PAGE_DOWN },
+	{ 36, AVC_POWER },
+	{ 37, AVC_VOLUME_UP },
+	{ 38, AVC_VOLUME_DOWN },
+	{ 39, AVC_MUTE },
+	{ 40, AVC_PLAY },
+	{ 41, AVC_STOP },
+	{ 42, AVC_PAUSE },
+	{ 43, AVC_RECORD },
+	{ 44, AVC_REWIND },
+	{ 45, AVC_FAST_FORWARD },
+	{ 46, AVC_EJECT },
+	{ 47, AVC_FORWARD },
+	{ 48, AVC_BACKWARD },
+	{ 49, AVC_ANGLE },
+	{ 50, AVC_SUBPICTURE },
+	{ 51, AVC_F1 },
+	{ 52, AVC_F2 },
+	{ 53, AVC_F3 },
+	{ 54, AVC_F4 },
+	{ 55, AVC_F5 },
+	{ 56, AVC_VENDOR_UNIQUE },
+	{ 0xff, 0xff }
+};
+
 static GSList *servers = NULL;
 static unsigned int avctp_id = 0;
 
-/* Default feature bit mask for media player as per avctp.c:key_map */
-static const uint8_t features[16] = {
-				0xF8, 0xBF, 0xFF, 0xBF, 0x1F,
-				0xFB, 0x3F, 0x60, 0x00, 0x00,
-				0x00, 0x00, 0x00, 0x00, 0x00,
-				0x00 };
+/* Default feature bit mask for media player */
+static uint8_t default_features[16];
 
 /* Company IDs supported by this device */
 static uint32_t company_ids[] = {
@@ -490,6 +550,22 @@  static sdp_record_t *avrcp_tg_record(void)
 	return record;
 }
 
+static void populate_default_features(void)
+{
+	int i;
+
+	for (i = 0; passthrough_map[i].feature_bit != 0xff; i++) {
+		if (avctp_supports_avc(passthrough_map[i].avc)) {
+			uint8_t bit = passthrough_map[i].feature_bit;
+
+			default_features[bit >> 3] |= (1 << (bit & 7));
+		}
+	}
+
+	/* supports at least AVRCP 1.4 */
+	default_features[7] |= (1 << 2);
+}
+
 static unsigned int attr_get_max_val(uint8_t attr)
 {
 	switch (attr) {
@@ -1913,7 +1989,8 @@  static void avrcp_handle_media_player_list(struct avrcp *session,
 		item->subtype = htonl(0x01); /* Audio Book */
 		item->status = player_get_status(player);
 		/* Assign Default Feature Bit Mask */
-		memcpy(&item->features, &features, sizeof(features));
+		memcpy(&item->features, &default_features,
+					sizeof(default_features));
 
 		item->charset = htons(AVRCP_CHARSET_UTF8);
 
@@ -4578,6 +4655,8 @@  static int avrcp_init(void)
 	btd_profile_register(&avrcp_controller_profile);
 	btd_profile_register(&avrcp_target_profile);
 
+	populate_default_features();
+
 	return 0;
 }