summaryrefslogtreecommitdiff
path: root/attrib/att.c
diff options
context:
space:
mode:
Diffstat (limited to 'attrib/att.c')
-rw-r--r--attrib/att.c337
1 files changed, 268 insertions, 69 deletions
diff --git a/attrib/att.c b/attrib/att.c
index c8e2e1d9..753c7539 100644
--- a/attrib/att.c
+++ b/attrib/att.c
@@ -22,15 +22,19 @@
*
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include <bluetooth/bluetooth.h>
-#include <bluetooth/uuid.h>
#include <glib.h>
+#include "lib/uuid.h"
#include "att.h"
const char *att_ecode2str(uint8_t status)
@@ -101,6 +105,9 @@ struct att_data_list *att_data_list_alloc(uint16_t num, uint16_t len)
struct att_data_list *list;
int i;
+ if (len > UINT8_MAX)
+ return NULL;
+
list = g_new0(struct att_data_list, 1);
list->len = len;
list->num = num;
@@ -114,9 +121,9 @@ struct att_data_list *att_data_list_alloc(uint16_t num, uint16_t len)
}
uint16_t enc_read_by_grp_req(uint16_t start, uint16_t end, bt_uuid_t *uuid,
- uint8_t *pdu, int len)
+ uint8_t *pdu, size_t len)
{
- const uint16_t min_len = sizeof(pdu[0]) + sizeof(start) + sizeof(end);
+ uint16_t min_len = sizeof(pdu[0]) + sizeof(start) + sizeof(end);
uint16_t length;
if (!uuid)
@@ -141,10 +148,10 @@ uint16_t enc_read_by_grp_req(uint16_t start, uint16_t end, bt_uuid_t *uuid,
return min_len + length;
}
-uint16_t dec_read_by_grp_req(const uint8_t *pdu, int len, uint16_t *start,
+uint16_t dec_read_by_grp_req(const uint8_t *pdu, size_t len, uint16_t *start,
uint16_t *end, bt_uuid_t *uuid)
{
- const uint16_t min_len = sizeof(pdu[0]) + sizeof(*start) + sizeof(*end);
+ const size_t min_len = sizeof(pdu[0]) + sizeof(*start) + sizeof(*end);
if (pdu == NULL)
return 0;
@@ -169,7 +176,7 @@ uint16_t dec_read_by_grp_req(const uint8_t *pdu, int len, uint16_t *start,
}
uint16_t enc_read_by_grp_resp(struct att_data_list *list, uint8_t *pdu,
- int len)
+ size_t len)
{
int i;
uint16_t w;
@@ -178,7 +185,7 @@ uint16_t enc_read_by_grp_resp(struct att_data_list *list, uint8_t *pdu,
if (list == NULL)
return 0;
- if (len < list->len + 2)
+ if (len < list->len + sizeof(uint8_t) * 2)
return 0;
pdu[0] = ATT_OP_READ_BY_GROUP_RESP;
@@ -195,7 +202,7 @@ uint16_t enc_read_by_grp_resp(struct att_data_list *list, uint8_t *pdu,
return w;
}
-struct att_data_list *dec_read_by_grp_resp(const uint8_t *pdu, int len)
+struct att_data_list *dec_read_by_grp_resp(const uint8_t *pdu, size_t len)
{
struct att_data_list *list;
const uint8_t *ptr;
@@ -208,6 +215,8 @@ struct att_data_list *dec_read_by_grp_resp(const uint8_t *pdu, int len)
elen = pdu[1];
num = (len - 2) / elen;
list = att_data_list_alloc(num, elen);
+ if (list == NULL)
+ return NULL;
ptr = &pdu[2];
@@ -220,7 +229,8 @@ struct att_data_list *dec_read_by_grp_resp(const uint8_t *pdu, int len)
}
uint16_t enc_find_by_type_req(uint16_t start, uint16_t end, bt_uuid_t *uuid,
- const uint8_t *value, int vlen, uint8_t *pdu, int len)
+ const uint8_t *value, size_t vlen,
+ uint8_t *pdu, size_t len)
{
uint16_t min_len = sizeof(pdu[0]) + sizeof(start) + sizeof(end) +
sizeof(uint16_t);
@@ -253,10 +263,11 @@ uint16_t enc_find_by_type_req(uint16_t start, uint16_t end, bt_uuid_t *uuid,
return min_len;
}
-uint16_t dec_find_by_type_req(const uint8_t *pdu, int len, uint16_t *start,
- uint16_t *end, bt_uuid_t *uuid, uint8_t *value, int *vlen)
+uint16_t dec_find_by_type_req(const uint8_t *pdu, size_t len, uint16_t *start,
+ uint16_t *end, bt_uuid_t *uuid,
+ uint8_t *value, size_t *vlen)
{
- int valuelen;
+ size_t valuelen;
uint16_t min_len = sizeof(pdu[0]) + sizeof(*start) +
sizeof(*end) + sizeof(uint16_t);
@@ -293,7 +304,7 @@ uint16_t dec_find_by_type_req(const uint8_t *pdu, int len, uint16_t *start,
return len;
}
-uint16_t enc_find_by_type_resp(GSList *matches, uint8_t *pdu, int len)
+uint16_t enc_find_by_type_resp(GSList *matches, uint8_t *pdu, size_t len)
{
GSList *l;
uint16_t offset;
@@ -303,8 +314,9 @@ uint16_t enc_find_by_type_resp(GSList *matches, uint8_t *pdu, int len)
pdu[0] = ATT_OP_FIND_BY_TYPE_RESP;
- for (l = matches, offset = 1; l && len >= (offset + 4);
- l = l->next, offset += 4) {
+ for (l = matches, offset = 1;
+ l && len >= (offset + sizeof(uint16_t) * 2);
+ l = l->next, offset += sizeof(uint16_t) * 2) {
struct att_range *range = l->data;
att_put_u16(range->start, &pdu[offset]);
@@ -314,11 +326,11 @@ uint16_t enc_find_by_type_resp(GSList *matches, uint8_t *pdu, int len)
return offset;
}
-GSList *dec_find_by_type_resp(const uint8_t *pdu, int len)
+GSList *dec_find_by_type_resp(const uint8_t *pdu, size_t len)
{
struct att_range *range;
GSList *matches;
- int offset;
+ off_t offset;
if (pdu == NULL || len < 5)
return NULL;
@@ -326,7 +338,9 @@ GSList *dec_find_by_type_resp(const uint8_t *pdu, int len)
if (pdu[0] != ATT_OP_FIND_BY_TYPE_RESP)
return NULL;
- for (offset = 1, matches = NULL; len >= (offset + 4); offset += 4) {
+ for (offset = 1, matches = NULL;
+ len >= (offset + sizeof(uint16_t) * 2);
+ offset += sizeof(uint16_t) * 2) {
range = g_new0(struct att_range, 1);
range->start = att_get_u16(&pdu[offset]);
range->end = att_get_u16(&pdu[offset + 2]);
@@ -338,9 +352,9 @@ GSList *dec_find_by_type_resp(const uint8_t *pdu, int len)
}
uint16_t enc_read_by_type_req(uint16_t start, uint16_t end, bt_uuid_t *uuid,
- uint8_t *pdu, int len)
+ uint8_t *pdu, size_t len)
{
- const uint16_t min_len = sizeof(pdu[0]) + sizeof(start) + sizeof(end);
+ uint16_t min_len = sizeof(pdu[0]) + sizeof(start) + sizeof(end);
uint16_t length;
if (!uuid)
@@ -365,10 +379,10 @@ uint16_t enc_read_by_type_req(uint16_t start, uint16_t end, bt_uuid_t *uuid,
return min_len + length;
}
-uint16_t dec_read_by_type_req(const uint8_t *pdu, int len, uint16_t *start,
+uint16_t dec_read_by_type_req(const uint8_t *pdu, size_t len, uint16_t *start,
uint16_t *end, bt_uuid_t *uuid)
{
- const uint16_t min_len = sizeof(pdu[0]) + sizeof(*start) + sizeof(*end);
+ const size_t min_len = sizeof(pdu[0]) + sizeof(*start) + sizeof(*end);
if (pdu == NULL)
return 0;
@@ -393,10 +407,11 @@ uint16_t dec_read_by_type_req(const uint8_t *pdu, int len, uint16_t *start,
return len;
}
-uint16_t enc_read_by_type_resp(struct att_data_list *list, uint8_t *pdu, int len)
+uint16_t enc_read_by_type_resp(struct att_data_list *list, uint8_t *pdu,
+ size_t len)
{
uint8_t *ptr;
- int i, w, l;
+ size_t i, w, l;
if (list == NULL)
return 0;
@@ -419,7 +434,7 @@ uint16_t enc_read_by_type_resp(struct att_data_list *list, uint8_t *pdu, int len
return w;
}
-struct att_data_list *dec_read_by_type_resp(const uint8_t *pdu, int len)
+struct att_data_list *dec_read_by_type_resp(const uint8_t *pdu, size_t len)
{
struct att_data_list *list;
const uint8_t *ptr;
@@ -432,6 +447,8 @@ struct att_data_list *dec_read_by_type_resp(const uint8_t *pdu, int len)
elen = pdu[1];
num = (len - 2) / elen;
list = att_data_list_alloc(num, elen);
+ if (list == NULL)
+ return NULL;
ptr = &pdu[2];
@@ -443,8 +460,8 @@ struct att_data_list *dec_read_by_type_resp(const uint8_t *pdu, int len)
return list;
}
-uint16_t enc_write_cmd(uint16_t handle, const uint8_t *value, int vlen,
- uint8_t *pdu, int len)
+uint16_t enc_write_cmd(uint16_t handle, const uint8_t *value, size_t vlen,
+ uint8_t *pdu, size_t len)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(handle);
@@ -468,8 +485,8 @@ uint16_t enc_write_cmd(uint16_t handle, const uint8_t *value, int vlen,
return min_len;
}
-uint16_t dec_write_cmd(const uint8_t *pdu, int len, uint16_t *handle,
- uint8_t *value, int *vlen)
+uint16_t dec_write_cmd(const uint8_t *pdu, size_t len, uint16_t *handle,
+ uint8_t *value, size_t *vlen)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(*handle);
@@ -492,8 +509,8 @@ uint16_t dec_write_cmd(const uint8_t *pdu, int len, uint16_t *handle,
return len;
}
-uint16_t enc_write_req(uint16_t handle, const uint8_t *value, int vlen,
- uint8_t *pdu, int len)
+uint16_t enc_write_req(uint16_t handle, const uint8_t *value, size_t vlen,
+ uint8_t *pdu, size_t len)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(handle);
@@ -517,8 +534,8 @@ uint16_t enc_write_req(uint16_t handle, const uint8_t *value, int vlen,
return min_len;
}
-uint16_t dec_write_req(const uint8_t *pdu, int len, uint16_t *handle,
- uint8_t *value, int *vlen)
+uint16_t dec_write_req(const uint8_t *pdu, size_t len, uint16_t *handle,
+ uint8_t *value, size_t *vlen)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(*handle);
@@ -542,7 +559,7 @@ uint16_t dec_write_req(const uint8_t *pdu, int len, uint16_t *handle,
return len;
}
-uint16_t enc_write_resp(uint8_t *pdu, int len)
+uint16_t enc_write_resp(uint8_t *pdu)
{
if (pdu == NULL)
return 0;
@@ -552,7 +569,7 @@ uint16_t enc_write_resp(uint8_t *pdu, int len)
return sizeof(pdu[0]);
}
-uint16_t dec_write_resp(const uint8_t *pdu, int len)
+uint16_t dec_write_resp(const uint8_t *pdu, size_t len)
{
if (pdu == NULL)
return 0;
@@ -563,7 +580,7 @@ uint16_t dec_write_resp(const uint8_t *pdu, int len)
return len;
}
-uint16_t enc_read_req(uint16_t handle, uint8_t *pdu, int len)
+uint16_t enc_read_req(uint16_t handle, uint8_t *pdu, size_t len)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(handle);
@@ -580,7 +597,7 @@ uint16_t enc_read_req(uint16_t handle, uint8_t *pdu, int len)
}
uint16_t enc_read_blob_req(uint16_t handle, uint16_t offset, uint8_t *pdu,
- int len)
+ size_t len)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(handle) +
sizeof(offset);
@@ -598,7 +615,7 @@ uint16_t enc_read_blob_req(uint16_t handle, uint16_t offset, uint8_t *pdu,
return min_len;
}
-uint16_t dec_read_req(const uint8_t *pdu, int len, uint16_t *handle)
+uint16_t dec_read_req(const uint8_t *pdu, size_t len, uint16_t *handle)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(*handle);
@@ -619,7 +636,7 @@ uint16_t dec_read_req(const uint8_t *pdu, int len, uint16_t *handle)
return min_len;
}
-uint16_t dec_read_blob_req(const uint8_t *pdu, int len, uint16_t *handle,
+uint16_t dec_read_blob_req(const uint8_t *pdu, size_t len, uint16_t *handle,
uint16_t *offset)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(*handle) +
@@ -646,7 +663,7 @@ uint16_t dec_read_blob_req(const uint8_t *pdu, int len, uint16_t *handle,
return min_len;
}
-uint16_t enc_read_resp(uint8_t *value, int vlen, uint8_t *pdu, int len)
+uint16_t enc_read_resp(uint8_t *value, size_t vlen, uint8_t *pdu, size_t len)
{
if (pdu == NULL)
return 0;
@@ -664,8 +681,8 @@ uint16_t enc_read_resp(uint8_t *value, int vlen, uint8_t *pdu, int len)
return vlen + 1;
}
-uint16_t enc_read_blob_resp(uint8_t *value, int vlen, uint16_t offset,
- uint8_t *pdu, int len)
+uint16_t enc_read_blob_resp(uint8_t *value, size_t vlen, uint16_t offset,
+ uint8_t *pdu, size_t len)
{
if (pdu == NULL)
return 0;
@@ -681,26 +698,28 @@ uint16_t enc_read_blob_resp(uint8_t *value, int vlen, uint16_t offset,
return vlen + 1;
}
-uint16_t dec_read_resp(const uint8_t *pdu, int len, uint8_t *value, int *vlen)
+ssize_t dec_read_resp(const uint8_t *pdu, size_t len, uint8_t *value,
+ size_t vlen)
{
if (pdu == NULL)
- return 0;
-
- if (value == NULL || vlen == NULL)
- return 0;
+ return -EINVAL;
if (pdu[0] != ATT_OP_READ_RESP)
- return 0;
+ return -EINVAL;
- memcpy(value, pdu + 1, len - 1);
+ if (value == NULL)
+ return len - 1;
- *vlen = len - 1;
+ if (vlen < (len - 1))
+ return -ENOBUFS;
- return len;
+ memcpy(value, pdu + 1, len - 1);
+
+ return len - 1;
}
uint16_t enc_error_resp(uint8_t opcode, uint16_t handle, uint8_t status,
- uint8_t *pdu, int len)
+ uint8_t *pdu, size_t len)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(opcode) +
sizeof(handle) + sizeof(status);
@@ -718,7 +737,8 @@ uint16_t enc_error_resp(uint8_t opcode, uint16_t handle, uint8_t status,
return min_len;
}
-uint16_t enc_find_info_req(uint16_t start, uint16_t end, uint8_t *pdu, int len)
+uint16_t enc_find_info_req(uint16_t start, uint16_t end, uint8_t *pdu,
+ size_t len)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(start) + sizeof(end);
@@ -735,7 +755,7 @@ uint16_t enc_find_info_req(uint16_t start, uint16_t end, uint8_t *pdu, int len)
return min_len;
}
-uint16_t dec_find_info_req(const uint8_t *pdu, int len, uint16_t *start,
+uint16_t dec_find_info_req(const uint8_t *pdu, size_t len, uint16_t *start,
uint16_t *end)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(*start) + sizeof(*end);
@@ -759,10 +779,10 @@ uint16_t dec_find_info_req(const uint8_t *pdu, int len, uint16_t *start,
}
uint16_t enc_find_info_resp(uint8_t format, struct att_data_list *list,
- uint8_t *pdu, int len)
+ uint8_t *pdu, size_t len)
{
uint8_t *ptr;
- int i, w;
+ size_t i, w;
if (pdu == NULL)
return 0;
@@ -770,7 +790,7 @@ uint16_t enc_find_info_resp(uint8_t format, struct att_data_list *list,
if (list == NULL)
return 0;
- if (len < list->len + 2)
+ if (len < list->len + sizeof(uint8_t) * 2)
return 0;
pdu[0] = ATT_OP_FIND_INFO_RESP;
@@ -786,7 +806,7 @@ uint16_t enc_find_info_resp(uint8_t format, struct att_data_list *list,
return w;
}
-struct att_data_list *dec_find_info_resp(const uint8_t *pdu, int len,
+struct att_data_list *dec_find_info_resp(const uint8_t *pdu, size_t len,
uint8_t *format)
{
struct att_data_list *list;
@@ -815,6 +835,8 @@ struct att_data_list *dec_find_info_resp(const uint8_t *pdu, int len,
ptr = (void *) &pdu[2];
list = att_data_list_alloc(num, elen);
+ if (list == NULL)
+ return NULL;
for (i = 0; i < num; i++) {
memcpy(list->data[i], ptr, list->len);
@@ -824,8 +846,8 @@ struct att_data_list *dec_find_info_resp(const uint8_t *pdu, int len,
return list;
}
-uint16_t enc_notification(uint16_t handle, uint8_t *value, int vlen,
- uint8_t *pdu, int len)
+uint16_t enc_notification(uint16_t handle, uint8_t *value, size_t vlen,
+ uint8_t *pdu, size_t len)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(uint16_t);
@@ -842,8 +864,8 @@ uint16_t enc_notification(uint16_t handle, uint8_t *value, int vlen,
return vlen + min_len;
}
-uint16_t enc_indication(uint16_t handle, uint8_t *value, int vlen,
- uint8_t *pdu, int len)
+uint16_t enc_indication(uint16_t handle, uint8_t *value, size_t vlen,
+ uint8_t *pdu, size_t len)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(uint16_t);
@@ -860,8 +882,8 @@ uint16_t enc_indication(uint16_t handle, uint8_t *value, int vlen,
return vlen + min_len;
}
-uint16_t dec_indication(const uint8_t *pdu, int len, uint16_t *handle,
- uint8_t *value, int vlen)
+uint16_t dec_indication(const uint8_t *pdu, size_t len, uint16_t *handle,
+ uint8_t *value, size_t vlen)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(uint16_t);
uint16_t dlen;
@@ -885,7 +907,7 @@ uint16_t dec_indication(const uint8_t *pdu, int len, uint16_t *handle,
return dlen;
}
-uint16_t enc_confirmation(uint8_t *pdu, int len)
+uint16_t enc_confirmation(uint8_t *pdu, size_t len)
{
const uint16_t min_len = sizeof(pdu[0]);
@@ -900,7 +922,7 @@ uint16_t enc_confirmation(uint8_t *pdu, int len)
return min_len;
}
-uint16_t enc_mtu_req(uint16_t mtu, uint8_t *pdu, int len)
+uint16_t enc_mtu_req(uint16_t mtu, uint8_t *pdu, size_t len)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(mtu);
@@ -916,7 +938,7 @@ uint16_t enc_mtu_req(uint16_t mtu, uint8_t *pdu, int len)
return min_len;
}
-uint16_t dec_mtu_req(const uint8_t *pdu, int len, uint16_t *mtu)
+uint16_t dec_mtu_req(const uint8_t *pdu, size_t len, uint16_t *mtu)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(*mtu);
@@ -937,7 +959,7 @@ uint16_t dec_mtu_req(const uint8_t *pdu, int len, uint16_t *mtu)
return min_len;
}
-uint16_t enc_mtu_resp(uint16_t mtu, uint8_t *pdu, int len)
+uint16_t enc_mtu_resp(uint16_t mtu, uint8_t *pdu, size_t len)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(mtu);
@@ -953,7 +975,7 @@ uint16_t enc_mtu_resp(uint16_t mtu, uint8_t *pdu, int len)
return min_len;
}
-uint16_t dec_mtu_resp(const uint8_t *pdu, int len, uint16_t *mtu)
+uint16_t dec_mtu_resp(const uint8_t *pdu, size_t len, uint16_t *mtu)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(*mtu);
@@ -973,3 +995,180 @@ uint16_t dec_mtu_resp(const uint8_t *pdu, int len, uint16_t *mtu)
return min_len;
}
+
+uint16_t enc_prep_write_req(uint16_t handle, uint16_t offset,
+ const uint8_t *value, size_t vlen,
+ uint8_t *pdu, size_t len)
+{
+ const uint16_t min_len = sizeof(pdu[0]) + sizeof(handle) +
+ sizeof(offset);
+
+ if (pdu == NULL)
+ return 0;
+
+ if (len < min_len)
+ return 0;
+
+ if (vlen > len - min_len)
+ vlen = len - min_len;
+
+ pdu[0] = ATT_OP_PREP_WRITE_REQ;
+ att_put_u16(handle, &pdu[1]);
+ att_put_u16(offset, &pdu[3]);
+
+ if (vlen > 0) {
+ memcpy(&pdu[5], value, vlen);
+ return min_len + vlen;
+ }
+
+ return min_len;
+}
+
+uint16_t dec_prep_write_req(const uint8_t *pdu, size_t len, uint16_t *handle,
+ uint16_t *offset, uint8_t *value, size_t *vlen)
+{
+ const uint16_t min_len = sizeof(pdu[0]) + sizeof(*handle) +
+ sizeof(*offset);
+
+ if (pdu == NULL)
+ return 0;
+
+ if (handle == NULL || offset == NULL || value == NULL || vlen == NULL)
+ return 0;
+
+ if (len < min_len)
+ return 0;
+
+ if (pdu[0] != ATT_OP_PREP_WRITE_REQ)
+ return 0;
+
+ *handle = att_get_u16(&pdu[1]);
+ *offset = att_get_u16(&pdu[3]);
+
+ *vlen = len - min_len;
+ if (*vlen > 0)
+ memcpy(value, pdu + min_len, *vlen);
+
+ return len;
+}
+
+uint16_t enc_prep_write_resp(uint16_t handle, uint16_t offset,
+ const uint8_t *value, size_t vlen,
+ uint8_t *pdu, size_t len)
+{
+ const uint16_t min_len = sizeof(pdu[0]) + sizeof(handle) +
+ sizeof(offset);
+
+ if (pdu == NULL)
+ return 0;
+
+ if (len < min_len)
+ return 0;
+
+ if (vlen > len - min_len)
+ vlen = len - min_len;
+
+ pdu[0] = ATT_OP_PREP_WRITE_RESP;
+ att_put_u16(handle, &pdu[1]);
+ att_put_u16(offset, &pdu[3]);
+
+ if (vlen > 0) {
+ memcpy(&pdu[5], value, vlen);
+ return min_len + vlen;
+ }
+
+ return min_len;
+}
+
+uint16_t dec_prep_write_resp(const uint8_t *pdu, size_t len, uint16_t *handle,
+ uint16_t *offset, uint8_t *value, size_t *vlen)
+{
+ const uint16_t min_len = sizeof(pdu[0]) + sizeof(*handle) +
+ sizeof(*offset);
+
+ if (pdu == NULL)
+ return 0;
+
+ if (handle == NULL || offset == NULL || value == NULL || vlen == NULL)
+ return 0;
+
+ if (len < min_len)
+ return 0;
+
+ if (pdu[0] != ATT_OP_PREP_WRITE_REQ)
+ return 0;
+
+ *handle = att_get_u16(&pdu[1]);
+ *offset = att_get_u16(&pdu[3]);
+ *vlen = len - min_len;
+ if (*vlen > 0)
+ memcpy(value, pdu + min_len, *vlen);
+
+ return len;
+}
+
+uint16_t enc_exec_write_req(uint8_t flags, uint8_t *pdu, size_t len)
+{
+ const uint16_t min_len = sizeof(pdu[0]) + sizeof(flags);
+
+ if (pdu == NULL)
+ return 0;
+
+ if (len < min_len)
+ return 0;
+
+ if (flags > 1)
+ return 0;
+
+ pdu[0] = ATT_OP_EXEC_WRITE_REQ;
+ pdu[1] = flags;
+
+ return min_len;
+}
+
+uint16_t dec_exec_write_req(const uint8_t *pdu, size_t len, uint8_t *flags)
+{
+ const uint16_t min_len = sizeof(pdu[0]) + sizeof(*flags);
+
+ if (pdu == NULL)
+ return 0;
+
+ if (flags == NULL)
+ return 0;
+
+ if (len < min_len)
+ return 0;
+
+ if (pdu[0] != ATT_OP_EXEC_WRITE_REQ)
+ return 0;
+
+ *flags = pdu[1];
+
+ return min_len;
+}
+
+uint16_t enc_exec_write_resp(uint8_t *pdu)
+{
+ if (pdu == NULL)
+ return 0;
+
+ pdu[0] = ATT_OP_EXEC_WRITE_RESP;
+
+ return sizeof(pdu[0]);
+}
+
+uint16_t dec_exec_write_resp(const uint8_t *pdu, size_t len)
+{
+ const uint16_t min_len = sizeof(pdu[0]);
+
+ if (pdu == NULL)
+ return 0;
+
+ if (len < min_len)
+ return 0;
+
+ if (pdu[0] != ATT_OP_EXEC_WRITE_RESP)
+ return 0;
+
+ return len;
+}