~cyphermox/bluez/5.23

« back to all changes in this revision

Viewing changes to mgmt/main.c

  • Committer: Package Import Robot
  • Author(s): Nobuhiro Iwamatsu
  • Date: 2012-01-24 05:35:09 UTC
  • mfrom: (1.5.11) (7.1.6 experimental)
  • Revision ID: package-import@ubuntu.com-20120124053509-uwpwqi783lz08wm3
Tags: 4.98-1
* New upstream release.
* Update debian/bluetooth-dbus.conf.
* Update debian/control.
  Add Multi-Arch: foreign to bluez.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  BlueZ - Bluetooth protocol stack for Linux
 
3
 *
 
4
 *  Copyright (C) 2011  Intel Corporation. All rights reserved.
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
19
 *
 
20
 */
 
21
 
 
22
#ifdef HAVE_CONFIG_H
 
23
#include <config.h>
 
24
#endif
 
25
 
 
26
#include <stdlib.h>
 
27
#include <stdio.h>
 
28
#include <unistd.h>
 
29
#include <errno.h>
 
30
#include <string.h>
 
31
#include <sys/types.h>
 
32
#include <sys/socket.h>
 
33
#include <poll.h>
 
34
#include <getopt.h>
 
35
#include <stdbool.h>
 
36
 
 
37
#include <bluetooth/bluetooth.h>
 
38
#include <bluetooth/hci.h>
 
39
#include <bluetooth/hci_lib.h>
 
40
#include <bluetooth/mgmt.h>
 
41
 
 
42
#ifndef NELEM
 
43
#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
 
44
#endif
 
45
 
 
46
static const char *mgmt_op[] = {
 
47
        "<0x0000>",
 
48
        "Read Version",
 
49
        "Read Features",
 
50
        "Read Index List",
 
51
        "Read Controller Info",
 
52
        "Set Powered",
 
53
        "Set Discoverable",
 
54
        "Set Connectable",
 
55
        "Set Pairable",                 /* 0x0008 */
 
56
        "Add UUID",
 
57
        "Remove UUID",
 
58
        "Set Dev Class",
 
59
        "Set Service Cache",
 
60
        "Load Link Keys",
 
61
        "Remove Keys",
 
62
        "Disconnect",
 
63
        "Get Connections",              /* 0x0010 */
 
64
        "PIN Code Reply",
 
65
        "PIN Code Neg Reply",
 
66
        "Set IO Capability",
 
67
        "Pair Device",
 
68
        "User Confirm Reply",
 
69
        "User Confirm Neg Reply",
 
70
        "Set Local Name",
 
71
        "Read Local OOB Data",          /* 0x0018 */
 
72
        "Add Remote OOB Data",
 
73
        "Remove Remove OOB Data",
 
74
        "Start Discoery",
 
75
        "Block Device",
 
76
        "Unblock Device",
 
77
        "Set Fast Connectable",
 
78
};
 
79
 
 
80
static const char *mgmt_ev[] = {
 
81
        "<0x0000>",
 
82
        "Command Complete",
 
83
        "Command Status",
 
84
        "Controller Error",
 
85
        "Index Added",
 
86
        "Index Removed",
 
87
        "Powered",
 
88
        "Discoverable",
 
89
        "Connectable",                  /* 0x0008 */
 
90
        "Pairable",
 
91
        "New Link Key",
 
92
        "Device Connected",
 
93
        "Device Disconnected",
 
94
        "Connect Failed",
 
95
        "PIN Code Request",
 
96
        "User Confirm Request",
 
97
        "Authentication Failed",        /* 0x0010 */
 
98
        "Local Name Changed",
 
99
        "Device Found",
 
100
        "Remote Name",
 
101
        "Discovering",
 
102
        "Device Blocked",
 
103
        "Device Unblocked",
 
104
};
 
105
 
 
106
static const char *mgmt_status[] = {
 
107
        "Success",
 
108
        "Unknown Command",
 
109
        "Not Connected",
 
110
        "Failed",
 
111
        "Connect Failed",
 
112
        "Authentication Failed",
 
113
        "Not Paired",
 
114
        "No Resources",
 
115
        "Timeout",
 
116
        "Already Connected",
 
117
        "Busy",
 
118
        "Rejected",
 
119
        "Not Supported",
 
120
        "Invalid Parameters",
 
121
        "Disconnected",
 
122
        "Not Powered",
 
123
};
 
124
 
 
125
static bool monitor = false;
 
126
static bool discovery = false;
 
127
static bool resolve_names = true;
 
128
 
 
129
typedef void (*cmd_cb)(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
 
130
                                void *rsp, uint16_t len, void *user_data);
 
131
 
 
132
static struct pending_cmd {
 
133
        uint16_t op;
 
134
        uint16_t id;
 
135
        cmd_cb cb;
 
136
        void *user_data;
 
137
        struct pending_cmd *next;
 
138
} *pending = NULL;
 
139
 
 
140
static const char *mgmt_opstr(uint16_t op)
 
141
{
 
142
        if (op >= NELEM(mgmt_op))
 
143
                return "<unknown opcode>";
 
144
        return mgmt_op[op];
 
145
}
 
146
 
 
147
static const char *mgmt_evstr(uint16_t ev)
 
148
{
 
149
        if (ev >= NELEM(mgmt_ev))
 
150
                return "<unknown event>";
 
151
        return mgmt_ev[ev];
 
152
}
 
153
 
 
154
static const char *mgmt_errstr(uint8_t status)
 
155
{
 
156
        if (status >= NELEM(mgmt_status))
 
157
                return "<unknown status>";
 
158
        return mgmt_status[status];
 
159
}
 
160
 
 
161
static int mgmt_send_cmd(int mgmt_sk, uint16_t op, uint16_t id, void *data,
 
162
                                size_t len, cmd_cb func, void *user_data)
 
163
{
 
164
        char buf[1024];
 
165
        struct pending_cmd *cmd;
 
166
        struct mgmt_hdr *hdr = (void *) buf;
 
167
 
 
168
        if (len + MGMT_HDR_SIZE > sizeof(buf))
 
169
                return -EINVAL;
 
170
 
 
171
        cmd = calloc(1, sizeof(struct pending_cmd));
 
172
        if (cmd == NULL)
 
173
                return -errno;
 
174
 
 
175
        cmd->op = op;
 
176
        cmd->id = id;
 
177
        cmd->cb = func;
 
178
        cmd->user_data = user_data;
 
179
 
 
180
        memset(buf, 0, sizeof(buf));
 
181
        hdr->opcode = htobs(op);
 
182
        hdr->index = htobs(id);
 
183
        hdr->len = htobs(len);
 
184
        memcpy(buf + MGMT_HDR_SIZE, data, len);
 
185
 
 
186
        if (write(mgmt_sk, buf, MGMT_HDR_SIZE + len) < 0) {
 
187
                fprintf(stderr, "Unable to write to socket: %s\n",
 
188
                                                        strerror(errno));
 
189
                free(cmd);
 
190
                return -1;
 
191
        }
 
192
 
 
193
        cmd->next = pending;
 
194
        pending = cmd;
 
195
 
 
196
        return 0;
 
197
}
 
198
 
 
199
static int mgmt_open(void)
 
200
{
 
201
        struct sockaddr_hci addr;
 
202
        int sk;
 
203
 
 
204
        sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
 
205
        if (sk < 0) {
 
206
                fprintf(stderr, "socket: %s\n", strerror(errno));
 
207
                return sk;
 
208
        }
 
209
 
 
210
        memset(&addr, 0, sizeof(addr));
 
211
        addr.hci_family = AF_BLUETOOTH;
 
212
        addr.hci_dev = HCI_DEV_NONE;
 
213
        addr.hci_channel = HCI_CHANNEL_CONTROL;
 
214
 
 
215
        if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
 
216
                fprintf(stderr, "bind: %s\n", strerror(errno));
 
217
                close(sk);
 
218
                return -1;
 
219
        }
 
220
 
 
221
        return sk;
 
222
}
 
223
 
 
224
static void mgmt_check_pending(int mgmt_sk, uint16_t op, uint16_t index,
 
225
                                uint16_t status, void *data, uint16_t len)
 
226
{
 
227
        struct pending_cmd *c, *prev;
 
228
 
 
229
        for (c = pending, prev = NULL; c != NULL; prev = c, c = c->next) {
 
230
                if (c->op != op)
 
231
                        continue;
 
232
                if (c->id != index)
 
233
                        continue;
 
234
 
 
235
                if (c == pending)
 
236
                        pending = c->next;
 
237
                else
 
238
                        prev->next = c->next;
 
239
 
 
240
                c->cb(mgmt_sk, op, index, status, data, len, c->user_data);
 
241
 
 
242
                free(c);
 
243
        }
 
244
}
 
245
 
 
246
static int mgmt_cmd_complete(int mgmt_sk, uint16_t index,
 
247
                                struct mgmt_ev_cmd_complete *ev, uint16_t len)
 
248
{
 
249
        uint16_t op;
 
250
 
 
251
        if (len < sizeof(*ev)) {
 
252
                fprintf(stderr, "Too short (%u bytes) cmd complete event\n",
 
253
                                                                        len);
 
254
                return -EINVAL;
 
255
        }
 
256
 
 
257
        op = bt_get_le16(&ev->opcode);
 
258
 
 
259
        len -= sizeof(*ev);
 
260
 
 
261
        if (monitor)
 
262
                printf("%s complete, opcode 0x%04x len %u\n", mgmt_opstr(op),
 
263
                                                                op, len);
 
264
 
 
265
        mgmt_check_pending(mgmt_sk, op, index, 0, ev->data, len);
 
266
 
 
267
        return 0;
 
268
}
 
269
 
 
270
static int mgmt_cmd_status(int mgmt_sk, uint16_t index,
 
271
                                struct mgmt_ev_cmd_status *ev, uint16_t len)
 
272
{
 
273
        uint16_t opcode;
 
274
 
 
275
        if (len < sizeof(*ev)) {
 
276
                fprintf(stderr, "Too short (%u bytes) cmd status event\n",
 
277
                                                                        len);
 
278
                return -EINVAL;
 
279
        }
 
280
 
 
281
        opcode = bt_get_le16(&ev->opcode);
 
282
 
 
283
        if (monitor)
 
284
                printf("cmd status, opcode 0x%04x status 0x%02x (%s)\n",
 
285
                                opcode, ev->status, mgmt_errstr(ev->status));
 
286
 
 
287
        if (ev->status != 0)
 
288
                mgmt_check_pending(mgmt_sk, opcode, index, ev->status,
 
289
                                                                NULL, 0);
 
290
 
 
291
        return 0;
 
292
}
 
293
 
 
294
static int mgmt_controller_error(uint16_t index,
 
295
                                        struct mgmt_ev_controller_error *ev,
 
296
                                        uint16_t len)
 
297
{
 
298
        if (len < sizeof(*ev)) {
 
299
                fprintf(stderr,
 
300
                        "Too short (%u bytes) controller error event\n", len);
 
301
                return -EINVAL;
 
302
        }
 
303
 
 
304
        if (monitor)
 
305
                printf("hci%u error 0x%02x\n", index, ev->error_code);
 
306
 
 
307
        return 0;
 
308
}
 
309
 
 
310
static int mgmt_index_added(int mgmt_sk, uint16_t index)
 
311
{
 
312
        if (monitor)
 
313
                printf("hci%u added\n", index);
 
314
        return 0;
 
315
}
 
316
 
 
317
static int mgmt_index_removed(int mgmt_sk, uint16_t index)
 
318
{
 
319
        if (monitor)
 
320
                printf("hci%u removed\n", index);
 
321
        return 0;
 
322
}
 
323
 
 
324
static const char *settings_str[] = {
 
325
                                "powered",
 
326
                                "connectable",
 
327
                                "fast-connectable",
 
328
                                "discoverable",
 
329
                                "pairable",
 
330
                                "link-security",
 
331
                                "ssp",
 
332
                                "br/edr",
 
333
                                "hs",
 
334
                                "le" ,
 
335
};
 
336
 
 
337
static void print_settings(uint32_t settings)
 
338
{
 
339
        unsigned i;
 
340
 
 
341
        for (i = 0; i < NELEM(settings_str); i++) {
 
342
                if ((settings & (1 << i)) != 0)
 
343
                        printf("%s ", settings_str[i]);
 
344
        }
 
345
}
 
346
 
 
347
static int mgmt_new_settings(int mgmt_sk, uint16_t index,
 
348
                                        uint32_t *ev, uint16_t len)
 
349
{
 
350
        if (len < sizeof(*ev)) {
 
351
                fprintf(stderr, "Too short new_settings event (%u)\n", len);
 
352
                return -EINVAL;
 
353
        }
 
354
 
 
355
        if (monitor) {
 
356
                printf("hci%u new_settings: ", index);
 
357
                print_settings(bt_get_le32(ev));
 
358
                printf("\n");
 
359
        }
 
360
 
 
361
        return 0;
 
362
}
 
363
 
 
364
static int mgmt_discovering(int mgmt_sk, uint16_t index,
 
365
                                        struct mgmt_mode *ev, uint16_t len)
 
366
{
 
367
        if (len < sizeof(*ev)) {
 
368
                fprintf(stderr, "Too short (%u bytes) discovering event\n",
 
369
                                                                        len);
 
370
                return -EINVAL;
 
371
        }
 
372
 
 
373
        if (ev->val == 0 && discovery)
 
374
                exit(EXIT_SUCCESS);
 
375
 
 
376
        if (monitor)
 
377
                printf("hci%u discovering %s\n", index,
 
378
                                                ev->val ? "on" : "off");
 
379
 
 
380
        return 0;
 
381
}
 
382
 
 
383
static int mgmt_new_link_key(int mgmt_sk, uint16_t index,
 
384
                                struct mgmt_ev_new_link_key *ev, uint16_t len)
 
385
{
 
386
 
 
387
        if (len != sizeof(*ev)) {
 
388
                fprintf(stderr, "Invalid new_link_key length (%u bytes)\n",
 
389
                                                                        len);
 
390
                return -EINVAL;
 
391
        }
 
392
 
 
393
        if (monitor) {
 
394
                char addr[18];
 
395
                ba2str(&ev->key.bdaddr, addr);
 
396
                printf("hci%u new_link_key %s type 0x%02x pin_len %d "
 
397
                                "store_hint %u\n", index, addr, ev->key.type,
 
398
                                ev->key.pin_len, ev->store_hint);
 
399
        }
 
400
 
 
401
        return 0;
 
402
}
 
403
 
 
404
static const char *typestr(uint8_t type)
 
405
{
 
406
        const char *str[] = { "BR/EDR", "LE Public", "LE Random" };
 
407
 
 
408
        if (type <= MGMT_ADDR_LE_RANDOM)
 
409
                return str[type];
 
410
 
 
411
        return "(unknown)";
 
412
}
 
413
 
 
414
static int mgmt_connected(int mgmt_sk, uint16_t index, bool connected,
 
415
                                struct mgmt_addr_info *ev, uint16_t len)
 
416
{
 
417
        const char *ev_name = connected ? "connected" : "disconnected";
 
418
 
 
419
        if (len != sizeof(*ev)) {
 
420
                fprintf(stderr,
 
421
                        "Invalid %s event length (%u bytes)\n", ev_name, len);
 
422
                return -EINVAL;
 
423
        }
 
424
 
 
425
        if (monitor) {
 
426
                char addr[18];
 
427
                ba2str(&ev->bdaddr, addr);
 
428
                printf("hci%u %s type %s %s\n", index, addr,
 
429
                                                typestr(ev->type), ev_name);
 
430
        }
 
431
 
 
432
        return 0;
 
433
}
 
434
 
 
435
static int mgmt_conn_failed(int mgmt_sk, uint16_t index,
 
436
                                struct mgmt_ev_connect_failed *ev,
 
437
                                uint16_t len)
 
438
{
 
439
        if (len != sizeof(*ev)) {
 
440
                fprintf(stderr,
 
441
                        "Invalid connect_failed event length (%u bytes)\n", len);
 
442
                return -EINVAL;
 
443
        }
 
444
 
 
445
        if (monitor) {
 
446
                char addr[18];
 
447
                ba2str(&ev->addr.bdaddr, addr);
 
448
                printf("hci%u %s type %s connect failed (status 0x%02x, %s)\n",
 
449
                                index, addr, typestr(ev->addr.type), ev->status,
 
450
                                mgmt_errstr(ev->status));
 
451
        }
 
452
 
 
453
        return 0;
 
454
}
 
455
 
 
456
static int mgmt_auth_failed(int mgmt_sk, uint16_t index,
 
457
                                struct mgmt_ev_auth_failed *ev,
 
458
                                uint16_t len)
 
459
{
 
460
        if (len != sizeof(*ev)) {
 
461
                fprintf(stderr,
 
462
                        "Invalid auth_failed event length (%u bytes)\n", len);
 
463
                return -EINVAL;
 
464
        }
 
465
 
 
466
        if (monitor) {
 
467
                char addr[18];
 
468
                ba2str(&ev->bdaddr, addr);
 
469
                printf("hci%u %s auth failed with status 0x%02x (%s)\n",
 
470
                        index, addr, ev->status, mgmt_errstr(ev->status));
 
471
        }
 
472
 
 
473
        return 0;
 
474
}
 
475
 
 
476
static int mgmt_name_changed(int mgmt_sk, uint16_t index,
 
477
                                struct mgmt_ev_local_name_changed *ev,
 
478
                                uint16_t len)
 
479
{
 
480
        if (len != sizeof(*ev)) {
 
481
                fprintf(stderr,
 
482
                        "Invalid local_name_changed length (%u bytes)\n", len);
 
483
                return -EINVAL;
 
484
        }
 
485
 
 
486
        if (monitor)
 
487
                printf("hci%u name changed: %s\n", index, ev->name);
 
488
 
 
489
        return 0;
 
490
}
 
491
 
 
492
static void confirm_name_rsp(int mgmt_sk, uint16_t op, uint16_t id,
 
493
                                uint8_t status, void *rsp, uint16_t len,
 
494
                                void *user_data)
 
495
{
 
496
        struct mgmt_rp_confirm_name *rp = rsp;
 
497
        char addr[18];
 
498
 
 
499
        if (status != 0) {
 
500
                fprintf(stderr,
 
501
                        "hci%u confirm_name failed with status 0x%02x (%s)\n",
 
502
                                        id, status, mgmt_errstr(status));
 
503
                return;
 
504
        }
 
505
 
 
506
        if (len != sizeof(*rp)) {
 
507
                fprintf(stderr,
 
508
                        "hci%u confirm_name rsp length %u instead of %zu\n",
 
509
                        id, len, sizeof(*rp));
 
510
                return;
 
511
        }
 
512
 
 
513
        ba2str(&rp->bdaddr, addr);
 
514
 
 
515
        if (rp->status != 0)
 
516
                fprintf(stderr,
 
517
                        "hci%u confirm_name for %s failed: 0x%02x (%s)\n",
 
518
                        id, addr, rp->status, mgmt_errstr(status));
 
519
        else
 
520
                printf("hci%u confirm_name succeeded for %s\n", id, addr);
 
521
}
 
522
 
 
523
static int mgmt_device_found(int mgmt_sk, uint16_t index,
 
524
                                struct mgmt_ev_device_found *ev, uint16_t len)
 
525
{
 
526
        if (len != sizeof(*ev)) {
 
527
                fprintf(stderr,
 
528
                        "Invalid device_found event length (%u bytes)\n", len);
 
529
                return -EINVAL;
 
530
        }
 
531
 
 
532
        if (monitor || discovery) {
 
533
                char addr[18];
 
534
                ba2str(&ev->addr.bdaddr, addr);
 
535
                printf("hci%u dev_found: %s type %s class 0x%02x%02x%02x "
 
536
                        "rssi %d confirm_name %u eir (%s)\n", index, addr,
 
537
                        typestr(ev->addr.type),
 
538
                        ev->dev_class[2], ev->dev_class[1], ev->dev_class[0],
 
539
                        ev->rssi, ev->confirm_name,
 
540
                        ev->eir[0] == 0 ? "no" : "yes");
 
541
        }
 
542
 
 
543
        if (discovery && ev->confirm_name) {
 
544
                struct mgmt_cp_confirm_name cp;
 
545
 
 
546
                memset(&cp, 0, sizeof(cp));
 
547
                bacpy(&cp.bdaddr, &ev->addr.bdaddr);
 
548
                if (resolve_names)
 
549
                        cp.name_known = 0;
 
550
                else
 
551
                        cp.name_known = 1;
 
552
 
 
553
                mgmt_send_cmd(mgmt_sk, MGMT_OP_CONFIRM_NAME, index,
 
554
                                        &cp, sizeof(cp), confirm_name_rsp,
 
555
                                        NULL);
 
556
        }
 
557
 
 
558
        return 0;
 
559
}
 
560
 
 
561
static int mgmt_remote_name(int mgmt_sk, uint16_t index,
 
562
                                struct mgmt_ev_remote_name *ev, uint16_t len)
 
563
{
 
564
        if (len != sizeof(*ev)) {
 
565
                fprintf(stderr,
 
566
                        "Invalid remote_name event length (%u bytes)\n", len);
 
567
                return -EINVAL;
 
568
        }
 
569
 
 
570
        if (monitor || discovery) {
 
571
                char addr[18];
 
572
                ba2str(&ev->bdaddr, addr);
 
573
                printf("hci%u %s name %s\n", index, addr, ev->name);
 
574
        }
 
575
 
 
576
        return 0;
 
577
}
 
578
 
 
579
static void pin_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
 
580
                                void *rsp, uint16_t len, void *user_data)
 
581
{
 
582
        if (status != 0) {
 
583
                fprintf(stderr,
 
584
                        "hci%u PIN Code reply failed with status 0x%02x (%s)",
 
585
                                        id, status, mgmt_errstr(status));
 
586
                exit(EXIT_FAILURE);
 
587
        }
 
588
 
 
589
        printf("hci%u PIN Reply successful\n", id);
 
590
}
 
591
 
 
592
static int mgmt_pin_reply(int mgmt_sk, uint16_t index, bdaddr_t *bdaddr,
 
593
                                                const char *pin, size_t len)
 
594
{
 
595
        struct mgmt_cp_pin_code_reply cp;
 
596
 
 
597
        memset(&cp, 0, sizeof(cp));
 
598
        bacpy(&cp.bdaddr, bdaddr);
 
599
        cp.pin_len = len;
 
600
        memcpy(cp.pin_code, pin, len);
 
601
 
 
602
        return mgmt_send_cmd(mgmt_sk, MGMT_OP_PIN_CODE_REPLY, index,
 
603
                                        &cp, sizeof(cp), pin_rsp, NULL);
 
604
}
 
605
 
 
606
static void pin_neg_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
 
607
                                void *rsp, uint16_t len, void *user_data)
 
608
{
 
609
        if (status != 0) {
 
610
                fprintf(stderr,
 
611
                        "hci%u PIN Neg reply failed with status 0x%02x (%s)",
 
612
                                        id, status, mgmt_errstr(status));
 
613
                exit(EXIT_FAILURE);
 
614
        }
 
615
 
 
616
        printf("hci%u PIN Negative Reply successful\n", id);
 
617
}
 
618
 
 
619
static int mgmt_pin_neg_reply(int mgmt_sk, uint16_t index, bdaddr_t *bdaddr)
 
620
{
 
621
        struct mgmt_cp_pin_code_neg_reply cp;
 
622
 
 
623
        memset(&cp, 0, sizeof(cp));
 
624
        bacpy(&cp.bdaddr, bdaddr);
 
625
 
 
626
        return mgmt_send_cmd(mgmt_sk, MGMT_OP_PIN_CODE_NEG_REPLY, index,
 
627
                                        &cp, sizeof(cp), pin_neg_rsp, NULL);
 
628
}
 
629
 
 
630
static int mgmt_request_pin(int mgmt_sk, uint16_t index,
 
631
                                struct mgmt_ev_pin_code_request *ev,
 
632
                                uint16_t len)
 
633
{
 
634
        char pin[18];
 
635
        size_t pin_len;
 
636
 
 
637
        if (len != sizeof(*ev)) {
 
638
                fprintf(stderr,
 
639
                        "Invalid pin_code request length (%u bytes)\n", len);
 
640
                return -EINVAL;
 
641
        }
 
642
 
 
643
        if (monitor) {
 
644
                char addr[18];
 
645
                ba2str(&ev->bdaddr, addr);
 
646
                printf("hci%u %s request PIN\n", index, addr);
 
647
        }
 
648
 
 
649
        printf("PIN Request (press enter to reject) >> ");
 
650
        fflush(stdout);
 
651
 
 
652
        memset(pin, 0, sizeof(pin));
 
653
 
 
654
        if (fgets(pin, sizeof(pin), stdin) == NULL || pin[0] == '\n')
 
655
                return mgmt_pin_neg_reply(mgmt_sk, index, &ev->bdaddr);
 
656
 
 
657
        pin_len = strlen(pin);
 
658
        if (pin[pin_len - 1] == '\n') {
 
659
                pin[pin_len - 1] = '\0';
 
660
                pin_len--;
 
661
        }
 
662
 
 
663
        return mgmt_pin_reply(mgmt_sk, index, &ev->bdaddr, pin, pin_len);
 
664
}
 
665
 
 
666
static void confirm_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
 
667
                                void *rsp, uint16_t len, void *user_data)
 
668
{
 
669
        if (status != 0) {
 
670
                fprintf(stderr,
 
671
                        "hci%u User Confirm reply failed. status 0x%02x (%s)",
 
672
                                        id, status, mgmt_errstr(status));
 
673
                exit(EXIT_FAILURE);
 
674
        }
 
675
 
 
676
        printf("hci%u User Confirm Reply successful\n", id);
 
677
}
 
678
 
 
679
static int mgmt_confirm_reply(int mgmt_sk, uint16_t index, bdaddr_t *bdaddr)
 
680
{
 
681
        struct mgmt_cp_user_confirm_reply cp;
 
682
 
 
683
        memset(&cp, 0, sizeof(cp));
 
684
        bacpy(&cp.bdaddr, bdaddr);
 
685
 
 
686
        return mgmt_send_cmd(mgmt_sk, MGMT_OP_USER_CONFIRM_REPLY, index,
 
687
                                        &cp, sizeof(cp), confirm_rsp, NULL);
 
688
}
 
689
 
 
690
static void confirm_neg_rsp(int mgmt_sk, uint16_t op, uint16_t id,
 
691
                                uint8_t status, void *rsp, uint16_t len,
 
692
                                void *user_data)
 
693
{
 
694
        if (status != 0) {
 
695
                fprintf(stderr,
 
696
                        "hci%u Confirm Neg reply failed. status 0x%02x (%s)",
 
697
                                        id, status, mgmt_errstr(status));
 
698
                exit(EXIT_FAILURE);
 
699
        }
 
700
 
 
701
        printf("hci%u User Confirm Negative Reply successful\n", id);
 
702
}
 
703
 
 
704
static int mgmt_confirm_neg_reply(int mgmt_sk, uint16_t index,
 
705
                                                        bdaddr_t *bdaddr)
 
706
{
 
707
        struct mgmt_cp_user_confirm_reply cp;
 
708
 
 
709
        memset(&cp, 0, sizeof(cp));
 
710
        bacpy(&cp.bdaddr, bdaddr);
 
711
 
 
712
        return mgmt_send_cmd(mgmt_sk, MGMT_OP_USER_CONFIRM_NEG_REPLY, index,
 
713
                                &cp, sizeof(cp), confirm_neg_rsp, NULL);
 
714
}
 
715
 
 
716
 
 
717
static int mgmt_user_confirm(int mgmt_sk, uint16_t index,
 
718
                                struct mgmt_ev_user_confirm_request *ev,
 
719
                                uint16_t len)
 
720
{
 
721
        char rsp[5];
 
722
        size_t rsp_len;
 
723
        uint32_t val;
 
724
        char addr[18];
 
725
 
 
726
        if (len != sizeof(*ev)) {
 
727
                fprintf(stderr,
 
728
                        "Invalid user_confirm request length (%u)\n", len);
 
729
                return -EINVAL;
 
730
        }
 
731
 
 
732
        ba2str(&ev->bdaddr, addr);
 
733
        val = bt_get_le32(&ev->value);
 
734
 
 
735
        if (monitor)
 
736
                printf("hci%u %s User Confirm %06u hint %u\n", index, addr,
 
737
                                                        val, ev->confirm_hint);
 
738
 
 
739
        if (ev->confirm_hint)
 
740
                printf("Accept pairing with %s (yes/no) >> ", addr);
 
741
        else
 
742
                printf("Confirm value %06u for %s (yes/no) >> ", val, addr);
 
743
 
 
744
        fflush(stdout);
 
745
 
 
746
        memset(rsp, 0, sizeof(rsp));
 
747
 
 
748
        if (fgets(rsp, sizeof(rsp), stdin) == NULL || rsp[0] == '\n')
 
749
                return mgmt_confirm_neg_reply(mgmt_sk, index, &ev->bdaddr);
 
750
 
 
751
        rsp_len = strlen(rsp);
 
752
        if (rsp[rsp_len - 1] == '\n') {
 
753
                rsp[rsp_len - 1] = '\0';
 
754
                rsp_len--;
 
755
        }
 
756
 
 
757
        if (rsp[0] == 'y' || rsp[0] == 'Y')
 
758
                return mgmt_confirm_reply(mgmt_sk, index, &ev->bdaddr);
 
759
        else
 
760
                return mgmt_confirm_neg_reply(mgmt_sk, index, &ev->bdaddr);
 
761
}
 
762
 
 
763
static int mgmt_handle_event(int mgmt_sk, uint16_t ev, uint16_t index,
 
764
                                                void *data, uint16_t len)
 
765
{
 
766
        if (monitor)
 
767
                printf("event: %s\n", mgmt_evstr(ev));
 
768
 
 
769
        switch (ev) {
 
770
        case MGMT_EV_CMD_COMPLETE:
 
771
                return mgmt_cmd_complete(mgmt_sk, index, data, len);
 
772
        case MGMT_EV_CMD_STATUS:
 
773
                return mgmt_cmd_status(mgmt_sk, index, data, len);
 
774
        case MGMT_EV_CONTROLLER_ERROR:
 
775
                return mgmt_controller_error(index, data, len);
 
776
        case MGMT_EV_INDEX_ADDED:
 
777
                return mgmt_index_added(mgmt_sk, index);
 
778
        case MGMT_EV_INDEX_REMOVED:
 
779
                return mgmt_index_removed(mgmt_sk, index);
 
780
        case MGMT_EV_NEW_SETTINGS:
 
781
                return mgmt_new_settings(mgmt_sk, index, data, len);
 
782
        case MGMT_EV_DISCOVERING:
 
783
                return mgmt_discovering(mgmt_sk, index, data, len);
 
784
        case MGMT_EV_NEW_LINK_KEY:
 
785
                return mgmt_new_link_key(mgmt_sk, index, data, len);
 
786
        case MGMT_EV_DEVICE_CONNECTED:
 
787
                return mgmt_connected(mgmt_sk, index, true, data, len);
 
788
        case MGMT_EV_DEVICE_DISCONNECTED:
 
789
                return mgmt_connected(mgmt_sk, index, false, data, len);
 
790
        case MGMT_EV_CONNECT_FAILED:
 
791
                return mgmt_conn_failed(mgmt_sk, index, data, len);
 
792
        case MGMT_EV_AUTH_FAILED:
 
793
                return mgmt_auth_failed(mgmt_sk, index, data, len);
 
794
        case MGMT_EV_LOCAL_NAME_CHANGED:
 
795
                return mgmt_name_changed(mgmt_sk, index, data, len);
 
796
        case MGMT_EV_DEVICE_FOUND:
 
797
                return mgmt_device_found(mgmt_sk, index, data, len);
 
798
        case MGMT_EV_REMOTE_NAME:
 
799
                return mgmt_remote_name(mgmt_sk, index, data, len);
 
800
        case MGMT_EV_PIN_CODE_REQUEST:
 
801
                return mgmt_request_pin(mgmt_sk, index, data, len);
 
802
        case MGMT_EV_USER_CONFIRM_REQUEST:
 
803
                return mgmt_user_confirm(mgmt_sk, index, data, len);
 
804
        default:
 
805
                if (monitor)
 
806
                        printf("Unhandled event 0x%04x (%s)\n", ev, mgmt_evstr(ev));
 
807
                return 0;
 
808
        }
 
809
}
 
810
 
 
811
static int mgmt_process_data(int mgmt_sk)
 
812
{
 
813
        char buf[1024];
 
814
        struct mgmt_hdr *hdr = (void *) buf;
 
815
        uint16_t len, ev, index;
 
816
        ssize_t ret;
 
817
 
 
818
        ret = read(mgmt_sk, buf, sizeof(buf));
 
819
        if (ret < 0) {
 
820
                fprintf(stderr, "read: %s\n", strerror(errno));
 
821
                return ret;
 
822
        }
 
823
 
 
824
        if (ret < MGMT_HDR_SIZE) {
 
825
                fprintf(stderr, "Too small mgmt packet (%zd bytes)\n", ret);
 
826
                return 0;
 
827
        }
 
828
 
 
829
        ev = bt_get_le16(&hdr->opcode);
 
830
        index = bt_get_le16(&hdr->index);
 
831
        len = bt_get_le16(&hdr->len);
 
832
 
 
833
        if (monitor)
 
834
                printf("event 0x%04x len 0x%04x index 0x%04x\n", ev, len, index);
 
835
 
 
836
        if (ret != MGMT_HDR_SIZE + len) {
 
837
                fprintf(stderr, "Packet length mismatch. ret %zd len %u",
 
838
                                                                ret, len);
 
839
                return 0;
 
840
        }
 
841
 
 
842
        mgmt_handle_event(mgmt_sk, ev, index, buf + MGMT_HDR_SIZE, len);
 
843
 
 
844
        return 0;
 
845
}
 
846
 
 
847
static void cmd_monitor(int mgmt_sk, uint16_t index, int argc, char **argv)
 
848
{
 
849
        printf("Monitoring mgmt events...\n");
 
850
        monitor = true;
 
851
}
 
852
 
 
853
static void info_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
 
854
                                void *rsp, uint16_t len, void *user_data)
 
855
{
 
856
        struct mgmt_rp_read_info *rp = rsp;
 
857
        char addr[18];
 
858
 
 
859
        if (status != 0) {
 
860
                fprintf(stderr,
 
861
                        "Reading hci%u info failed with status 0x%02x (%s)\n",
 
862
                                        id, status, mgmt_errstr(status));
 
863
                exit(EXIT_FAILURE);
 
864
        }
 
865
 
 
866
        if (len < sizeof(*rp)) {
 
867
                fprintf(stderr, "Too small info reply (%u bytes)\n", len);
 
868
                exit(EXIT_FAILURE);
 
869
        }
 
870
 
 
871
        ba2str(&rp->bdaddr, addr);
 
872
        printf("hci%u:\taddr %s version %u manufacturer %u"
 
873
                        " class 0x%02x%02x%02x\n",
 
874
                        id, addr, rp->version, bt_get_le16(&rp->manufacturer),
 
875
                        rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
 
876
 
 
877
        printf("\tsupported settings: ");
 
878
        print_settings(bt_get_le32(&rp->supported_settings));
 
879
 
 
880
        printf("\n\tcurrent settings: ");
 
881
        print_settings(bt_get_le32(&rp->current_settings));
 
882
 
 
883
        printf("\n\tname %s\n", rp->name);
 
884
        printf("\tshort name %s\n", rp->short_name);
 
885
 
 
886
        if (pending == NULL)
 
887
                exit(EXIT_SUCCESS);
 
888
}
 
889
 
 
890
static void index_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
 
891
                                void *rsp, uint16_t len, void *user_data)
 
892
{
 
893
        struct mgmt_rp_read_index_list *rp = rsp;
 
894
        uint16_t count;
 
895
        unsigned int i;
 
896
 
 
897
        if (status != 0) {
 
898
                fprintf(stderr,
 
899
                        "Reading index list failed with status 0x%02x (%s)\n",
 
900
                                                status, mgmt_errstr(status));
 
901
                exit(EXIT_FAILURE);
 
902
        }
 
903
 
 
904
        if (len < sizeof(*rp)) {
 
905
                fprintf(stderr, "Too small index list reply (%u bytes)\n",
 
906
                                                                        len);
 
907
                exit(EXIT_FAILURE);
 
908
        }
 
909
 
 
910
        count = bt_get_le16(&rp->num_controllers);
 
911
 
 
912
        if (len < sizeof(*rp) + count * sizeof(uint16_t)) {
 
913
                fprintf(stderr,
 
914
                        "Index count (%u) doesn't match reply length (%u)\n",
 
915
                                                                count, len);
 
916
                exit(EXIT_FAILURE);
 
917
        }
 
918
 
 
919
        if (monitor)
 
920
                printf("Index list with %u item%s\n",
 
921
                                                count, count > 1 ? "s" : "");
 
922
 
 
923
        if (count == 0)
 
924
                exit(EXIT_SUCCESS);
 
925
 
 
926
        if (monitor && count > 0)
 
927
                printf("\t");
 
928
 
 
929
        for (i = 0; i < count; i++) {
 
930
                uint16_t index;
 
931
 
 
932
                index = bt_get_le16(&rp->index[i]);
 
933
 
 
934
                if (monitor)
 
935
                        printf("hci%u ", index);
 
936
 
 
937
                if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INFO, index, NULL,
 
938
                                        0, info_rsp, NULL) < 0) {
 
939
                        fprintf(stderr, "Unable to send read_info cmd\n");
 
940
                        exit(EXIT_FAILURE);
 
941
                }
 
942
        }
 
943
 
 
944
        if (monitor && count > 0)
 
945
                printf("\n");
 
946
}
 
947
 
 
948
static void cmd_info(int mgmt_sk, uint16_t index, int argc, char **argv)
 
949
{
 
950
        if (index == MGMT_INDEX_NONE) {
 
951
                if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INDEX_LIST,
 
952
                                        MGMT_INDEX_NONE, NULL, 0,
 
953
                                        index_rsp, NULL) < 0) {
 
954
                        fprintf(stderr, "Unable to send index_list cmd\n");
 
955
                        exit(EXIT_FAILURE);
 
956
                }
 
957
 
 
958
                return;
 
959
        }
 
960
 
 
961
        if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INFO, index, NULL,
 
962
                                                0, info_rsp, NULL) < 0) {
 
963
                fprintf(stderr, "Unable to send read_info cmd\n");
 
964
                exit(EXIT_FAILURE);
 
965
        }
 
966
}
 
967
 
 
968
static void setting_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
 
969
                                void *rsp, uint16_t len, void *user_data)
 
970
{
 
971
        uint32_t *rp = rsp;
 
972
 
 
973
        if (status != 0) {
 
974
                fprintf(stderr,
 
975
                        "%s for hci%u failed with status 0x%02x (%s)\n",
 
976
                        mgmt_opstr(op), id, status, mgmt_errstr(status));
 
977
                exit(EXIT_FAILURE);
 
978
        }
 
979
 
 
980
        if (len < sizeof(*rp)) {
 
981
                fprintf(stderr, "Too small %s response (%u bytes)\n",
 
982
                                                        mgmt_opstr(op), len);
 
983
                exit(EXIT_FAILURE);
 
984
        }
 
985
 
 
986
        printf("hci%u %s complete, settings: ", id, mgmt_opstr(op));
 
987
        print_settings(bt_get_le32(rp));
 
988
        printf("\n");
 
989
 
 
990
        exit(EXIT_SUCCESS);
 
991
}
 
992
 
 
993
static void cmd_setting(int mgmt_sk, uint16_t index, uint16_t op,
 
994
                                                        int argc, char **argv)
 
995
{
 
996
        uint8_t val;
 
997
 
 
998
        if (argc < 2) {
 
999
                printf("Specify \"on\" or \"off\"\n");
 
1000
                exit(EXIT_FAILURE);
 
1001
        }
 
1002
 
 
1003
        if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
 
1004
                val = 1;
 
1005
        else if (strcasecmp(argv[1], "off") == 0)
 
1006
                val = 0;
 
1007
        else
 
1008
                val = atoi(argv[1]);
 
1009
 
 
1010
        if (index == MGMT_INDEX_NONE)
 
1011
                index = 0;
 
1012
 
 
1013
        if (mgmt_send_cmd(mgmt_sk, op, index, &val, sizeof(val),
 
1014
                                                setting_rsp, NULL) < 0) {
 
1015
                fprintf(stderr, "Unable to send %s cmd\n", mgmt_opstr(op));
 
1016
                exit(EXIT_FAILURE);
 
1017
        }
 
1018
}
 
1019
 
 
1020
static void cmd_power(int mgmt_sk, uint16_t index, int argc, char **argv)
 
1021
{
 
1022
        cmd_setting(mgmt_sk, index, MGMT_OP_SET_POWERED, argc, argv);
 
1023
}
 
1024
 
 
1025
static void cmd_discov(int mgmt_sk, uint16_t index, int argc, char **argv)
 
1026
{
 
1027
        struct mgmt_cp_set_discoverable cp;
 
1028
 
 
1029
        if (argc < 2) {
 
1030
                printf("Usage: btmgmt %s <yes/no> [timeout]\n", argv[0]);
 
1031
                exit(EXIT_FAILURE);
 
1032
        }
 
1033
 
 
1034
        memset(&cp, 0, sizeof(cp));
 
1035
 
 
1036
        if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
 
1037
                cp.val = 1;
 
1038
        else if (strcasecmp(argv[1], "off") == 0)
 
1039
                cp.val = 0;
 
1040
        else
 
1041
                cp.val = atoi(argv[1]);
 
1042
 
 
1043
        if (argc > 2)
 
1044
                cp.timeout = htobs(atoi(argv[2]));
 
1045
 
 
1046
        if (index == MGMT_INDEX_NONE)
 
1047
                index = 0;
 
1048
 
 
1049
        if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_DISCOVERABLE, index,
 
1050
                                &cp, sizeof(cp), setting_rsp, NULL) < 0) {
 
1051
                fprintf(stderr, "Unable to send set_discoverable cmd\n");
 
1052
                exit(EXIT_FAILURE);
 
1053
        }
 
1054
}
 
1055
 
 
1056
static void cmd_connectable(int mgmt_sk, uint16_t index, int argc, char **argv)
 
1057
{
 
1058
        cmd_setting(mgmt_sk, index, MGMT_OP_SET_CONNECTABLE, argc, argv);
 
1059
}
 
1060
 
 
1061
static void cmd_pairable(int mgmt_sk, uint16_t index, int argc, char **argv)
 
1062
{
 
1063
        cmd_setting(mgmt_sk, index, MGMT_OP_SET_PAIRABLE, argc, argv);
 
1064
}
 
1065
 
 
1066
static void class_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
 
1067
                                void *rsp, uint16_t len, void *user_data)
 
1068
{
 
1069
        if (status != 0) {
 
1070
                fprintf(stderr,
 
1071
                        "Setting hci%u class failed with status 0x%02x (%s)",
 
1072
                                        id, status, mgmt_errstr(status));
 
1073
                exit(EXIT_FAILURE);
 
1074
        }
 
1075
 
 
1076
        printf("hci%u class changed\n", id);
 
1077
        exit(EXIT_SUCCESS);
 
1078
}
 
1079
 
 
1080
static void cmd_class(int mgmt_sk, uint16_t index, int argc, char **argv)
 
1081
{
 
1082
        uint8_t class[2];
 
1083
 
 
1084
        if (argc < 3) {
 
1085
                printf("Usage: btmgmt %s <major> <minor>\n", argv[0]);
 
1086
                exit(EXIT_FAILURE);
 
1087
        }
 
1088
 
 
1089
        class[0] = atoi(argv[1]);
 
1090
        class[1] = atoi(argv[2]);
 
1091
 
 
1092
        if (index == MGMT_INDEX_NONE)
 
1093
                index = 0;
 
1094
 
 
1095
        if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_DEV_CLASS, index,
 
1096
                                class, sizeof(class), class_rsp, NULL) < 0) {
 
1097
                fprintf(stderr, "Unable to send set_dev_class cmd\n");
 
1098
                exit(EXIT_FAILURE);
 
1099
        }
 
1100
}
 
1101
 
 
1102
static void disconnect_rsp(int mgmt_sk, uint16_t op, uint16_t id,
 
1103
                                uint8_t status, void *rsp, uint16_t len,
 
1104
                                void *user_data)
 
1105
{
 
1106
        struct mgmt_rp_disconnect *rp = rsp;
 
1107
        char addr[18];
 
1108
 
 
1109
        if (status != 0) {
 
1110
                fprintf(stderr, "Disconnect failed with status 0x%02x (%s)\n",
 
1111
                                                status, mgmt_errstr(status));
 
1112
                exit(EXIT_FAILURE);
 
1113
        }
 
1114
 
 
1115
        if (len != sizeof(*rp)) {
 
1116
                fprintf(stderr, "Invalid disconnect response length (%u)\n",
 
1117
                                                                        len);
 
1118
                exit(EXIT_FAILURE);
 
1119
        }
 
1120
 
 
1121
        ba2str(&rp->bdaddr, addr);
 
1122
 
 
1123
        if (rp->status == 0) {
 
1124
                printf("%s disconnected\n", addr);
 
1125
                exit(EXIT_SUCCESS);
 
1126
        } else {
 
1127
                fprintf(stderr,
 
1128
                        "Disconnecting %s failed with status 0x%02x (%s)\n",
 
1129
                                addr, rp->status, mgmt_errstr(rp->status));
 
1130
                exit(EXIT_FAILURE);
 
1131
        }
 
1132
}
 
1133
 
 
1134
static void cmd_disconnect(int mgmt_sk, uint16_t index, int argc, char **argv)
 
1135
{
 
1136
        struct mgmt_cp_disconnect cp;
 
1137
 
 
1138
        if (argc < 2) {
 
1139
                printf("Usage: btmgmt %s <address>\n", argv[0]);
 
1140
                exit(EXIT_FAILURE);
 
1141
        }
 
1142
 
 
1143
        str2ba(argv[1], &cp.bdaddr);
 
1144
 
 
1145
        if (index == MGMT_INDEX_NONE)
 
1146
                index = 0;
 
1147
 
 
1148
        if (mgmt_send_cmd(mgmt_sk, MGMT_OP_DISCONNECT, index,
 
1149
                                &cp, sizeof(cp), disconnect_rsp, NULL) < 0) {
 
1150
                fprintf(stderr, "Unable to send disconnect cmd\n");
 
1151
                exit(EXIT_FAILURE);
 
1152
        }
 
1153
}
 
1154
 
 
1155
static void con_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
 
1156
                                void *rsp, uint16_t len, void *user_data)
 
1157
{
 
1158
        struct mgmt_rp_get_connections *rp = rsp;
 
1159
        uint16_t count, i;
 
1160
 
 
1161
        if (len < sizeof(*rp)) {
 
1162
                fprintf(stderr, "Too small (%u bytes) get_connections rsp\n",
 
1163
                                                                        len);
 
1164
                exit(EXIT_FAILURE);
 
1165
        }
 
1166
 
 
1167
        count = bt_get_le16(&rp->conn_count);
 
1168
        if (len != sizeof(*rp) + count * sizeof(struct mgmt_addr_info)) {
 
1169
                fprintf(stderr, "Invalid get_connections length "
 
1170
                                        " (count=%u, len=%u)\n", count, len);
 
1171
                exit(EXIT_FAILURE);
 
1172
        }
 
1173
 
 
1174
        for (i = 0; i < count; i++) {
 
1175
                char addr[18];
 
1176
 
 
1177
                ba2str(&rp->addr[i].bdaddr, addr);
 
1178
 
 
1179
                printf("%s type %s\n", addr, typestr(rp->addr[i].type));
 
1180
        }
 
1181
 
 
1182
        exit(EXIT_SUCCESS);
 
1183
}
 
1184
 
 
1185
static void cmd_con(int mgmt_sk, uint16_t index, int argc, char **argv)
 
1186
{
 
1187
        if (index == MGMT_INDEX_NONE)
 
1188
                index = 0;
 
1189
 
 
1190
        if (mgmt_send_cmd(mgmt_sk, MGMT_OP_GET_CONNECTIONS, index, NULL, 0,
 
1191
                                                        con_rsp, NULL) < 0) {
 
1192
                fprintf(stderr, "Unable to send get_connections cmd\n");
 
1193
                exit(EXIT_FAILURE);
 
1194
        }
 
1195
}
 
