Tizen 2.0 Release
[profile/ivi/bluez.git] / mgmt / main.c
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/sdp.h>
41 #include <bluetooth/sdp_lib.h>
42 #include <bluetooth/mgmt.h>
43
44 #include <glib.h>
45 #include "glib-helper.h"
46
47 static bool monitor = false;
48 static bool discovery = false;
49 static bool resolve_names = true;
50
51 typedef void (*cmd_cb)(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
52                                 void *rsp, uint16_t len, void *user_data);
53
54 static struct pending_cmd {
55         uint16_t op;
56         uint16_t id;
57         cmd_cb cb;
58         void *user_data;
59         struct pending_cmd *next;
60 } *pending = NULL;
61
62 static int mgmt_send_cmd(int mgmt_sk, uint16_t op, uint16_t id, void *data,
63                                 size_t len, cmd_cb func, void *user_data)
64 {
65         char buf[1024];
66         struct pending_cmd *cmd;
67         struct mgmt_hdr *hdr = (void *) buf;
68
69         if (len + MGMT_HDR_SIZE > sizeof(buf))
70                 return -EINVAL;
71
72         cmd = calloc(1, sizeof(struct pending_cmd));
73         if (cmd == NULL)
74                 return -errno;
75
76         cmd->op = op;
77         cmd->id = id;
78         cmd->cb = func;
79         cmd->user_data = user_data;
80
81         memset(buf, 0, sizeof(buf));
82         hdr->opcode = htobs(op);
83         hdr->index = htobs(id);
84         hdr->len = htobs(len);
85         memcpy(buf + MGMT_HDR_SIZE, data, len);
86
87         if (write(mgmt_sk, buf, MGMT_HDR_SIZE + len) < 0) {
88                 fprintf(stderr, "Unable to write to socket: %s\n",
89                                                         strerror(errno));
90                 free(cmd);
91                 return -1;
92         }
93
94         cmd->next = pending;
95         pending = cmd;
96
97         return 0;
98 }
99
100 static int mgmt_open(void)
101 {
102         struct sockaddr_hci addr;
103         int sk;
104
105         sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
106         if (sk < 0) {
107                 fprintf(stderr, "socket: %s\n", strerror(errno));
108                 return sk;
109         }
110
111         memset(&addr, 0, sizeof(addr));
112         addr.hci_family = AF_BLUETOOTH;
113         addr.hci_dev = HCI_DEV_NONE;
114         addr.hci_channel = HCI_CHANNEL_CONTROL;
115
116         if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
117                 fprintf(stderr, "bind: %s\n", strerror(errno));
118                 close(sk);
119                 return -1;
120         }
121
122         return sk;
123 }
124
125 static void mgmt_check_pending(int mgmt_sk, uint16_t op, uint16_t index,
126                                 uint16_t status, void *data, uint16_t len)
127 {
128         struct pending_cmd *c, *prev;
129
130         for (c = pending, prev = NULL; c != NULL; prev = c, c = c->next) {
131                 if (c->op != op)
132                         continue;
133                 if (c->id != index)
134                         continue;
135
136                 if (c == pending)
137                         pending = c->next;
138                 else
139                         prev->next = c->next;
140
141                 c->cb(mgmt_sk, op, index, status, data, len, c->user_data);
142
143                 free(c);
144                 break;
145         }
146 }
147
148 static int mgmt_cmd_complete(int mgmt_sk, uint16_t index,
149                                 struct mgmt_ev_cmd_complete *ev, uint16_t len)
150 {
151         uint16_t op;
152
153         if (len < sizeof(*ev)) {
154                 fprintf(stderr, "Too short (%u bytes) cmd complete event\n",
155                                                                         len);
156                 return -EINVAL;
157         }
158
159         op = bt_get_le16(&ev->opcode);
160
161         len -= sizeof(*ev);
162
163         if (monitor)
164                 printf("%s complete, opcode 0x%04x len %u\n", mgmt_opstr(op),
165                                                                 op, len);
166
167         mgmt_check_pending(mgmt_sk, op, index, ev->status, ev->data, len);
168
169         return 0;
170 }
171
172 static int mgmt_cmd_status(int mgmt_sk, uint16_t index,
173                                 struct mgmt_ev_cmd_status *ev, uint16_t len)
174 {
175         uint16_t opcode;
176
177         if (len < sizeof(*ev)) {
178                 fprintf(stderr, "Too short (%u bytes) cmd status event\n",
179                                                                         len);
180                 return -EINVAL;
181         }
182
183         opcode = bt_get_le16(&ev->opcode);
184
185         if (monitor)
186                 printf("cmd status, opcode 0x%04x status 0x%02x (%s)\n",
187                                 opcode, ev->status, mgmt_errstr(ev->status));
188
189         if (ev->status != 0)
190                 mgmt_check_pending(mgmt_sk, opcode, index, ev->status,
191                                                                 NULL, 0);
192
193         return 0;
194 }
195
196 static int mgmt_controller_error(uint16_t index,
197                                         struct mgmt_ev_controller_error *ev,
198                                         uint16_t len)
199 {
200         if (len < sizeof(*ev)) {
201                 fprintf(stderr,
202                         "Too short (%u bytes) controller error event\n", len);
203                 return -EINVAL;
204         }
205
206         if (monitor)
207                 printf("hci%u error 0x%02x\n", index, ev->error_code);
208
209         return 0;
210 }
211
212 static int mgmt_index_added(int mgmt_sk, uint16_t index)
213 {
214         if (monitor)
215                 printf("hci%u added\n", index);
216         return 0;
217 }
218
219 static int mgmt_index_removed(int mgmt_sk, uint16_t index)
220 {
221         if (monitor)
222                 printf("hci%u removed\n", index);
223         return 0;
224 }
225
226 static const char *settings_str[] = {
227                                 "powered",
228                                 "connectable",
229                                 "fast-connectable",
230                                 "discoverable",
231                                 "pairable",
232                                 "link-security",
233                                 "ssp",
234                                 "br/edr",
235                                 "hs",
236                                 "le" ,
237 };
238
239 static void print_settings(uint32_t settings)
240 {
241         unsigned i;
242
243         for (i = 0; i < NELEM(settings_str); i++) {
244                 if ((settings & (1 << i)) != 0)
245                         printf("%s ", settings_str[i]);
246         }
247 }
248
249 static int mgmt_new_settings(int mgmt_sk, uint16_t index,
250                                         uint32_t *ev, uint16_t len)
251 {
252         if (len < sizeof(*ev)) {
253                 fprintf(stderr, "Too short new_settings event (%u)\n", len);
254                 return -EINVAL;
255         }
256
257         if (monitor) {
258                 printf("hci%u new_settings: ", index);
259                 print_settings(bt_get_le32(ev));
260                 printf("\n");
261         }
262
263         return 0;
264 }
265
266 static int mgmt_discovering(int mgmt_sk, uint16_t index,
267                                 struct mgmt_ev_discovering *ev, uint16_t len)
268 {
269         if (len < sizeof(*ev)) {
270                 fprintf(stderr, "Too short (%u bytes) discovering event\n",
271                                                                         len);
272                 return -EINVAL;
273         }
274
275         if (ev->discovering == 0 && discovery)
276                 exit(EXIT_SUCCESS);
277
278         if (monitor)
279                 printf("hci%u type %u discovering %s\n", index,
280                                 ev->type, ev->discovering ? "on" : "off");
281
282         return 0;
283 }
284
285 static int mgmt_new_link_key(int mgmt_sk, uint16_t index,
286                                 struct mgmt_ev_new_link_key *ev, uint16_t len)
287 {
288
289         if (len != sizeof(*ev)) {
290                 fprintf(stderr, "Invalid new_link_key length (%u bytes)\n",
291                                                                         len);
292                 return -EINVAL;
293         }
294
295         if (monitor) {
296                 char addr[18];
297                 ba2str(&ev->key.addr.bdaddr, addr);
298                 printf("hci%u new_link_key %s type 0x%02x pin_len %d "
299                                 "store_hint %u\n", index, addr, ev->key.type,
300                                 ev->key.pin_len, ev->store_hint);
301         }
302
303         return 0;
304 }
305
306 static const char *typestr(uint8_t type)
307 {
308         const char *str[] = { "BR/EDR", "LE Public", "LE Random" };
309
310         if (type <= BDADDR_LE_RANDOM)
311                 return str[type];
312
313         return "(unknown)";
314 }
315
316 static int mgmt_connected(int mgmt_sk, uint16_t index,
317                                         struct mgmt_ev_device_connected *ev,
318                                         uint16_t len)
319 {
320         uint16_t eir_len;
321
322         if (len < sizeof(*ev)) {
323                 fprintf(stderr,
324                         "Invalid connected event length (%u bytes)\n", len);
325                 return -EINVAL;
326         }
327
328         eir_len = bt_get_le16(&ev->eir_len);
329         if (len != sizeof(*ev) + eir_len) {
330                 fprintf(stderr, "Invalid connected event length "
331                         "(%u bytes, eir_len %u bytes)\n", len, eir_len);
332                 return -EINVAL;
333         }
334
335         if (monitor) {
336                 char addr[18];
337                 ba2str(&ev->addr.bdaddr, addr);
338                 printf("hci%u %s type %s connected eir_len %u\n", index, addr,
339                                         typestr(ev->addr.type), eir_len);
340         }
341
342         return 0;
343 }
344
345 static int mgmt_disconnected(int mgmt_sk, uint16_t index,
346                                 struct mgmt_addr_info *ev, uint16_t len)
347 {
348         if (len != sizeof(*ev)) {
349                 fprintf(stderr,
350                         "Invalid disconnected event length (%u bytes)\n", len);
351                 return -EINVAL;
352         }
353
354         if (monitor) {
355                 char addr[18];
356                 ba2str(&ev->bdaddr, addr);
357                 printf("hci%u %s type %s disconnected\n", index, addr,
358                                                         typestr(ev->type));
359         }
360
361         return 0;
362 }
363
364 static int mgmt_conn_failed(int mgmt_sk, uint16_t index,
365                                 struct mgmt_ev_connect_failed *ev,
366                                 uint16_t len)
367 {
368         if (len != sizeof(*ev)) {
369                 fprintf(stderr,
370                         "Invalid connect_failed event length (%u bytes)\n", len);
371                 return -EINVAL;
372         }
373
374         if (monitor) {
375                 char addr[18];
376                 ba2str(&ev->addr.bdaddr, addr);
377                 printf("hci%u %s type %s connect failed (status 0x%02x, %s)\n",
378                                 index, addr, typestr(ev->addr.type), ev->status,
379                                 mgmt_errstr(ev->status));
380         }
381
382         return 0;
383 }
384
385 static int mgmt_auth_failed(int mgmt_sk, uint16_t index,
386                                 struct mgmt_ev_auth_failed *ev,
387                                 uint16_t len)
388 {
389         if (len != sizeof(*ev)) {
390                 fprintf(stderr,
391                         "Invalid auth_failed event length (%u bytes)\n", len);
392                 return -EINVAL;
393         }
394
395         if (monitor) {
396                 char addr[18];
397                 ba2str(&ev->addr.bdaddr, addr);
398                 printf("hci%u %s auth failed with status 0x%02x (%s)\n",
399                         index, addr, ev->status, mgmt_errstr(ev->status));
400         }
401
402         return 0;
403 }
404
405 static int mgmt_name_changed(int mgmt_sk, uint16_t index,
406                                 struct mgmt_ev_local_name_changed *ev,
407                                 uint16_t len)
408 {
409         if (len != sizeof(*ev)) {
410                 fprintf(stderr,
411                         "Invalid local_name_changed length (%u bytes)\n", len);
412                 return -EINVAL;
413         }
414
415         if (monitor)
416                 printf("hci%u name changed: %s\n", index, ev->name);
417
418         return 0;
419 }
420
421 static void confirm_name_rsp(int mgmt_sk, uint16_t op, uint16_t id,
422                                 uint8_t status, void *rsp, uint16_t len,
423                                 void *user_data)
424 {
425         struct mgmt_rp_confirm_name *rp = rsp;
426         char addr[18];
427
428         if (len == 0 && status != 0) {
429                 fprintf(stderr,
430                         "hci%u confirm_name failed with status 0x%02x (%s)\n",
431                                         id, status, mgmt_errstr(status));
432                 return;
433         }
434
435         if (len != sizeof(*rp)) {
436                 fprintf(stderr,
437                         "hci%u confirm_name rsp length %u instead of %zu\n",
438                         id, len, sizeof(*rp));
439                 return;
440         }
441
442         ba2str(&rp->addr.bdaddr, addr);
443
444         if (status != 0)
445                 fprintf(stderr,
446                         "hci%u confirm_name for %s failed: 0x%02x (%s)\n",
447                         id, addr, status, mgmt_errstr(status));
448         else
449                 printf("hci%u confirm_name succeeded for %s\n", id, addr);
450 }
451
452 static int mgmt_device_found(int mgmt_sk, uint16_t index,
453                                 struct mgmt_ev_device_found *ev, uint16_t len)
454 {
455         uint32_t flags;
456         uint16_t eir_len;
457
458         if (len < sizeof(*ev)) {
459                 fprintf(stderr,
460                         "Too short device_found length (%u bytes)\n", len);
461                 return -EINVAL;
462         }
463
464         flags = btohs(ev->flags);
465
466         eir_len = bt_get_le16(&ev->eir_len);
467         if (len != sizeof(*ev) + eir_len) {
468                 fprintf(stderr, "dev_found: expected %zu bytes, got %u bytes",
469                                                 sizeof(*ev) + eir_len, len);
470                 return -EINVAL;
471         }
472
473         if (monitor || discovery) {
474                 char addr[18];
475                 ba2str(&ev->addr.bdaddr, addr);
476                 printf("hci%u dev_found: %s type %s rssi %d "
477                         "flags 0x%04x eir_len %u\n", index, addr,
478                         typestr(ev->addr.type), ev->rssi, flags, eir_len);
479         }
480
481         if (discovery && (flags & MGMT_DEV_FOUND_CONFIRM_NAME)) {
482                 struct mgmt_cp_confirm_name cp;
483
484                 memset(&cp, 0, sizeof(cp));
485                 memcpy(&cp.addr, &ev->addr, sizeof(cp.addr));
486                 if (resolve_names)
487                         cp.name_known = 0;
488                 else
489                         cp.name_known = 1;
490
491                 mgmt_send_cmd(mgmt_sk, MGMT_OP_CONFIRM_NAME, index,
492                                         &cp, sizeof(cp), confirm_name_rsp,
493                                         NULL);
494         }
495
496         return 0;
497 }
498
499 static void pin_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
500                                 void *rsp, uint16_t len, void *user_data)
501 {
502         if (status != 0) {
503                 fprintf(stderr,
504                         "hci%u PIN Code reply failed with status 0x%02x (%s)",
505                                         id, status, mgmt_errstr(status));
506                 exit(EXIT_FAILURE);
507         }
508
509         printf("hci%u PIN Reply successful\n", id);
510 }
511
512 static int mgmt_pin_reply(int mgmt_sk, uint16_t index,
513                                                 struct mgmt_addr_info *addr,
514                                                 const char *pin, size_t len)
515 {
516         struct mgmt_cp_pin_code_reply cp;
517
518         memset(&cp, 0, sizeof(cp));
519         memcpy(&cp.addr, addr, sizeof(cp.addr));
520         cp.pin_len = len;
521         memcpy(cp.pin_code, pin, len);
522
523         return mgmt_send_cmd(mgmt_sk, MGMT_OP_PIN_CODE_REPLY, index,
524                                         &cp, sizeof(cp), pin_rsp, NULL);
525 }
526
527 static void pin_neg_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
528                                 void *rsp, uint16_t len, void *user_data)
529 {
530         if (status != 0) {
531                 fprintf(stderr,
532                         "hci%u PIN Neg reply failed with status 0x%02x (%s)",
533                                         id, status, mgmt_errstr(status));
534                 exit(EXIT_FAILURE);
535         }
536
537         printf("hci%u PIN Negative Reply successful\n", id);
538 }
539
540 static int mgmt_pin_neg_reply(int mgmt_sk, uint16_t index,
541                                                 struct mgmt_addr_info *addr)
542 {
543         struct mgmt_cp_pin_code_neg_reply cp;
544
545         memset(&cp, 0, sizeof(cp));
546         memcpy(&cp.addr, addr, sizeof(cp.addr));
547
548         return mgmt_send_cmd(mgmt_sk, MGMT_OP_PIN_CODE_NEG_REPLY, index,
549                                         &cp, sizeof(cp), pin_neg_rsp, NULL);
550 }
551
552 static int mgmt_request_pin(int mgmt_sk, uint16_t index,
553                                 struct mgmt_ev_pin_code_request *ev,
554                                 uint16_t len)
555 {
556         char pin[18];
557         size_t pin_len;
558
559         if (len != sizeof(*ev)) {
560                 fprintf(stderr,
561                         "Invalid pin_code request length (%u bytes)\n", len);
562                 return -EINVAL;
563         }
564
565         if (monitor) {
566                 char addr[18];
567                 ba2str(&ev->addr.bdaddr, addr);
568                 printf("hci%u %s request PIN\n", index, addr);
569         }
570
571         printf("PIN Request (press enter to reject) >> ");
572         fflush(stdout);
573
574         memset(pin, 0, sizeof(pin));
575
576         if (fgets(pin, sizeof(pin), stdin) == NULL || pin[0] == '\n')
577                 return mgmt_pin_neg_reply(mgmt_sk, index, &ev->addr);
578
579         pin_len = strlen(pin);
580         if (pin[pin_len - 1] == '\n') {
581                 pin[pin_len - 1] = '\0';
582                 pin_len--;
583         }
584
585         return mgmt_pin_reply(mgmt_sk, index, &ev->addr, pin, pin_len);
586 }
587
588 static void confirm_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
589                                 void *rsp, uint16_t len, void *user_data)
590 {
591         if (status != 0) {
592                 fprintf(stderr,
593                         "hci%u User Confirm reply failed. status 0x%02x (%s)",
594                                         id, status, mgmt_errstr(status));
595                 exit(EXIT_FAILURE);
596         }
597
598         printf("hci%u User Confirm Reply successful\n", id);
599 }
600
601 static int mgmt_confirm_reply(int mgmt_sk, uint16_t index, bdaddr_t *bdaddr)
602 {
603         struct mgmt_cp_user_confirm_reply cp;
604
605         memset(&cp, 0, sizeof(cp));
606         bacpy(&cp.addr.bdaddr, bdaddr);
607
608         return mgmt_send_cmd(mgmt_sk, MGMT_OP_USER_CONFIRM_REPLY, index,
609                                         &cp, sizeof(cp), confirm_rsp, NULL);
610 }
611
612 static void confirm_neg_rsp(int mgmt_sk, uint16_t op, uint16_t id,
613                                 uint8_t status, void *rsp, uint16_t len,
614                                 void *user_data)
615 {
616         if (status != 0) {
617                 fprintf(stderr,
618                         "hci%u Confirm Neg reply failed. status 0x%02x (%s)",
619                                         id, status, mgmt_errstr(status));
620                 exit(EXIT_FAILURE);
621         }
622
623         printf("hci%u User Confirm Negative Reply successful\n", id);
624 }
625
626 static int mgmt_confirm_neg_reply(int mgmt_sk, uint16_t index,
627                                                         bdaddr_t *bdaddr)
628 {
629         struct mgmt_cp_user_confirm_reply cp;
630
631         memset(&cp, 0, sizeof(cp));
632         bacpy(&cp.addr.bdaddr, bdaddr);
633
634         return mgmt_send_cmd(mgmt_sk, MGMT_OP_USER_CONFIRM_NEG_REPLY, index,
635                                 &cp, sizeof(cp), confirm_neg_rsp, NULL);
636 }
637
638
639 static int mgmt_user_confirm(int mgmt_sk, uint16_t index,
640                                 struct mgmt_ev_user_confirm_request *ev,
641                                 uint16_t len)
642 {
643         char rsp[5];
644         size_t rsp_len;
645         uint32_t val;
646         char addr[18];
647
648         if (len != sizeof(*ev)) {
649                 fprintf(stderr,
650                         "Invalid user_confirm request length (%u)\n", len);
651                 return -EINVAL;
652         }
653
654         ba2str(&ev->addr.bdaddr, addr);
655         val = bt_get_le32(&ev->value);
656
657         if (monitor)
658                 printf("hci%u %s User Confirm %06u hint %u\n", index, addr,
659                                                         val, ev->confirm_hint);
660
661         if (ev->confirm_hint)
662                 printf("Accept pairing with %s (yes/no) >> ", addr);
663         else
664                 printf("Confirm value %06u for %s (yes/no) >> ", val, addr);
665
666         fflush(stdout);
667
668         memset(rsp, 0, sizeof(rsp));
669
670         if (fgets(rsp, sizeof(rsp), stdin) == NULL || rsp[0] == '\n')
671                 return mgmt_confirm_neg_reply(mgmt_sk, index, &ev->addr.bdaddr);
672
673         rsp_len = strlen(rsp);
674         if (rsp[rsp_len - 1] == '\n') {
675                 rsp[rsp_len - 1] = '\0';
676                 rsp_len--;
677         }
678
679         if (rsp[0] == 'y' || rsp[0] == 'Y')
680                 return mgmt_confirm_reply(mgmt_sk, index, &ev->addr.bdaddr);
681         else
682                 return mgmt_confirm_neg_reply(mgmt_sk, index, &ev->addr.bdaddr);
683 }
684
685 static int mgmt_handle_event(int mgmt_sk, uint16_t ev, uint16_t index,
686                                                 void *data, uint16_t len)
687 {
688         if (monitor)
689                 printf("event: %s\n", mgmt_evstr(ev));
690
691         switch (ev) {
692         case MGMT_EV_CMD_COMPLETE:
693                 return mgmt_cmd_complete(mgmt_sk, index, data, len);
694         case MGMT_EV_CMD_STATUS:
695                 return mgmt_cmd_status(mgmt_sk, index, data, len);
696         case MGMT_EV_CONTROLLER_ERROR:
697                 return mgmt_controller_error(index, data, len);
698         case MGMT_EV_INDEX_ADDED:
699                 return mgmt_index_added(mgmt_sk, index);
700         case MGMT_EV_INDEX_REMOVED:
701                 return mgmt_index_removed(mgmt_sk, index);
702         case MGMT_EV_NEW_SETTINGS:
703                 return mgmt_new_settings(mgmt_sk, index, data, len);
704         case MGMT_EV_DISCOVERING:
705                 return mgmt_discovering(mgmt_sk, index, data, len);
706         case MGMT_EV_NEW_LINK_KEY:
707                 return mgmt_new_link_key(mgmt_sk, index, data, len);
708         case MGMT_EV_DEVICE_CONNECTED:
709                 return mgmt_connected(mgmt_sk, index, data, len);
710         case MGMT_EV_DEVICE_DISCONNECTED:
711                 return mgmt_disconnected(mgmt_sk, index, data, len);
712         case MGMT_EV_CONNECT_FAILED:
713                 return mgmt_conn_failed(mgmt_sk, index, data, len);
714         case MGMT_EV_AUTH_FAILED:
715                 return mgmt_auth_failed(mgmt_sk, index, data, len);
716         case MGMT_EV_LOCAL_NAME_CHANGED:
717                 return mgmt_name_changed(mgmt_sk, index, data, len);
718         case MGMT_EV_DEVICE_FOUND:
719                 return mgmt_device_found(mgmt_sk, index, data, len);
720         case MGMT_EV_PIN_CODE_REQUEST:
721                 return mgmt_request_pin(mgmt_sk, index, data, len);
722         case MGMT_EV_USER_CONFIRM_REQUEST:
723                 return mgmt_user_confirm(mgmt_sk, index, data, len);
724         default:
725                 if (monitor)
726                         printf("Unhandled event 0x%04x (%s)\n", ev, mgmt_evstr(ev));
727                 return 0;
728         }
729 }
730
731 static int mgmt_process_data(int mgmt_sk)
732 {
733         char buf[1024];
734         struct mgmt_hdr *hdr = (void *) buf;
735         uint16_t len, ev, index;
736         ssize_t ret;
737
738         ret = read(mgmt_sk, buf, sizeof(buf));
739         if (ret < 0) {
740                 fprintf(stderr, "read: %s\n", strerror(errno));
741                 return ret;
742         }
743
744         if (ret < MGMT_HDR_SIZE) {
745                 fprintf(stderr, "Too small mgmt packet (%zd bytes)\n", ret);
746                 return 0;
747         }
748
749         ev = bt_get_le16(&hdr->opcode);
750         index = bt_get_le16(&hdr->index);
751         len = bt_get_le16(&hdr->len);
752
753         if (monitor)
754                 printf("event 0x%04x len 0x%04x index 0x%04x\n", ev, len, index);
755
756         if (ret != MGMT_HDR_SIZE + len) {
757                 fprintf(stderr, "Packet length mismatch. ret %zd len %u",
758                                                                 ret, len);
759                 return 0;
760         }
761
762         mgmt_handle_event(mgmt_sk, ev, index, buf + MGMT_HDR_SIZE, len);
763
764         return 0;
765 }
766
767 static void cmd_monitor(int mgmt_sk, uint16_t index, int argc, char **argv)
768 {
769         printf("Monitoring mgmt events...\n");
770         monitor = true;
771 }
772
773 static void version_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
774                                 void *rsp, uint16_t len, void *user_data)
775 {
776         struct mgmt_rp_read_version *rp = rsp;
777
778         if (status != 0) {
779                 fprintf(stderr, "Reading mgmt version failed with status"
780                         " 0x%02x (%s)\n", status, mgmt_errstr(status));
781                 exit(EXIT_FAILURE);
782         }
783
784         if (len < sizeof(*rp)) {
785                 fprintf(stderr, "Too small version reply (%u bytes)\n", len);
786                 exit(EXIT_FAILURE);
787         }
788
789         printf("MGMT Version %u, revision %u\n", rp->version,
790                                                 bt_get_le16(&rp->revision));
791
792         exit(EXIT_SUCCESS);
793 }
794
795 static void cmd_version(int mgmt_sk, uint16_t index, int argc, char **argv)
796 {
797         if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_VERSION, MGMT_INDEX_NONE,
798                                         NULL, 0, version_rsp, NULL) < 0) {
799                 fprintf(stderr, "Unable to send read_version cmd\n");
800                 exit(EXIT_FAILURE);
801         }
802 }
803
804 static void commands_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
805                                 void *rsp, uint16_t len, void *user_data)
806 {
807         struct mgmt_rp_read_commands *rp = rsp;
808         uint16_t num_commands, num_events, *opcode;
809         size_t expected_len;
810         int i;
811
812         if (status != 0) {
813                 fprintf(stderr, "Reading supported commands failed with status"
814                         " 0x%02x (%s)\n", status, mgmt_errstr(status));
815                 exit(EXIT_FAILURE);
816         }
817
818         if (len < sizeof(*rp)) {
819                 fprintf(stderr, "Too small commands reply (%u bytes)\n", len);
820                 exit(EXIT_FAILURE);
821         }
822
823         num_commands = bt_get_le16(&rp->num_commands);
824         num_events = bt_get_le16(&rp->num_events);
825
826         expected_len = sizeof(*rp) + num_commands * sizeof(uint16_t) +
827                                                 num_events * sizeof(uint16_t);
828
829         if (len < expected_len) {
830                 fprintf(stderr, "Too small commands reply (%u != %zu)\n",
831                                                         len, expected_len);
832                 exit(EXIT_FAILURE);
833         }
834
835         opcode = rp->opcodes;
836
837         printf("%u commands:\n", num_commands);
838         for (i = 0; i < num_commands; i++) {
839                 uint16_t op = bt_get_le16(opcode++);
840                 printf("\t%s (0x%04x)\n", mgmt_opstr(op), op);
841         }
842
843         printf("%u events:\n", num_events);
844         for (i = 0; i < num_events; i++) {
845                 uint16_t ev = bt_get_le16(opcode++);
846                 printf("\t%s (0x%04x)\n", mgmt_evstr(ev), ev);
847         }
848
849         exit(EXIT_SUCCESS);
850 }
851
852 static void cmd_commands(int mgmt_sk, uint16_t index, int argc, char **argv)
853 {
854         if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_COMMANDS, MGMT_INDEX_NONE,
855                                         NULL, 0, commands_rsp, NULL) < 0) {
856                 fprintf(stderr, "Unable to send read_commands cmd\n");
857                 exit(EXIT_FAILURE);
858         }
859 }
860
861 static void info_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
862                                 void *rsp, uint16_t len, void *user_data)
863 {
864         struct mgmt_rp_read_info *rp = rsp;
865         char addr[18];
866
867         if (status != 0) {
868                 fprintf(stderr,
869                         "Reading hci%u info failed with status 0x%02x (%s)\n",
870                                         id, status, mgmt_errstr(status));
871                 exit(EXIT_FAILURE);
872         }
873
874         if (len < sizeof(*rp)) {
875                 fprintf(stderr, "Too small info reply (%u bytes)\n", len);
876                 exit(EXIT_FAILURE);
877         }
878
879         ba2str(&rp->bdaddr, addr);
880         printf("hci%u:\taddr %s version %u manufacturer %u"
881                         " class 0x%02x%02x%02x\n",
882                         id, addr, rp->version, bt_get_le16(&rp->manufacturer),
883                         rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
884
885         printf("\tsupported settings: ");
886         print_settings(bt_get_le32(&rp->supported_settings));
887
888         printf("\n\tcurrent settings: ");
889         print_settings(bt_get_le32(&rp->current_settings));
890
891         printf("\n\tname %s\n", rp->name);
892         printf("\tshort name %s\n", rp->short_name);
893
894         if (pending == NULL)
895                 exit(EXIT_SUCCESS);
896 }
897
898 static void index_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
899                                 void *rsp, uint16_t len, void *user_data)
900 {
901         struct mgmt_rp_read_index_list *rp = rsp;
902         uint16_t count;
903         unsigned int i;
904
905         if (status != 0) {
906                 fprintf(stderr,
907                         "Reading index list failed with status 0x%02x (%s)\n",
908                                                 status, mgmt_errstr(status));
909                 exit(EXIT_FAILURE);
910         }
911
912         if (len < sizeof(*rp)) {
913                 fprintf(stderr, "Too small index list reply (%u bytes)\n",
914                                                                         len);
915                 exit(EXIT_FAILURE);
916         }
917
918         count = bt_get_le16(&rp->num_controllers);
919
920         if (len < sizeof(*rp) + count * sizeof(uint16_t)) {
921                 fprintf(stderr,
922                         "Index count (%u) doesn't match reply length (%u)\n",
923                                                                 count, len);
924                 exit(EXIT_FAILURE);
925         }
926
927         if (monitor)
928                 printf("Index list with %u item%s\n",
929                                                 count, count > 1 ? "s" : "");
930
931         if (count == 0)
932                 exit(EXIT_SUCCESS);
933
934         if (monitor && count > 0)
935                 printf("\t");
936
937         for (i = 0; i < count; i++) {
938                 uint16_t index;
939
940                 index = bt_get_le16(&rp->index[i]);
941
942                 if (monitor)
943                         printf("hci%u ", index);
944
945                 if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INFO, index, NULL,
946                                         0, info_rsp, NULL) < 0) {
947                         fprintf(stderr, "Unable to send read_info cmd\n");
948                         exit(EXIT_FAILURE);
949                 }
950         }
951
952         if (monitor && count > 0)
953                 printf("\n");
954 }
955
956 static void cmd_info(int mgmt_sk, uint16_t index, int argc, char **argv)
957 {
958         if (index == MGMT_INDEX_NONE) {
959                 if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INDEX_LIST,
960                                         MGMT_INDEX_NONE, NULL, 0,
961                                         index_rsp, NULL) < 0) {
962                         fprintf(stderr, "Unable to send index_list cmd\n");
963                         exit(EXIT_FAILURE);
964                 }
965
966                 return;
967         }
968
969         if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INFO, index, NULL,
970                                                 0, info_rsp, NULL) < 0) {
971                 fprintf(stderr, "Unable to send read_info cmd\n");
972                 exit(EXIT_FAILURE);
973         }
974 }
975
976 static void setting_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
977                                 void *rsp, uint16_t len, void *user_data)
978 {
979         uint32_t *rp = rsp;
980
981         if (status != 0) {
982                 fprintf(stderr,
983                         "%s for hci%u failed with status 0x%02x (%s)\n",
984                         mgmt_opstr(op), id, status, mgmt_errstr(status));
985                 exit(EXIT_FAILURE);
986         }
987
988         if (len < sizeof(*rp)) {
989                 fprintf(stderr, "Too small %s response (%u bytes)\n",
990                                                         mgmt_opstr(op), len);
991                 exit(EXIT_FAILURE);
992         }
993
994         printf("hci%u %s complete, settings: ", id, mgmt_opstr(op));
995         print_settings(bt_get_le32(rp));
996         printf("\n");
997
998         exit(EXIT_SUCCESS);
999 }
1000
1001 static void cmd_setting(int mgmt_sk, uint16_t index, uint16_t op,
1002                                                         int argc, char **argv)
1003 {
1004         uint8_t val;
1005
1006         if (argc < 2) {
1007                 printf("Specify \"on\" or \"off\"\n");
1008                 exit(EXIT_FAILURE);
1009         }
1010
1011         if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
1012                 val = 1;
1013         else if (strcasecmp(argv[1], "off") == 0)
1014                 val = 0;
1015         else
1016                 val = atoi(argv[1]);
1017
1018         if (index == MGMT_INDEX_NONE)
1019                 index = 0;
1020
1021         if (mgmt_send_cmd(mgmt_sk, op, index, &val, sizeof(val),
1022                                                 setting_rsp, NULL) < 0) {
1023                 fprintf(stderr, "Unable to send %s cmd\n", mgmt_opstr(op));
1024                 exit(EXIT_FAILURE);
1025         }
1026 }
1027
1028 static void cmd_power(int mgmt_sk, uint16_t index, int argc, char **argv)
1029 {
1030         cmd_setting(mgmt_sk, index, MGMT_OP_SET_POWERED, argc, argv);
1031 }
1032
1033 static void cmd_discov(int mgmt_sk, uint16_t index, int argc, char **argv)
1034 {
1035         struct mgmt_cp_set_discoverable cp;
1036
1037         if (argc < 2) {
1038                 printf("Usage: btmgmt %s <yes/no> [timeout]\n", argv[0]);
1039                 exit(EXIT_FAILURE);
1040         }
1041
1042         memset(&cp, 0, sizeof(cp));
1043
1044         if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
1045                 cp.val = 1;
1046         else if (strcasecmp(argv[1], "off") == 0)
1047                 cp.val = 0;
1048         else
1049                 cp.val = atoi(argv[1]);
1050
1051         if (argc > 2)
1052                 cp.timeout = htobs(atoi(argv[2]));
1053
1054         if (index == MGMT_INDEX_NONE)
1055                 index = 0;
1056
1057         if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_DISCOVERABLE, index,
1058                                 &cp, sizeof(cp), setting_rsp, NULL) < 0) {
1059                 fprintf(stderr, "Unable to send set_discoverable cmd\n");
1060                 exit(EXIT_FAILURE);
1061         }
1062 }
1063
1064 static void cmd_connectable(int mgmt_sk, uint16_t index, int argc, char **argv)
1065 {
1066         cmd_setting(mgmt_sk, index, MGMT_OP_SET_CONNECTABLE, argc, argv);
1067 }
1068
1069 static void cmd_pairable(int mgmt_sk, uint16_t index, int argc, char **argv)
1070 {
1071         cmd_setting(mgmt_sk, index, MGMT_OP_SET_PAIRABLE, argc, argv);
1072 }
1073
1074 static void cmd_linksec(int mgmt_sk, uint16_t index, int argc, char **argv)
1075 {
1076         cmd_setting(mgmt_sk, index, MGMT_OP_SET_LINK_SECURITY, argc, argv);
1077 }
1078
1079 static void cmd_ssp(int mgmt_sk, uint16_t index, int argc, char **argv)
1080 {
1081         cmd_setting(mgmt_sk, index, MGMT_OP_SET_SSP, argc, argv);
1082 }
1083
1084 static void cmd_hs(int mgmt_sk, uint16_t index, int argc, char **argv)
1085 {
1086         cmd_setting(mgmt_sk, index, MGMT_OP_SET_HS, argc, argv);
1087 }
1088
1089 static void cmd_le(int mgmt_sk, uint16_t index, int argc, char **argv)
1090 {
1091         cmd_setting(mgmt_sk, index, MGMT_OP_SET_LE, argc, argv);
1092 }
1093
1094 static void class_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
1095                                 void *rsp, uint16_t len, void *user_data)
1096 {
1097         struct mgmt_ev_class_of_dev_changed *rp = rsp;
1098
1099         if (len == 0 && status != 0) {
1100                 fprintf(stderr, "%s failed, status 0x%02x (%s)\n",
1101                                 mgmt_opstr(op), status, mgmt_errstr(status));
1102                 exit(EXIT_FAILURE);
1103         }
1104
1105         if (len != sizeof(*rp)) {
1106                 fprintf(stderr, "Unexpected %s len %u\n", mgmt_opstr(op), len);
1107                 exit(EXIT_FAILURE);
1108         }
1109
1110         printf("%s succeeded. Class 0x%02x%02x%02x\n", mgmt_opstr(op),
1111                 rp->class_of_dev[2], rp->class_of_dev[1], rp->class_of_dev[0]);
1112
1113         exit(EXIT_SUCCESS);
1114 }
1115
1116 static void cmd_class(int mgmt_sk, uint16_t index, int argc, char **argv)
1117 {
1118         uint8_t class[2];
1119
1120         if (argc < 3) {
1121                 printf("Usage: btmgmt %s <major> <minor>\n", argv[0]);
1122                 exit(EXIT_FAILURE);
1123         }
1124
1125         class[0] = atoi(argv[1]);
1126         class[1] = atoi(argv[2]);
1127
1128         if (index == MGMT_INDEX_NONE)
1129                 index = 0;
1130
1131         if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_DEV_CLASS, index,
1132                                 class, sizeof(class), class_rsp, NULL) < 0) {
1133                 fprintf(stderr, "Unable to send set_dev_class cmd\n");
1134                 exit(EXIT_FAILURE);
1135         }
1136 }
1137
1138 static void disconnect_rsp(int mgmt_sk, uint16_t op, uint16_t id,
1139                                 uint8_t status, void *rsp, uint16_t len,
1140                                 void *user_data)
1141 {
1142         struct mgmt_rp_disconnect *rp = rsp;
1143         char addr[18];
1144
1145         if (len == 0 && status != 0) {
1146                 fprintf(stderr, "Disconnect failed with status 0x%02x (%s)\n",
1147                                                 status, mgmt_errstr(status));
1148                 exit(EXIT_FAILURE);
1149         }
1150
1151         if (len != sizeof(*rp)) {
1152                 fprintf(stderr, "Invalid disconnect response length (%u)\n",
1153                                                                         len);
1154                 exit(EXIT_FAILURE);
1155         }
1156
1157         ba2str(&rp->addr.bdaddr, addr);
1158
1159         if (status == 0) {
1160                 printf("%s disconnected\n", addr);
1161                 exit(EXIT_SUCCESS);
1162         } else {
1163                 fprintf(stderr,
1164                         "Disconnecting %s failed with status 0x%02x (%s)\n",
1165                                 addr, status, mgmt_errstr(status));
1166                 exit(EXIT_FAILURE);
1167         }
1168 }
1169
1170 static void cmd_disconnect(int mgmt_sk, uint16_t index, int argc, char **argv)
1171 {
1172         struct mgmt_cp_disconnect cp;
1173
1174         if (argc < 2) {
1175                 printf("Usage: btmgmt %s <address>\n", argv[0]);
1176                 exit(EXIT_FAILURE);
1177         }
1178
1179         str2ba(argv[1], &cp.addr.bdaddr);
1180
1181         if (index == MGMT_INDEX_NONE)
1182                 index = 0;
1183
1184         if (mgmt_send_cmd(mgmt_sk, MGMT_OP_DISCONNECT, index,
1185                                 &cp, sizeof(cp), disconnect_rsp, NULL) < 0) {
1186                 fprintf(stderr, "Unable to send disconnect cmd\n");
1187                 exit(EXIT_FAILURE);
1188         }
1189 }
1190
1191 static void con_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
1192                                 void *rsp, uint16_t len, void *user_data)
1193 {
1194         struct mgmt_rp_get_connections *rp = rsp;
1195         uint16_t count, i;
1196
1197         if (len < sizeof(*rp)) {
1198                 fprintf(stderr, "Too small (%u bytes) get_connections rsp\n",
1199                                                                         len);
1200                 exit(EXIT_FAILURE);
1201         }
1202
1203         count = bt_get_le16(&rp->conn_count);
1204         if (len != sizeof(*rp) + count * sizeof(struct mgmt_addr_info)) {
1205                 fprintf(stderr, "Invalid get_connections length "
1206                                         " (count=%u, len=%u)\n", count, len);
1207                 exit(EXIT_FAILURE);
1208         }
1209
1210         for (i = 0; i < count; i++) {
1211                 char addr[18];
1212
1213                 ba2str(&rp->addr[i].bdaddr, addr);
1214
1215                 printf("%s type %s\n", addr, typestr(rp->addr[i].type));
1216         }
1217
1218         exit(EXIT_SUCCESS);
1219 }
1220
1221 static void cmd_con(int mgmt_sk, uint16_t index, int argc, char **argv)
1222 {
1223         if (index == MGMT_INDEX_NONE)
1224                 index = 0;
1225
1226         if (mgmt_send_cmd(mgmt_sk, MGMT_OP_GET_CONNECTIONS, index, NULL, 0,
1227                                                         con_rsp, NULL) < 0) {
1228                 fprintf(stderr, "Unable to send get_connections cmd\n");
1229                 exit(EXIT_FAILURE);
1230         }
1231 }
1232
1233 static void find_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
1234                                 void *rsp, uint16_t len, void *user_data)
1235 {
1236         if (status != 0) {
1237                 fprintf(stderr,
1238                         "Unable to start discovery. status 0x%02x (%s)\n",
1239                                                 status, mgmt_errstr(status));
1240                 exit(EXIT_FAILURE);
1241         }
1242
1243         printf("Discovery started\n");
1244         discovery = true;
1245 }
1246
1247 static void find_usage(void)
1248 {
1249         printf("Usage: btmgmt find [-l|-b]>\n");
1250 }
1251
1252 static struct option find_options[] = {
1253         { "help",       0, 0, 'h' },
1254         { "le-only",    1, 0, 'l' },
1255         { "bredr-only", 1, 0, 'b' },
1256         { 0, 0, 0, 0 }
1257 };
1258
1259 static void cmd_find(int mgmt_sk, uint16_t index, int argc, char **argv)
1260 {
1261         struct mgmt_cp_start_discovery cp;
1262         uint8_t type;
1263         int opt;
1264
1265         if (index == MGMT_INDEX_NONE)
1266                 index = 0;
1267
1268         type = 0;
1269         hci_set_bit(BDADDR_BREDR, &type);
1270         hci_set_bit(BDADDR_LE_PUBLIC, &type);
1271         hci_set_bit(BDADDR_LE_RANDOM, &type);
1272
1273         while ((opt = getopt_long(argc, argv, "+lbh", find_options,
1274                                                                 NULL)) != -1) {
1275                 switch (opt) {
1276                 case 'l':
1277                         hci_clear_bit(BDADDR_BREDR, &type);
1278                         hci_set_bit(BDADDR_LE_PUBLIC, &type);
1279                         hci_set_bit(BDADDR_LE_RANDOM, &type);
1280                         break;
1281                 case 'b':
1282                         hci_set_bit(BDADDR_BREDR, &type);
1283                         hci_clear_bit(BDADDR_LE_PUBLIC, &type);
1284                         hci_clear_bit(BDADDR_LE_RANDOM, &type);
1285                         break;
1286                 case 'h':
1287                 default:
1288                         find_usage();
1289                         exit(EXIT_SUCCESS);
1290                 }
1291         }
1292
1293         argc -= optind;
1294         argv += optind;
1295         optind = 0;
1296
1297         memset(&cp, 0, sizeof(cp));
1298         cp.type = type;
1299
1300         if (mgmt_send_cmd(mgmt_sk, MGMT_OP_START_DISCOVERY, index,
1301                                 &cp, sizeof(cp), find_rsp, NULL) < 0) {
1302                 fprintf(stderr, "Unable to send start_discovery cmd\n");
1303                 exit(EXIT_FAILURE);
1304         }
1305 }
1306
1307 static void name_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
1308                                 void *rsp, uint16_t len, void *user_data)
1309 {
1310         if (status != 0) {
1311                 fprintf(stderr, "Unable to set local name. status 0x%02x (%s)",
1312                                                 status, mgmt_errstr(status));
1313                 exit(EXIT_FAILURE);
1314         }
1315
1316         exit(EXIT_SUCCESS);
1317 }
1318
1319 static void cmd_name(int mgmt_sk, uint16_t index, int argc, char **argv)
1320 {
1321         struct mgmt_cp_set_local_name cp;
1322
1323         if (argc < 2) {
1324                 printf("Usage: btmgmt %s <name> [shortname]\n", argv[0]);
1325                 exit(EXIT_FAILURE);
1326         }
1327
1328         if (index == MGMT_INDEX_NONE)
1329                 index = 0;
1330
1331         memset(&cp, 0, sizeof(cp));
1332         strncpy((char *) cp.name, argv[1], HCI_MAX_NAME_LENGTH);
1333         if (argc > 2)
1334                 strncpy((char *) cp.short_name, argv[2],
1335                                         MGMT_MAX_SHORT_NAME_LENGTH);
1336
1337         if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_LOCAL_NAME, index,
1338                                         &cp, sizeof(cp), name_rsp, NULL) < 0) {
1339                 fprintf(stderr, "Unable to send set_name cmd\n");
1340                 exit(EXIT_FAILURE);
1341         }
1342 }
1343
1344 static void pair_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
1345                                 void *rsp, uint16_t len, void *user_data)
1346 {
1347         struct mgmt_rp_pair_device *rp = rsp;
1348         char addr[18];
1349
1350         if (len == 0 && status != 0) {
1351                 fprintf(stderr, "Pairing failed with status 0x%02x (%s)\n",
1352                                                 status, mgmt_errstr(status));
1353                 exit(EXIT_FAILURE);
1354         }
1355
1356         if (len != sizeof(*rp)) {
1357                 fprintf(stderr, "Unexpected pair_rsp len %u\n", len);
1358                 exit(EXIT_FAILURE);
1359         }
1360
1361         ba2str(&rp->addr.bdaddr, addr);
1362
1363         if (status != 0) {
1364                 fprintf(stderr,
1365                         "Pairing with %s (%s) failed. status 0x%02x (%s)\n",
1366                         addr, typestr(rp->addr.type), status,
1367                         mgmt_errstr(status));
1368                 exit(EXIT_FAILURE);
1369         }
1370
1371         printf("Paired with %s\n", addr);
1372
1373         exit(EXIT_SUCCESS);
1374 }
1375
1376 static void pair_usage(void)
1377 {
1378         printf("Usage: btmgmt pair [-c cap] [-t type] <remote address>\n");
1379 }
1380
1381 static struct option pair_options[] = {
1382         { "help",       0, 0, 'h' },
1383         { "capability", 1, 0, 'c' },
1384         { "type",       1, 0, 't' },
1385         { 0, 0, 0, 0 }
1386 };
1387
1388 static void cmd_pair(int mgmt_sk, uint16_t index, int argc, char **argv)
1389 {
1390         struct mgmt_cp_pair_device cp;
1391         uint8_t cap = 0x01;
1392         uint8_t type = BDADDR_BREDR;
1393         int opt;
1394
1395         while ((opt = getopt_long(argc, argv, "+c:t:h", pair_options,
1396                                                                 NULL)) != -1) {
1397                 switch (opt) {
1398                 case 'c':
1399                         cap = strtol(optarg, NULL, 0);
1400                         break;
1401                 case 't':
1402                         type = strtol(optarg, NULL, 0);
1403                         break;
1404                 case 'h':
1405                 default:
1406                         pair_usage();
1407                         exit(EXIT_SUCCESS);
1408                 }
1409         }
1410
1411         argc -= optind;
1412         argv += optind;
1413         optind = 0;
1414
1415         if (argc < 1) {
1416                 pair_usage();
1417                 exit(EXIT_FAILURE);
1418         }
1419
1420         if (index == MGMT_INDEX_NONE)
1421                 index = 0;
1422
1423         memset(&cp, 0, sizeof(cp));
1424         str2ba(argv[0], &cp.addr.bdaddr);
1425         cp.addr.type = type;
1426         cp.io_cap = cap;
1427
1428         if (mgmt_send_cmd(mgmt_sk, MGMT_OP_PAIR_DEVICE, index, &cp, sizeof(cp),
1429                                                         pair_rsp, NULL) < 0) {
1430                 fprintf(stderr, "Unable to send pair_device cmd\n");
1431                 exit(EXIT_FAILURE);
1432         }
1433 }
1434
1435 static void unpair_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
1436                                 void *rsp, uint16_t len, void *user_data)
1437 {
1438         struct mgmt_rp_unpair_device *rp = rsp;
1439         char addr[18];
1440
1441         if (len == 0 && status != 0) {
1442                 fprintf(stderr, "Unpair device failed. status 0x%02x (%s)\n",
1443                                                 status, mgmt_errstr(status));
1444                 exit(EXIT_FAILURE);
1445         }
1446
1447         if (len != sizeof(*rp)) {
1448                 fprintf(stderr, "Unexpected unpair_device_rsp len %u\n", len);
1449                 exit(EXIT_FAILURE);
1450         }
1451
1452         ba2str(&rp->addr.bdaddr, addr);
1453
1454         if (status != 0) {
1455                 fprintf(stderr,
1456                         "Unpairing %s failed. status 0x%02x (%s)\n",
1457                                 addr, status, mgmt_errstr(status));
1458                 exit(EXIT_FAILURE);
1459         }
1460
1461         printf("%s unpaired\n", addr);
1462
1463         exit(EXIT_SUCCESS);
1464 }
1465
1466 static void cmd_unpair(int mgmt_sk, uint16_t index, int argc, char **argv)
1467 {
1468         struct mgmt_cp_unpair_device cp;
1469
1470         if (argc < 2) {
1471                 printf("Usage: btmgmt %s <remote address>\n", argv[0]);
1472                 exit(EXIT_FAILURE);
1473         }
1474
1475         if (index == MGMT_INDEX_NONE)
1476                 index = 0;
1477
1478         memset(&cp, 0, sizeof(cp));
1479         str2ba(argv[1], &cp.addr.bdaddr);
1480         cp.disconnect = 1;
1481
1482         if (mgmt_send_cmd(mgmt_sk, MGMT_OP_UNPAIR_DEVICE, index, &cp,
1483                                         sizeof(cp), unpair_rsp, NULL) < 0) {
1484                 fprintf(stderr, "Unable to send unpair_device cmd\n");
1485                 exit(EXIT_FAILURE);
1486         }
1487 }
1488
1489 static void keys_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
1490                                 void *rsp, uint16_t len, void *user_data)
1491 {
1492         if (status != 0) {
1493                 fprintf(stderr, "Load keys failed with status 0x%02x (%s)\n",
1494                                                 status, mgmt_errstr(status));
1495                 exit(EXIT_FAILURE);
1496         }
1497
1498         printf("Keys successfully loaded\n");
1499
1500         exit(EXIT_SUCCESS);
1501 }
1502
1503 static void cmd_keys(int mgmt_sk, uint16_t index, int argc, char **argv)
1504 {
1505         struct mgmt_cp_load_link_keys cp;
1506
1507         if (index == MGMT_INDEX_NONE)
1508                 index = 0;
1509
1510         memset(&cp, 0, sizeof(cp));
1511
1512         if (mgmt_send_cmd(mgmt_sk, MGMT_OP_LOAD_LINK_KEYS, index,
1513                                 &cp, sizeof(cp), keys_rsp, NULL) < 0) {
1514                 fprintf(stderr, "Unable to send load_keys cmd\n");
1515                 exit(EXIT_FAILURE);
1516         }
1517 }
1518
1519 static void block_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
1520                                 void *rsp, uint16_t len, void *user_data)
1521 {
1522         struct mgmt_addr_info *rp = rsp;
1523         char addr[18];
1524
1525         if (len == 0 && status != 0) {
1526                 fprintf(stderr, "%s failed, status 0x%02x (%s)\n",
1527                                 mgmt_opstr(op), status, mgmt_errstr(status));
1528                 exit(EXIT_FAILURE);
1529         }
1530
1531         if (len != sizeof(*rp)) {
1532                 fprintf(stderr, "Unexpected %s len %u\n", mgmt_opstr(op), len);
1533                 exit(EXIT_FAILURE);
1534         }
1535
1536         ba2str(&rp->bdaddr, addr);
1537
1538         if (status != 0) {
1539                 fprintf(stderr, "%s %s (%s) failed. status 0x%02x (%s)\n",
1540                                 mgmt_opstr(op), addr, typestr(rp->type),
1541                                 status, mgmt_errstr(status));
1542                 exit(EXIT_FAILURE);
1543         }
1544
1545         printf("%s %s succeeded\n", mgmt_opstr(op), addr);
1546
1547         exit(EXIT_SUCCESS);
1548 }
1549
1550 static void block_usage(void)
1551 {
1552         printf("Usage: btmgmt block [-t type] <remote address>\n");
1553 }
1554
1555 static struct option block_options[] = {
1556         { "help",       0, 0, 'h' },
1557         { "type",       1, 0, 't' },
1558         { 0, 0, 0, 0 }
1559 };
1560
1561 static void cmd_block(int mgmt_sk, uint16_t index, int argc, char **argv)
1562 {
1563         struct mgmt_cp_block_device cp;
1564         uint8_t type = BDADDR_BREDR;
1565         int opt;
1566
1567         while ((opt = getopt_long(argc, argv, "+t:h", block_options,
1568                                                         NULL)) != -1) {
1569                 switch (opt) {
1570                 case 't':
1571                         type = strtol(optarg, NULL, 0);
1572                         break;
1573                 case 'h':
1574                 default:
1575                         block_usage();
1576                         exit(EXIT_SUCCESS);
1577                 }
1578         }
1579
1580         argc -= optind;
1581         argv += optind;
1582         optind = 0;
1583
1584         if (argc < 1) {
1585                 block_usage();
1586                 exit(EXIT_FAILURE);
1587         }
1588
1589         if (index == MGMT_INDEX_NONE)
1590                 index = 0;
1591
1592         memset(&cp, 0, sizeof(cp));
1593         str2ba(argv[0], &cp.addr.bdaddr);
1594         cp.addr.type = type;
1595
1596         if (mgmt_send_cmd(mgmt_sk, MGMT_OP_BLOCK_DEVICE, index,
1597                                 &cp, sizeof(cp), block_rsp, NULL) < 0) {
1598                 fprintf(stderr, "Unable to send block_device cmd\n");
1599                 exit(EXIT_FAILURE);
1600         }
1601 }
1602
1603 static void unblock_usage(void)
1604 {
1605         printf("Usage: btmgmt unblock [-t type] <remote address>\n");
1606 }
1607
1608 static void cmd_unblock(int mgmt_sk, uint16_t index, int argc, char **argv)
1609 {
1610         struct mgmt_cp_unblock_device cp;
1611         uint8_t type = BDADDR_BREDR;
1612         int opt;
1613
1614         while ((opt = getopt_long(argc, argv, "+t:h", block_options,
1615                                                         NULL)) != -1) {
1616                 switch (opt) {
1617                 case 't':
1618                         type = strtol(optarg, NULL, 0);
1619                         break;
1620                 case 'h':
1621                 default:
1622                         unblock_usage();
1623                         exit(EXIT_SUCCESS);
1624                 }
1625         }
1626
1627         argc -= optind;
1628         argv += optind;
1629         optind = 0;
1630
1631         if (argc < 1) {
1632                 unblock_usage();
1633                 exit(EXIT_FAILURE);
1634         }
1635
1636         if (index == MGMT_INDEX_NONE)
1637                 index = 0;
1638
1639         memset(&cp, 0, sizeof(cp));
1640         str2ba(argv[0], &cp.addr.bdaddr);
1641         cp.addr.type = type;
1642
1643         if (mgmt_send_cmd(mgmt_sk, MGMT_OP_UNBLOCK_DEVICE, index,
1644                                 &cp, sizeof(cp), block_rsp, NULL) < 0) {
1645                 fprintf(stderr, "Unable to send unblock_device cmd\n");
1646                 exit(EXIT_FAILURE);
1647         }
1648 }
1649
1650 static void uuid_to_uuid128(uuid_t *uuid128, const uuid_t *uuid)
1651 {
1652         if (uuid->type == SDP_UUID16)
1653                 sdp_uuid16_to_uuid128(uuid128, uuid);
1654         else if (uuid->type == SDP_UUID32)
1655                 sdp_uuid32_to_uuid128(uuid128, uuid);
1656         else
1657                 memcpy(uuid128, uuid, sizeof(*uuid));
1658 }
1659
1660 static void cmd_add_uuid(int mgmt_sk, uint16_t index, int argc, char **argv)
1661 {
1662         struct mgmt_cp_add_uuid cp;
1663         uint128_t uint128;
1664         uuid_t uuid, uuid128;
1665
1666         if (argc < 3) {
1667                 printf("UUID and service hint needed\n");
1668                 exit(EXIT_FAILURE);
1669         }
1670
1671         if (index == MGMT_INDEX_NONE)
1672                 index = 0;
1673
1674         if (bt_string2uuid(&uuid, argv[1]) < 0) {
1675                 printf("Invalid UUID: %s\n", argv[1]);
1676                 exit(EXIT_FAILURE);
1677         }
1678
1679         memset(&cp, 0, sizeof(cp));
1680
1681         uuid_to_uuid128(&uuid128, &uuid);
1682         ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
1683         htob128(&uint128, (uint128_t *) cp.uuid);
1684
1685         cp.svc_hint = atoi(argv[2]);
1686
1687         if (mgmt_send_cmd(mgmt_sk, MGMT_OP_ADD_UUID, index,
1688                                 &cp, sizeof(cp), class_rsp, NULL) < 0) {
1689                 fprintf(stderr, "Unable to send add_uuid cmd\n");
1690                 exit(EXIT_FAILURE);
1691         }
1692 }
1693
1694 static void cmd_remove_uuid(int mgmt_sk, uint16_t index, int argc, char **argv)
1695 {
1696         struct mgmt_cp_remove_uuid cp;
1697         uint128_t uint128;
1698         uuid_t uuid, uuid128;
1699
1700         if (argc < 2) {
1701                 printf("UUID needed\n");
1702                 exit(EXIT_FAILURE);
1703         }
1704
1705         if (index == MGMT_INDEX_NONE)
1706                 index = 0;
1707
1708         if (bt_string2uuid(&uuid, argv[1]) < 0) {
1709                 printf("Invalid UUID: %s\n", argv[1]);
1710                 exit(EXIT_FAILURE);
1711         }
1712
1713         memset(&cp, 0, sizeof(cp));
1714
1715         uuid_to_uuid128(&uuid128, &uuid);
1716         ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
1717         htob128(&uint128, (uint128_t *) cp.uuid);
1718
1719         if (mgmt_send_cmd(mgmt_sk, MGMT_OP_REMOVE_UUID, index,
1720                                 &cp, sizeof(cp), class_rsp, NULL) < 0) {
1721                 fprintf(stderr, "Unable to send remove_uuid cmd\n");
1722                 exit(EXIT_FAILURE);
1723         }
1724 }
1725
1726 static void cmd_clr_uuids(int mgmt_sk, uint16_t index, int argc, char **argv)
1727 {
1728         char *uuid_any = "00000000-0000-0000-0000-000000000000";
1729         char *rm_argv[] = { "rm-uuid", uuid_any, NULL };
1730
1731         cmd_remove_uuid(mgmt_sk, index, 2, rm_argv);
1732 }
1733
1734 static void did_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
1735                                 void *rsp, uint16_t len, void *user_data)
1736 {
1737         if (status != 0) {
1738                 fprintf(stderr, "Set Device ID failed with status 0x%02x (%s)\n",
1739                                                 status, mgmt_errstr(status));
1740                 exit(EXIT_FAILURE);
1741         }
1742
1743         printf("Device ID successfully set\n");
1744
1745         exit(EXIT_SUCCESS);
1746 }
1747
1748 static void did_usage(void)
1749 {
1750         printf("Usage: btmgmt did <source>:<vendor>:<product>:<version>\n");
1751         printf("       possible source values: bluetooth, usb\n");
1752 }
1753
1754 static void cmd_did(int mgmt_sk, uint16_t index, int argc, char **argv)
1755 {
1756         struct mgmt_cp_set_device_id cp;
1757         uint16_t vendor, product, version , source;
1758         int result;
1759
1760         if (argc < 2) {
1761                 did_usage();
1762                 exit(EXIT_FAILURE);
1763         }
1764
1765         result = sscanf(argv[1], "bluetooth:%4hx:%4hx:%4hx", &vendor, &product,
1766                                                                 &version);
1767         if (result == 3) {
1768                 source = 0x0001;
1769                 goto done;
1770         }
1771
1772         result = sscanf(argv[1], "usb:%4hx:%4hx:%4hx", &vendor, &product,
1773                                                                 &version);
1774         if (result == 3) {
1775                 source = 0x0002;
1776                 goto done;
1777         }
1778
1779         did_usage();
1780         exit(EXIT_FAILURE);
1781
1782 done:
1783         if (index == MGMT_INDEX_NONE)
1784                 index = 0;
1785
1786         cp.source = htobs(source);
1787         cp.vendor = htobs(vendor);
1788         cp.product = htobs(product);
1789         cp.version = htobs(version);
1790
1791         if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_DEVICE_ID, index,
1792                                 &cp, sizeof(cp), did_rsp, NULL) < 0) {
1793                 fprintf(stderr, "Unable to send set_dev_class cmd\n");
1794                 exit(EXIT_FAILURE);
1795         }
1796 }
1797
1798 static struct {
1799         char *cmd;
1800         void (*func)(int mgmt_sk, uint16_t index, int argc, char **argv);
1801         char *doc;
1802 } command[] = {
1803         { "monitor",    cmd_monitor,    "Monitor events"                },
1804         { "version",    cmd_version,    "Get the MGMT Version"          },
1805         { "commands",   cmd_commands,   "List supported commands"       },
1806         { "info",       cmd_info,       "Show controller info"          },
1807         { "power",      cmd_power,      "Toggle powered state"          },
1808         { "discov",     cmd_discov,     "Toggle discoverable state"     },
1809         { "connectable",cmd_connectable,"Toggle connectable state"      },
1810         { "pairable",   cmd_pairable,   "Toggle pairable state"         },
1811         { "linksec",    cmd_linksec,    "Toggle link level security"    },
1812         { "ssp",        cmd_ssp,        "Toggle SSP mode"               },
1813         { "hs",         cmd_hs,         "Toggle HS Support"             },
1814         { "le",         cmd_le,         "Toggle LE Support"             },
1815         { "class",      cmd_class,      "Set device major/minor class"  },
1816         { "disconnect", cmd_disconnect, "Disconnect device"             },
1817         { "con",        cmd_con,        "List connections"              },
1818         { "find",       cmd_find,       "Discover nearby devices"       },
1819         { "name",       cmd_name,       "Set local name"                },
1820         { "pair",       cmd_pair,       "Pair with a remote device"     },
1821         { "unpair",     cmd_unpair,     "Unpair device"                 },
1822         { "keys",       cmd_keys,       "Load Keys"                     },
1823         { "block",      cmd_block,      "Block Device"                  },
1824         { "unblock",    cmd_unblock,    "Unblock Device"                },
1825         { "add-uuid",   cmd_add_uuid,   "Add UUID"                      },
1826         { "rm-uuid",    cmd_add_uuid,   "Remove UUID"                   },
1827         { "clr-uuids",  cmd_clr_uuids,  "Clear UUIDs",                  },
1828         { "did",        cmd_did,        "Set Device ID",                },
1829         { NULL, NULL, 0 }
1830 };
1831
1832 static void usage(void)
1833 {
1834         int i;
1835
1836         printf("btmgmt ver %s\n", VERSION);
1837         printf("Usage:\n"
1838                 "\tbtmgmt [options] <command> [command parameters]\n");
1839
1840         printf("Options:\n"
1841                 "\t--index <id>\tSpecify adapter index\n"
1842                 "\t--verbose\tEnable extra logging\n"
1843                 "\t--help\tDisplay help\n");
1844
1845         printf("Commands:\n");
1846         for (i = 0; command[i].cmd; i++)
1847                 printf("\t%-15s\t%s\n", command[i].cmd, command[i].doc);
1848
1849         printf("\n"
1850                 "For more information on the usage of each command use:\n"
1851                 "\tbtmgmt <command> --help\n" );
1852 }
1853
1854 static struct option main_options[] = {
1855         { "index",      1, 0, 'i' },
1856         { "verbose",    0, 0, 'v' },
1857         { "help",       0, 0, 'h' },
1858         { 0, 0, 0, 0 }
1859 };
1860
1861 int main(int argc, char *argv[])
1862 {
1863         int opt, i, mgmt_sk;
1864         uint16_t index = MGMT_INDEX_NONE;
1865         struct pollfd pollfd;
1866
1867         while ((opt = getopt_long(argc, argv, "+hvi:",
1868                                                 main_options, NULL)) != -1) {
1869                 switch (opt) {
1870                 case 'i':
1871                         if (strlen(optarg) > 3 &&
1872                                         strncasecmp(optarg, "hci", 3) == 0)
1873                                 index = atoi(&optarg[4]);
1874                         else
1875                                 index = atoi(optarg);
1876                         break;
1877                 case 'v':
1878                         monitor = true;
1879                         break;
1880                 case 'h':
1881                 default:
1882                         usage();
1883                         return 0;
1884                 }
1885         }
1886
1887         argc -= optind;
1888         argv += optind;
1889         optind = 0;
1890
1891         if (argc < 1) {
1892                 usage();
1893                 return 0;
1894         }
1895
1896         mgmt_sk = mgmt_open();
1897         if (mgmt_sk < 0) {
1898                 fprintf(stderr, "Unable to open mgmt socket\n");
1899                 return -1;
1900         }
1901
1902         for (i = 0; command[i].cmd; i++) {
1903                 if (strcmp(command[i].cmd, argv[0]) != 0)
1904                         continue;
1905
1906                 command[i].func(mgmt_sk, index, argc, argv);
1907                 break;
1908         }
1909
1910         if (command[i].cmd == NULL) {
1911                 fprintf(stderr, "Unknown command: %s\n", argv[0]);
1912                 close(mgmt_sk);
1913                 return -1;
1914         }
1915
1916         pollfd.fd = mgmt_sk;
1917         pollfd.events = POLLIN;
1918         pollfd.revents = 0;
1919
1920         while (poll(&pollfd, 1, -1) >= 0) {
1921                 if (pollfd.revents & (POLLHUP | POLLERR | POLLNVAL))
1922                         break;
1923
1924                 if (pollfd.revents & POLLIN)
1925                         mgmt_process_data(mgmt_sk);
1926
1927                 pollfd.revents = 0;
1928         }
1929
1930         close(mgmt_sk);
1931
1932         return 0;
1933 }