linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 BlueZ 1/6] android/avrcp-lib: Make avrcp_send_browsing_req to take struct iovec
@ 2014-04-11 13:58 Luiz Augusto von Dentz
  2014-04-11 13:58 ` [PATCH v2 BlueZ 2/6] android/avrcp-lib: Add checks in avrcp_get_item_attributes Luiz Augusto von Dentz
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2014-04-11 13:58 UTC (permalink / raw)
  To: linux-bluetooth

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

This makes it possible to pass data without copying.
---
v2: Remove unnecessary casts when assigning to iov_base and add patch 6/6

 android/avrcp-lib.c | 85 ++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 58 insertions(+), 27 deletions(-)

diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 3209023..999e8aa 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -795,27 +795,35 @@ static int avrcp_send_req(struct avrcp *session, uint8_t code, uint8_t subunit,
 }
 
 static int avrcp_send_browsing_req(struct avrcp *session, uint8_t pdu_id,
-					uint8_t *params, size_t params_len,
+					const struct iovec *iov, int iov_cnt,
 					avctp_browsing_rsp_cb func,
 					void *user_data)
 {
 	struct avrcp_browsing_header *pdu = (void *) session->tx_buf;
 	size_t len = sizeof(*pdu);
+	int i;
 
 	memset(pdu, 0, len);
 
 	pdu->pdu_id = pdu_id;
 
-	if (params_len > 0) {
-		len += params_len;
+	if (iov_cnt <= 0)
+		goto done;
+
+	for (i = 0; i < iov_cnt; i++) {
+		len += iov[i].iov_len;
 
 		if (len > session->tx_mtu)
 			return -ENOBUFS;
 
-		memcpy(pdu->params, params, params_len);
-		pdu->params_len = htons(params_len);
+		memcpy(&pdu->params[pdu->params_len], iov[i].iov_base,
+							iov[i].iov_len);
+		pdu->params_len += iov[i].iov_len;
 	}
 
+	pdu->params_len = htons(pdu->params_len);
+
+done:
 	return avctp_send_browsing_req(session->conn, session->tx_buf, len,
 							func, user_data);
 }
@@ -1707,13 +1715,16 @@ done:
 
 int avrcp_set_browsed_player(struct avrcp *session, uint16_t player_id)
 {
+	struct iovec iov;
 	uint8_t pdu[2];
 
 	put_be16(player_id, pdu);
 
+	iov.iov_base = pdu;
+	iov.iov_len = sizeof(pdu);
+
 	return avrcp_send_browsing_req(session, AVRCP_SET_BROWSED_PLAYER,
-					pdu, sizeof(pdu), set_browsed_rsp,
-					session);
+					&iov, 1, set_browsed_rsp, session);
 }
 
 static gboolean get_folder_items_rsp(struct avctp *conn,
@@ -1762,7 +1773,9 @@ int avrcp_get_folder_items(struct avrcp *session, uint8_t scope,
 				uint32_t start, uint32_t end, uint8_t number,
 				uint32_t *attrs)
 {
-	uint8_t pdu[10 + number * sizeof(uint32_t)];
+
+	struct iovec iov[2];
+	uint8_t pdu[10];
 	int i;
 
 	pdu[0] = scope;
@@ -1770,18 +1783,22 @@ int avrcp_get_folder_items(struct avrcp *session, uint8_t scope,
 	put_be32(end, &pdu[5]);
 	pdu[9] = number;
 
+	iov[0].iov_base = pdu;
+	iov[0].iov_len = sizeof(pdu);
+
 	if (!number)
-		goto done;
+		return avrcp_send_browsing_req(session, AVRCP_GET_FOLDER_ITEMS,
+						iov, 1, get_folder_items_rsp,
+						session);
 
 	for (i = 0; i < number; i++)
 		put_be32(attrs[i], &attrs[i]);
 
-	memcpy(&pdu[10], attrs, number * sizeof(*attrs));
+	iov[1].iov_base = attrs;
+	iov[1].iov_len = number * sizeof(*attrs);
 
-done:
 	return avrcp_send_browsing_req(session, AVRCP_GET_FOLDER_ITEMS,
-					pdu, sizeof(pdu),
-					get_folder_items_rsp, session);
+					iov, 2, get_folder_items_rsp, session);
 }
 
 static gboolean change_path_rsp(struct avctp *conn, uint8_t *operands,
@@ -1824,15 +1841,18 @@ done:
 int avrcp_change_path(struct avrcp *session, uint8_t direction, uint64_t uid,
 							uint16_t counter)
 {
+	struct iovec iov;
 	uint8_t pdu[11];
 
 	put_be16(counter, &pdu[0]);
 	pdu[2] = direction;
 	put_be64(uid, &pdu[3]);
 
+	iov.iov_base = pdu;
+	iov.iov_len = sizeof(pdu);
+
 	return avrcp_send_browsing_req(session, AVRCP_CHANGE_PATH,
-					pdu, sizeof(pdu),
-					change_path_rsp, session);
+					&iov, 1, change_path_rsp, session);
 }
 
 static gboolean get_item_attributes_rsp(struct avctp *conn, uint8_t *operands,
@@ -1874,7 +1894,8 @@ int avrcp_get_item_attributes(struct avrcp *session, uint8_t scope,
 				uint64_t uid, uint16_t counter, uint8_t number,
 				uint32_t *attrs)
 {
-	uint8_t pdu[12 + number * sizeof(uint32_t)];
+	struct iovec iov[2];
+	uint8_t pdu[12];
 	int i;
 
 	pdu[0] = scope;
@@ -1882,18 +1903,24 @@ int avrcp_get_item_attributes(struct avrcp *session, uint8_t scope,
 	put_be16(counter, &pdu[9]);
 	pdu[11] = number;
 
+	iov[0].iov_base = pdu;
+	iov[0].iov_len = sizeof(pdu);
+
 	if (!number)
-		goto done;
+		return avrcp_send_browsing_req(session,
+						AVRCP_GET_ITEM_ATTRIBUTES,
+						iov, 1, get_item_attributes_rsp,
+						session);
 
 	for (i = 0; i < number; i++)
 		put_be32(attrs[i], &attrs[i]);
 
-	memcpy(&pdu[12], attrs, number * sizeof(uint32_t));
+	iov[1].iov_base = attrs;
+	iov[1].iov_len = number * sizeof(*attrs);
 
-done:
 	return avrcp_send_browsing_req(session, AVRCP_GET_ITEM_ATTRIBUTES,
-					pdu, sizeof(pdu),
-					get_item_attributes_rsp, session);
+					iov, 2, get_item_attributes_rsp,
+					session);
 }
 
 static gboolean search_rsp(struct avctp *conn, uint8_t *operands,
@@ -1939,22 +1966,26 @@ done:
 
 int avrcp_search(struct avrcp *session, const char *string)
 {
-	uint8_t pdu[255];
+	struct iovec iov[2];
+	uint8_t pdu[4];
 	size_t len;
 
 	if (!string)
 		return -EINVAL;
 
-	len = strnlen(string, 255 - 4);
+	len = strnlen(string, UINT8_MAX);
 
 	put_be16(AVRCP_CHARSET_UTF8, &pdu[0]);
 	put_be16(len, &pdu[2]);
 
-	memcpy(&pdu[4], string, len);
-	len += 4;
+	iov[0].iov_base = pdu;
+	iov[0].iov_len = sizeof(pdu);
+
+	iov[1].iov_base = (void *) string;
+	iov[1].iov_len = len;
 
-	return avrcp_send_browsing_req(session, AVRCP_SEARCH,
-					pdu, len, search_rsp, session);
+	return avrcp_send_browsing_req(session, AVRCP_SEARCH, iov, 2,
+							search_rsp, session);
 }
 
 int avrcp_get_capabilities_rsp(struct avrcp *session, uint8_t transaction,
-- 
1.9.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 BlueZ 2/6] android/avrcp-lib: Add checks in avrcp_get_item_attributes
  2014-04-11 13:58 [PATCH v2 BlueZ 1/6] android/avrcp-lib: Make avrcp_send_browsing_req to take struct iovec Luiz Augusto von Dentz
@ 2014-04-11 13:58 ` Luiz Augusto von Dentz
  2014-04-11 13:58 ` [PATCH v2 BlueZ 3/6] android/avrcp-lib: Make avrcp_send_req to take struct iovec Luiz Augusto von Dentz
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2014-04-11 13:58 UTC (permalink / raw)
  To: linux-bluetooth

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

This adds checks for number of attributes is within the valid range and
if the data pointer is valid.
---
 android/avrcp-lib.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 999e8aa..3d27856 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -1912,8 +1912,15 @@ int avrcp_get_item_attributes(struct avrcp *session, uint8_t scope,
 						iov, 1, get_item_attributes_rsp,
 						session);
 
-	for (i = 0; i < number; i++)
+	if (number > AVRCP_MEDIA_ATTRIBUTE_LAST)
+		return -EINVAL;
+
+	for (i = 0; i < number; i++) {
+		if (attrs[i] > AVRCP_MEDIA_ATTRIBUTE_LAST ||
+				attrs[i] == AVRCP_MEDIA_ATTRIBUTE_ILLEGAL)
+			return -EINVAL;
 		put_be32(attrs[i], &attrs[i]);
+	}
 
 	iov[1].iov_base = attrs;
 	iov[1].iov_len = number * sizeof(*attrs);
-- 
1.9.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 BlueZ 3/6] android/avrcp-lib: Make avrcp_send_req to take struct iovec
  2014-04-11 13:58 [PATCH v2 BlueZ 1/6] android/avrcp-lib: Make avrcp_send_browsing_req to take struct iovec Luiz Augusto von Dentz
  2014-04-11 13:58 ` [PATCH v2 BlueZ 2/6] android/avrcp-lib: Add checks in avrcp_get_item_attributes Luiz Augusto von Dentz
@ 2014-04-11 13:58 ` Luiz Augusto von Dentz
  2014-04-11 13:58 ` [PATCH v2 BlueZ 4/6] android/avctp: Make avctp_send_browsing_req " Luiz Augusto von Dentz
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2014-04-11 13:58 UTC (permalink / raw)
  To: linux-bluetooth

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

This makes it possible to pass data without copying.
---
 android/avrcp-lib.c | 126 ++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 88 insertions(+), 38 deletions(-)

diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 3d27856..75186bd 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -767,12 +767,13 @@ static int parse_browsing_status(struct avrcp_browsing_header *pdu)
 }
 
 static int avrcp_send_req(struct avrcp *session, uint8_t code, uint8_t subunit,
-					uint8_t pdu_id, uint8_t *params,
-					size_t params_len, avctp_rsp_cb func,
+					uint8_t pdu_id, const struct iovec *iov,
+					int iov_cnt, avctp_rsp_cb func,
 					void *user_data)
 {
 	struct avrcp_header *pdu = (void *) session->tx_buf;
 	size_t len = sizeof(*pdu);
+	int i;
 
 	memset(pdu, 0, len);
 
@@ -780,16 +781,23 @@ static int avrcp_send_req(struct avrcp *session, uint8_t code, uint8_t subunit,
 	pdu->pdu_id = pdu_id;
 	pdu->packet_type = AVRCP_PACKET_TYPE_SINGLE;
 
-	if (params_len > 0) {
-		len += params_len;
+	if (iov_cnt <= 0)
+		goto done;
+
+	for (i = 0; i < iov_cnt; i++) {
+		len += iov[i].iov_len;
 
 		if (len > session->tx_mtu)
 			return -ENOBUFS;
 
-		memcpy(pdu->params, params, params_len);
-		pdu->params_len = htons(params_len);
+		memcpy(&pdu->params[pdu->params_len], iov[i].iov_base,
+							iov[i].iov_len);
+		pdu->params_len += iov[i].iov_len;
 	}
 
+	pdu->params_len = htons(pdu->params_len);
+
+done:
 	return avctp_send_vendordep_req(session->conn, code, subunit,
 					session->tx_buf, len, func, user_data);
 }
@@ -887,9 +895,14 @@ done:
 
 int avrcp_get_capabilities(struct avrcp *session, uint8_t param)
 {
+	struct iovec iov;
+
+	iov.iov_base = &param;
+	iov.iov_len = sizeof(param);
+
 	return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
-				AVRCP_GET_CAPABILITIES, &param, sizeof(param),
-				get_capabilities_rsp, session);
+					AVRCP_GET_CAPABILITIES, &iov, 1,
+					get_capabilities_rsp, session);
 }
 
 static gboolean register_notification_rsp(struct avctp *conn,
@@ -983,15 +996,18 @@ done:
 int avrcp_register_notification(struct avrcp *session, uint8_t event,
 							uint32_t interval)
 {
-	uint8_t params[5];
+	struct iovec iov;
+	uint8_t pdu[5];
 
-	params[0] = event;
-	put_be32(interval, &params[1]);
+	pdu[0] = event;
+	put_be32(interval, &pdu[1]);
+
+	iov.iov_base = pdu;
+	iov.iov_len = sizeof(pdu);
 
 	return avrcp_send_req(session, AVC_CTYPE_NOTIFY, AVC_SUBUNIT_PANEL,
-					AVRCP_REGISTER_NOTIFICATION,
-					params, sizeof(params),
-					register_notification_rsp, session);
+				AVRCP_REGISTER_NOTIFICATION, &iov, 1,
+				register_notification_rsp, session);
 }
 
 static gboolean list_attributes_rsp(struct avctp *conn,
@@ -1136,8 +1152,13 @@ done:
 int avrcp_get_player_attribute_text(struct avrcp *session, uint8_t number,
 								uint8_t *attrs)
 {
+	struct iovec iov;
+
+	iov.iov_base = attrs;
+	iov.iov_len = number;
+
 	return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
-				AVRCP_GET_PLAYER_ATTRIBUTE_TEXT, attrs, number,
+				AVRCP_GET_PLAYER_ATTRIBUTE_TEXT, &iov, 1,
 				get_attribute_text_rsp, session);
 }
 
