[PATCH v2 BlueZ 12/12] android/avrcp-lib: Add support for parsing RegisterNotification response

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>

---
 android/avrcp-lib.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 android/avrcp-lib.h |  6 ++--
 android/avrcp.c     | 39 ++++++++++------------
 unit/test-avrcp.c   |  3 +-
 4 files changed, 114 insertions(+), 28 deletions(-)

diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 80b778a..cf7dadf 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -801,6 +801,7 @@ done:
 	return FALSE;
 }
 
+
 int avrcp_get_capabilities(struct avrcp *session, uint8_t param)
 {
 	return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
@@ -808,10 +809,97 @@ int avrcp_get_capabilities(struct avrcp *session, uint8_t param)
 				get_capabilities_rsp, session);
 }
 
-int avrcp_register_notification(struct avrcp *session, uint8_t event,
-					uint32_t interval, avctp_rsp_cb func,
+static gboolean register_notification_rsp(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_player *player = session->player;
+	struct avrcp_header *pdu;
+	uint8_t event = 0;
+	uint16_t value16;
+	uint32_t value32;
+	uint64_t value64;
+	uint8_t *params = NULL;
+	int err;
+
+	DBG("");
+
+	if (!player || !player->cfm || !player->cfm->register_notification)
+		return FALSE;
+
+	pdu = parse_pdu(operands, operand_count);
+	if (!pdu) {
+		err = -EPROTO;
+		goto done;
+	}
+
+	if (code == AVC_CTYPE_REJECTED) {
+		err = parse_status(pdu);
+		goto done;
+	}
+
+	if (pdu->params_len < 1) {
+		err = -EPROTO;
+		goto done;
+	}
+
+	event = pdu->params[0];
+
+	switch (event) {
+	case AVRCP_EVENT_STATUS_CHANGED:
+	case AVRCP_EVENT_VOLUME_CHANGED:
+		if (pdu->params_len != 2) {
+			err = -EPROTO;
+			goto done;
+		}
+		params = &pdu->params[1];
+		break;
+	case AVRCP_EVENT_TRACK_CHANGED:
+		if (pdu->params_len != 9) {
+			err = -EPROTO;
+			goto done;
+		}
+		value64 = bt_get_be64(&pdu->params[1]);
+		params = (uint8_t *) &value64;
+		break;
+	case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
+		if (pdu->params_len != 5) {
+			err = -EPROTO;
+			goto done;
+		}
+		value32 = bt_get_be32(&pdu->params[1]);
+		params = (uint8_t *) &value32;
+		break;
+	case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
+	case AVRCP_EVENT_SETTINGS_CHANGED:
+		if (pdu->params_len < 2) {
+			err = -EPROTO;
+			goto done;
+		}
+		params = &pdu->params[1];
+		break;
+	case AVRCP_EVENT_UIDS_CHANGED:
+		if (pdu->params_len != 3) {
+			err = -EPROTO;
+			goto done;
+		}
+		value16 = bt_get_be16(&pdu->params[1]);
+		params = (uint8_t *) &value16;
+		break;
+	}
+
+	err = 0;
+
+done:
+	return player->cfm->register_notification(session, err, code, event,
+						params, player->user_data);
+}
+
+int avrcp_register_notification(struct avrcp *session, uint8_t event,
+							uint32_t interval)
+{
 	uint8_t params[5];
 
 	params[0] = event;
@@ -820,7 +908,7 @@ int avrcp_register_notification(struct avrcp *session, uint8_t event,
 	return avrcp_send_req(session, AVC_CTYPE_NOTIFY, AVC_SUBUNIT_PANEL,
 					AVRCP_REGISTER_NOTIFICATION,
 					params, sizeof(params),
-					func, user_data);
+					register_notification_rsp, session);
 }
 
 static gboolean list_attributes_rsp(struct avctp *conn,
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 2f35e90..0b867aa 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -191,6 +191,9 @@ struct avrcp_control_cfm {
 	void (*get_element_attributes) (struct avrcp *session, int err,
 					uint8_t number, uint32_t *attrs,
 					char **text, void *user_data);
+	bool (*register_notification) (struct avrcp *session, int err,
+					uint8_t code, uint8_t event,
+					uint8_t *params, void *user_data);
 };
 
 struct avrcp_passthrough_handler {
@@ -219,8 +222,7 @@ int avrcp_send(struct avrcp *session, uint8_t transaction, uint8_t code,
 					uint8_t *params, size_t params_len);
 int avrcp_get_capabilities(struct avrcp *session, uint8_t param);
 int avrcp_register_notification(struct avrcp *session, uint8_t event,
-					uint32_t interval, avctp_rsp_cb func,
-					void *user_data);
+							uint32_t interval);
 int avrcp_list_player_attributes(struct avrcp *session);
 int avrcp_get_player_attribute_text(struct avrcp *session, uint8_t number,
 							uint8_t *attrs);
diff --git a/android/avrcp.c b/android/avrcp.c
index 0995a06..add069b 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -724,39 +724,37 @@ static const struct avrcp_control_ind control_ind = {
 	.register_notification = handle_register_notification_cmd,
 };
 
-static gboolean register_notification_rsp(struct avctp *conn,
-					uint8_t code, uint8_t subunit,
-					uint8_t *operands, size_t operand_count,
-					void *user_data)
+static bool handle_register_notification_rsp(struct avrcp *session, int err,
+						uint8_t code, uint8_t event,
+						uint8_t *params,
+						void *user_data)
 {
 	struct avrcp_device *dev = user_data;
 	struct hal_ev_avrcp_volume_changed ev;
-	uint8_t *params;
 
-	if (code != AVC_CTYPE_INTERIM && code != AVC_CTYPE_CHANGED)
-		return FALSE;
-
-	if (operands == NULL || operand_count < 7)
-		return FALSE;
+	if (err < 0) {
+		error("AVRCP: %s", strerror(-err));
+		return false;
+	}
 
-	params = &operands[7];
+	if (code != AVC_CTYPE_INTERIM && code != AVC_CTYPE_CHANGED)
+		return false;
 
-	if (params == NULL || params[0] != AVRCP_EVENT_VOLUME_CHANGED)
-		return FALSE;
+	if (event != AVRCP_EVENT_VOLUME_CHANGED)
+		return false;
 
 	ev.type = code;
-	ev.volume = params[1] & 0x7F;
+	ev.volume = params[0] & 0x7f;
 
 	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
 					HAL_EV_AVRCP_VOLUME_CHANGED,
 					sizeof(ev), &ev);
 
 	if (code == AVC_CTYPE_INTERIM)
-		return TRUE;
+		return true;
 
-	avrcp_register_notification(dev->session, params[0], 0,
-					register_notification_rsp, dev);
-	return FALSE;
+	avrcp_register_notification(dev->session, event, 0);
+	return false;
 }
 
 static void handle_get_capabilities_rsp(struct avrcp *session, int err,
@@ -775,9 +773,7 @@ static void handle_get_capabilities_rsp(struct avrcp *session, int err,
 		if (events[i] != AVRCP_EVENT_VOLUME_CHANGED)
 			continue;
 
-		avrcp_register_notification(dev->session, events[i], 0,
-						register_notification_rsp,
-						dev);
+		avrcp_register_notification(dev->session, events[i], 0);
 		break;
 	}
 
@@ -786,6 +782,7 @@ static void handle_get_capabilities_rsp(struct avrcp *session, int err,
 
 static const struct avrcp_control_cfm control_cfm = {
 	.get_capabilities = handle_get_capabilities_rsp,
+	.register_notification = handle_register_notification_rsp,
 };
 
 static int avrcp_device_add_session(struct avrcp_device *dev, int fd,
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index a0b009a..5b259bd 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -524,8 +524,7 @@ static void test_client(gconstpointer data)
 
 	if (g_str_equal(context->data->test_name, "/TP/NFY/BV-01-C"))
 		avrcp_register_notification(context->session,
-						AVRCP_EVENT_STATUS_CHANGED, 0,
-						NULL, NULL);
+						AVRCP_EVENT_STATUS_CHANGED, 0);
 
 	if (g_str_equal(context->data->test_name, "/TP/BGN/BV-01-I"))
 		avrcp_send_passthrough(context->session, IEEEID_BTSIG,
-- 
1.8.5.3

--
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




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux