3
* BlueZ - Bluetooth protocol stack for Linux
5
* Copyright (C) 2010 Nokia Corporation
6
* Copyright (C) 2010 Marcel Holtmann <marcel@holtmann.org>
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or
12
* (at your option) any later version.
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29
#include <bluetooth/bluetooth.h>
30
#include <bluetooth/sdp.h>
31
#include <bluetooth/sdp_lib.h>
37
const char *att_ecode2str(uint8_t status)
40
case ATT_ECODE_INVALID_HANDLE:
41
return "Invalid handle";
42
case ATT_ECODE_READ_NOT_PERM:
43
return "Atribute can't be read";
44
case ATT_ECODE_WRITE_NOT_PERM:
45
return "Attribute can't be written";
46
case ATT_ECODE_INVALID_PDU:
47
return "Attribute PDU was invalid";
48
case ATT_ECODE_INSUFF_AUTHEN:
49
return "Attribute requires authentication before read/write";
50
case ATT_ECODE_REQ_NOT_SUPP:
51
return "Server doesn't support the request received";
52
case ATT_ECODE_INVALID_OFFSET:
53
return "Offset past the end of the attribute";
54
case ATT_ECODE_INSUFF_AUTHO:
55
return "Attribute requires authorization before read/write";
56
case ATT_ECODE_PREP_QUEUE_FULL:
57
return "Too many prepare writes have been queued";
58
case ATT_ECODE_ATTR_NOT_FOUND:
59
return "No attribute found within the given range";
60
case ATT_ECODE_ATTR_NOT_LONG:
61
return "Attribute can't be read/written using Read Blob Req";
62
case ATT_ECODE_INSUFF_ENCR_KEY_SIZE:
63
return "Encryption Key Size is insufficient";
64
case ATT_ECODE_INVAL_ATTR_VALUE_LEN:
65
return "Attribute value length is invalid";
66
case ATT_ECODE_UNLIKELY:
67
return "Request attribute has encountered an unlikely error";
68
case ATT_ECODE_INSUFF_ENC:
69
return "Encryption required before read/write";
70
case ATT_ECODE_UNSUPP_GRP_TYPE:
71
return "Attribute type is not a supported grouping attribute";
72
case ATT_ECODE_INSUFF_RESOURCES:
73
return "Insufficient Resources to complete the request";
75
return "Internal application error: I/O";
77
return "Unexpected error code";
81
void att_data_list_free(struct att_data_list *list)
85
for (i = 0; i < list->num; i++)
92
uint16_t enc_read_by_grp_req(uint16_t start, uint16_t end, uuid_t *uuid,
93
uint8_t *pdu, int len)
95
const uint16_t min_len = sizeof(pdu[0]) + sizeof(start) + sizeof(end);
101
if (uuid->type == SDP_UUID16)
103
else if (uuid->type == SDP_UUID128)
108
if (len < min_len + length)
111
pdu[0] = ATT_OP_READ_BY_GROUP_REQ;
112
att_put_u16(start, &pdu[1]);
113
att_put_u16(end, &pdu[3]);
115
if (uuid->type == SDP_UUID16)
116
att_put_u16(uuid->value.uuid16, &pdu[5]);
118
memcpy(&pdu[5], &uuid->value.uuid128, length);
120
return min_len + length;
123
uint16_t dec_read_by_grp_req(const uint8_t *pdu, int len, uint16_t *start,
124
uint16_t *end, uuid_t *uuid)
126
const uint16_t min_len = sizeof(pdu[0]) + sizeof(*start) + sizeof(*end);
131
if (start == NULL || end == NULL || uuid == NULL)
134
if (pdu[0] != ATT_OP_READ_BY_GROUP_REQ)
137
if (len < min_len + 2)
140
*start = att_get_u16(&pdu[1]);
141
*end = att_get_u16(&pdu[3]);
142
if (len == min_len + 2)
143
sdp_uuid16_create(uuid, att_get_u16(&pdu[5]));
145
sdp_uuid128_create(uuid, &pdu[5]);
150
uint16_t enc_read_by_grp_resp(struct att_data_list *list, uint8_t *pdu,
160
if (len < list->len + 2)
163
pdu[0] = ATT_OP_READ_BY_GROUP_RESP;
168
for (i = 0, w = 2; i < list->num && w + list->len <= len; i++) {
169
memcpy(ptr, list->data[i], list->len);
177
struct att_data_list *dec_read_by_grp_resp(const uint8_t *pdu, int len)
179
struct att_data_list *list;
183
if (pdu[0] != ATT_OP_READ_BY_GROUP_RESP)
186
list = malloc(sizeof(struct att_data_list));
188
list->num = (len - 2) / list->len;
190
list->data = malloc(sizeof(uint8_t *) * list->num);
193
for (i = 0; i < list->num; i++) {
194
list->data[i] = malloc(sizeof(uint8_t) * list->len);
195
memcpy(list->data[i], ptr, list->len);
202
uint16_t enc_find_by_type_req(uint16_t start, uint16_t end, uuid_t *uuid,
203
const uint8_t *value, int vlen, uint8_t *pdu, int len)
205
uint16_t min_len = sizeof(pdu[0]) + sizeof(start) + sizeof(end) +
214
if (uuid->type != SDP_UUID16)
220
if (vlen > len - min_len)
221
vlen = len - min_len;
223
pdu[0] = ATT_OP_FIND_BY_TYPE_REQ;
224
att_put_u16(start, &pdu[1]);
225
att_put_u16(end, &pdu[3]);
226
att_put_u16(uuid->value.uuid16, &pdu[5]);
229
memcpy(&pdu[7], value, vlen);
230
return min_len + vlen;
236
uint16_t dec_find_by_type_req(const uint8_t *pdu, int len, uint16_t *start,
237
uint16_t *end, uuid_t *uuid, uint8_t *value, int *vlen)
240
uint16_t min_len = sizeof(pdu[0]) + sizeof(*start) +
241
sizeof(*end) + sizeof(uint16_t);
249
if (pdu[0] != ATT_OP_FIND_BY_TYPE_REQ)
252
/* First requested handle number */
254
*start = att_get_u16(&pdu[1]);
256
/* Last requested handle number */
258
*end = att_get_u16(&pdu[3]);
262
sdp_uuid16_create(uuid, att_get_u16(&pdu[5]));
264
valuelen = len - min_len;
266
/* Attribute value to find */
267
if (valuelen > 0 && value)
268
memcpy(value, pdu + min_len, valuelen);
276
uint16_t enc_find_by_type_resp(GSList *matches, uint8_t *pdu, int len)
281
if (pdu == NULL || len < 5)
284
pdu[0] = ATT_OP_FIND_BY_TYPE_RESP;
286
for (l = matches, offset = 1; l && len >= (offset + 4);
287
l = l->next, offset += 4) {
288
struct att_range *range = l->data;
290
att_put_u16(range->start, &pdu[offset]);
291
att_put_u16(range->end, &pdu[offset + 2]);
297
GSList *dec_find_by_type_resp(const uint8_t *pdu, int len)
299
struct att_range *range;
303
if (pdu == NULL || len < 5)
306
if (pdu[0] != ATT_OP_FIND_BY_TYPE_RESP)
309
for (offset = 1, matches = NULL; len >= (offset + 4); offset += 4) {
310
range = malloc(sizeof(struct att_range));
311
range->start = att_get_u16(&pdu[offset]);
312
range->end = att_get_u16(&pdu[offset + 2]);
314
matches = g_slist_append(matches, range);
320
uint16_t enc_read_by_type_req(uint16_t start, uint16_t end, uuid_t *uuid,
321
uint8_t *pdu, int len)
323
const uint16_t min_len = sizeof(pdu[0]) + sizeof(start) + sizeof(end);
329
if (uuid->type == SDP_UUID16)
331
else if (uuid->type == SDP_UUID128)
336
if (len < min_len + length)
339
pdu[0] = ATT_OP_READ_BY_TYPE_REQ;
340
att_put_u16(start, &pdu[1]);
341
att_put_u16(end, &pdu[3]);
343
if (uuid->type == SDP_UUID16)
344
att_put_u16(uuid->value.uuid16, &pdu[5]);
346
memcpy(&pdu[5], &uuid->value.uuid128, length);
348
return min_len + length;
351
uint16_t dec_read_by_type_req(const uint8_t *pdu, int len, uint16_t *start,
352
uint16_t *end, uuid_t *uuid)
354
const uint16_t min_len = sizeof(pdu[0]) + sizeof(*start) + sizeof(*end);
359
if (start == NULL || end == NULL || uuid == NULL)
362
if (len < min_len + 2)
365
if (pdu[0] != ATT_OP_READ_BY_TYPE_REQ)
368
*start = att_get_u16(&pdu[1]);
369
*end = att_get_u16(&pdu[3]);
371
if (len == min_len + 2)
372
sdp_uuid16_create(uuid, att_get_u16(&pdu[5]));
374
sdp_uuid128_create(uuid, &pdu[5]);
379
uint16_t enc_read_by_type_resp(struct att_data_list *list, uint8_t *pdu, int len)
390
l = MIN(len - 2, list->len);
392
pdu[0] = ATT_OP_READ_BY_TYPE_RESP;
396
for (i = 0, w = 2; i < list->num && w + l <= len; i++) {
397
memcpy(ptr, list->data[i], l);
405
struct att_data_list *dec_read_by_type_resp(const uint8_t *pdu, int len)
407
struct att_data_list *list;
411
if (pdu[0] != ATT_OP_READ_BY_TYPE_RESP)
414
list = malloc(sizeof(struct att_data_list));
416
list->num = (len - 2) / list->len;
418
list->data = malloc(sizeof(uint8_t *) * list->num);
421
for (i = 0; i < list->num; i++) {
422
list->data[i] = malloc(sizeof(uint8_t) * list->len);
423
memcpy(list->data[i], ptr, list->len);
430
uint16_t enc_write_cmd(uint16_t handle, const uint8_t *value, int vlen,
431
uint8_t *pdu, int len)
433
const uint16_t min_len = sizeof(pdu[0]) + sizeof(handle);
441
if (vlen > len - min_len)
442
vlen = len - min_len;
444
pdu[0] = ATT_OP_WRITE_CMD;
445
att_put_u16(handle, &pdu[1]);
448
memcpy(&pdu[3], value, vlen);
449
return min_len + vlen;
455
uint16_t dec_write_cmd(const uint8_t *pdu, int len, uint16_t *handle,
456
uint8_t *value, int *vlen)
458
const uint16_t min_len = sizeof(pdu[0]) + sizeof(*handle);
463
if (value == NULL || vlen == NULL || handle == NULL)
469
if (pdu[0] != ATT_OP_WRITE_CMD)
472
*handle = att_get_u16(&pdu[1]);
473
memcpy(value, pdu + min_len, len - min_len);
474
*vlen = len - min_len;
479
uint16_t enc_write_req(uint16_t handle, const uint8_t *value, int vlen,
480
uint8_t *pdu, int len)
482
const uint16_t min_len = sizeof(pdu[0]) + sizeof(handle);
490
if (vlen > len - min_len)
491
vlen = len - min_len;
493
pdu[0] = ATT_OP_WRITE_REQ;
494
att_put_u16(handle, &pdu[1]);
497
memcpy(&pdu[3], value, vlen);
498
return min_len + vlen;
504
uint16_t dec_write_req(const uint8_t *pdu, int len, uint16_t *handle,
505
uint8_t *value, int *vlen)
507
const uint16_t min_len = sizeof(pdu[0]) + sizeof(*handle);
512
if (value == NULL || vlen == NULL || handle == NULL)
518
if (pdu[0] != ATT_OP_WRITE_REQ)
521
*handle = att_get_u16(&pdu[1]);
522
*vlen = len - min_len;
524
memcpy(value, pdu + min_len, *vlen);
529
uint16_t enc_read_req(uint16_t handle, uint8_t *pdu, int len)
531
const uint16_t min_len = sizeof(pdu[0]) + sizeof(handle);
539
pdu[0] = ATT_OP_READ_REQ;
540
att_put_u16(handle, &pdu[1]);
545
uint16_t dec_read_req(const uint8_t *pdu, int len, uint16_t *handle)
547
const uint16_t min_len = sizeof(pdu[0]) + sizeof(*handle);
558
if (pdu[0] != ATT_OP_READ_REQ)
561
*handle = att_get_u16(&pdu[1]);
566
uint16_t enc_read_resp(uint8_t *value, int vlen, uint8_t *pdu, int len)
571
/* If the attribute value length is longer than the allowed PDU size,
572
* send only the octets that fit on the PDU. The remaining octets can
573
* be requested using the Read Blob Request. */
577
pdu[0] = ATT_OP_READ_RESP;
579
memcpy(pdu + 1, value, vlen);
584
uint16_t dec_read_resp(const uint8_t *pdu, int len, uint8_t *value, int *vlen)
589
if (value == NULL || vlen == NULL)
592
if (pdu[0] != ATT_OP_READ_RESP)
595
memcpy(value, pdu + 1, len - 1);
602
uint16_t enc_error_resp(uint8_t opcode, uint16_t handle, uint8_t status,
603
uint8_t *pdu, int len)
605
const uint16_t min_len = sizeof(pdu[0]) + sizeof(opcode) +
606
sizeof(handle) + sizeof(status);
613
pdu[0] = ATT_OP_ERROR;
615
memcpy(&pdu[2], &u16, sizeof(u16));
621
uint16_t enc_find_info_req(uint16_t start, uint16_t end, uint8_t *pdu, int len)
623
const uint16_t min_len = sizeof(pdu[0]) + sizeof(start) + sizeof(end);
631
pdu[0] = ATT_OP_FIND_INFO_REQ;
632
att_put_u16(start, &pdu[1]);
633
att_put_u16(end, &pdu[3]);
638
uint16_t dec_find_info_req(const uint8_t *pdu, int len, uint16_t *start,
641
const uint16_t min_len = sizeof(pdu[0]) + sizeof(*start) + sizeof(*end);
649
if (start == NULL || end == NULL)
652
if (pdu[0] != ATT_OP_FIND_INFO_REQ)
655
*start = att_get_u16(&pdu[1]);
656
*end = att_get_u16(&pdu[3]);
661
uint16_t enc_find_info_resp(uint8_t format, struct att_data_list *list,
662
uint8_t *pdu, int len)
673
if (len < list->len + 2)
676
pdu[0] = ATT_OP_FIND_INFO_RESP;
678
ptr = (void *) &pdu[2];
680
for (i = 0, w = 2; i < list->num && w + list->len <= len; i++) {
681
memcpy(ptr, list->data[i], list->len);
689
struct att_data_list *dec_find_info_resp(const uint8_t *pdu, int len,
692
struct att_data_list *list;
702
if (pdu[0] != ATT_OP_FIND_INFO_RESP)
707
list = malloc(sizeof(struct att_data_list));
709
list->len = sizeof(pdu[0]) + sizeof(*format);
712
else if (*format == 0x02)
715
list->num = (len - 2) / list->len;
716
list->data = malloc(sizeof(uint8_t *) * list->num);
718
ptr = (void *) &pdu[2];
720
for (i = 0; i < list->num; i++) {
721
list->data[i] = malloc(list->len);
722
memcpy(list->data[i], ptr, list->len);
729
uint16_t enc_notification(struct attribute *a, uint8_t *pdu, int len)
731
const uint16_t min_len = sizeof(pdu[0]) + sizeof(uint16_t);
736
if (len < (a->len + min_len))
739
pdu[0] = ATT_OP_HANDLE_NOTIFY;
740
att_put_u16(a->handle, &pdu[1]);
741
memcpy(&pdu[3], a->data, a->len);
743
return a->len + min_len;
746
uint16_t enc_indication(struct attribute *a, uint8_t *pdu, int len)
748
const uint16_t min_len = sizeof(pdu[0]) + sizeof(uint16_t);
753
if (len < (a->len + min_len))
756
pdu[0] = ATT_OP_HANDLE_IND;
757
att_put_u16(a->handle, &pdu[1]);
758
memcpy(&pdu[3], a->data, a->len);
760
return a->len + min_len;
763
struct attribute *dec_indication(const uint8_t *pdu, int len)
765
const uint16_t min_len = sizeof(pdu[0]) + sizeof(uint16_t);
772
if (pdu[0] != ATT_OP_HANDLE_IND)
778
a = malloc(sizeof(struct attribute) + len - min_len);
782
a->len = len - min_len;
784
a->handle = att_get_u16(&pdu[1]);
785
memcpy(a->data, &pdu[3], a->len);
790
uint16_t enc_confirmation(uint8_t *pdu, int len)
792
const uint16_t min_len = sizeof(pdu[0]);
800
pdu[0] = ATT_OP_HANDLE_CNF;
805
uint16_t enc_mtu_req(uint16_t mtu, uint8_t *pdu, int len)
807
const uint16_t min_len = sizeof(pdu[0]) + sizeof(mtu);
815
pdu[0] = ATT_OP_MTU_REQ;
816
att_put_u16(mtu, &pdu[1]);
821
uint16_t dec_mtu_req(const uint8_t *pdu, int len, uint16_t *mtu)
823
const uint16_t min_len = sizeof(pdu[0]) + sizeof(*mtu);
834
if (pdu[0] != ATT_OP_MTU_REQ)
837
*mtu = att_get_u16(&pdu[1]);
842
uint16_t enc_mtu_resp(uint16_t mtu, uint8_t *pdu, int len)
844
const uint16_t min_len = sizeof(pdu[0]) + sizeof(mtu);
852
pdu[0] = ATT_OP_MTU_RESP;
853
att_put_u16(mtu, &pdu[1]);
858
uint16_t dec_mtu_resp(const uint8_t *pdu, int len, uint16_t *mtu)
860
const uint16_t min_len = sizeof(pdu[0]) + sizeof(*mtu);
871
if (pdu[0] != ATT_OP_MTU_RESP)
874
*mtu = att_get_u16(&pdu[1]);