@@ -1184,9 +1205,14 @@ done:
 
 int avrcp_list_player_values(struct avrcp *session, uint8_t attr)
 {
+	struct iovec iov;
+
+	iov.iov_base = &attr;
+	iov.iov_len = sizeof(attr);
+
 	return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
-				AVRCP_LIST_PLAYER_VALUES, &attr, sizeof(attr),
-				list_values_rsp, session);
+					AVRCP_LIST_PLAYER_VALUES, &iov, 1,
+					list_values_rsp, session);
 }
 
 static gboolean get_value_text_rsp(struct avctp *conn,
@@ -1230,9 +1256,20 @@ done:
 int avrcp_get_player_value_text(struct avrcp *session, uint8_t attr,
 					uint8_t number, uint8_t *values)
 {
+	struct iovec iov[2];
+
+	if (!number)
+		return -EINVAL;
+
+	iov[0].iov_base = &attr;
+	iov[0].iov_len = sizeof(attr);
+
+	iov[1].iov_base = values;
+	iov[0].iov_len = number;
+
 	return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
-				AVRCP_GET_PLAYER_VALUE_TEXT, &attr,
-				sizeof(attr), get_value_text_rsp, session);
+					AVRCP_GET_PLAYER_VALUE_TEXT, iov, 2,
+					get_value_text_rsp, session);
 }
 
 static int parse_value(struct avrcp_header *pdu, uint8_t *number,
@@ -1304,22 +1341,20 @@ int avrcp_get_current_player_value(struct avrcp *session, uint8_t number,
 							uint8_t *attrs)
 
 {
-	uint8_t pdu[AVRCP_ATTRIBUTE_LAST + 1];
+	struct iovec iov[2];
 
 	if (number > AVRCP_ATTRIBUTE_LAST)
 		return -EINVAL;
 
-	if (number > 0) {
-		if (!attrs)
-			return -EINVAL;
+	iov[0].iov_base = &number;
+	iov[0].iov_len = sizeof(number);
 
-		pdu[0] = number;
-		memcpy(&pdu[1], attrs, number);
-	}
+	iov[1].iov_base = attrs;
+	iov[1].iov_len = number;
 
 	return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
-				AVRCP_GET_CURRENT_PLAYER_VALUE, pdu,
-				number + 1, get_value_rsp, session);
+				AVRCP_GET_CURRENT_PLAYER_VALUE, iov, 2,
+				get_value_rsp, session);
 }
 
 static gboolean set_value_rsp(struct avctp *conn,
@@ -1363,6 +1398,7 @@ done:
 int avrcp_set_player_value(struct avrcp *session, uint8_t number,
 					uint8_t *attrs, uint8_t *values)
 {
+	struct iovec iov;
 	uint8_t pdu[2 * AVRCP_ATTRIBUTE_LAST + 1];
 	int i;
 
@@ -1376,8 +1412,11 @@ int avrcp_set_player_value(struct avrcp *session, uint8_t number,
 		pdu[i * 2 + 2] = values[i];
 	}
 
+	iov.iov_base = pdu;
+	iov.iov_len = 1 + number * 2;
+
 	return avrcp_send_req(session, AVC_CTYPE_CONTROL, AVC_SUBUNIT_PANEL,
-				AVRCP_SET_PLAYER_VALUE, pdu, 2 * number + 1,
+				AVRCP_SET_PLAYER_VALUE, &iov, 1,
 				set_value_rsp, session);
 }
 
@@ -1477,10 +1516,14 @@ done:
 
 int avrcp_set_volume(struct avrcp *session, uint8_t volume)
 {
+	struct iovec iov;
+
+	iov.iov_base = &volume;
+	iov.iov_len = sizeof(volume);
+
 	return avrcp_send_req(session, AVC_CTYPE_CONTROL, AVC_SUBUNIT_PANEL,
-						AVRCP_SET_ABSOLUTE_VOLUME,
-						&volume, sizeof(volume),
-						set_volume_rsp, session);
+				AVRCP_SET_ABSOLUTE_VOLUME, &iov, 1,
+				set_volume_rsp, session);
 }
 
 static int parse_attribute_list(uint8_t *params, uint16_t params_len,
@@ -1596,13 +1639,17 @@ done:
 
 int avrcp_get_element_attributes(struct avrcp *session)
 {
+	struct iovec iov;
 	uint8_t pdu[9];
 
 	/* This returns all attributes */
 	memset(pdu, 0, sizeof(pdu));
 
+	iov.iov_base = pdu;
+	iov.iov_len = sizeof(pdu);
+
 	return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
-				AVRCP_GET_ELEMENT_ATTRIBUTES, pdu, sizeof(pdu),
+				AVRCP_GET_ELEMENT_ATTRIBUTES, &iov, 1,
 				get_element_attributes_rsp, session);
 }
 
@@ -1637,14 +1684,17 @@ done:
 
 int avrcp_set_addressed_player(struct avrcp *session, uint16_t player_id)
 {
-	uint8_t params[2];
+	struct iovec iov;
+	uint8_t pdu[2];
 
-	put_be16(player_id, params);
+	put_be16(player_id, pdu);
+
+	iov.iov_base = pdu;
+	iov.iov_len = sizeof(pdu);
 
 	return avrcp_send_req(session, AVC_CTYPE_CONTROL, AVC_SUBUNIT_PANEL,
-				AVRCP_SET_ADDRESSED_PLAYER, params,
-				sizeof(params), set_addressed_rsp,
-				session);
+				AVRCP_SET_ADDRESSED_PLAYER, &iov, 1,
+				set_addressed_rsp, session);
 }
 
 static gboolean set_browsed_rsp(struct avctp *conn, uint8_t *operands,
-- 
1.9.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 BlueZ 4/6] android/avctp: Make avctp_send_browsing_req to take struct iovec
  2014-04-11 13:58 [PATCH v2 BlueZ 1/6] android/avrcp-lib: Make avrcp_send_browsing_req to take struct iovec Luiz Augusto von Dentz
  2014-04-11 13:58 ` [PATCH v2 BlueZ 2/6] android/avrcp-lib: Add checks in avrcp_get_item_attributes Luiz Augusto von Dentz
  2014-04-11 13:58 ` [PATCH v2 BlueZ 3/6] android/avrcp-lib: Make avrcp_send_req to take struct iovec Luiz Augusto von Dentz
@ 2014-04-11 13:58 ` Luiz Augusto von Dentz
  2014-04-11 13:58 ` [PATCH v2 BlueZ 5/6] android/avctp: Make avctp_send_vendor_req " Luiz Augusto von Dentz
  2014-04-11 13:58 ` [PATCH v2 BlueZ 6/6] android/avctp: Make avctp_send_vendor " Luiz Augusto von Dentz
  4 siblings, 0 replies; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2014-04-11 13:58 UTC (permalink / raw)
  To: linux-bluetooth

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

This makes it possible to pass data without copying.
---
 android/avctp.c     | 65 +++++++++++++++++++++++++++++++++--------------------
 android/avctp.h     |  2 +-
 android/avrcp-lib.c | 31 ++++++++++---------------
 3 files changed, 54 insertions(+), 44 deletions(-)

diff --git a/android/avctp.c b/android/avctp.c
index ed91810..56d4f4a 100644
--- a/android/avctp.c
+++ b/android/avctp.c
@@ -123,8 +123,8 @@ struct avctp_control_req {
 
 struct avctp_browsing_req {
 	struct avctp_pending_req *p;
-	uint8_t *operands;
-	uint16_t operand_count;
+	struct iovec *iov;
+	int iov_cnt;
 	avctp_browsing_rsp_cb func;
 	void *user_data;
 };
@@ -552,35 +552,39 @@ static int avctp_send(struct avctp_channel *control, uint8_t transaction,
 
 static int avctp_browsing_send(struct avctp_channel *browsing,
 				uint8_t transaction, uint8_t cr,
-				uint8_t *operands, size_t operand_count)
+				const struct iovec *iov, int iov_cnt)
 {
-	struct avctp_header *avctp;
+	struct avctp_header avctp;
 	struct msghdr msg;
-	struct iovec iov[2];
+	struct iovec pdu[iov_cnt + 1];
 	int sk, err = 0;
+	int i;
+	size_t len = sizeof(avctp);
 
-	iov[0].iov_base = browsing->buffer;
-	iov[0].iov_len  = sizeof(*avctp);
-	iov[1].iov_base = operands;
-	iov[1].iov_len  = operand_count;
+	for (i = 0; i < iov_cnt; i++) {
+		pdu[i + 1].iov_base = iov[i].iov_base;
+		pdu[i + 1].iov_len  = iov[i].iov_len;
+		len += iov[i].iov_len;
+	}
 
-	if (browsing->omtu < (iov[0].iov_len + iov[1].iov_len))
+	pdu[0].iov_base = &avctp;
+	pdu[0].iov_len  = sizeof(avctp);
+
+	if (browsing->omtu < len)
 		return -EOVERFLOW;
 
 	sk = g_io_channel_unix_get_fd(browsing->io);
 
-	memset(browsing->buffer, 0, iov[0].iov_len);
-
-	avctp = (void *) browsing->buffer;
+	memset(&avctp, 0, sizeof(avctp));
 
-	avctp->transaction = transaction;
-	avctp->packet_type = AVCTP_PACKET_SINGLE;
-	avctp->cr = cr;
-	avctp->pid = htons(AV_REMOTE_SVCLASS_ID);
+	avctp.transaction = transaction;
+	avctp.packet_type = AVCTP_PACKET_SINGLE;
+	avctp.cr = cr;
+	avctp.pid = htons(AV_REMOTE_SVCLASS_ID);
 
 	memset(&msg, 0, sizeof(msg));
-	msg.msg_iov = iov;
-	msg.msg_iovlen = 2;
+	msg.msg_iov = pdu;
+	msg.msg_iovlen = iov_cnt + 1;
 
 	if (sendmsg(sk, &msg, 0) < 0)
 		err = -errno;
@@ -610,6 +614,7 @@ static void browsing_req_destroy(void *data)
 	struct avctp_browsing_req *req = data;
 	struct avctp_pending_req *p = req->p;
 	struct avctp *session = p->chan->session;
+	int i;
 
 	if (p->err == 0 || req->func == NULL)
 		goto done;
@@ -617,7 +622,10 @@ static void browsing_req_destroy(void *data)
 	req->func(session, NULL, 0, req->user_data);
 
 done:
-	g_free(req->operands);
+	for (i = 0; i < req->iov_cnt; i++)
+		g_free(req->iov[i].iov_base);
+
+	g_free(req->iov);
 	g_free(req);
 }
 
@@ -656,7 +664,7 @@ static int process_browsing(void *data)
 	struct avctp_pending_req *p = req->p;
 
 	return avctp_browsing_send(p->chan, p->transaction, AVCTP_COMMAND,
-					req->operands, req->operand_count);
+						req->iov, req->iov_cnt);
 }
 
 static gboolean process_queue(void *user_data)
@@ -1125,20 +1133,29 @@ static int avctp_send_req(struct avctp *session, uint8_t code,
 }
 
 int avctp_send_browsing_req(struct avctp *session,
-				uint8_t *operands, size_t operand_count,
+				const struct iovec *iov, int iov_cnt,
 				avctp_browsing_rsp_cb func, void *user_data)
 {
 	struct avctp_channel *browsing = session->browsing;
 	struct avctp_pending_req *p;
 	struct avctp_browsing_req *req;
+	struct iovec *pdu;
+	int i;
 
 	if (browsing == NULL)
 		return -ENOTCONN;
 
+	pdu = g_new0(struct iovec, iov_cnt);
+
+	for (i = 0; i < iov_cnt; i++) {
+		pdu[i].iov_len = iov[i].iov_len;
+		pdu[i].iov_base = g_memdup(iov[i].iov_base, iov[i].iov_len);
+	}
+
 	req = g_new0(struct avctp_browsing_req, 1);
 	req->func = func;
-	req->operands = g_memdup(operands, operand_count);
-	req->operand_count = operand_count;
+	req->iov = pdu;
+	req->iov_cnt = iov_cnt;
 	req->user_data = user_data;
 
 	p = pending_create(browsing, process_browsing, req,
diff --git a/android/avctp.h b/android/avctp.h
index 98c1142..6e6bfad 100644
--- a/android/avctp.h
+++ b/android/avctp.h
@@ -174,5 +174,5 @@ int avctp_send_vendordep_req(struct avctp *session, uint8_t code,
 					size_t operand_count,
 					avctp_rsp_cb func, void *user_data);
 int avctp_send_browsing_req(struct avctp *session,
-				uint8_t *operands, size_t operand_count,
+				const struct iovec *iov, int iov_cnt,
 				avctp_browsing_rsp_cb func, void *user_data);
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 75186bd..22a68f7 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -807,32 +807,25 @@ static int avrcp_send_browsing_req(struct avrcp *session, uint8_t pdu_id,
 					avctp_browsing_rsp_cb func,
 					void *user_data)
 {
-	struct avrcp_browsing_header *pdu = (void *) session->tx_buf;
-	size_t len = sizeof(*pdu);
+	struct iovec pdu[iov_cnt + 1];
+	struct avrcp_browsing_header hdr;
 	int i;
 
-	memset(pdu, 0, len);
-
-	pdu->pdu_id = pdu_id;
-
-	if (iov_cnt <= 0)
-		goto done;
+	memset(&hdr, 0, sizeof(hdr));
 
 	for (i = 0; i < iov_cnt; i++) {
-		len += iov[i].iov_len;
-
-		if (len > session->tx_mtu)
-			return -ENOBUFS;
-
-		memcpy(&pdu->params[pdu->params_len], iov[i].iov_base,
-							iov[i].iov_len);
-		pdu->params_len += iov[i].iov_len;
+		pdu[i + 1].iov_base = iov[i].iov_base;
+		pdu[i + 1].iov_len = iov[i].iov_len;
+		hdr.params_len += iov[i].iov_len;
 	}
 
-	pdu->params_len = htons(pdu->params_len);
+	hdr.pdu_id = pdu_id;
+	hdr.params_len = htons(hdr.params_len);
 
-done:
-	return avctp_send_browsing_req(session->conn, session->tx_buf, len,
+	pdu[0].iov_base = &hdr;
+	pdu[0].iov_len = sizeof(hdr);
+
+	return avctp_send_browsing_req(session->conn, pdu, iov_cnt + 1,
 							func, user_data);
 }
 
-- 
1.9.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 BlueZ 5/6] android/avctp: Make avctp_send_vendor_req to take struct iovec
  2014-04-11 13:58 [PATCH v2 BlueZ 1/6] android/avrcp-lib: Make avrcp_send_browsing_req to take struct iovec Luiz Augusto von Dentz
                   ` (2 preceding siblings ...)
  2014-04-11 13:58 ` [PATCH v2 BlueZ 4/6] android/avctp: Make avctp_send_browsing_req " Luiz Augusto von Dentz
@ 2014-04-11 13:58 ` Luiz Augusto von Dentz
  2014-04-11 13:58 ` [PATCH v2 BlueZ 6/6] android/avctp: Make avctp_send_vendor " Luiz Augusto von Dentz
  4 siblings, 0 replies; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2014-04-11 13:58 UTC (permalink / raw)
  To: linux-bluetooth

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

This makes it possible to pass data without copying.
---
 android/avctp.c     | 152 +++++++++++++++++++++++++++++++---------------------
 android/avctp.h     |   7 ++-
 android/avrcp-lib.c |  45 +++++++---------
 unit/test-avctp.c   |   2 +-
 4 files changed, 114 insertions(+), 92 deletions(-)

diff --git a/android/avctp.c b/android/avctp.c
index 56d4f4a..62c41fd 100644
--- a/android/avctp.c
+++ b/android/avctp.c
@@ -115,8 +115,8 @@ struct avctp_control_req {
 	uint8_t code;
 	uint8_t subunit;
 	uint8_t op;
-	uint8_t *operands;
-	uint16_t operand_count;
+	struct iovec *iov;
+	int iov_cnt;
 	avctp_rsp_cb func;
 	void *user_data;
 };
@@ -508,41 +508,50 @@ static void avctp_channel_destroy(struct avctp_channel *chan)
 static int avctp_send(struct avctp_channel *control, uint8_t transaction,
 				uint8_t cr, uint8_t code,
 				uint8_t subunit, uint8_t opcode,
-				uint8_t *operands, size_t operand_count)
+				const struct iovec *iov, int iov_cnt)
 {
-	struct avctp_header *avctp;
-	struct avc_header *avc;
+	struct avctp_header avctp;
+	struct avc_header avc;
 	struct msghdr msg;
-	struct iovec iov[2];
 	int sk, err = 0;
+	struct iovec pdu[iov_cnt + 2];
+	int i;
+	size_t len = sizeof(avctp) + sizeof(avc);
+
+	DBG("");
+
+	pdu[0].iov_base = &avctp;
+	pdu[0].iov_len  = sizeof(avctp);
+	pdu[1].iov_base = &avc;
+	pdu[1].iov_len  = sizeof(avc);
 
-	iov[0].iov_base = control->buffer;
-	iov[0].iov_len  = sizeof(*avctp) + sizeof(*avc);
-	iov[1].iov_base = operands;
-	iov[1].iov_len  = operand_count;
+	for (i = 0; i < iov_cnt; i++) {
+		pdu[i + 2].iov_base = iov[i].iov_base;
+		pdu[i + 2].iov_len  = iov[i].iov_len;
+		len += iov[i].iov_len;
+	}
 
-	if (control->omtu < (iov[0].iov_len + iov[1].iov_len))
+	if (control->omtu < len)
 		return -EOVERFLOW;
 
 	sk = g_io_channel_unix_get_fd(control->io);
 
-	memset(control->buffer, 0, iov[0].iov_len);
+	memset(&avctp, 0, sizeof(avctp));
 
-	avctp = (void *) control->buffer;
-	avc = (void *) avctp + sizeof(*avctp);
+	avctp.transaction = transaction;
+	avctp.packet_type = AVCTP_PACKET_SINGLE;
+	avctp.cr = cr;
+	avctp.pid = htons(AV_REMOTE_SVCLASS_ID);
 
-	avctp->transaction = transaction;
-	avctp->packet_type = AVCTP_PACKET_SINGLE;
-	avctp->cr = cr;
-	avctp->pid = htons(AV_REMOTE_SVCLASS_ID);
+	memset(&avc, 0, sizeof(avc));
 
-	avc->code = code;
-	avc->subunit_type = subunit;
-	avc->opcode = opcode;
+	avc.code = code;
+	avc.subunit_type = subunit;
+	avc.opcode = opcode;
 
 	memset(&msg, 0, sizeof(msg));
-	msg.msg_iov = iov;
-	msg.msg_iovlen = 2;
+	msg.msg_iov = pdu;
+	msg.msg_iovlen = iov_cnt + 2;
 
 	if (sendmsg(sk, &msg, 0) < 0)
 		err = -errno;
@@ -597,6 +606,7 @@ static void control_req_destroy(void *data)
 	struct avctp_control_req *req = data;
 	struct avctp_pending_req *p = req->p;
 	struct avctp *session = p->chan->session;
+	int i;
 
 	if (p->err == 0 || req->func == NULL)
 		goto done;
@@ -605,7 +615,10 @@ static void control_req_destroy(void *data)
 							req->user_data);
 
 done:
-	g_free(req->operands);
+	for (i = 0; i < req->iov_cnt; i++)
+		g_free(req->iov[i].iov_base);
+
+	g_free(req->iov);
 	g_free(req);
 }
 
@@ -654,8 +667,7 @@ static int process_control(void *data)
 	struct avctp_pending_req *p = req->p;
 
 	return avctp_send(p->chan, p->transaction, AVCTP_COMMAND, req->code,
-					req->subunit, req->op,
-					req->operands, req->operand_count);
+				req->subunit, req->op, req->iov, req->iov_cnt);
 }
 
 static int process_browsing(void *data)
@@ -1099,25 +1111,33 @@ done:
 	return p;
 }
 
-static int avctp_send_req(struct avctp *session, uint8_t code,
-				uint8_t subunit, uint8_t opcode,
-				uint8_t *operands, size_t operand_count,
-				avctp_rsp_cb func, void *user_data)
+static int avctp_send_req(struct avctp *session, uint8_t code, uint8_t subunit,
+			uint8_t opcode, const struct iovec *iov, int iov_cnt,
+			avctp_rsp_cb func, void *user_data)
 {
 	struct avctp_channel *control = session->control;
 	struct avctp_pending_req *p;
 	struct avctp_control_req *req;
+	struct iovec *pdu;
+	int i;
 
 	if (control == NULL)
 		return -ENOTCONN;
 
+	pdu = g_new0(struct iovec, iov_cnt);
+
+	for (i = 0; i < iov_cnt; i++) {
+		pdu[i].iov_len = iov[i].iov_len;
+		pdu[i].iov_base = g_memdup(iov[i].iov_base, iov[i].iov_len);
+	}
+
 	req = g_new0(struct avctp_control_req, 1);
 	req->code = code;
 	req->subunit = subunit;
 	req->op = opcode;
 	req->func = func;
-	req->operands = g_memdup(operands, operand_count);
-	req->operand_count = operand_count;
+	req->iov = pdu;
+	req->iov_cnt = iov_cnt;
 	req->user_data = user_data;
 
 	p = pending_create(control, process_control, req, control_req_destroy);
@@ -1190,53 +1210,61 @@ static const char *op2str(uint8_t op)
 static int avctp_passthrough_press(struct avctp *session, uint8_t op,
 					uint8_t *params, size_t params_len)
 {
-	uint8_t operands[7];
-	size_t len;
+	struct iovec iov[2];
+	int iov_cnt;
+	uint8_t operands[2];
+
+	DBG("%s", op2str(op));
 
-	DBG("op 0x%02x %s params_len %zd", op, op2str(op), params_len);
+	iov[0].iov_base = operands;
+	iov[0].iov_len = sizeof(operands);
 
 	/* Button pressed */
 	operands[0] = op & 0x7f;
 
-	if (op == AVC_VENDOR_UNIQUE && params &&
-				params_len == 5) {
-		memcpy(&operands[2], params, params_len);
-		len = params_len + 2;
+	if (params_len > 0) {
+		iov[1].iov_base = params;
+		iov[1].iov_len = params_len;
+		iov_cnt = 2;
 		operands[1] = params_len;
 	} else {
-		len = 2;
+		iov_cnt = 1;
 		operands[1] = 0;
 	}
 
 	return avctp_send_req(session, AVC_CTYPE_CONTROL,
 				AVC_SUBUNIT_PANEL, AVC_OP_PASSTHROUGH,
-				operands, len,
-				avctp_passthrough_rsp, NULL);
+				iov, iov_cnt, avctp_passthrough_rsp, NULL);
 }
 
 static int avctp_passthrough_release(struct avctp *session, uint8_t op,
 					uint8_t *params, size_t params_len)
 {
-	uint8_t operands[7];
-	size_t len;
+	struct iovec iov[2];
+	int iov_cnt;
+	uint8_t operands[2];
 
 	DBG("%s", op2str(op));
 
+	iov[0].iov_base = operands;
+	iov[0].iov_len = sizeof(operands);
+
 	/* Button released */
 	operands[0] = op | 0x80;
-	operands[1] = 0;
 
-	if (op == AVC_VENDOR_UNIQUE && params &&
-				params_len > sizeof(operands) - 2) {
-		memcpy(&operands[2], params, params_len);
-		len = params_len;
-	} else
-		len = 2;
+	if (params_len > 0) {
+		iov[1].iov_base = params;
+		iov[1].iov_len = params_len;
+		iov_cnt = 2;
+		operands[1] = params_len;
+	} else {
+		iov_cnt = 1;
+		operands[1] = 0;
+	}
 
 	return avctp_send_req(session, AVC_CTYPE_CONTROL,
 				AVC_SUBUNIT_PANEL, AVC_OP_PASSTHROUGH,
-				operands, len,
-				NULL, NULL);
+				iov, iov_cnt, NULL, NULL);
 }
 
 static gboolean repeat_timeout(gpointer user_data)
@@ -1322,27 +1350,29 @@ int avctp_send_passthrough(struct avctp *session, uint8_t op, uint8_t *params,
 	return avctp_passthrough_press(session, op, params, params_len);
 }
 
-int avctp_send_vendordep(struct avctp *session, uint8_t transaction,
+int avctp_send_vendor(struct avctp *session, uint8_t transaction,
 				uint8_t code, uint8_t subunit,
 				uint8_t *operands, size_t operand_count)
 {
 	struct avctp_channel *control = session->control;
+	struct iovec iov;
 
 	if (control == NULL)
 		return -ENOTCONN;
 
+	iov.iov_base = operands;
+	iov.iov_len = operand_count;
+
 	return avctp_send(control, transaction, AVCTP_RESPONSE, code, subunit,
-					AVC_OP_VENDORDEP, operands, operand_count);
+						AVC_OP_VENDORDEP, &iov, 1);
 }
 
-int avctp_send_vendordep_req(struct avctp *session, uint8_t code,
-					uint8_t subunit, uint8_t *operands,
-					size_t operand_count,
+int avctp_send_vendor_req(struct avctp *session, uint8_t code, uint8_t subunit,
+					const struct iovec *iov, int iov_cnt,
 					avctp_rsp_cb func, void *user_data)
 {
-	return avctp_send_req(session, code, subunit, AVC_OP_VENDORDEP,
-						operands, operand_count,
-						func, user_data);
+	return avctp_send_req(session, code, subunit, AVC_OP_VENDORDEP, iov,
+						iov_cnt, func, user_data);
 }
 
 unsigned int avctp_register_passthrough_handler(struct avctp *session,
diff --git a/android/avctp.h b/android/avctp.h
index 6e6bfad..1b15398 100644
--- a/android/avctp.h
+++ b/android/avctp.h
@@ -166,12 +166,11 @@ bool avctp_unregister_browsing_pdu_handler(struct avctp *session,
 
 int avctp_send_passthrough(struct avctp *session, uint8_t op, uint8_t *params,
 							size_t params_len);
-int avctp_send_vendordep(struct avctp *session, uint8_t transaction,
+int avctp_send_vendor(struct avctp *session, uint8_t transaction,
 				uint8_t code, uint8_t subunit,
 				uint8_t *operands, size_t operand_count);
-int avctp_send_vendordep_req(struct avctp *session, uint8_t code,
-					uint8_t subunit, uint8_t *operands,
-					size_t operand_count,
+int avctp_send_vendor_req(struct avctp *session, uint8_t code, uint8_t subunit,
+					const struct iovec *iov, int iov_cnt,
 					avctp_rsp_cb func, void *user_data);
 int avctp_send_browsing_req(struct avctp *session,
 				const struct iovec *iov, int iov_cnt,
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 22a68f7..e2bba11 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -724,7 +724,7 @@ int avrcp_send(struct avrcp *session, uint8_t transaction, uint8_t code,
 		pdu->params_len = htons(params_len);
 	}
 
-	return avctp_send_vendordep(session->conn, transaction, code, subunit,
+	return avctp_send_vendor(session->conn, transaction, code, subunit,
 							session->tx_buf, len);
 }
 
@@ -771,35 +771,28 @@ static int avrcp_send_req(struct avrcp *session, uint8_t code, uint8_t subunit,
 					int iov_cnt, avctp_rsp_cb func,
 					void *user_data)
 {
-	struct avrcp_header *pdu = (void *) session->tx_buf;
-	size_t len = sizeof(*pdu);
+	struct iovec pdu[iov_cnt + 1];
+	struct avrcp_header hdr;
 	int i;
 
-	memset(pdu, 0, len);
-
-	hton24(pdu->company_id, IEEEID_BTSIG);
-	pdu->pdu_id = pdu_id;
-	pdu->packet_type = AVRCP_PACKET_TYPE_SINGLE;
+	memset(&hdr, 0, sizeof(hdr));
 
-	if (iov_cnt <= 0)
-		goto done;
+	pdu[0].iov_base = &hdr;
+	pdu[0].iov_len = sizeof(hdr);
 
 	for (i = 0; i < iov_cnt; i++) {
-		len += iov[i].iov_len;
-
-		if (len > session->tx_mtu)
-			return -ENOBUFS;
-
-		memcpy(&pdu->params[pdu->params_len], iov[i].iov_base,
-							iov[i].iov_len);
-		pdu->params_len += iov[i].iov_len;
+		pdu[i + 1].iov_base = iov[i].iov_base;
+		pdu[i + 1].iov_len = iov[i].iov_len;
+		hdr.params_len += iov[i].iov_len;
 	}
 
-	pdu->params_len = htons(pdu->params_len);
+	hton24(hdr.company_id, IEEEID_BTSIG);
+	hdr.pdu_id = pdu_id;
+	hdr.packet_type = AVRCP_PACKET_TYPE_SINGLE;
+	hdr.params_len = htons(hdr.params_len);
 
-done:
-	return avctp_send_vendordep_req(session->conn, code, subunit,
-					session->tx_buf, len, func, user_data);
+	return avctp_send_vendor_req(session->conn, code, subunit, pdu,
+						iov_cnt + 1, func, user_data);
 }
 
 static int avrcp_send_browsing_req(struct avrcp *session, uint8_t pdu_id,
@@ -1409,8 +1402,8 @@ int avrcp_set_player_value(struct avrcp *session, uint8_t number,
 	iov.iov_len = 1 + number * 2;
 
 	return avrcp_send_req(session, AVC_CTYPE_CONTROL, AVC_SUBUNIT_PANEL,
-				AVRCP_SET_PLAYER_VALUE, &iov, 1,
-				set_value_rsp, session);
+					AVRCP_SET_PLAYER_VALUE, &iov, 1,
+					set_value_rsp, session);
 }
 
 static gboolean get_play_status_rsp(struct avctp *conn,
@@ -1686,8 +1679,8 @@ int avrcp_set_addressed_player(struct avrcp *session, uint16_t player_id)
 	iov.iov_len = sizeof(pdu);
 
 	return avrcp_send_req(session, AVC_CTYPE_CONTROL, AVC_SUBUNIT_PANEL,
-				AVRCP_SET_ADDRESSED_PLAYER, &iov, 1,
-				set_addressed_rsp, session);
+					AVRCP_SET_ADDRESSED_PLAYER, &iov, 1,
+					set_addressed_rsp, session);
 }
 
 static gboolean set_browsed_rsp(struct avctp *conn, uint8_t *operands,
diff --git a/unit/test-avctp.c b/unit/test-avctp.c
index 0759731..8f7d5ad 100644
--- a/unit/test-avctp.c
+++ b/unit/test-avctp.c
@@ -264,7 +264,7 @@ static void test_client(gconstpointer data)
 {
 	struct context *context = create_context(0x0100, data);
 
-	avctp_send_vendordep_req(context->session, AVC_CTYPE_CONTROL, 0, NULL,
+	avctp_send_vendor_req(context->session, AVC_CTYPE_CONTROL, 0, NULL,
 						0, handler_response, context);
 
 	execute_context(context);
-- 
1.9.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 BlueZ 6/6] android/avctp: Make avctp_send_vendor to take struct iovec
  2014-04-11 13:58 [PATCH v2 BlueZ 1/6] android/avrcp-lib: Make avrcp_send_browsing_req to take struct iovec Luiz Augusto von Dentz
                   ` (3 preceding siblings ...)
  2014-04-11 13:58 ` [PATCH v2 BlueZ 5/6] android/avctp: Make avctp_send_vendor_req " Luiz Augusto von Dentz
@ 2014-04-11 13:58 ` Luiz Augusto von Dentz
  4 siblings, 0 replies; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2014-04-11 13:58 UTC (permalink / raw)
  To: linux-bluetooth

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

This makes it possible to pass data without copying.
---
 android/avctp.c     |   8 +--
 android/avctp.h     |   2 +-
 android/avrcp-lib.c | 182 +++++++++++++++++++++++++++++++---------------------
 android/avrcp-lib.h |   2 +-
 4 files changed, 113 insertions(+), 81 deletions(-)

diff --git a/android/avctp.c b/android/avctp.c
index 62c41fd..2271d2c 100644
--- a/android/avctp.c
+++ b/android/avctp.c
@@ -1352,19 +1352,15 @@ int avctp_send_passthrough(struct avctp *session, uint8_t op, uint8_t *params,
 
 int avctp_send_vendor(struct avctp *session, uint8_t transaction,
 				uint8_t code, uint8_t subunit,
-				uint8_t *operands, size_t operand_count)
+				const struct iovec *iov, int iov_cnt)
 {
 	struct avctp_channel *control = session->control;
-	struct iovec iov;
 
 	if (control == NULL)
 		return -ENOTCONN;
 
-	iov.iov_base = operands;
-	iov.iov_len = operand_count;
-
 	return avctp_send(control, transaction, AVCTP_RESPONSE, code, subunit,
-						AVC_OP_VENDORDEP, &iov, 1);
+						AVC_OP_VENDORDEP, iov, iov_cnt);
 }
 
 int avctp_send_vendor_req(struct avctp *session, uint8_t code, uint8_t subunit,
diff --git a/android/avctp.h b/android/avctp.h
index 1b15398..6bfc4cb 100644
--- a/android/avctp.h
+++ b/android/avctp.h
@@ -168,7 +168,7 @@ int avctp_send_passthrough(struct avctp *session, uint8_t op, uint8_t *params,
 							size_t params_len);
 int avctp_send_vendor(struct avctp *session, uint8_t transaction,
 				uint8_t code, uint8_t subunit,
-				uint8_t *operands, size_t operand_count);
+				const struct iovec *iov, int iov_cnt);
 int avctp_send_vendor_req(struct avctp *session, uint8_t code, uint8_t subunit,
 					const struct iovec *iov, int iov_cnt,
 					avctp_rsp_cb func, void *user_data);
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index e2bba11..6957422 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -703,29 +703,30 @@ int avrcp_init_uinput(struct avrcp *session, const char *name,
 
 int avrcp_send(struct avrcp *session, uint8_t transaction, uint8_t code,
 					uint8_t subunit, uint8_t pdu_id,
-					uint8_t *params, size_t params_len)
+					const struct iovec *iov, int iov_cnt)
 {
-	struct avrcp_header *pdu = (void *) session->tx_buf;
-	size_t len = sizeof(*pdu);
-
-	memset(pdu, 0, len);
-
-	hton24(pdu->company_id, IEEEID_BTSIG);
-	pdu->pdu_id = pdu_id;
-	pdu->packet_type = AVRCP_PACKET_TYPE_SINGLE;
+	struct iovec pdu[iov_cnt + 1];
+	struct avrcp_header hdr;
+	int i;
 
-	if (params_len > 0) {
-		len += params_len;
+	memset(&hdr, 0, sizeof(hdr));
 
-		if (len > session->tx_mtu)
-			return -ENOBUFS;
+	pdu[0].iov_base = &hdr;
+	pdu[0].iov_len = sizeof(hdr);
 
-		memcpy(pdu->params, params, params_len);
-		pdu->params_len = htons(params_len);
+	for (i = 0; i < iov_cnt; i++) {
+		pdu[i + 1].iov_base = iov[i].iov_base;
+		pdu[i + 1].iov_len = iov[i].iov_len;
+		hdr.params_len += iov[i].iov_len;
 	}
 
+	hton24(hdr.company_id, IEEEID_BTSIG);
+	hdr.pdu_id = pdu_id;
+	hdr.packet_type = AVRCP_PACKET_TYPE_SINGLE;
+	hdr.params_len = htons(hdr.params_len);
+
 	return avctp_send_vendor(session->conn, transaction, code, subunit,
-							session->tx_buf, len);
+							pdu, iov_cnt + 1);
 }
 
 static int status2errno(uint8_t status)
@@ -2034,52 +2035,61 @@ int avrcp_search(struct avrcp *session, const char *string)
 int avrcp_get_capabilities_rsp(struct avrcp *session, uint8_t transaction,
 						uint8_t number, uint8_t *events)
 {
-	uint8_t pdu[AVRCP_EVENT_LAST + 1];
+	struct iovec iov[2];
 
 	if (number > AVRCP_EVENT_LAST)
 		return -EINVAL;
 
-	pdu[0] = number;
-	memcpy(&pdu[1], events, number);
+	iov[0].iov_base = &number;
+	iov[0].iov_len = sizeof(number);
+
+	iov[1].iov_base = events;
+	iov[1].iov_len = number;
 
 	return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
 				AVC_SUBUNIT_PANEL, AVRCP_GET_CAPABILITIES,
-				pdu, number + 1);
+				iov, 2);
 }
 
 int avrcp_list_player_attributes_rsp(struct avrcp *session, uint8_t transaction,
 					uint8_t number, uint8_t *attrs)
 {
-	uint8_t pdu[AVRCP_ATTRIBUTE_LAST + 1];
+	struct iovec iov[2];
 
 	if (number > AVRCP_ATTRIBUTE_LAST)
 		return -EINVAL;
 
-	pdu[0] = number;
+	iov[0].iov_base = &number;
+	iov[0].iov_len = sizeof(number);
 
-	if (number > 0)
-		memcpy(&pdu[1], attrs, number);
+	if (!number)
+		return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
+				AVC_SUBUNIT_PANEL, AVRCP_LIST_PLAYER_ATTRIBUTES,
+				iov, 1);
+
+	iov[1].iov_base = attrs;
+	iov[1].iov_len = number;
 
 	return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
 				AVC_SUBUNIT_PANEL, AVRCP_LIST_PLAYER_ATTRIBUTES,
-				pdu, number + 1);
+				iov, 2);
 }
 
 int avrcp_get_player_attribute_text_rsp(struct avrcp *session,
 					uint8_t transaction, uint8_t number,
 					uint8_t *attrs, const char **text)
 {
-	uint8_t pdu[AVRCP_ATTRIBUTE_LAST * (4 + 255)];
-	uint8_t *ptr;
-	uint16_t length;
+	struct iovec iov[1 + AVRCP_ATTRIBUTE_LAST * 2];
+	uint8_t val[AVRCP_ATTRIBUTE_LAST][4];
 	int i;
 
 	if (number > AVRCP_ATTRIBUTE_LAST)
 		return -EINVAL;
 
-	pdu[0] = number;
-	length = 1;
-	for (i = 0, ptr = &pdu[1]; i < number; i++) {
+	iov[0].iov_base = &number;
+	iov[0].iov_len = sizeof(number);
+
+	for (i = 0; i < number; i++) {
 		uint8_t len = 0;
 
 		if (attrs[i] > AVRCP_ATTRIBUTE_LAST ||
@@ -2089,135 +2099,161 @@ int avrcp_get_player_attribute_text_rsp(struct avrcp *session,
 		if (text[i])
 			len = strlen(text[i]);
 
-		ptr[0] = attrs[i];
-		put_be16(AVRCP_CHARSET_UTF8, &ptr[1]);
-		ptr[3] = len;
+		val[i][0] = attrs[i];
+		put_be16(AVRCP_CHARSET_UTF8, &val[i][1]);
+		val[i][3] = len;
 
-		if (len)
-			memcpy(&ptr[4], text[i], len);
+		iov[i + 1].iov_base = val[i];
+		iov[i + 1].iov_len = sizeof(val[i]);
 
-		ptr += 4 + len;
-		length += 4 + len;
+		iov[i + 2].iov_base = (void *) text[i];
+		iov[i + 2].iov_len = len;
 	}
 
 	return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
 			AVC_SUBUNIT_PANEL, AVRCP_GET_PLAYER_ATTRIBUTE_TEXT,
-			pdu, length);
+			iov, 1 + i * 2);
 }
 
 int avrcp_list_player_values_rsp(struct avrcp *session, uint8_t transaction,
 					uint8_t number, uint8_t *values)
 {
-	uint8_t pdu[AVRCP_ATTRIBUTE_LAST + 1];
+	struct iovec iov[2];
 
 	if (number > AVRCP_ATTRIBUTE_LAST)
 		return -EINVAL;
 
-	pdu[0] = number;
-	memcpy(&pdu[1], values, number);
+	iov[0].iov_base = &number;
+	iov[0].iov_len = sizeof(number);
+
+	iov[1].iov_base = values;
+	iov[1].iov_len = number;
 
 	return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
-			AVC_SUBUNIT_PANEL, AVRCP_LIST_PLAYER_VALUES,
-			pdu, number + 1);
+				AVC_SUBUNIT_PANEL, AVRCP_LIST_PLAYER_VALUES,
+				iov, 2);
 }
 
 int avrcp_get_play_status_rsp(struct avrcp *session, uint8_t transaction,
 				uint32_t position, uint32_t duration,
 				uint8_t status)
 {
+	struct iovec iov;
 	uint8_t pdu[9];
 
 	put_be32(position, &pdu[0]);
 	put_be32(duration, &pdu[4]);
 	pdu[8] = status;
 
+	iov.iov_base = &pdu;
+	iov.iov_len = sizeof(pdu);
+
 	return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
 				AVC_SUBUNIT_PANEL, AVRCP_GET_PLAY_STATUS,
-				pdu, sizeof(pdu));
+				&iov, 1);
 }
 
 int avrcp_get_player_values_text_rsp(struct avrcp *session,
 					uint8_t transaction, uint8_t number,
 					uint8_t *values, const char **text)
 {
-	uint8_t pdu[AVRCP_ATTRIBUTE_LAST * (4 + 255)];
-	uint8_t *ptr;
-	uint16_t length;
+	struct iovec iov[1 + AVRCP_ATTRIBUTE_LAST * 2];
+	uint8_t val[AVRCP_ATTRIBUTE_LAST][4];
 	int i;
 
 	if (number > AVRCP_ATTRIBUTE_LAST)
 		return -EINVAL;
 
-	pdu[0] = number;
-	length = 1;
-	for (i = 0, ptr = &pdu[1]; i < number; i++) {
+	iov[0].iov_base = &number;
+	iov[0].iov_len = sizeof(number);
+
+	for (i = 0; i < number; i++) {
 		uint8_t len = 0;
 
 		if (text[i])
 			len = strlen(text[i]);
 
-		ptr[0] = values[i];
-		put_be16(AVRCP_CHARSET_UTF8, &ptr[1]);
-		ptr[3] = len;
-		memcpy(&ptr[4], text[i], len);
-		ptr += 4 + len;
-		length += 4 + len;
+		val[i][0] = values[i];
+		put_be16(AVRCP_CHARSET_UTF8, &val[i][1]);
+		val[i][3] = len;
+
+		iov[i + 1].iov_base = val[i];
+		iov[i + 1].iov_len = sizeof(val[i]);
+
+		iov[i + 2].iov_base = (void *) text[i];
+		iov[i + 2].iov_len = len;
 	}
 
 	return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
-			AVC_SUBUNIT_PANEL, AVRCP_GET_PLAYER_VALUE_TEXT,
-			pdu, length);
+				AVC_SUBUNIT_PANEL, AVRCP_GET_PLAYER_VALUE_TEXT,
+				iov, 1 + i * 2);
 }
 
 int avrcp_get_current_player_value_rsp(struct avrcp *session,
 					uint8_t transaction, uint8_t number,
 					uint8_t *attrs, uint8_t *values)
 {
-	uint8_t pdu[AVRCP_ATTRIBUTE_LAST * 2  + 1];
-	uint8_t *ptr;
-	uint16_t length;
+	struct iovec iov[1 + AVRCP_ATTRIBUTE_LAST];
+	uint8_t val[AVRCP_ATTRIBUTE_LAST][2];
 	int i;
 
 	if (number > AVRCP_ATTRIBUTE_LAST)
 		return -EINVAL;
 
-	pdu[0] = number;
-	length = 1;
-	for (i = 0, ptr = &pdu[1]; i < number; i++) {
-		ptr[0] = attrs[i];
-		ptr[1] = values[i];
-		ptr += 2;
-		length += 2;
+	iov[0].iov_base = &number;
+	iov[0].iov_len = sizeof(number);
+
+	for (i = 0; i < number; i++) {
+		val[i][0] = attrs[i];
+		val[i][1] = values[i];
+
+		iov[i + 1].iov_base = val[i];
+		iov[i + 1].iov_len = sizeof(val[i]);
 	}
 
 	return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
 			AVC_SUBUNIT_PANEL, AVRCP_GET_CURRENT_PLAYER_VALUE,
-			pdu, length);
+			iov, 1 + i);
 }
 
 int avrcp_get_element_attrs_rsp(struct avrcp *session, uint8_t transaction,
 					uint8_t *params, size_t params_len)
 {
+	struct iovec iov;
+
+	iov.iov_base = params;
+	iov.iov_len = params_len;
+
 	return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
 				AVC_SUBUNIT_PANEL, AVRCP_GET_ELEMENT_ATTRIBUTES,
-				params, params_len);
+				&iov, 1);
 }
 
 int avrcp_register_notification_rsp(struct avrcp *session, uint8_t transaction,
 					uint8_t code, uint8_t *params,
 					size_t params_len)
 {
+	struct iovec iov;
+
+	iov.iov_base = params;
+	iov.iov_len = params_len;
+
 	return avrcp_send(session, transaction, code,
 				AVC_SUBUNIT_PANEL, AVRCP_REGISTER_NOTIFICATION,
-				params, params_len);
+				&iov, 1);
 }
 
 int avrcp_set_addressed_player_rsp(struct avrcp *session, uint8_t transaction,
 							uint8_t status)
 {
+	struct iovec iov;
+
+	iov.iov_base = &status;
+	iov.iov_len = sizeof(status);
+
 	return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
 				AVC_SUBUNIT_PANEL, AVRCP_SET_ADDRESSED_PLAYER,
-				&status, sizeof(status));
+				&iov, 1);
 }
 
 int avrcp_send_passthrough(struct avrcp *session, uint32_t vendor, uint8_t op)
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 3364e01..8b2424c 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -241,7 +241,7 @@ int avrcp_init_uinput(struct avrcp *session, const char *name,
 							const char *address);
 int avrcp_send(struct avrcp *session, uint8_t transaction, uint8_t code,
 					uint8_t subunit, uint8_t pdu_id,
-					uint8_t *params, size_t params_len);
+					const struct iovec *iov, int iov_cnt);
 int avrcp_get_capabilities(struct avrcp *session, uint8_t param);
 int avrcp_register_notification(struct avrcp *session, uint8_t event,
 							uint32_t interval);
-- 
1.9.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2014-04-11 13:58 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-11 13:58 [PATCH v2 BlueZ 1/6] android/avrcp-lib: Make avrcp_send_browsing_req to take struct iovec Luiz Augusto von Dentz
2014-04-11 13:58 ` [PATCH v2 BlueZ 2/6] android/avrcp-lib: Add checks in avrcp_get_item_attributes Luiz Augusto von Dentz
2014-04-11 13:58 ` [PATCH v2 BlueZ 3/6] android/avrcp-lib: Make avrcp_send_req to take struct iovec Luiz Augusto von Dentz
2014-04-11 13:58 ` [PATCH v2 BlueZ 4/6] android/avctp: Make avctp_send_browsing_req " Luiz Augusto von Dentz
2014-04-11 13:58 ` [PATCH v2 BlueZ 5/6] android/avctp: Make avctp_send_vendor_req " Luiz Augusto von Dentz
2014-04-11 13:58 ` [PATCH v2 BlueZ 6/6] android/avctp: Make avctp_send_vendor " Luiz Augusto von Dentz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).