From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH BlueZ 13/16] AVRCP: Add proper role init procedure
Date: Mon, 15 Oct 2012 16:05:33 +0200 [thread overview]
Message-ID: <1350309936-31588-13-git-send-email-luiz.dentz@gmail.com> (raw)
In-Reply-To: <1350309936-31588-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
audio/avrcp.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 103 insertions(+), 10 deletions(-)
diff --git a/audio/avrcp.c b/audio/avrcp.c
index 85dd241..8336831 100644
--- a/audio/avrcp.c
+++ b/audio/avrcp.c
@@ -104,6 +104,7 @@
#define CAP_EVENTS_SUPPORTED 0x03
#define AVRCP_REGISTER_NOTIFICATION_PARAM_LENGTH 5
+#define AVRCP_GET_CAPABILITIES_PARAM_LENGTH 1
#define AVRCP_FEATURE_CATEGORY_1 0x0001
#define AVRCP_FEATURE_CATEGORY_2 0x0002
@@ -215,7 +216,7 @@ static uint32_t company_ids[] = {
IEEEID_BTSIG,
};
-static void register_volume_notification(struct avrcp *session);
+static void register_notification(struct avrcp *session, uint8_t event);
static sdp_record_t *avrcp_ct_record(void)
{
@@ -1306,7 +1307,7 @@ static struct avrcp_server *find_server(GSList *list, const bdaddr_t *src)
return NULL;
}
-static gboolean avrcp_handle_volume_changed(struct avctp *conn,
+static gboolean avrcp_handle_event(struct avctp *conn,
uint8_t code, uint8_t subunit,
uint8_t *operands, size_t operand_count,
void *user_data)
@@ -1314,26 +1315,34 @@ static gboolean avrcp_handle_volume_changed(struct avctp *conn,
struct avrcp *session = user_data;
struct avrcp_player *player = session->player;
struct avrcp_header *pdu = (void *) operands;
+ uint8_t event;
uint8_t volume;
if (code != AVC_CTYPE_INTERIM && code != AVC_CTYPE_CHANGED)
return FALSE;
- volume = pdu->params[1] & 0x7F;
+ event = pdu->params[0];
- if (player)
- player->cb->set_volume(volume, session->dev,
+ switch (event) {
+ case AVRCP_EVENT_VOLUME_CHANGED:
+ volume = pdu->params[1] & 0x7F;
+
+ if (player)
+ player->cb->set_volume(volume, session->dev,
player->user_data);
+ break;
+ }
+
if (code == AVC_CTYPE_CHANGED) {
- register_volume_notification(session);
+ register_notification(session, event);
return FALSE;
}
return TRUE;
}
-static void register_volume_notification(struct avrcp *session)
+static void register_notification(struct avrcp *session, uint8_t event)
{
uint8_t buf[AVRCP_HEADER_LENGTH + AVRCP_REGISTER_NOTIFICATION_PARAM_LENGTH];
struct avrcp_header *pdu = (void *) buf;
@@ -1344,14 +1353,89 @@ static void register_volume_notification(struct avrcp *session)
set_company_id(pdu->company_id, IEEEID_BTSIG);
pdu->pdu_id = AVRCP_REGISTER_NOTIFICATION;
pdu->packet_type = AVRCP_PACKET_TYPE_SINGLE;
- pdu->params[0] = AVRCP_EVENT_VOLUME_CHANGED;
+ pdu->params[0] = event;
pdu->params_len = htons(AVRCP_REGISTER_NOTIFICATION_PARAM_LENGTH);
length = AVRCP_HEADER_LENGTH + ntohs(pdu->params_len);
avctp_send_vendordep_req(session->conn, AVC_CTYPE_NOTIFY,
AVC_SUBUNIT_PANEL, buf, length,
- avrcp_handle_volume_changed, session);
+ avrcp_handle_event, session);
+}
+
+static gboolean avrcp_get_capabilities_resp(struct avctp *conn,
+ uint8_t code, uint8_t subunit,
+ uint8_t *operands, size_t operand_count,
+ void *user_data)
+{
+ struct avrcp *session = user_data;
+ struct avrcp_header *pdu = (void *) operands;
+ uint8_t count;
+
+ if (pdu->params[0] != CAP_EVENTS_SUPPORTED)
+ return FALSE;
+
+ count = pdu->params[1];
+
+ for (; count > 0; count--) {
+ uint8_t event = pdu->params[1 + count];
+
+ switch (event) {
+ case AVRCP_EVENT_STATUS_CHANGED:
+ case AVRCP_EVENT_TRACK_CHANGED:
+ register_notification(session, event);
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+static void avrcp_get_capabilities(struct avrcp *session)
+{
+ uint8_t buf[AVRCP_HEADER_LENGTH + AVRCP_GET_CAPABILITIES_PARAM_LENGTH];
+ struct avrcp_header *pdu = (void *) buf;
+ uint8_t length;
+
+ memset(buf, 0, sizeof(buf));
+
+ set_company_id(pdu->company_id, IEEEID_BTSIG);
+ pdu->pdu_id = AVRCP_GET_CAPABILITIES;
+ pdu->packet_type = AVRCP_PACKET_TYPE_SINGLE;
+ pdu->params[0] = CAP_EVENTS_SUPPORTED;
+ pdu->params_len = htons(AVRCP_GET_CAPABILITIES_PARAM_LENGTH);
+
+ length = AVRCP_HEADER_LENGTH + ntohs(pdu->params_len);
+
+ avctp_send_vendordep_req(session->conn, AVC_CTYPE_STATUS,
+ AVC_SUBUNIT_PANEL, buf, length,
+ avrcp_get_capabilities_resp,
+ session);
+}
+
+static gboolean avrcp_get_play_status_rsp(struct avctp *conn,
+ uint8_t code, uint8_t subunit,
+ uint8_t *operands, size_t operand_count,
+ void *user_data)
+{
+ return FALSE;
+}
+
+static void avrcp_get_play_status(struct avrcp *session)
+{
+ uint8_t buf[AVRCP_HEADER_LENGTH];
+ struct avrcp_header *pdu = (void *) buf;
+
+ memset(buf, 0, sizeof(buf));
+
+ set_company_id(pdu->company_id, IEEEID_BTSIG);
+ pdu->pdu_id = AVRCP_GET_PLAY_STATUS;
+ pdu->packet_type = AVRCP_PACKET_TYPE_SINGLE;
+
+ avctp_send_vendordep_req(session->conn, AVC_CTYPE_STATUS,
+ AVC_SUBUNIT_PANEL, buf, sizeof(buf),
+ avrcp_get_play_status_rsp,
+ session);
}
static struct avrcp *find_session(GSList *list, struct audio_device *dev)
@@ -1370,11 +1454,13 @@ static void session_tg_init(struct avrcp *session)
{
struct avrcp_server *server = session->server;
+ DBG("%p version 0x%04x", session, session->version);
+
session->player = g_slist_nth_data(server->players, 0);
session->control_handlers = tg_control_handlers;
if (session->version >= 0x0104) {
- register_volume_notification(session);
+ register_notification(session, AVRCP_EVENT_VOLUME_CHANGED);
if (session->features & AVRCP_FEATURE_BROWSING)
avctp_connect_browsing(session->conn);
}
@@ -1393,6 +1479,13 @@ static void session_ct_init(struct avrcp *session)
{
session->control_handlers = ct_control_handlers;
+ DBG("%p version 0x%04x", session, session->version);
+
+ if (session->version >= 0x0103) {
+ avrcp_get_capabilities(session);
+ avrcp_get_play_status(session);
+ }
+
session->control_id = avctp_register_pdu_handler(session->conn,
AVC_OP_VENDORDEP,
handle_vendordep_pdu,
--
1.7.11.4
next prev parent reply other threads:[~2012-10-15 14:05 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-10-15 14:05 [PATCH BlueZ 01/16] AVCTP: Simplify channel handling Luiz Augusto von Dentz
2012-10-15 14:05 ` [PATCH BlueZ 02/16] AVCTP: Allocate memory to hold incoming/outgoing PDUs Luiz Augusto von Dentz
2012-10-15 14:05 ` [PATCH BlueZ 03/16] AVRCP: Register to AVCTP state changes without depending on player Luiz Augusto von Dentz
2012-10-15 14:05 ` [PATCH BlueZ 04/16] AVRCP: Don't respond with errors when no player is registered Luiz Augusto von Dentz
2012-10-15 14:37 ` Johan Hedberg
2012-10-15 14:05 ` [PATCH BlueZ 05/16] AVRCP: Fix crash on disconnect Luiz Augusto von Dentz
2012-10-15 14:05 ` [PATCH BlueZ 06/16] AVRCP: Simplify state_changed callback Luiz Augusto von Dentz
2012-10-15 14:05 ` [PATCH BlueZ 07/16] AVCTP: Make use of allocate buffer to send data Luiz Augusto von Dentz
2012-10-15 14:05 ` [PATCH BlueZ 08/16] AVCTP: Wait confirmation to send button release Luiz Augusto von Dentz
2012-10-15 14:05 ` [PATCH BlueZ 09/16] AVCTP: Add proper prefix to AVC passthrough codes Luiz Augusto von Dentz
2012-10-15 14:05 ` [PATCH BlueZ 10/16] AVCTP: Add proper queueing for channels Luiz Augusto von Dentz
2012-10-15 14:05 ` [PATCH BlueZ 11/16] AVRCP: Fix reading wrong profile when acting as a controller Luiz Augusto von Dentz
2012-10-15 14:05 ` [PATCH BlueZ 12/16] AVRCP: Fix handling TG PDUs as they were CT PDUs Luiz Augusto von Dentz
2012-10-15 14:05 ` Luiz Augusto von Dentz [this message]
2012-10-15 14:05 ` [PATCH BlueZ 14/16] control: Add basic support for AVRCP 1.0 controller Luiz Augusto von Dentz
2012-10-15 14:05 ` [PATCH BlueZ 15/16] control: Add Control.Connect API Luiz Augusto von Dentz
2012-10-15 14:05 ` [PATCH BlueZ 16/16] control: Add Control.Disconnect method Luiz Augusto von Dentz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1350309936-31588-13-git-send-email-luiz.dentz@gmail.com \
--to=luiz.dentz@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox