From: Andrei Emeltchenko <andrei.emeltchenko@xxxxxxxxx> --- android/avrcp-lib.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++ android/avrcp-lib.h | 12 +++++++++++ 2 files changed, 72 insertions(+) diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c index 136801e..95e10f2 100644 --- a/android/avrcp-lib.c +++ b/android/avrcp-lib.c @@ -56,6 +56,15 @@ #define AVRCP_PACKET_TYPE_CONTINUING 0x02 #define AVRCP_PACKET_TYPE_END 0x03 +/* Capabilities for AVRCP_GET_CAPABILITIES pdu */ +#define CAP_COMPANY_ID 0x02 +#define CAP_EVENTS_SUPPORTED 0x03 + +/* Company IDs supported by this device */ +static uint32_t company_ids[] = { + IEEEID_BTSIG, +}; + #if __BYTE_ORDER == __LITTLE_ENDIAN struct avrcp_header { @@ -108,6 +117,8 @@ struct avrcp { const struct avrcp_passthrough_handler *passthrough_handlers; void *passthrough_data; unsigned int passthrough_id; + + uint16_t supported_events; }; void avrcp_shutdown(struct avrcp *session) @@ -220,6 +231,53 @@ static void set_company_id(uint8_t cid[3], const uint32_t cid_in) cid[2] = cid_in; } +static uint8_t avrcp_handle_get_capabilities(struct avrcp *session, + uint8_t transaction, uint16_t *params_len, + uint8_t *params, void *user_data) +{ + unsigned int i; + + DBG("id %d params_len %d", params[0], *params_len); + + if (*params_len != 1) + goto fail; + + switch (params[0]) { + case CAP_COMPANY_ID: + for (i = 0; i < G_N_ELEMENTS(company_ids); i++) + set_company_id(¶ms[2 + i * 3], company_ids[i]); + + *params_len = 2 + (3 * G_N_ELEMENTS(company_ids)); + params[1] = G_N_ELEMENTS(company_ids); + + return AVC_CTYPE_STABLE; + case CAP_EVENTS_SUPPORTED: + params[1] = 0; + for (i = 1; i <= AVRCP_EVENT_LAST; i++) { + if (session->supported_events & (1 << i)) { + params[1]++; + params[params[1] + 1] = i; + } + } + + *params_len = 2 + params[1]; + + return AVC_CTYPE_STABLE; + } + +fail: + *params_len = htons(1); + params[0] = AVRCP_STATUS_INVALID_PARAM; + + return AVC_CTYPE_REJECTED; +} + +static const struct avrcp_control_handler control_handlers[] = { + { AVRCP_GET_CAPABILITIES, AVC_CTYPE_STATUS, + avrcp_handle_get_capabilities }, + { }, +}; + struct avrcp *avrcp_new(int fd, size_t imtu, size_t omtu, uint16_t version) { struct avrcp *session; @@ -241,6 +299,8 @@ struct avrcp *avrcp_new(int fd, size_t imtu, size_t omtu, uint16_t version) handle_vendordep_pdu, session); + avrcp_set_control_handlers(session, control_handlers, NULL); + return session; } diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h index 4f3a632..0821287 100644 --- a/android/avrcp-lib.h +++ b/android/avrcp-lib.h @@ -46,6 +46,18 @@ #define AVRCP_ADD_TO_NOW_PLAYING 0x90 #define AVRCP_GENERAL_REJECT 0xA0 +/* Notification events */ +#define AVRCP_EVENT_STATUS_CHANGED 0x01 +#define AVRCP_EVENT_TRACK_CHANGED 0x02 +#define AVRCP_EVENT_TRACK_REACHED_END 0x03 +#define AVRCP_EVENT_TRACK_REACHED_START 0x04 +#define AVRCP_EVENT_SETTINGS_CHANGED 0x08 +#define AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED 0x0a +#define AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED 0x0b +#define AVRCP_EVENT_UIDS_CHANGED 0x0c +#define AVRCP_EVENT_VOLUME_CHANGED 0x0d +#define AVRCP_EVENT_LAST AVRCP_EVENT_VOLUME_CHANGED + struct avrcp; struct avrcp_control_handler { -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html