1196
 
 
1197
static void find_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
 
1198
                                void *rsp, uint16_t len, void *user_data)
 
1199
{
 
1200
        if (status != 0) {
 
1201
                fprintf(stderr,
 
1202
                        "Unable to start discovery. status 0x%02x (%s)\n",
 
1203
                                                status, mgmt_errstr(status));
 
1204
                exit(EXIT_FAILURE);
 
1205
        }
 
1206
 
 
1207
        printf("Discovery started\n");
 
1208
        discovery = true;
 
1209
}
 
1210
 
 
1211
static void cmd_find(int mgmt_sk, uint16_t index, int argc, char **argv)
 
1212
{
 
1213
        struct mgmt_cp_start_discovery cp;
 
1214
        uint8_t type;
 
1215
 
 
1216
        if (index == MGMT_INDEX_NONE)
 
1217
                index = 0;
 
1218
 
 
1219
        type = 0;
 
1220
        hci_set_bit(MGMT_ADDR_BREDR, &type);
 
1221
        hci_set_bit(MGMT_ADDR_LE_PUBLIC, &type);
 
1222
        hci_set_bit(MGMT_ADDR_LE_RANDOM, &type);
 
1223
 
 
1224
        memset(&cp, 0, sizeof(cp));
 
1225
        cp.type = type;
 
1226
 
 
1227
        if (mgmt_send_cmd(mgmt_sk, MGMT_OP_START_DISCOVERY, index,
 
1228
                                &cp, sizeof(cp), find_rsp, NULL) < 0) {
 
1229
                fprintf(stderr, "Unable to send start_discovery cmd\n");
 
1230
                exit(EXIT_FAILURE);
 
1231
        }
 
1232
}
 
1233
 
 
1234
static void name_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
 
1235
                                void *rsp, uint16_t len, void *user_data)
 
1236
{
 
1237
        if (status != 0) {
 
1238
                fprintf(stderr, "Unable to set local name. status 0x%02x (%s)",
 
1239
                                                status, mgmt_errstr(status));
 
1240
                exit(EXIT_FAILURE);
 
1241
        }
 
1242
 
 
1243
        exit(EXIT_SUCCESS);
 
1244
}
 
1245
 
 
1246
static void cmd_name(int mgmt_sk, uint16_t index, int argc, char **argv)
 
1247
{
 
1248
        struct mgmt_cp_set_local_name cp;
 
1249
 
 
1250
        if (argc < 2) {
 
1251
                printf("Usage: btmgmt %s <name>\n", argv[0]);
 
1252
                exit(EXIT_FAILURE);
 
1253
        }
 
1254
 
 
1255
        if (index == MGMT_INDEX_NONE)
 
1256
                index = 0;
 
1257
 
 
1258
        memset(&cp, 0, sizeof(cp));
 
1259
        strncpy((char *) cp.name, argv[1], HCI_MAX_NAME_LENGTH);
 
1260
 
 
1261
        if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_LOCAL_NAME, index,
 
1262
                                        &cp, sizeof(cp), name_rsp, NULL) < 0) {
 
1263
                fprintf(stderr, "Unable to send set_name cmd\n");
 
1264
                exit(EXIT_FAILURE);
 
1265
        }
 
1266
}
 
1267
 
 
1268
static void pair_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
 
1269
                                void *rsp, uint16_t len, void *user_data)
 
1270
{
 
1271
        struct mgmt_rp_pair_device *rp = rsp;
 
1272
        char addr[18];
 
1273
 
 
1274
        if (status != 0) {
 
1275
                fprintf(stderr, "Pairing failed with status 0x%02x (%s)\n",
 
1276
                                                status, mgmt_errstr(status));
 
1277
                exit(EXIT_FAILURE);
 
1278
        }
 
1279
 
 
1280
        if (len != sizeof(*rp)) {
 
1281
                fprintf(stderr, "Unexpected pair_rsp len %u\n", len);
 
1282
                exit(EXIT_FAILURE);
 
1283
        }
 
1284
 
 
1285
        ba2str(&rp->addr.bdaddr, addr);
 
1286
 
 
1287
        if (rp->status != 0) {
 
1288
                fprintf(stderr,
 
1289
                        "Pairing with %s (%s) failed. status 0x%02x (%s)\n",
 
1290
                        addr, typestr(rp->addr.type), rp->status,
 
1291
                        mgmt_errstr(rp->status));
 
1292
                exit(EXIT_FAILURE);
 
1293
        }
 
1294
 
 
1295
        printf("Paired with %s\n", addr);
 
1296
 
 
1297
        exit(EXIT_SUCCESS);
 
1298
}
 
1299
 
 
1300
static void pair_usage(void)
 
1301
{
 
1302
        printf("Usage: btmgmt pair [-c cap] [-t type] <remote address>\n");
 
1303
}
 
1304
 
 
1305
static struct option pair_options[] = {
 
1306
        { "help",       0, 0, 'h' },
 
1307
        { "capability", 1, 0, 'c' },
 
1308
        { "type",       1, 0, 't' },
 
1309
        { 0, 0, 0, 0 }
 
1310
};
 
1311
 
 
1312
static void cmd_pair(int mgmt_sk, uint16_t index, int argc, char **argv)
 
1313
{
 
1314
        struct mgmt_cp_pair_device cp;
 
1315
        uint8_t cap = 0x01;
 
1316
        uint8_t type = MGMT_ADDR_BREDR;
 
1317
        int opt;
 
1318
 
 
1319
        while ((opt = getopt_long(argc, argv, "+c:t:h", pair_options,
 
1320
                                                                NULL)) != -1) {
 
1321
                switch (opt) {
 
1322
                case 'c':
 
1323
                        cap = strtol(optarg, NULL, 0);
 
1324
                        break;
 
1325
                case 't':
 
1326
                        type = strtol(optarg, NULL, 0);
 
1327
                        break;
 
1328
                case 'h':
 
1329
                default:
 
1330
                        pair_usage();
 
1331
                        exit(EXIT_SUCCESS);
 
1332
                }
 
1333
        }
 
1334
 
 
1335
        argc -= optind;
 
1336
        argv += optind;
 
1337
        optind = 0;
 
1338
 
 
1339
        if (argc < 1) {
 
1340
                pair_usage();
 
1341
                exit(EXIT_FAILURE);
 
1342
        }
 
1343
 
 
1344
        if (index == MGMT_INDEX_NONE)
 
1345
                index = 0;
 
1346
 
 
1347
        memset(&cp, 0, sizeof(cp));
 
1348
        str2ba(argv[0], &cp.addr.bdaddr);
 
1349
        cp.addr.type = type;
 
1350
        cp.io_cap = cap;
 
1351
 
 
1352
        if (mgmt_send_cmd(mgmt_sk, MGMT_OP_PAIR_DEVICE, index, &cp, sizeof(cp),
 
1353
                                                        pair_rsp, NULL) < 0) {
 
1354
                fprintf(stderr, "Unable to send pair_device cmd\n");
 
1355
                exit(EXIT_FAILURE);
 
1356
        }
 
1357
}
 
1358
 
 
1359
static void remove_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
 
1360
                                void *rsp, uint16_t len, void *user_data)
 
1361
{
 
1362
        struct mgmt_rp_remove_keys *rp = rsp;
 
1363
        char addr[18];
 
1364
 
 
1365
        if (status != 0) {
 
1366
                fprintf(stderr, "Remove keys failed with status 0x%02x (%s)\n",
 
1367
                                                status, mgmt_errstr(status));
 
1368
                exit(EXIT_FAILURE);
 
1369
        }
 
1370
 
 
1371
        if (len != sizeof(*rp)) {
 
1372
                fprintf(stderr, "Unexpected remove_keys_rsp len %u\n", len);
 
1373
                exit(EXIT_FAILURE);
 
1374
        }
 
1375
 
 
1376
        ba2str(&rp->bdaddr, addr);
 
1377
 
 
1378
        if (rp->status != 0) {
 
1379
                fprintf(stderr,
 
1380
                        "Removing keys for %s failed. status 0x%02x (%s)\n",
 
1381
                                addr, rp->status, mgmt_errstr(rp->status));
 
1382
                exit(EXIT_FAILURE);
 
1383
        }
 
1384
 
 
1385
        printf("Removed keys for %s\n", addr);
 
1386
 
 
1387
        exit(EXIT_SUCCESS);
 
1388
}
 
1389
 
 
1390
static void cmd_remove(int mgmt_sk, uint16_t index, int argc, char **argv)
 
1391
{
 
1392
        struct mgmt_cp_remove_keys cp;
 
1393
 
 
1394
        if (argc < 2) {
 
1395
                printf("Usage: btmgmt %s <remote address>\n", argv[0]);
 
1396
                exit(EXIT_FAILURE);
 
1397
        }
 
1398
 
 
1399
        if (index == MGMT_INDEX_NONE)
 
1400
                index = 0;
 
1401
 
 
1402
        memset(&cp, 0, sizeof(cp));
 
1403
        str2ba(argv[1], &cp.bdaddr);
 
1404
        cp.disconnect = 1;
 
1405
 
 
1406
        if (mgmt_send_cmd(mgmt_sk, MGMT_OP_REMOVE_KEYS, index, &cp, sizeof(cp),
 
1407
                                                remove_rsp, NULL) < 0) {
 
1408
                fprintf(stderr, "Unable to send remove_keys cmd\n");
 
1409
                exit(EXIT_FAILURE);
 
1410
        }
 
1411
}
 
1412
 
 
1413
static void keys_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
 
1414
                                void *rsp, uint16_t len, void *user_data)
 
1415
{
 
1416
        if (status != 0) {
 
1417
                fprintf(stderr, "Load keys failed with status 0x%02x (%s)\n",
 
1418
                                                status, mgmt_errstr(status));
 
1419
                exit(EXIT_FAILURE);
 
1420
        }
 
1421
 
 
1422
        printf("Keys successfully loaded\n");
 
1423
 
 
1424
        exit(EXIT_SUCCESS);
 
1425
}
 
1426
 
 
1427
static void cmd_keys(int mgmt_sk, uint16_t index, int argc, char **argv)
 
1428
{
 
1429
        struct mgmt_cp_load_link_keys cp;
 
1430
 
 
1431
        if (index == MGMT_INDEX_NONE)
 
1432
                index = 0;
 
1433
 
 
1434
        memset(&cp, 0, sizeof(cp));
 
1435
 
 
1436
        if (mgmt_send_cmd(mgmt_sk, MGMT_OP_LOAD_LINK_KEYS, index,
 
1437
                                &cp, sizeof(cp), keys_rsp, NULL) < 0) {
 
1438
                fprintf(stderr, "Unable to send load_keys cmd\n");
 
1439
                exit(EXIT_FAILURE);
 
1440
        }
 
1441
}
 
1442
 
 
1443
static struct {
 
1444
        char *cmd;
 
1445
        void (*func)(int mgmt_sk, uint16_t index, int argc, char **argv);
 
1446
        char *doc;
 
1447
} command[] = {
 
1448
        { "monitor",    cmd_monitor,    "Monitor events"                },
 
1449
        { "info",       cmd_info,       "Show controller info"          },
 
1450
        { "power",      cmd_power,      "Toggle powered state"          },
 
1451
        { "discov",     cmd_discov,     "Toggle discoverable state"     },
 
1452
        { "connectable",cmd_connectable,"Toggle connectable state"      },
 
1453
        { "pairable",   cmd_pairable,   "Toggle pairable state"         },
 
1454
        { "class",      cmd_class,      "Set device major/minor class"  },
 
1455
        { "disconnect", cmd_disconnect, "Disconnect device"             },
 
1456
        { "con",        cmd_con,        "List connections"              },
 
1457
        { "find",       cmd_find,       "Discover nearby devices"       },
 
1458
        { "name",       cmd_name,       "Set local name"                },
 
1459
        { "pair",       cmd_pair,       "Pair with a remote device"     },
 
1460
        { "remove",     cmd_remove,     "Remove pairing (all keys)"     },
 
1461
        { "keys",       cmd_keys,       "Load Keys"                     },
 
1462
        { NULL, NULL, 0 }
 
1463
};
 
1464
 
 
1465
static void usage(void)
 
1466
{
 
1467
        int i;
 
1468
 
 
1469
        printf("btmgmt ver %s\n", VERSION);
 
1470
        printf("Usage:\n"
 
1471
                "\tbtmgmt [options] <command> [command parameters]\n");
 
1472
 
 
1473
        printf("Options:\n"
 
1474
                "\t--index <id>\tSpecify adapter index\n"
 
1475
                "\t--verbose\tEnable extra logging\n"
 
1476
                "\t--help\tDisplay help\n");
 
1477
 
 
1478
        printf("Commands:\n");
 
1479
        for (i = 0; command[i].cmd; i++)
 
1480
                printf("\t%-15s\t%s\n", command[i].cmd, command[i].doc);
 
1481
 
 
1482
        printf("\n"
 
1483
                "For more information on the usage of each command use:\n"
 
1484
                "\tbtmgmt <command> --help\n" );
 
1485
}
 
1486
 
 
1487
static struct option main_options[] = {
 
1488
        { "index",      1, 0, 'i' },
 
1489
        { "verbose",    0, 0, 'v' },
 
1490
        { "help",       0, 0, 'h' },
 
1491
        { 0, 0, 0, 0 }
 
1492
};
 
1493
 
 
1494
int main(int argc, char *argv[])
 
1495
{
 
1496
        int opt, i, mgmt_sk;
 
1497
        uint16_t index = MGMT_INDEX_NONE;
 
1498
        struct pollfd pollfd;
 
1499
 
 
1500
        while ((opt = getopt_long(argc, argv, "+hvi:",
 
1501
                                                main_options, NULL)) != -1) {
 
1502
                switch (opt) {
 
1503
                case 'i':
 
1504
                        if (strlen(optarg) > 3 &&
 
1505
                                        strncasecmp(optarg, "hci", 3) == 0)
 
1506
                                index = atoi(&optarg[4]);
 
1507
                        else
 
1508
                                index = atoi(optarg);
 
1509
                        break;
 
1510
                case 'v':
 
1511
                        monitor = true;
 
1512
                        break;
 
1513
                case 'h':
 
1514
                default:
 
1515
                        usage();
 
1516
                        return 0;
 
1517
                }
 
1518
        }
 
1519
 
 
1520
        argc -= optind;
 
1521
        argv += optind;
 
1522
        optind = 0;
 
1523
 
 
1524
        if (argc < 1) {
 
1525
                usage();
 
1526
                return 0;
 
1527
        }
 
1528
 
 
1529
        mgmt_sk = mgmt_open();
 
1530
        if (mgmt_sk < 0) {
 
1531
                fprintf(stderr, "Unable to open mgmt socket\n");
 
1532
                return -1;
 
1533
        }
 
1534
 
 
1535
        for (i = 0; command[i].cmd; i++) {
 
1536
                if (strcmp(command[i].cmd, argv[0]) != 0)
 
1537
                        continue;
 
1538
 
 
1539
                command[i].func(mgmt_sk, index, argc, argv);
 
1540
                break;
 
1541
        }
 
1542
 
 
1543
        if (command[i].cmd == NULL) {
 
1544
                fprintf(stderr, "Unknown command: %s\n", argv[0]);
 
1545
                close(mgmt_sk);
 
1546
                return -1;
 
1547
        }
 
1548
 
 
1549
        pollfd.fd = mgmt_sk;
 
1550
        pollfd.events = POLLIN;
 
1551
        pollfd.revents = 0;
 
1552
 
 
1553
        while (poll(&pollfd, 1, -1) >= 0) {
 
1554
                if (pollfd.revents & (POLLHUP | POLLERR | POLLNVAL))
 
1555
                        break;
 
1556
 
 
1557
                if (pollfd.revents & POLLIN)
 
1558
                        mgmt_process_data(mgmt_sk);
 
1559
 
 
1560
                pollfd.revents = 0;
 
1561
        }
 
1562
 
 
1563
        close(mgmt_sk);
 
1564
 
 
1565
        return 0;
 
1566
}