From: Archie Pusaka <apusaka@xxxxxxxxxxxx> 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@xxxxxxxxxxxx> --- 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