From 7c90092b2eab3d430686dd791875adc1d0c3d1a0 Mon Sep 17 00:00:00 2001 From: ctf Date: Tue, 24 Mar 2020 19:42:23 +0800 Subject: [PATCH 15/19] profiles audio add avrcp key code report Signed-off-by: ctf --- profiles/audio/avctp.c | 59 +++++++++++++++++++++++++++++++++++++++++ profiles/audio/avctp.h | 6 +++++ profiles/audio/avrcp.c | 24 +++++++++++++++++ profiles/audio/player.c | 30 ++++++++++++++++++++- profiles/audio/player.h | 1 + 5 files changed, 119 insertions(+), 1 deletion(-) diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c index 5f8625c..3d31d24 100644 --- a/profiles/audio/avctp.c +++ b/profiles/audio/avctp.c @@ -210,6 +210,7 @@ struct avctp { struct avctp_channel *browsing; struct avctp_passthrough_handler *handler; + struct avctp_keycode_handler *keycode_handler; uint8_t key_quirks[256]; struct key_pressed key; @@ -229,6 +230,12 @@ struct avctp_pdu_handler { unsigned int id; }; +struct avctp_keycode_handler { + avctp_keycode_cb cb; + void *user_data; + unsigned int id; +}; + struct avctp_browsing_pdu_handler { avctp_browsing_pdu_cb cb; void *user_data; @@ -380,6 +387,7 @@ static size_t handle_panel_passthrough(struct avctp *session, size_t operand_count, void *user_data) { struct avctp_passthrough_handler *handler = session->handler; + struct avctp_keycode_handler *keycode_handler = session->keycode_handler; const char *status; int pressed, i; @@ -399,6 +407,11 @@ static size_t handle_panel_passthrough(struct avctp *session, pressed = 1; } + if(pressed && keycode_handler != NULL) { + if(keycode_handler->cb) + keycode_handler->cb(session, operands[0] & 0x7F, keycode_handler->user_data); + } + if (session->key.timer == 0 && handler != NULL) { if (handler->cb(session, operands[0] & 0x7F, pressed, handler->user_data)) @@ -1981,6 +1994,52 @@ bool avctp_unregister_passthrough_handler(unsigned int id) return false; } +unsigned int avctp_register_keycode_handler(struct avctp *session, + avctp_keycode_cb cb, + void *user_data) +{ + struct avctp_channel *control = session->control; + struct avctp_keycode_handler *handler; + static unsigned int id = 0; + + if (control == NULL || session->keycode_handler != NULL) + return 0; + + handler = g_new(struct avctp_keycode_handler, 1); + handler->cb = cb; + handler->user_data = user_data; + handler->id = ++id; + + session->keycode_handler = handler; + + return handler->id; +} + +bool avctp_unregister_keycode_handler(unsigned int id) +{ + GSList *l; + + for (l = servers; l; l = l->next) { + struct avctp_server *server = l->data; + GSList *s; + + for (s = server->sessions; s; s = s->next) { + struct avctp *session = s->data; + + if (session->keycode_handler == NULL) + continue; + + if (session->keycode_handler->id == id) { + g_free(session->keycode_handler); + session->keycode_handler = NULL; + return true; + } + } + } + + return false; +} + unsigned int avctp_register_pdu_handler(struct avctp *session, uint8_t opcode, avctp_control_pdu_cb cb, void *user_data) diff --git a/profiles/audio/avctp.h b/profiles/audio/avctp.h index 68a2735..0ce5ec6 100644 --- a/profiles/audio/avctp.h +++ b/profiles/audio/avctp.h @@ -127,6 +127,7 @@ typedef void (*avctp_state_cb) (struct btd_device *dev, typedef bool (*avctp_passthrough_cb) (struct avctp *session, uint8_t op, bool pressed, void *user_data); +typedef bool (*avctp_keycode_cb) (struct avctp *session, uint8_t op, void *user_data); typedef size_t (*avctp_control_pdu_cb) (struct avctp *session, uint8_t transaction, uint8_t *code, uint8_t *subunit, uint8_t *operands, @@ -161,6 +162,11 @@ unsigned int avctp_register_passthrough_handler(struct avctp *session, void *user_data); bool avctp_unregister_passthrough_handler(unsigned int id); +unsigned int avctp_register_keycode_handler(struct avctp *session, + avctp_keycode_cb cb, + void *user_data); +bool avctp_unregister_keycode_handler(unsigned int id); + unsigned int avctp_register_pdu_handler(struct avctp *session, uint8_t opcode, avctp_control_pdu_cb cb, void *user_data); diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c index 729f586..1242c47 100644 --- a/profiles/audio/avrcp.c +++ b/profiles/audio/avrcp.c @@ -270,6 +270,7 @@ struct avrcp { const struct control_pdu_handler *control_handlers; unsigned int passthrough_id; + unsigned int keycode_id; unsigned int control_id; unsigned int browsing_id; unsigned int browsing_timer; @@ -1510,6 +1511,20 @@ static bool handle_passthrough(struct avctp *conn, uint8_t op, bool pressed, return handler->func(session); } +static bool handle_keycode(struct avctp *conn, uint8_t op, void *user_data) +{ + struct avrcp *session = user_data; + struct avrcp_player *player = session->controller->player; + struct media_player *mp = player->user_data; + + if(!session || !player || !mp) { + DBG("session or player or mp is null"); + return; + } + + media_player_set_key_code(mp, (uint32_t)op); +} + static uint8_t avrcp_handle_register_notification(struct avrcp *session, struct avrcp_header *pdu, uint8_t transaction) @@ -4083,6 +4098,12 @@ static void session_init_control(struct avrcp *session) handle_passthrough, session); session->passthrough_handlers = passthrough_handlers; + + session->keycode_id = avctp_register_keycode_handler( + session->conn, + handle_keycode, + session); + session->control_id = avctp_register_pdu_handler(session->conn, AVC_OP_VENDORDEP, handle_vendordep_pdu, @@ -4157,6 +4178,9 @@ static void session_destroy(struct avrcp *session, int err) if (session->passthrough_id > 0) avctp_unregister_passthrough_handler(session->passthrough_id); + if(session->keycode_id > 0) + avctp_unregister_keycode_handler(session->keycode_id); + if (session->control_id > 0) avctp_unregister_pdu_handler(session->control_id); diff --git a/profiles/audio/player.c b/profiles/audio/player.c index eaaa54c..74d9590 100644 --- a/profiles/audio/player.c +++ b/profiles/audio/player.c @@ -101,7 +101,8 @@ struct media_player { struct player_callback *cb; GSList *pending; GSList *folders; - bool pos_change; + bool pos_change; + uint32_t key_code; }; static void append_track(void *key, void *value, void *user_data) @@ -464,6 +465,18 @@ static gboolean get_position_change(const GDBusPropertyTable *property, return TRUE; } +static gboolean get_keycode(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct media_player *mp = data; + uint32_t key_code; + + key_code = mp->key_code; + dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &key_code); + + return TRUE; +} + static DBusMessage *media_player_getstatus(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -758,6 +771,7 @@ static const GDBusPropertyTable media_player_properties[] = { { "Searchable", "b", get_searchable, NULL, searchable_exists }, { "Playlist", "o", get_playlist, NULL, playlist_exists }, { "PosChange", "b", get_position_change, NULL, NULL }, + { "KeyCode", "u", get_keycode, NULL, NULL }, { } }; @@ -1563,6 +1577,20 @@ void media_player_set_poschange(struct media_player *mp, bool enabled) "PosChange"); } +void media_player_set_key_code(struct media_player *mp, uint32_t key_code) +{ + if(!mp) { + DBG("media_player == NULL"); + return; + } + + mp->key_code = key_code; + + g_dbus_emit_property_changed(btd_get_dbus_connection(), + mp->path, MEDIA_PLAYER_INTERFACE, + "KeyCode"); +} + static DBusMessage *media_item_play(DBusConnection *conn, DBusMessage *msg, void *data) { diff --git a/profiles/audio/player.h b/profiles/audio/player.h index 70c89b6..bd260a2 100644 --- a/profiles/audio/player.h +++ b/profiles/audio/player.h @@ -92,6 +92,7 @@ void media_player_set_folder(struct media_player *mp, const char *path, uint32_t items); void media_player_set_playlist(struct media_player *mp, const char *name); void media_player_set_poschange(struct media_player *mp, bool enabled); +void media_player_set_key_code(struct media_player *mp, uint32_t key_code); struct media_item *media_player_set_playlist_item(struct media_player *mp, uint64_t uid); -- 2.20.1