* [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 = ¶m;
+ iov.iov_len = sizeof(param);
+
return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
- AVRCP_GET_CAPABILITIES, ¶m, 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, ¶ms[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).