~ubuntu-branches/ubuntu/wily/bluez/wily

« back to all changes in this revision

Viewing changes to plugins/mgmtops.c

ImportĀ upstreamĀ versionĀ 4.81

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 *  BlueZ - Bluetooth protocol stack for Linux
 
4
 *
 
5
 *  Copyright (C) 2010  Nokia Corporation
 
6
 *  Copyright (C) 2010  Marcel Holtmann <marcel@holtmann.org>
 
7
 *
 
8
 *  This program is free software; you can redistribute it and/or modify
 
9
 *  it under the terms of the GNU General Public License as published by
 
10
 *  the Free Software Foundation; either version 2 of the License, or
 
11
 *  (at your option) any later version.
 
12
 *
 
13
 *  This program is distributed in the hope that it will be useful,
 
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 *  GNU General Public License for more details.
 
17
 *
 
18
 *  You should have received a copy of the GNU General Public License
 
19
 *  along with this program; if not, write to the Free Software
 
20
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
21
 *
 
22
 */
 
23
 
 
24
#ifdef HAVE_CONFIG_H
 
25
#include <config.h>
 
26
#endif
 
27
 
 
28
#include <stdio.h>
 
29
#include <errno.h>
 
30
#include <unistd.h>
 
31
#include <stdlib.h>
 
32
#include <sys/types.h>
 
33
#include <sys/ioctl.h>
 
34
#include <sys/wait.h>
 
35
 
 
36
#include <glib.h>
 
37
 
 
38
#include <bluetooth/bluetooth.h>
 
39
#include <bluetooth/hci.h>
 
40
#include <bluetooth/mgmt.h>
 
41
 
 
42
#include "plugin.h"
 
43
#include "log.h"
 
44
#include "manager.h"
 
45
#include "adapter.h"
 
46
#include "device.h"
 
47
#include "event.h"
 
48
 
 
49
#define MGMT_BUF_SIZE 1024
 
50
 
 
51
static int max_index = -1;
 
52
static struct controller_info {
 
53
        gboolean valid;
 
54
        gboolean notified;
 
55
        uint8_t type;
 
56
        bdaddr_t bdaddr;
 
57
        uint8_t features[8];
 
58
        uint16_t manufacturer;
 
59
        uint8_t hci_ver;
 
60
        uint16_t hci_rev;
 
61
        gboolean enabled;
 
62
        uint8_t mode;
 
63
} *controllers = NULL;
 
64
 
 
65
static int mgmt_sock = -1;
 
66
static guint mgmt_watch = 0;
 
67
 
 
68
static uint8_t mgmt_version = 0;
 
69
static uint16_t mgmt_revision = 0;
 
70
 
 
71
static void read_version_complete(int sk, void *buf, size_t len)
 
72
{
 
73
        struct mgmt_hdr hdr;
 
74
        struct mgmt_rp_read_version *rp = buf;
 
75
 
 
76
        if (len < sizeof(*rp)) {
 
77
                error("Too small read version complete event");
 
78
                return;
 
79
        }
 
80
 
 
81
        mgmt_revision = btohs(bt_get_unaligned(&rp->revision));
 
82
        mgmt_version = rp->version;
 
83
 
 
84
        DBG("version %u revision %u", mgmt_version, mgmt_revision);
 
85
 
 
86
        memset(&hdr, 0, sizeof(hdr));
 
87
        hdr.opcode = MGMT_OP_READ_INDEX_LIST;
 
88
        if (write(sk, &hdr, sizeof(hdr)) < 0)
 
89
                error("Unable to read controller index list: %s (%d)",
 
90
                                                strerror(errno), errno);
 
91
}
 
92
 
 
93
static void add_controller(uint16_t index)
 
94
{
 
95
        if (index > max_index) {
 
96
                size_t size = sizeof(struct controller_info) * (index + 1);
 
97
                max_index = index;
 
98
                controllers = g_realloc(controllers, size);
 
99
        }
 
100
 
 
101
        memset(&controllers[index], 0, sizeof(struct controller_info));
 
102
 
 
103
        controllers[index].valid = TRUE;
 
104
 
 
105
        DBG("Added controller %u", index);
 
106
}
 
107
 
 
108
static void read_info(int sk, uint16_t index)
 
109
{
 
110
        char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_read_info)];
 
111
        struct mgmt_hdr *hdr = (void *) buf;
 
112
        struct mgmt_cp_read_info *cp = (void *) &buf[sizeof(*hdr)];
 
113
 
 
114
        memset(buf, 0, sizeof(buf));
 
115
        hdr->opcode = MGMT_OP_READ_INFO;
 
116
        hdr->len = htobs(sizeof(*cp));
 
117
 
 
118
        cp->index = htobs(index);
 
119
 
 
120
        if (write(sk, buf, sizeof(buf)) < 0)
 
121
                error("Unable to send read_info command: %s (%d)",
 
122
                                                strerror(errno), errno);
 
123
}
 
124
 
 
125
static void mgmt_index_added(int sk, void *buf, size_t len)
 
126
{
 
127
        struct mgmt_ev_index_added *ev = buf;
 
128
        uint16_t index;
 
129
 
 
130
        if (len < sizeof(*ev)) {
 
131
                error("Too small index added event");
 
132
                return;
 
133
        }
 
134
 
 
135
        index = btohs(bt_get_unaligned(&ev->index));
 
136
 
 
137
        add_controller(index);
 
138
        read_info(sk, index);
 
139
}
 
140
 
 
141
static void remove_controller(uint16_t index)
 
142
{
 
143
        if (index > max_index)
 
144
                return;
 
145
 
 
146
        if (!controllers[index].valid)
 
147
                return;
 
148
 
 
149
        manager_unregister_adapter(index);
 
150
 
 
151
        memset(&controllers[index], 0, sizeof(struct controller_info));
 
152
 
 
153
        DBG("Removed controller %u", index);
 
154
}
 
155
 
 
156
static void mgmt_index_removed(int sk, void *buf, size_t len)
 
157
{
 
158
        struct mgmt_ev_index_removed *ev = buf;
 
159
        uint16_t index;
 
160
 
 
161
        if (len < sizeof(*ev)) {
 
162
                error("Too small index removed event");
 
163
                return;
 
164
        }
 
165
 
 
166
        index = btohs(bt_get_unaligned(&ev->index));
 
167
 
 
168
        remove_controller(index);
 
169
}
 
170
 
 
171
static void read_mode(int sk, uint16_t index)
 
172
{
 
173
        char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_read_mode)];
 
174
        struct mgmt_hdr *hdr = (void *) buf;
 
175
        struct mgmt_cp_read_mode *cp = (void *) &buf[sizeof(*hdr)];
 
176
 
 
177
        memset(buf, 0, sizeof(buf));
 
178
        hdr->opcode = MGMT_OP_READ_MODE;
 
179
        hdr->len = htobs(sizeof(*cp));
 
180
 
 
181
        cp->index = htobs(index);
 
182
 
 
183
        if (write(sk, buf, sizeof(buf)) < 0)
 
184
                error("Unable to send read_mode command: %s (%d)",
 
185
                                                strerror(errno), errno);
 
186
}
 
187
 
 
188
static void read_index_list_complete(int sk, void *buf, size_t len)
 
189
{
 
190
        struct mgmt_rp_read_index_list *rp = buf;
 
191
        uint16_t num;
 
192
        int i;
 
193
 
 
194
        if (len < sizeof(*rp)) {
 
195
                error("Too small read index list complete event");
 
196
                return;
 
197
        }
 
198
 
 
199
        num = btohs(bt_get_unaligned(&rp->num_controllers));
 
200
 
 
201
        if (num * sizeof(uint16_t) + sizeof(*rp) != len) {
 
202
                error("Incorrect packet size for index list event");
 
203
                return;
 
204
        }
 
205
 
 
206
        for (i = 0; i < num; i++) {
 
207
                uint16_t index;
 
208
 
 
209
                index = btohs(bt_get_unaligned(&rp->index[i]));
 
210
 
 
211
                add_controller(index);
 
212
                read_info(sk, index);
 
213
        }
 
214
}
 
215
 
 
216
static void read_info_complete(int sk, void *buf, size_t len)
 
217
{
 
218
        struct mgmt_rp_read_info *rp = buf;
 
219
        struct controller_info *info;
 
220
        uint16_t index;
 
221
        char addr[18];
 
222
 
 
223
        if (len < sizeof(*rp)) {
 
224
                error("Too small read info complete event");
 
225
                return;
 
226
        }
 
227
 
 
228
        if (rp->status != 0) {
 
229
                error("Reading controller info failed: %s (%u)",
 
230
                                        strerror(rp->status), rp->status);
 
231
                return;
 
232
        }
 
233
 
 
234
        index = btohs(bt_get_unaligned(&rp->index));
 
235
        if (index > max_index) {
 
236
                error("Unexpected index %u in read info complete", index);
 
237
                return;
 
238
        }
 
239
 
 
240
        info = &controllers[index];
 
241
        info->type = rp->type;
 
242
        bacpy(&info->bdaddr, &rp->bdaddr);
 
243
        memcpy(info->features, rp->features, 8);
 
244
        info->manufacturer = btohs(bt_get_unaligned(&rp->manufacturer));
 
245
        info->hci_ver = rp->hci_ver;
 
246
        info->hci_rev = btohs(bt_get_unaligned(&rp->hci_rev));
 
247
 
 
248
        ba2str(&info->bdaddr, addr);
 
249
        DBG("hci%u addr %s type %u manufacturer %d hci ver %d:%d",
 
250
                                index, addr, info->type, info->manufacturer,
 
251
                                info->hci_ver, info->hci_rev);
 
252
 
 
253
        read_mode(sk, index);
 
254
}
 
255
 
 
256
static void read_mode_complete(int sk, void *buf, size_t len)
 
257
{
 
258
        struct mgmt_rp_read_mode *rp = buf;
 
259
        struct controller_info *info;
 
260
        uint16_t index;
 
261
 
 
262
        if (len < sizeof(*rp)) {
 
263
                error("Too small read mode complete event (%zu != %zu)",
 
264
                                                        len, sizeof(*rp));
 
265
                return;
 
266
        }
 
267
 
 
268
        if (rp->status != 0) {
 
269
                error("Reading controller mode failed: %s (%u)",
 
270
                                        strerror(rp->status), rp->status);
 
271
                return;
 
272
        }
 
273
 
 
274
        index = btohs(bt_get_unaligned(&rp->index));
 
275
        if (index > max_index) {
 
276
                error("Unexpected index %u in read mode complete", index);
 
277
                return;
 
278
        }
 
279
 
 
280
        info = &controllers[index];
 
281
        info->enabled = rp->enabled ? TRUE : FALSE;
 
282
        info->mode = rp->mode;
 
283
 
 
284
        DBG("hci%u enabled %u mode %u", index, info->enabled, info->mode);
 
285
 
 
286
        manager_register_adapter(index, info->enabled);
 
287
 
 
288
        if (info->enabled)
 
289
                manager_start_adapter(index);
 
290
}
 
291
 
 
292
static void mgmt_cmd_complete(int sk, void *buf, size_t len)
 
293
{
 
294
        struct mgmt_ev_cmd_complete *ev = buf;
 
295
        uint16_t opcode;
 
296
 
 
297
        DBG("");
 
298
 
 
299
        if (len < sizeof(*ev)) {
 
300
                error("Too small management command complete event packet");
 
301
                return;
 
302
        }
 
303
 
 
304
        opcode = btohs(bt_get_unaligned(&ev->opcode));
 
305
 
 
306
        switch (opcode) {
 
307
        case MGMT_OP_READ_VERSION:
 
308
                read_version_complete(sk, ev->data, len - sizeof(*ev));
 
309
                break;
 
310
        case MGMT_OP_READ_INDEX_LIST:
 
311
                read_index_list_complete(sk, ev->data, len - sizeof(*ev));
 
312
                break;
 
313
        case MGMT_OP_READ_INFO:
 
314
                read_info_complete(sk, ev->data, len - sizeof(*ev));
 
315
                break;
 
316
        case MGMT_OP_READ_MODE:
 
317
                read_mode_complete(sk, ev->data, len - sizeof(*ev));
 
318
                break;
 
319
        default:
 
320
                error("Unknown command complete for opcode %u", opcode);
 
321
                break;
 
322
        }
 
323
}
 
324
 
 
325
static void mgmt_cmd_status(int sk, void *buf, size_t len)
 
326
{
 
327
        struct mgmt_ev_cmd_status *ev = buf;
 
328
        uint16_t opcode;
 
329
 
 
330
        if (len < sizeof(*ev)) {
 
331
                error("Too small management command status event packet");
 
332
                return;
 
333
        }
 
334
 
 
335
        opcode = btohs(bt_get_unaligned(&ev->opcode));
 
336
 
 
337
        DBG("status %u opcode %u", ev->status, opcode);
 
338
}
 
339
 
 
340
static void mgmt_controller_error(int sk, void *buf, size_t len)
 
341
{
 
342
        struct mgmt_ev_controller_error *ev = buf;
 
343
        uint16_t index;
 
344
 
 
345
        if (len < sizeof(*ev)) {
 
346
                error("Too small management controller error event packet");
 
347
                return;
 
348
        }
 
349
 
 
350
        index = btohs(bt_get_unaligned(&ev->index));
 
351
 
 
352
        DBG("index %u error_code %u", index, ev->error_code);
 
353
}
 
354
 
 
355
static gboolean mgmt_event(GIOChannel *io, GIOCondition cond, gpointer user_data)
 
356
{
 
357
        char buf[MGMT_BUF_SIZE];
 
358
        struct mgmt_hdr *hdr = (void *) buf;
 
359
        int sk;
 
360
        ssize_t ret;
 
361
        uint16_t len, opcode;
 
362
 
 
363
        DBG("cond %d", cond);
 
364
 
 
365
        if (cond & G_IO_NVAL)
 
366
                return FALSE;
 
367
 
 
368
        sk = g_io_channel_unix_get_fd(io);
 
369
 
 
370
        if (cond & (G_IO_ERR | G_IO_HUP)) {
 
371
                error("Error on management socket");
 
372
                return FALSE;
 
373
        }
 
374
 
 
375
        ret = read(sk, buf, sizeof(buf));
 
376
        if (ret < 0) {
 
377
                error("Unable to read from management socket: %s (%d)",
 
378
                                                strerror(errno), errno);
 
379
                return TRUE;
 
380
        }
 
381
 
 
382
        DBG("Received %zd bytes from management socket", ret);
 
383
 
 
384
        if (ret < MGMT_HDR_SIZE) {
 
385
                error("Too small Management packet");
 
386
                return TRUE;
 
387
        }
 
388
 
 
389
        opcode = btohs(bt_get_unaligned(&hdr->opcode));
 
390
        len = btohs(bt_get_unaligned(&hdr->len));
 
391
 
 
392
        if (ret != MGMT_HDR_SIZE + len) {
 
393
                error("Packet length mismatch. ret %zd len %u", ret, len);
 
394
                return TRUE;
 
395
        }
 
396
 
 
397
        switch (opcode) {
 
398
        case MGMT_EV_CMD_COMPLETE:
 
399
                mgmt_cmd_complete(sk, buf + MGMT_HDR_SIZE, len);
 
400
                break;
 
401
        case MGMT_EV_CMD_STATUS:
 
402
                mgmt_cmd_status(sk, buf + MGMT_HDR_SIZE, len);
 
403
                break;
 
404
        case MGMT_EV_CONTROLLER_ERROR:
 
405
                mgmt_controller_error(sk, buf + MGMT_HDR_SIZE, len);
 
406
                break;
 
407
        case MGMT_EV_INDEX_ADDED:
 
408
                mgmt_index_added(sk, buf + MGMT_HDR_SIZE, len);
 
409
                break;
 
410
        case MGMT_EV_INDEX_REMOVED:
 
411
                mgmt_index_removed(sk, buf + MGMT_HDR_SIZE, len);
 
412
                break;
 
413
        default:
 
414
                error("Unknown Management opcode %u", opcode);
 
415
                break;
 
416
        }
 
417
 
 
418
        return TRUE;
 
419
}
 
420
 
 
421
static int mgmt_setup(void)
 
422
{
 
423
        struct mgmt_hdr hdr;
 
424
        struct sockaddr_hci addr;
 
425
        GIOChannel *io;
 
426
        GIOCondition condition;
 
427
        int dd, err;
 
428
 
 
429
        dd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
 
430
        if (dd < 0)
 
431
                return -errno;
 
432
 
 
433
        memset(&addr, 0, sizeof(addr));
 
434
        addr.hci_family = AF_BLUETOOTH;
 
435
        addr.hci_dev = HCI_DEV_NONE;
 
436
        addr.hci_channel = HCI_CHANNEL_CONTROL;
 
437
 
 
438
        if (bind(dd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
 
439
                err = -errno;
 
440
                goto fail;
 
441
        }
 
442
 
 
443
        memset(&hdr, 0, sizeof(hdr));
 
444
        hdr.opcode = MGMT_OP_READ_VERSION;
 
445
        if (write(dd, &hdr, sizeof(hdr)) < 0) {
 
446
                err = -errno;
 
447
                goto fail;
 
448
        }
 
449
 
 
450
        io = g_io_channel_unix_new(dd);
 
451
        condition = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
 
452
        mgmt_watch = g_io_add_watch(io, condition, mgmt_event, NULL);
 
453
        g_io_channel_unref(io);
 
454
 
 
455
        mgmt_sock = dd;
 
456
 
 
457
        info("Bluetooth Management interface initialized");
 
458
 
 
459
        return 0;
 
460
 
 
461
fail:
 
462
        close(dd);
 
463
        return err;
 
464
}
 
465
 
 
466
static void mgmt_cleanup(void)
 
467
{
 
468
        g_free(controllers);
 
469
        controllers = NULL;
 
470
        max_index = -1;
 
471
 
 
472
        if (mgmt_sock >= 0) {
 
473
                close(mgmt_sock);
 
474
                mgmt_sock = -1;
 
475
        }
 
476
 
 
477
        if (mgmt_watch > 0) {
 
478
                g_source_remove(mgmt_watch);
 
479
                mgmt_watch = 0;
 
480
        }
 
481
}
 
482
 
 
483
static int mgmt_start(int index)
 
484
{
 
485
        DBG("index %d", index);
 
486
        return -ENOSYS;
 
487
}
 
488
 
 
489
static int mgmt_stop(int index)
 
490
{
 
491
        DBG("index %d", index);
 
492
        return -ENOSYS;
 
493
}
 
494
 
 
495
static int mgmt_powered(int index, gboolean powered)
 
496
{
 
497
        DBG("index %d powered %d", index, powered);
 
498
        return -ENOSYS;
 
499
}
 
500
 
 
501
static int mgmt_connectable(int index)
 
502
{
 
503
        DBG("index %d", index);
 
504
        return -ENOSYS;
 
505
}
 
506
 
 
507
static int mgmt_discoverable(int index)
 
508
{
 
509
        DBG("index %d", index);
 
510
        return -ENOSYS;
 
511
}
 
512
 
 
513
static int mgmt_set_class(int index, uint32_t class)
 
514
{
 
515
        DBG("index %d class %u", index, class);
 
516
        return -ENOSYS;
 
517
}
 
518
 
 
519
static int mgmt_set_limited_discoverable(int index, uint32_t class,
 
520
                                                        gboolean limited)
 
521
{
 
522
        DBG("index %d class %u, limited %d", index, class, limited);
 
523
        return -ENOSYS;
 
524
}
 
525
 
 
526
static int mgmt_start_inquiry(int index, uint8_t length, gboolean periodic)
 
527
{
 
528
        DBG("index %d length %u periodic %d", index, length, periodic);
 
529
        return -ENOSYS;
 
530
}
 
531
 
 
532
static int mgmt_stop_inquiry(int index)
 
533
{
 
534
        DBG("index %d", index);
 
535
        return -ENOSYS;
 
536
}
 
537
 
 
538
static int mgmt_start_scanning(int index)
 
539
{
 
540
        DBG("index %d", index);
 
541
        return -ENOSYS;
 
542
}
 
543
 
 
544
static int mgmt_stop_scanning(int index)
 
545
{
 
546
        DBG("index %d", index);
 
547
        return -ENOSYS;
 
548
}
 
549
 
 
550
static int mgmt_resolve_name(int index, bdaddr_t *bdaddr)
 
551
{
 
552
        char addr[18];
 
553
 
 
554
        ba2str(bdaddr, addr);
 
555
        DBG("index %d addr %s", index, addr);
 
556
 
 
557
        return -ENOSYS;
 
558
}
 
559
 
 
560
static int mgmt_set_name(int index, const char *name)
 
561
{
 
562
        DBG("index %d, name %s", index, name);
 
563
        return -ENOSYS;
 
564
}
 
565
 
 
566
static int mgmt_cancel_resolve_name(int index, bdaddr_t *bdaddr)
 
567
{
 
568
        char addr[18];
 
569
 
 
570
        ba2str(bdaddr, addr);
 
571
        DBG("index %d addr %s", index, addr);
 
572
 
 
573
        return -ENOSYS;
 
574
}
 
575
 
 
576
static int mgmt_fast_connectable(int index, gboolean enable)
 
577
{
 
578
        DBG("index %d enable %d", index, enable);
 
579
        return -ENOSYS;
 
580
}
 
581
 
 
582
static int mgmt_read_clock(int index, int handle, int which, int timeout,
 
583
                                        uint32_t *clock, uint16_t *accuracy)
 
584
{
 
585
        DBG("index %d handle %d which %d timeout %d", index, handle,
 
586
                                                        which, timeout);
 
587
        return -ENOSYS;
 
588
}
 
589
 
 
590
static int mgmt_conn_handle(int index, const bdaddr_t *bdaddr, int *handle)
 
591
{
 
592
        char addr[18];
 
593
 
 
594
        ba2str(bdaddr, addr);
 
595
        DBG("index %d addr %s", index, addr);
 
596
 
 
597
        return -ENOSYS;
 
598
}
 
599
 
 
600
static int mgmt_write_eir_data(int index, uint8_t *data)
 
601
{
 
602
        DBG("index %d", index);
 
603
        return -ENOSYS;
 
604
}
 
605
 
 
606
static int mgmt_read_bdaddr(int index, bdaddr_t *bdaddr)
 
607
{
 
608
        char addr[18];
 
609
        struct controller_info *info = &controllers[index];
 
610
 
 
611
        ba2str(&info->bdaddr, addr);
 
612
        DBG("index %d addr %s", index, addr);
 
613
 
 
614
        if (!info->valid)
 
615
                return -ENODEV;
 
616
 
 
617
        bacpy(bdaddr, &info->bdaddr);
 
618
 
 
619
        return 0;
 
620
}
 
621
 
 
622
static int mgmt_block_device(int index, bdaddr_t *bdaddr)
 
623
{
 
624
        char addr[18];
 
625
 
 
626
        ba2str(bdaddr, addr);
 
627
        DBG("index %d addr %s", index, addr);
 
628
 
 
629
        return -ENOSYS;
 
630
}
 
631
 
 
632
static int mgmt_unblock_device(int index, bdaddr_t *bdaddr)
 
633
{
 
634
        char addr[18];
 
635
 
 
636
        ba2str(bdaddr, addr);
 
637
        DBG("index %d addr %s", index, addr);
 
638
 
 
639
        return -ENOSYS;
 
640
}
 
641
 
 
642
static int mgmt_get_conn_list(int index, GSList **conns)
 
643
{
 
644
        DBG("index %d", index);
 
645
        return -ENOSYS;
 
646
}
 
647
 
 
648
static int mgmt_read_local_version(int index, struct hci_version *ver)
 
649
{
 
650
        struct controller_info *info = &controllers[index];
 
651
 
 
652
        DBG("index %d", index);
 
653
 
 
654
        if (!info->valid)
 
655
                return -ENODEV;
 
656
 
 
657
        memset(ver, 0, sizeof(*ver));
 
658
        ver->manufacturer = info->manufacturer;
 
659
        ver->hci_ver = info->hci_ver;
 
660
        ver->hci_rev = info->hci_rev;
 
661
 
 
662
        return 0;
 
663
}
 
664
 
 
665
static int mgmt_read_local_features(int index, uint8_t *features)
 
666
{
 
667
        struct controller_info *info = &controllers[index];
 
668
 
 
669
        DBG("index %d", index);
 
670
 
 
671
        if (!info->valid)
 
672
                return -ENODEV;
 
673
 
 
674
        memcpy(features, info->features, 8);
 
675
 
 
676
        return 0;
 
677
}
 
678
 
 
679
static int mgmt_read_local_ext_features(int index)
 
680
{
 
681
        DBG("index %d", index);
 
682
        return -ENOSYS;
 
683
}
 
684
 
 
685
static int mgmt_read_link_policy(int index)
 
686
{
 
687
        DBG("index %d", index);
 
688
        return -ENOSYS;
 
689
}
 
690
 
 
691
static int mgmt_disconnect(int index, uint16_t handle)
 
692
{
 
693
        DBG("index %d handle %u", index, handle);
 
694
        return -ENOSYS;
 
695
}
 
696
 
 
697
static int mgmt_remove_bonding(int index, bdaddr_t *bdaddr)
 
698
{
 
699
        char addr[18];
 
700
 
 
701
        ba2str(bdaddr, addr);
 
702
        DBG("index %d addr %s", index, addr);
 
703
 
 
704
        return -ENOSYS;
 
705
}
 
706
 
 
707
static int mgmt_request_authentication(int index, uint16_t handle)
 
708
{
 
709
        DBG("index %d handle %u", index, handle);
 
710
        return -ENOSYS;
 
711
}
 
712
 
 
713
static int mgmt_pincode_reply(int index, bdaddr_t *bdaddr, const char *pin)
 
714
{
 
715
        char addr[18];
 
716
 
 
717
        ba2str(bdaddr, addr);
 
718
        DBG("index %d addr %s pin %s", index, addr, pin);
 
719
 
 
720
        return -ENOSYS;
 
721
}
 
722
 
 
723
static int mgmt_confirm_reply(int index, bdaddr_t *bdaddr, gboolean success)
 
724
{
 
725
        char addr[18];
 
726
 
 
727
        ba2str(bdaddr, addr);
 
728
        DBG("index %d addr %s success %d", index, addr, success);
 
729
 
 
730
        return -ENOSYS;
 
731
}
 
732
 
 
733
static int mgmt_passkey_reply(int index, bdaddr_t *bdaddr, uint32_t passkey)
 
734
{
 
735
        char addr[18];
 
736
 
 
737
        ba2str(bdaddr, addr);
 
738
        DBG("index %d addr %s passkey %06u", index, addr, passkey);
 
739
 
 
740
        return -ENOSYS;
 
741
}
 
742
 
 
743
static int mgmt_get_auth_info(int index, bdaddr_t *bdaddr, uint8_t *auth)
 
744
{
 
745
        char addr[18];
 
746
 
 
747
        ba2str(bdaddr, addr);
 
748
        DBG("index %d addr %s", index, addr);
 
749
 
 
750
        return -ENOSYS;
 
751
}
 
752
 
 
753
static int mgmt_read_scan_enable(int index)
 
754
{
 
755
        DBG("index %d", index);
 
756
        return -ENOSYS;
 
757
}
 
758
 
 
759
static int mgmt_write_le_host(int index, uint8_t le, uint8_t simul)
 
760
{
 
761
        DBG("index %d le %u simul %u", index, le, simul);
 
762
        return -ENOSYS;
 
763
}
 
764
 
 
765
static int mgmt_get_remote_version(int index, uint16_t handle,
 
766
                                                        gboolean delayed)
 
767
{
 
768
        DBG("index %d handle %u delayed %d", index, handle, delayed);
 
769
        return -ENOSYS;
 
770
}
 
771
 
 
772
static int mgmt_encrypt_link(int index, bdaddr_t *dst, bt_hci_result_t cb,
 
773
                                                        gpointer user_data)
 
774
{
 
775
        char addr[18];
 
776
 
 
777
        ba2str(dst, addr);
 
778
        DBG("index %d addr %s", index, addr);
 
779
 
 
780
        return -ENOSYS;
 
781
}
 
782
 
 
783
static struct btd_adapter_ops mgmt_ops = {
 
784
        .setup = mgmt_setup,
 
785
        .cleanup = mgmt_cleanup,
 
786
        .start = mgmt_start,
 
787
        .stop = mgmt_stop,
 
788
        .set_powered = mgmt_powered,
 
789
        .set_connectable = mgmt_connectable,
 
790
        .set_discoverable = mgmt_discoverable,
 
791
        .set_limited_discoverable = mgmt_set_limited_discoverable,
 
792
        .start_inquiry = mgmt_start_inquiry,
 
793
        .stop_inquiry = mgmt_stop_inquiry,
 
794
        .start_scanning = mgmt_start_scanning,
 
795
        .stop_scanning = mgmt_stop_scanning,
 
796
        .resolve_name = mgmt_resolve_name,
 
797
        .cancel_resolve_name = mgmt_cancel_resolve_name,
 
798
        .set_name = mgmt_set_name,
 
799
        .set_class = mgmt_set_class,
 
800
        .set_fast_connectable = mgmt_fast_connectable,
 
801
        .read_clock = mgmt_read_clock,
 
802
        .get_conn_handle = mgmt_conn_handle,
 
803
        .write_eir_data = mgmt_write_eir_data,
 
804
        .read_bdaddr = mgmt_read_bdaddr,
 
805
        .block_device = mgmt_block_device,
 
806
        .unblock_device = mgmt_unblock_device,
 
807
        .get_conn_list = mgmt_get_conn_list,
 
808
        .read_local_version = mgmt_read_local_version,
 
809
        .read_local_features = mgmt_read_local_features,
 
810
        .read_local_ext_features = mgmt_read_local_ext_features,
 
811
        .read_link_policy = mgmt_read_link_policy,
 
812
        .disconnect = mgmt_disconnect,
 
813
        .remove_bonding = mgmt_remove_bonding,
 
814
        .request_authentication = mgmt_request_authentication,
 
815
        .pincode_reply = mgmt_pincode_reply,
 
816
        .confirm_reply = mgmt_confirm_reply,
 
817
        .passkey_reply = mgmt_passkey_reply,
 
818
        .get_auth_info = mgmt_get_auth_info,
 
819
        .read_scan_enable = mgmt_read_scan_enable,
 
820
        .write_le_host = mgmt_write_le_host,
 
821
        .get_remote_version = mgmt_get_remote_version,
 
822
        .encrypt_link = mgmt_encrypt_link,
 
823
};
 
824
 
 
825
static int mgmt_init(void)
 
826
{
 
827
        return btd_register_adapter_ops(&mgmt_ops, TRUE);
 
828
}
 
829
 
 
830
static void mgmt_exit(void)
 
831
{
 
832
        btd_adapter_cleanup_ops(&mgmt_ops);
 
833
}
 
834
 
 
835
BLUETOOTH_PLUGIN_DEFINE(mgmtops, VERSION,
 
836
                BLUETOOTH_PLUGIN_PRIORITY_LOW, mgmt_init, mgmt_exit)