~ubuntu-branches/ubuntu/oneiric/bluez/oneiric-201105191013

« back to all changes in this revision

Viewing changes to src/attrib-server.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Ancell
  • Date: 2011-03-24 10:27:09 UTC
  • mfrom: (1.1.30 upstream)
  • Revision ID: james.westby@ubuntu.com-20110324102709-2hfis29dcozwxxo0
Tags: 4.90-0ubuntu1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
#include <glib.h>
34
34
 
35
35
#include <bluetooth/bluetooth.h>
 
36
#include <bluetooth/uuid.h>
36
37
#include <bluetooth/sdp.h>
37
38
#include <bluetooth/sdp_lib.h>
38
39
 
54
55
struct gatt_channel {
55
56
        bdaddr_t src;
56
57
        bdaddr_t dst;
 
58
        GSList *configs;
 
59
        GSList *notify;
 
60
        GSList *indicate;
57
61
        GAttrib *attrib;
58
62
        guint mtu;
 
63
        gboolean le;
59
64
        guint id;
60
65
        gboolean encrypted;
61
66
};
77
82
static uint16_t name_handle = 0x0000;
78
83
static uint16_t appearance_handle = 0x0000;
79
84
 
80
 
static uuid_t prim_uuid = {
81
 
                        .type = SDP_UUID16,
82
 
                        .value.uuid16 = GATT_PRIM_SVC_UUID
 
85
static bt_uuid_t prim_uuid = {
 
86
                        .type = BT_UUID16,
 
87
                        .value.u16 = GATT_PRIM_SVC_UUID
83
88
};
84
 
static uuid_t snd_uuid = {
85
 
                        .type = SDP_UUID16,
86
 
                        .value.uuid16 = GATT_SND_SVC_UUID
 
89
static bt_uuid_t snd_uuid = {
 
90
                        .type = BT_UUID16,
 
91
                        .value.u16 = GATT_SND_SVC_UUID
87
92
};
88
93
 
89
94
static sdp_record_t *server_record_new(uuid_t *uuid, uint16_t start, uint16_t end)
90
95
{
91
96
        sdp_list_t *svclass_id, *apseq, *proto[2], *root, *aproto;
92
 
        uuid_t root_uuid, proto_uuid, gatt_uuid, l2cap;
 
97
        uuid_t root_uuid, proto_uuid, l2cap;
93
98
        sdp_record_t *record;
94
99
        sdp_data_t *psm, *sh, *eh;
95
100
        uint16_t lp = GATT_PSM;
130
135
        aproto = sdp_list_append(NULL, apseq);
131
136
        sdp_set_access_protos(record, aproto);
132
137
 
133
 
        sdp_set_service_id(record, gatt_uuid);
134
 
 
135
138
        sdp_data_free(psm);
136
139
        sdp_data_free(sh);
137
140
        sdp_data_free(eh);
143
146
        return record;
144
147
}
145
148
 
 
149
static int handle_cmp(gconstpointer a, gconstpointer b)
 
150
{
 
151
        const struct attribute *attrib = a;
 
152
        uint16_t handle = GPOINTER_TO_UINT(b);
 
153
 
 
154
        return attrib->handle - handle;
 
155
}
 
156
 
 
157
static int attribute_cmp(gconstpointer a1, gconstpointer a2)
 
158
{
 
159
        const struct attribute *attrib1 = a1;
 
160
        const struct attribute *attrib2 = a2;
 
161
 
 
162
        return attrib1->handle - attrib2->handle;
 
163
}
 
164
 
146
165
static uint8_t att_check_reqs(struct gatt_channel *channel, uint8_t opcode,
147
166
                                                                int reqs)
148
167
{
174
193
        return 0;
175
194
}
176
195
 
 
196
static uint8_t client_set_notifications(struct attribute *attr,
 
197
                                                        gpointer user_data)
 
198
{
 
199
        struct gatt_channel *channel = user_data;
 
200
        struct attribute *last_chr_val = NULL;
 
201
        uint16_t cfg_val;
 
202
        uint8_t props;
 
203
        bt_uuid_t uuid;
 
204
        GSList *l;
 
205
 
 
206
        cfg_val = att_get_u16(attr->data);
 
207
 
 
208
        bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
 
209
        for (l = database, props = 0; l != NULL; l = l->next) {
 
210
                struct attribute *a = l->data;
 
211
                static uint16_t handle = 0;
 
212
 
 
213
                if (a->handle >= attr->handle)
 
214
                        break;
 
215
 
 
216
                if (bt_uuid_cmp(&a->uuid, &uuid) == 0) {
 
217
                        props = att_get_u8(&a->data[0]);
 
218
                        handle = att_get_u16(&a->data[1]);
 
219
                        continue;
 
220
                }
 
221
 
 
222
                if (handle && a->handle == handle)
 
223
                        last_chr_val = a;
 
224
        }
 
225
 
 
226
        if (last_chr_val == NULL)
 
227
                return 0;
 
228
 
 
229
        if ((cfg_val & 0x0001) && !(props & ATT_CHAR_PROPER_NOTIFY))
 
230
                return ATT_ECODE_WRITE_NOT_PERM;
 
231
 
 
232
        if ((cfg_val & 0x0002) && !(props & ATT_CHAR_PROPER_INDICATE))
 
233
                return ATT_ECODE_WRITE_NOT_PERM;
 
234
 
 
235
        if (cfg_val & 0x0001)
 
236
                channel->notify = g_slist_append(channel->notify, last_chr_val);
 
237
        else
 
238
                channel->notify = g_slist_remove(channel->notify, last_chr_val);
 
239
 
 
240
        if (cfg_val & 0x0002)
 
241
                channel->indicate = g_slist_append(channel->indicate,
 
242
                                                                last_chr_val);
 
243
        else
 
244
                channel->indicate = g_slist_remove(channel->indicate,
 
245
                                                                last_chr_val);
 
246
 
 
247
        return 0;
 
248
}
 
249
 
 
250
static struct attribute *client_cfg_attribute(struct gatt_channel *channel,
 
251
                                                struct attribute *orig_attr,
 
252
                                                const uint8_t *value, int vlen)
 
253
{
 
254
        guint handle = orig_attr->handle;
 
255
        bt_uuid_t uuid;
 
256
        GSList *l;
 
257
 
 
258
        bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
 
259
        if (bt_uuid_cmp(&orig_attr->uuid, &uuid) != 0)
 
260
                return NULL;
 
261
 
 
262
        /* Value is unchanged, not need to create a private copy yet */
 
263
        if (vlen == orig_attr->len && memcmp(orig_attr->data, value, vlen) == 0)
 
264
                return orig_attr;
 
265
 
 
266
        l = g_slist_find_custom(channel->configs, GUINT_TO_POINTER(handle),
 
267
                                                                handle_cmp);
 
268
        if (!l) {
 
269
                struct attribute *a;
 
270
 
 
271
                /* Create a private copy of the Client Characteristic
 
272
                 * Configuration attribute */
 
273
                a = g_malloc0(sizeof(*a) + vlen);
 
274
                memcpy(a, orig_attr, sizeof(*a));
 
275
                memcpy(a->data, value, vlen);
 
276
                a->write_cb = client_set_notifications;
 
277
                a->cb_user_data = channel;
 
278
 
 
279
                channel->configs = g_slist_insert_sorted(channel->configs, a,
 
280
                                                                attribute_cmp);
 
281
 
 
282
                return a;
 
283
        }
 
284
 
 
285
        return l->data;
 
286
}
 
287
 
177
288
static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
178
 
                                                uint16_t end, uuid_t *uuid,
 
289
                                                uint16_t end, bt_uuid_t *uuid,
179
290
                                                uint8_t *pdu, int len)
180
291
{
181
292
        struct att_data_list *adl;
195
306
         * types may be used in the Read By Group Type Request.
196
307
         */
197
308
 
198
 
        if (sdp_uuid_cmp(uuid, &prim_uuid) != 0 &&
199
 
                sdp_uuid_cmp(uuid, &snd_uuid) != 0)
 
309
        if (bt_uuid_cmp(uuid, &prim_uuid) != 0 &&
 
310
                bt_uuid_cmp(uuid, &snd_uuid) != 0)
200
311
                return enc_error_resp(ATT_OP_READ_BY_GROUP_REQ, 0x0000,
201
312
                                        ATT_ECODE_UNSUPP_GRP_TYPE, pdu, len);
202
313
 
203
314
        last_handle = end;
204
315
        for (l = database, groups = NULL; l; l = l->next) {
 
316
                struct attribute *client_attr;
 
317
 
205
318
                a = l->data;
206
319
 
207
320
                if (a->handle < start)
211
324
                        break;
212
325
 
213
326
                /* The old group ends when a new one starts */
214
 
                if (old && (sdp_uuid_cmp(&a->uuid, &prim_uuid) == 0 ||
215
 
                                sdp_uuid_cmp(&a->uuid, &snd_uuid) == 0)) {
 
327
                if (old && (bt_uuid_cmp(&a->uuid, &prim_uuid) == 0 ||
 
328
                                bt_uuid_cmp(&a->uuid, &snd_uuid) == 0)) {
216
329
                        old->end = last_handle;
217
330
                        old = NULL;
218
331
                }
219
332
 
220
 
                if (sdp_uuid_cmp(&a->uuid, uuid) != 0) {
 
333
                if (bt_uuid_cmp(&a->uuid, uuid) != 0) {
221
334
                        /* Still inside a service, update its last handle */
222
335
                        if (old)
223
336
                                last_handle = a->handle;
229
342
 
230
343
                status = att_check_reqs(channel, ATT_OP_READ_BY_GROUP_REQ,
231
344
                                                                a->read_reqs);
 
345
 
 
346
                client_attr = client_cfg_attribute(channel, a, a->data, a->len);
 
347
                if (client_attr)
 
348
                        a = client_attr;
 
349
 
 
350
                if (status == 0x00 && a->read_cb)
 
351
                        status = a->read_cb(a, a->cb_user_data);
 
352
 
232
353
                if (status) {
233
354
                        g_slist_foreach(groups, (GFunc) g_free, NULL);
234
355
                        g_slist_free(groups);
260
381
 
261
382
        length = g_slist_length(groups);
262
383
 
263
 
        adl = g_new0(struct att_data_list, 1);
264
 
        adl->len = last_size + 4;       /* Length of each element */
265
 
        adl->num = length;      /* Number of primary or secondary services */
266
 
        adl->data = g_malloc(length * sizeof(uint8_t *));
 
384
        adl = att_data_list_alloc(length, last_size + 4);
267
385
 
268
386
        for (i = 0, l = groups; l; l = l->next, i++) {
269
387
                uint8_t *value;
270
388
 
271
389
                cur = l->data;
272
390
 
273
 
                adl->data[i] = g_malloc(adl->len);
274
391
                value = (void *) adl->data[i];
275
392
 
276
393
                att_put_u16(cur->handle, value);
289
406
}
290
407
 
291
408
static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
292
 
                                                uint16_t end, uuid_t *uuid,
 
409
                                                uint16_t end, bt_uuid_t *uuid,
293
410
                                                uint8_t *pdu, int len)
294
411
{
295
412
        struct att_data_list *adl;
304
421
                                        ATT_ECODE_INVALID_HANDLE, pdu, len);
305
422
 
306
423
        for (l = database, length = 0, types = NULL; l; l = l->next) {
 
424
                struct attribute *client_attr;
 
425
 
307
426
                a = l->data;
308
427
 
309
428
                if (a->handle < start)
312
431
                if (a->handle >= end)
313
432
                        break;
314
433
 
315
 
                if (sdp_uuid_cmp(&a->uuid, uuid)  != 0)
 
434
                if (bt_uuid_cmp(&a->uuid, uuid)  != 0)
316
435
                        continue;
317
436
 
318
437
                status = att_check_reqs(channel, ATT_OP_READ_BY_TYPE_REQ,
319
438
                                                                a->read_reqs);
 
439
 
 
440
                client_attr = client_cfg_attribute(channel, a, a->data, a->len);
 
441
                if (client_attr)
 
442
                        a = client_attr;
 
443
 
 
444
                if (status == 0x00 && a->read_cb)
 
445
                        status = a->read_cb(a, a->cb_user_data);
 
446
 
320
447
                if (status) {
321
448
                        g_slist_free(types);
322
449
                        return enc_error_resp(ATT_OP_READ_BY_TYPE_REQ,
341
468
        /* Handle length plus attribute value length */
342
469
        length += 2;
343
470
 
344
 
        adl = g_new0(struct att_data_list, 1);
345
 
        adl->len = length;      /* Length of each element */
346
 
        adl->num = num;         /* Number of primary or secondary services */
347
 
        adl->data = g_malloc(num * sizeof(uint8_t *));
 
471
        adl = att_data_list_alloc(num, length);
348
472
 
349
473
        for (i = 0, l = types; l; i++, l = l->next) {
350
474
                uint8_t *value;
351
475
 
352
476
                a = l->data;
353
 
                adl->data[i] = g_malloc(length);
354
477
 
355
478
                value = (void *) adl->data[i];
356
479
 
373
496
        struct attribute *a;
374
497
        struct att_data_list *adl;
375
498
        GSList *l, *info;
376
 
        uint8_t format, last_type = SDP_UUID_UNSPEC;
 
499
        uint8_t format, last_type = BT_UUID_UNSPEC;
377
500
        uint16_t length, num;
378
501
        int i;
379
502
 
390
513
                if (a->handle > end)
391
514
                        break;
392
515
 
393
 
                if (last_type == SDP_UUID_UNSPEC)
 
516
                if (last_type == BT_UUID_UNSPEC)
394
517
                        last_type = a->uuid.type;
395
518
 
396
519
                if (a->uuid.type != last_type)
406
529
                return enc_error_resp(ATT_OP_FIND_INFO_REQ, start,
407
530
                                        ATT_ECODE_ATTR_NOT_FOUND, pdu, len);
408
531
 
409
 
        if (last_type == SDP_UUID16) {
 
532
        if (last_type == BT_UUID16) {
410
533
                length = 2;
411
534
                format = 0x01;
412
 
        } else if (last_type == SDP_UUID128) {
 
535
        } else if (last_type == BT_UUID128) {
413
536
                length = 16;
414
537
                format = 0x02;
415
538
        }
416
539
 
417
 
        adl = g_new0(struct att_data_list, 1);
418
 
        adl->len = length + 2;  /* Length of each element */
419
 
        adl->num = num;         /* Number of primary or secondary services */
420
 
        adl->data = g_malloc(num * sizeof(uint8_t *));
 
540
        adl = att_data_list_alloc(num, length + 2);
421
541
 
422
542
        for (i = 0, l = info; l; i++, l = l->next) {
423
543
                uint8_t *value;
424
544
 
425
545
                a = l->data;
426
 
                adl->data[i] = g_malloc(adl->len);
427
546
 
428
547
                value = (void *) adl->data[i];
429
548
 
430
549
                att_put_u16(a->handle, value);
431
550
 
432
551
                /* Attribute Value */
433
 
                memcpy(&value[2], &a->uuid.value, length);
 
552
                att_put_uuid(a->uuid, &value[2]);
434
553
        }
435
554
 
436
555
        length = enc_find_info_resp(format, adl, pdu, len);
441
560
        return length;
442
561
}
443
562
 
444
 
static int find_by_type(uint16_t start, uint16_t end, uuid_t *uuid,
 
563
static int find_by_type(uint16_t start, uint16_t end, bt_uuid_t *uuid,
445
564
                        const uint8_t *value, int vlen, uint8_t *opdu, int mtu)
446
565
{
447
566
        struct attribute *a;
464
583
                        break;
465
584
 
466
585
                /* Primary service? Attribute value matches? */
467
 
                if ((sdp_uuid_cmp(&a->uuid, uuid) == 0) && (a->len == vlen) &&
 
586
                if ((bt_uuid_cmp(&a->uuid, uuid) == 0) && (a->len == vlen) &&
468
587
                                        (memcmp(a->data, value, vlen) == 0)) {
469
588
 
470
589
                        range = g_new0(struct att_range, 1);
471
590
                        range->start = a->handle;
 
591
                        /* It is allowed to have end group handle the same as
 
592
                         * start handle, for groups with only one attribute. */
 
593
                        range->end = a->handle;
472
594
 
473
595
                        matches = g_slist_append(matches, range);
474
596
                } else if (range) {
475
597
                        /* Update the last found handle or reset the pointer
476
598
                         * to track that a new group started: Primary or
477
599
                         * Secondary service. */
478
 
                        if (sdp_uuid_cmp(&a->uuid, &prim_uuid) == 0 ||
479
 
                                        sdp_uuid_cmp(&a->uuid, &snd_uuid) == 0)
 
600
                        if (bt_uuid_cmp(&a->uuid, &prim_uuid) == 0 ||
 
601
                                        bt_uuid_cmp(&a->uuid, &snd_uuid) == 0)
480
602
                                range = NULL;
481
603
                        else
482
604
                                range->end = a->handle;
483
605
                }
484
606
        }
485
607
 
486
 
        if (range) {
487
 
                if (l == NULL) {
488
 
                        /* Avoids another iteration */
489
 
                        range->end = 0xFFFF;
490
 
                } else if (range->end == 0) {
491
 
                        /* Broken requests: requested End Handle is not
492
 
                         * 0xFFFF. Given handle is in the middle of a
493
 
                         * service definition. */
494
 
                        matches = g_slist_remove(matches, range);
495
 
                        g_free(range);
496
 
                }
497
 
        }
498
 
 
499
608
        if (matches == NULL)
500
609
                return enc_error_resp(ATT_OP_FIND_BY_TYPE_REQ, start,
501
610
                                ATT_ECODE_ATTR_NOT_FOUND, opdu, mtu);
508
617
        return len;
509
618
}
510
619
 
511
 
static int handle_cmp(gconstpointer a, gconstpointer b)
512
 
{
513
 
        const struct attribute *attrib = a;
514
 
        uint16_t handle = GPOINTER_TO_UINT(b);
515
 
 
516
 
        return attrib->handle - handle;
517
 
}
518
 
 
519
 
static int attribute_cmp(gconstpointer a1, gconstpointer a2)
520
 
{
521
 
        const struct attribute *attrib1 = a1;
522
 
        const struct attribute *attrib2 = a2;
523
 
 
524
 
        return attrib1->handle - attrib2->handle;
525
 
}
526
 
 
527
620
static struct attribute *find_primary_range(uint16_t start, uint16_t *end)
528
621
{
529
622
        struct attribute *attrib;
534
627
                return NULL;
535
628
 
536
629
        l = g_slist_find_custom(database, GUINT_TO_POINTER(h), handle_cmp);
537
 
 
538
630
        if (!l)
539
631
                return NULL;
540
632
 
541
633
        attrib = l->data;
542
634
 
543
 
        if (sdp_uuid_cmp(&attrib->uuid, &prim_uuid) != 0)
 
635
        if (bt_uuid_cmp(&attrib->uuid, &prim_uuid) != 0)
544
636
                return NULL;
545
637
 
546
638
        *end = start;
548
640
        for (l = l->next; l; l = l->next) {
549
641
                struct attribute *a = l->data;
550
642
 
551
 
                if (sdp_uuid_cmp(&a->uuid, &prim_uuid) == 0 ||
552
 
                                sdp_uuid_cmp(&a->uuid, &snd_uuid) == 0)
 
643
                if (bt_uuid_cmp(&a->uuid, &prim_uuid) == 0 ||
 
644
                                bt_uuid_cmp(&a->uuid, &snd_uuid) == 0)
553
645
                        break;
554
646
 
555
647
                *end = a->handle;
561
653
static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
562
654
                                                        uint8_t *pdu, int len)
563
655
{
564
 
        struct attribute *a;
 
656
        struct attribute *a, *client_attr;
565
657
        uint8_t status;
566
658
        GSList *l;
567
659
        guint h = handle;
574
666
        a = l->data;
575
667
 
576
668
        status = att_check_reqs(channel, ATT_OP_READ_REQ, a->read_reqs);
 
669
 
 
670
        client_attr = client_cfg_attribute(channel, a, a->data, a->len);
 
671
        if (client_attr)
 
672
                a = client_attr;
 
673
 
 
674
        if (status == 0x00 && a->read_cb)
 
675
                status = a->read_cb(a, a->cb_user_data);
 
676
 
577
677
        if (status)
578
678
                return enc_error_resp(ATT_OP_READ_REQ, handle, status, pdu,
579
679
                                                                        len);
584
684
static uint16_t read_blob(struct gatt_channel *channel, uint16_t handle,
585
685
                                        uint16_t offset, uint8_t *pdu, int len)
586
686
{
587
 
        struct attribute *a;
 
687
        struct attribute *a, *client_attr;
588
688
        uint8_t status;
589
689
        GSList *l;
590
690
        guint h = handle;
601
701
                                        ATT_ECODE_INVALID_OFFSET, pdu, len);
602
702
 
603
703
        status = att_check_reqs(channel, ATT_OP_READ_BLOB_REQ, a->read_reqs);
 
704
 
 
705
        client_attr = client_cfg_attribute(channel, a, a->data, a->len);
 
706
        if (client_attr)
 
707
                a = client_attr;
 
708
 
 
709
        if (status == 0x00 && a->read_cb)
 
710
                status = a->read_cb(a, a->cb_user_data);
 
711
 
604
712
        if (status)
605
713
                return enc_error_resp(ATT_OP_READ_BLOB_REQ, handle, status,
606
714
                                                                pdu, len);
612
720
                                                const uint8_t *value, int vlen,
613
721
                                                uint8_t *pdu, int len)
614
722
{
615
 
        struct attribute *a;
 
723
        struct attribute *a, *client_attr;
616
724
        uint8_t status;
617
725
        GSList *l;
618
726
        guint h = handle;
619
 
        uuid_t uuid;
620
727
 
621
728
        l = g_slist_find_custom(database, GUINT_TO_POINTER(h), handle_cmp);
622
729
        if (!l)
630
737
                return enc_error_resp(ATT_OP_WRITE_REQ, handle, status, pdu,
631
738
                                                                        len);
632
739
 
633
 
        memcpy(&uuid, &a->uuid, sizeof(uuid_t));
634
 
        attrib_db_update(handle, &uuid, value, vlen);
 
740
        client_attr = client_cfg_attribute(channel, a, value, vlen);
 
741
        if (client_attr)
 
742
                a = client_attr;
 
743
        else
 
744
                attrib_db_update(a->handle, &a->uuid, value, vlen);
 
745
 
 
746
        if (a->write_cb) {
 
747
                status = a->write_cb(a, a->cb_user_data);
 
748
                if (status)
 
749
                        return enc_error_resp(ATT_OP_WRITE_REQ, handle, status,
 
750
                                                                pdu, len);
 
751
        }
 
752
 
 
753
        DBG("Notifications: %d, indications: %d",
 
754
                                        g_slist_length(channel->notify),
 
755
                                        g_slist_length(channel->indicate));
635
756
 
636
757
        return enc_write_resp(pdu, len);
637
758
}
639
760
static uint16_t mtu_exchange(struct gatt_channel *channel, uint16_t mtu,
640
761
                uint8_t *pdu, int len)
641
762
{
642
 
        channel->mtu = MIN(mtu, channel->mtu);
643
 
 
644
 
        return enc_mtu_resp(channel->mtu, pdu, len);
 
763
        guint old_mtu = channel->mtu;
 
764
 
 
765
        if (mtu < ATT_DEFAULT_LE_MTU)
 
766
                channel->mtu = ATT_DEFAULT_LE_MTU;
 
767
        else
 
768
                channel->mtu = MIN(mtu, channel->mtu);
 
769
 
 
770
        bt_io_set(le_io, BT_IO_L2CAP, NULL,
 
771
                        BT_IO_OPT_OMTU, channel->mtu,
 
772
                        BT_IO_OPT_INVALID);
 
773
 
 
774
        return enc_mtu_resp(old_mtu, pdu, len);
645
775
}
646
776
 
647
777
static void channel_disconnect(void *user_data)
651
781
        g_attrib_unref(channel->attrib);
652
782
        clients = g_slist_remove(clients, channel);
653
783
 
 
784
        g_slist_free(channel->notify);
 
785
        g_slist_free(channel->indicate);
 
786
        g_slist_foreach(channel->configs, (GFunc) g_free, NULL);
 
787
        g_slist_free(channel->configs);
 
788
 
654
789
        g_free(channel);
655
790
}
656
791
 
660
795
        struct gatt_channel *channel = user_data;
661
796
        uint8_t opdu[ATT_MAX_MTU], value[ATT_MAX_MTU];
662
797
        uint16_t length, start, end, mtu, offset;
663
 
        uuid_t uuid;
 
798
        bt_uuid_t uuid;
664
799
        uint8_t status = 0;
665
800
        int vlen;
666
801
 
706
841
                length = read_blob(channel, start, offset, opdu, channel->mtu);
707
842
                break;
708
843
        case ATT_OP_MTU_REQ:
 
844
                if (!channel->le) {
 
845
                        status = ATT_ECODE_REQ_NOT_SUPP;
 
846
                        goto done;
 
847
                }
 
848
 
709
849
                length = dec_mtu_req(ipdu, len, &mtu);
710
850
                if (length == 0) {
711
851
                        status = ATT_ECODE_INVALID_PDU;
750
890
                length = find_by_type(start, end, &uuid, value, vlen,
751
891
                                                        opdu, channel->mtu);
752
892
                break;
 
893
        case ATT_OP_HANDLE_CNF:
 
894
                return;
753
895
        case ATT_OP_READ_MULTI_REQ:
754
896
        case ATT_OP_PREP_WRITE_REQ:
755
897
        case ATT_OP_EXEC_WRITE_REQ:
774
916
static void connect_event(GIOChannel *io, GError *err, void *user_data)
775
917
{
776
918
        struct gatt_channel *channel;
777
 
        GIOChannel **server_io = user_data;
 
919
        uint16_t cid;
778
920
        GError *gerr = NULL;
779
921
 
780
922
        if (err) {
787
929
        bt_io_get(io, BT_IO_L2CAP, &gerr,
788
930
                        BT_IO_OPT_SOURCE_BDADDR, &channel->src,
789
931
                        BT_IO_OPT_DEST_BDADDR, &channel->dst,
 
932
                        BT_IO_OPT_CID, &cid,
 
933
                        BT_IO_OPT_OMTU, &channel->mtu,
790
934
                        BT_IO_OPT_INVALID);
791
935
        if (gerr) {
792
936
                error("bt_io_get: %s", gerr->message);
796
940
                return;
797
941
        }
798
942
 
799
 
        if (server_io == &l2cap_io)
800
 
                channel->mtu = ATT_DEFAULT_L2CAP_MTU;
 
943
        if (channel->mtu > ATT_MAX_MTU)
 
944
                channel->mtu = ATT_MAX_MTU;
 
945
 
 
946
        if (cid != GATT_CID)
 
947
                channel->le = FALSE;
801
948
        else
802
 
                channel->mtu = ATT_DEFAULT_LE_MTU;
 
949
                channel->le = TRUE;
803
950
 
804
951
        channel->attrib = g_attrib_new(io);
805
952
        g_io_channel_unref(io);
826
973
        return;
827
974
}
828
975
 
 
976
static void attrib_notify_clients(struct attribute *attr)
 
977
{
 
978
        guint handle = attr->handle;
 
979
        GSList *l;
 
980
 
 
981
        for (l = clients; l; l = l->next) {
 
982
                struct gatt_channel *channel = l->data;
 
983
 
 
984
                /* Notification */
 
985
                if (g_slist_find_custom(channel->notify,
 
986
                                        GUINT_TO_POINTER(handle), handle_cmp)) {
 
987
                        uint8_t pdu[ATT_MAX_MTU];
 
988
                        uint16_t len;
 
989
 
 
990
                        len = enc_notification(attr, pdu, channel->mtu);
 
991
                        if (len == 0)
 
992
                                continue;
 
993
 
 
994
                        g_attrib_send(channel->attrib, 0, pdu[0], pdu, len,
 
995
                                                        NULL, NULL, NULL);
 
996
                }
 
997
 
 
998
                /* Indication */
 
999
                if (g_slist_find_custom(channel->indicate,
 
1000
                                        GUINT_TO_POINTER(handle), handle_cmp)) {
 
1001
                        uint8_t pdu[ATT_MAX_MTU];
 
1002
                        uint16_t len;
 
1003
 
 
1004
                        len = enc_indication(attr, pdu, channel->mtu);
 
1005
                        if (len == 0)
 
1006
                                return;
 
1007
 
 
1008
                        g_attrib_send(channel->attrib, 0, pdu[0], pdu, len,
 
1009
                                                        NULL, NULL, NULL);
 
1010
                }
 
1011
        }
 
1012
}
 
1013
 
829
1014
static gboolean register_core_services(void)
830
1015
{
831
1016
        uint8_t atval[256];
832
 
        uuid_t uuid;
 
1017
        bt_uuid_t uuid;
833
1018
        uint16_t appearance = 0x0000;
834
1019
 
835
1020
        /* GAP service: primary service definition */
836
 
        sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
 
1021
        bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
837
1022
        att_put_u16(GENERIC_ACCESS_PROFILE_ID, &atval[0]);
838
1023
        attrib_db_add(0x0001, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
839
1024
 
840
1025
        /* GAP service: device name characteristic */
841
1026
        name_handle = 0x0006;
842
 
        sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
 
1027
        bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
843
1028
        atval[0] = ATT_CHAR_PROPER_READ;
844
1029
        att_put_u16(name_handle, &atval[1]);
845
1030
        att_put_u16(GATT_CHARAC_DEVICE_NAME, &atval[3]);
846
1031
        attrib_db_add(0x0004, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
847
1032
 
848
1033
        /* GAP service: device name attribute */
849
 
        sdp_uuid16_create(&uuid, GATT_CHARAC_DEVICE_NAME);
 
1034
        bt_uuid16_create(&uuid, GATT_CHARAC_DEVICE_NAME);
850
1035
        attrib_db_add(name_handle, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
851
1036
                                                                NULL, 0);
852
1037
 
853
1038
        /* GAP service: device appearance characteristic */
854
1039
        appearance_handle = 0x0008;
855
 
        sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
 
1040
        bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
856
1041
        atval[0] = ATT_CHAR_PROPER_READ;
857
1042
        att_put_u16(appearance_handle, &atval[1]);
858
1043
        att_put_u16(GATT_CHARAC_APPEARANCE, &atval[3]);
859
1044
        attrib_db_add(0x0007, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
860
1045
 
861
1046
        /* GAP service: device appearance attribute */
862
 
        sdp_uuid16_create(&uuid, GATT_CHARAC_APPEARANCE);
 
1047
        bt_uuid16_create(&uuid, GATT_CHARAC_APPEARANCE);
863
1048
        att_put_u16(appearance, &atval[0]);
864
1049
        attrib_db_add(appearance_handle, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
865
1050
                                                                atval, 2);
866
1051
        gap_sdp_handle = attrib_create_sdp(0x0001, "Generic Access Profile");
867
 
 
868
1052
        if (gap_sdp_handle == 0) {
869
1053
                error("Failed to register GAP service record");
870
1054
                goto failed;
871
1055
        }
872
1056
 
873
1057
        /* GATT service: primary service definition */
874
 
        sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
 
1058
        bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
875
1059
        att_put_u16(GENERIC_ATTRIB_PROFILE_ID, &atval[0]);
876
1060
        attrib_db_add(0x0010, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
877
1061
 
897
1081
 
898
1082
        /* BR/EDR socket */
899
1083
        l2cap_io = bt_io_listen(BT_IO_L2CAP, NULL, confirm_event,
900
 
                                        &l2cap_io, NULL, &gerr,
 
1084
                                        NULL, NULL, &gerr,
901
1085
                                        BT_IO_OPT_SOURCE_BDADDR, BDADDR_ANY,
902
1086
                                        BT_IO_OPT_PSM, GATT_PSM,
903
1087
                                        BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
904
1088
                                        BT_IO_OPT_INVALID);
905
 
 
906
1089
        if (l2cap_io == NULL) {
907
1090
                error("%s", gerr->message);
908
1091
                g_error_free(gerr);
922
1105
                                        BT_IO_OPT_CID, GATT_CID,
923
1106
                                        BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
924
1107
                                        BT_IO_OPT_INVALID);
925
 
 
926
1108
        if (le_io == NULL) {
927
1109
                error("%s", gerr->message);
928
1110
                g_error_free(gerr);
963
1145
        for (l = clients; l; l = l->next) {
964
1146
                struct gatt_channel *channel = l->data;
965
1147
 
 
1148
                g_slist_free(channel->notify);
 
1149
                g_slist_free(channel->indicate);
 
1150
                g_slist_foreach(channel->configs, (GFunc) g_free, NULL);
 
1151
                g_slist_free(channel->configs);
 
1152
 
966
1153
                g_attrib_unref(channel->attrib);
967
1154
                g_free(channel);
968
1155
        }
996
1183
                return 0;
997
1184
 
998
1185
        record = server_record_new(&svc, handle, end);
999
 
 
1000
1186
        if (record == NULL)
1001
1187
                return 0;
1002
1188
 
1023
1209
        remove_record_from_server(sdp_handle);
1024
1210
}
1025
1211
 
1026
 
int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs,
1027
 
                                                const uint8_t *value, int len)
 
1212
struct attribute *attrib_db_add(uint16_t handle, bt_uuid_t *uuid, int read_reqs,
 
1213
                                int write_reqs, const uint8_t *value, int len)
1028
1214
{
1029
1215
        struct attribute *a;
1030
1216
 
1032
1218
 
1033
1219
        a = g_malloc0(sizeof(struct attribute) + len);
1034
1220
        a->handle = handle;
1035
 
        memcpy(&a->uuid, uuid, sizeof(uuid_t));
 
1221
        memcpy(&a->uuid, uuid, sizeof(bt_uuid_t));
1036
1222
        a->read_reqs = read_reqs;
1037
1223
        a->write_reqs = write_reqs;
1038
1224
        a->len = len;
1040
1226
 
1041
1227
        database = g_slist_insert_sorted(database, a, attribute_cmp);
1042
1228
 
1043
 
        return 0;
 
1229
        return a;
1044
1230
}
1045
1231
 
1046
 
int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value,
 
1232
int attrib_db_update(uint16_t handle, bt_uuid_t *uuid, const uint8_t *value,
1047
1233
                                                                int len)
1048
1234
{
1049
1235
        struct attribute *a;
1060
1246
 
1061
1247
        l->data = a;
1062
1248
        a->handle = handle;
1063
 
        memcpy(&a->uuid, uuid, sizeof(uuid_t));
 
1249
        if (uuid != &a->uuid)
 
1250
                memcpy(&a->uuid, uuid, sizeof(bt_uuid_t));
1064
1251
        a->len = len;
1065
1252
        memcpy(a->data, value, len);
1066
1253
 
1067
 
        /*
1068
 
         * <<Client/Server Characteristic Configuration>> descriptors are
1069
 
         * not supported yet. If a given attribute changes, the attribute
1070
 
         * server shall report the new values using the mechanism selected
1071
 
         * by the client. Notification/Indication shall not be automatically
1072
 
         * sent if the client didn't request them.
1073
 
         */
 
1254
        attrib_notify_clients(a);
1074
1255
 
1075
1256
        return 0;
1076
1257
}
1094
1275
 
1095
1276
int attrib_gap_set(uint16_t uuid, const uint8_t *value, int len)
1096
1277
{
1097
 
        uuid_t u16;
 
1278
        bt_uuid_t u16;
1098
1279
        uint16_t handle;
1099
1280
 
1100
1281
        /* FIXME: Missing Privacy and Reconnection Address */
1101
1282
 
1102
 
        sdp_uuid16_create(&u16, uuid);
 
1283
        bt_uuid16_create(&u16, uuid);
1103
1284
 
1104
1285
        switch (uuid) {
1105
1286
        case GATT_CHARAC_DEVICE_NAME: