diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index b7de051..4acf396 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
void (*init_browsing) (struct avrcp *session);
void (*destroy) (struct avrcp *sesion);
+ const struct passthrough_handler *passthrough_handlers;
const struct control_pdu_handler *control_handlers;
+ unsigned int passthrough_id;
unsigned int control_id;
unsigned int browsing_id;
uint16_t supported_events;
struct pending_pdu *pending_pdu;
};
+struct passthrough_handler {
+ uint8_t op;
+ bool (*func) (struct avrcp *session);
+};
+
struct control_pdu_handler {
uint8_t pdu_id;
uint8_t code;
return player->cb->list_settings(player->user_data);
}
+static bool avrcp_handle_play(struct avrcp *session)
+{
+ struct avrcp_player *player = session->player;
+
+ if (session->player == NULL)
+ return false;
+
+ return player->cb->play(player->user_data);
+}
+
+static bool avrcp_handle_stop(struct avrcp *session)
+{
+ struct avrcp_player *player = session->player;
+
+ if (session->player == NULL)
+ return false;
+
+ return player->cb->stop(player->user_data);
+}
+
+static bool avrcp_handle_pause(struct avrcp *session)
+{
+ struct avrcp_player *player = session->player;
+
+ if (session->player == NULL)
+ return false;
+
+ return player->cb->pause(player->user_data);
+}
+
+static bool avrcp_handle_next(struct avrcp *session)
+{
+ struct avrcp_player *player = session->player;
+
+ if (session->player == NULL)
+ return false;
+
+ return player->cb->next(player->user_data);
+}
+
+static bool avrcp_handle_previous(struct avrcp *session)
+{
+ struct avrcp_player *player = session->player;
+
+ if (session->player == NULL)
+ return false;
+
+ return player->cb->previous(player->user_data);
+}
+
+static const struct passthrough_handler tg_passthrough_handlers[] = {
+ { AVC_PLAY, avrcp_handle_play },
+ { AVC_STOP, avrcp_handle_stop },
+ { AVC_PAUSE, avrcp_handle_pause },
+ { AVC_FORWARD, avrcp_handle_next },
+ { AVC_BACKWARD, avrcp_handle_previous },
+ { },
+};
+
+static bool handle_passthrough(struct avctp *conn, uint8_t op, bool pressed,
+ void *user_data)
+{
+ struct avrcp *session = user_data;
+ const struct passthrough_handler *handler;
+
+ for (handler = session->passthrough_handlers; handler->func;
+ handler++) {
+ if (handler->op == op)
+ break;
+ }
+
+ if (handler->func == NULL)
+ return false;
+
+ /* Do not trigger handler on release */
+ if (!pressed)
+ return true;
+
+ return handler->func(session);
+}
+
static uint8_t avrcp_handle_register_notification(struct avrcp *session,
struct avrcp_header *pdu,
uint8_t transaction)
player->sessions = g_slist_prepend(player->sessions, session);
}
+ session->passthrough_id = avctp_register_passthrough_handler(
+ session->conn,
+ handle_passthrough,
+ session);
+ session->passthrough_handlers = tg_passthrough_handlers;
session->control_id = avctp_register_pdu_handler(session->conn,
AVC_OP_VENDORDEP,
handle_vendordep_pdu,
server->sessions = g_slist_remove(server->sessions, session);
+ if (session->passthrough_id > 0)
+ avctp_unregister_passthrough_handler(session->passthrough_id);
+
if (session->control_id > 0)
avctp_unregister_pdu_handler(session->control_id);
diff --git a/profiles/audio/avrcp.h b/profiles/audio/avrcp.h
index 7b6fe92..3b1963f 100644
--- a/profiles/audio/avrcp.h
+++ b/profiles/audio/avrcp.h
uint32_t (*get_duration) (void *user_data);
void (*set_volume) (uint8_t volume, struct audio_device *dev,
void *user_data);
+ bool (*play) (void *user_data);
+ bool (*stop) (void *user_data);
+ bool (*pause) (void *user_data);
+ bool (*next) (void *user_data);
+ bool (*previous) (void *user_data);
};
int avrcp_target_register(struct btd_adapter *adapter, GKeyFile *config);