2
* BlueZ - Bluetooth protocol stack for Linux
4
* Copyright (C) 2011 Intel Corporation. All rights reserved.
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.
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.
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
31
#include <sys/types.h>
32
#include <sys/socket.h>
37
#include <bluetooth/bluetooth.h>
38
#include <bluetooth/hci.h>
39
#include <bluetooth/hci_lib.h>
40
#include <bluetooth/mgmt.h>
43
#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
46
static const char *mgmt_op[] = {
51
"Read Controller Info",
55
"Set Pairable", /* 0x0008 */
63
"Get Connections", /* 0x0010 */
69
"User Confirm Neg Reply",
71
"Read Local OOB Data", /* 0x0018 */
72
"Add Remote OOB Data",
73
"Remove Remove OOB Data",
77
"Set Fast Connectable",
80
static const char *mgmt_ev[] = {
89
"Connectable", /* 0x0008 */
93
"Device Disconnected",
96
"User Confirm Request",
97
"Authentication Failed", /* 0x0010 */
106
static const char *mgmt_status[] = {
112
"Authentication Failed",
120
"Invalid Parameters",
125
static bool monitor = false;
126
static bool discovery = false;
127
static bool resolve_names = true;
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);
132
static struct pending_cmd {
137
struct pending_cmd *next;
140
static const char *mgmt_opstr(uint16_t op)
142
if (op >= NELEM(mgmt_op))
143
return "<unknown opcode>";
147
static const char *mgmt_evstr(uint16_t ev)
149
if (ev >= NELEM(mgmt_ev))
150
return "<unknown event>";
154
static const char *mgmt_errstr(uint8_t status)
156
if (status >= NELEM(mgmt_status))
157
return "<unknown status>";
158
return mgmt_status[status];
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)
165
struct pending_cmd *cmd;
166
struct mgmt_hdr *hdr = (void *) buf;
168
if (len + MGMT_HDR_SIZE > sizeof(buf))
171
cmd = calloc(1, sizeof(struct pending_cmd));
178
cmd->user_data = user_data;
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);
186
if (write(mgmt_sk, buf, MGMT_HDR_SIZE + len) < 0) {
187
fprintf(stderr, "Unable to write to socket: %s\n",
199
static int mgmt_open(void)
201
struct sockaddr_hci addr;
204
sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
206
fprintf(stderr, "socket: %s\n", strerror(errno));
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;
215
if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
216
fprintf(stderr, "bind: %s\n", strerror(errno));
224
static void mgmt_check_pending(int mgmt_sk, uint16_t op, uint16_t index,
225
uint16_t status, void *data, uint16_t len)
227
struct pending_cmd *c, *prev;
229
for (c = pending, prev = NULL; c != NULL; prev = c, c = c->next) {
238
prev->next = c->next;
240
c->cb(mgmt_sk, op, index, status, data, len, c->user_data);
246
static int mgmt_cmd_complete(int mgmt_sk, uint16_t index,
247
struct mgmt_ev_cmd_complete *ev, uint16_t len)
251
if (len < sizeof(*ev)) {
252
fprintf(stderr, "Too short (%u bytes) cmd complete event\n",
257
op = bt_get_le16(&ev->opcode);
262
printf("%s complete, opcode 0x%04x len %u\n", mgmt_opstr(op),
265
mgmt_check_pending(mgmt_sk, op, index, 0, ev->data, len);
270
static int mgmt_cmd_status(int mgmt_sk, uint16_t index,
271
struct mgmt_ev_cmd_status *ev, uint16_t len)
275
if (len < sizeof(*ev)) {
276
fprintf(stderr, "Too short (%u bytes) cmd status event\n",
281
opcode = bt_get_le16(&ev->opcode);
284
printf("cmd status, opcode 0x%04x status 0x%02x (%s)\n",
285
opcode, ev->status, mgmt_errstr(ev->status));
288
mgmt_check_pending(mgmt_sk, opcode, index, ev->status,
294
static int mgmt_controller_error(uint16_t index,
295
struct mgmt_ev_controller_error *ev,
298
if (len < sizeof(*ev)) {
300
"Too short (%u bytes) controller error event\n", len);
305
printf("hci%u error 0x%02x\n", index, ev->error_code);
310
static int mgmt_index_added(int mgmt_sk, uint16_t index)
313
printf("hci%u added\n", index);
317
static int mgmt_index_removed(int mgmt_sk, uint16_t index)
320
printf("hci%u removed\n", index);
324
static const char *settings_str[] = {
337
static void print_settings(uint32_t settings)
341
for (i = 0; i < NELEM(settings_str); i++) {
342
if ((settings & (1 << i)) != 0)
343
printf("%s ", settings_str[i]);
347
static int mgmt_new_settings(int mgmt_sk, uint16_t index,
348
uint32_t *ev, uint16_t len)
350
if (len < sizeof(*ev)) {
351
fprintf(stderr, "Too short new_settings event (%u)\n", len);
356
printf("hci%u new_settings: ", index);
357
print_settings(bt_get_le32(ev));
364
static int mgmt_discovering(int mgmt_sk, uint16_t index,
365
struct mgmt_mode *ev, uint16_t len)
367
if (len < sizeof(*ev)) {
368
fprintf(stderr, "Too short (%u bytes) discovering event\n",
373
if (ev->val == 0 && discovery)
377
printf("hci%u discovering %s\n", index,
378
ev->val ? "on" : "off");
383
static int mgmt_new_link_key(int mgmt_sk, uint16_t index,
384
struct mgmt_ev_new_link_key *ev, uint16_t len)
387
if (len != sizeof(*ev)) {
388
fprintf(stderr, "Invalid new_link_key length (%u bytes)\n",
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);
404
static const char *typestr(uint8_t type)
406
const char *str[] = { "BR/EDR", "LE Public", "LE Random" };
408
if (type <= MGMT_ADDR_LE_RANDOM)
414
static int mgmt_connected(int mgmt_sk, uint16_t index, bool connected,
415
struct mgmt_addr_info *ev, uint16_t len)
417
const char *ev_name = connected ? "connected" : "disconnected";
419
if (len != sizeof(*ev)) {
421
"Invalid %s event length (%u bytes)\n", ev_name, len);
427
ba2str(&ev->bdaddr, addr);
428
printf("hci%u %s type %s %s\n", index, addr,
429
typestr(ev->type), ev_name);
435
static int mgmt_conn_failed(int mgmt_sk, uint16_t index,
436
struct mgmt_ev_connect_failed *ev,
439
if (len != sizeof(*ev)) {
441
"Invalid connect_failed event length (%u bytes)\n", len);
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));
456
static int mgmt_auth_failed(int mgmt_sk, uint16_t index,
457
struct mgmt_ev_auth_failed *ev,
460
if (len != sizeof(*ev)) {
462
"Invalid auth_failed event length (%u bytes)\n", len);
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));
476
static int mgmt_name_changed(int mgmt_sk, uint16_t index,
477
struct mgmt_ev_local_name_changed *ev,
480
if (len != sizeof(*ev)) {
482
"Invalid local_name_changed length (%u bytes)\n", len);
487
printf("hci%u name changed: %s\n", index, ev->name);
492
static void confirm_name_rsp(int mgmt_sk, uint16_t op, uint16_t id,
493
uint8_t status, void *rsp, uint16_t len,
496
struct mgmt_rp_confirm_name *rp = rsp;
501
"hci%u confirm_name failed with status 0x%02x (%s)\n",
502
id, status, mgmt_errstr(status));
506
if (len != sizeof(*rp)) {
508
"hci%u confirm_name rsp length %u instead of %zu\n",
509
id, len, sizeof(*rp));
513
ba2str(&rp->bdaddr, addr);
517
"hci%u confirm_name for %s failed: 0x%02x (%s)\n",
518
id, addr, rp->status, mgmt_errstr(status));
520
printf("hci%u confirm_name succeeded for %s\n", id, addr);
523
static int mgmt_device_found(int mgmt_sk, uint16_t index,
524
struct mgmt_ev_device_found *ev, uint16_t len)
526
if (len != sizeof(*ev)) {
528
"Invalid device_found event length (%u bytes)\n", len);
532
if (monitor || discovery) {
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");
543
if (discovery && ev->confirm_name) {
544
struct mgmt_cp_confirm_name cp;
546
memset(&cp, 0, sizeof(cp));
547
bacpy(&cp.bdaddr, &ev->addr.bdaddr);
553
mgmt_send_cmd(mgmt_sk, MGMT_OP_CONFIRM_NAME, index,
554
&cp, sizeof(cp), confirm_name_rsp,
561
static int mgmt_remote_name(int mgmt_sk, uint16_t index,
562
struct mgmt_ev_remote_name *ev, uint16_t len)
564
if (len != sizeof(*ev)) {
566
"Invalid remote_name event length (%u bytes)\n", len);
570
if (monitor || discovery) {
572
ba2str(&ev->bdaddr, addr);
573
printf("hci%u %s name %s\n", index, addr, ev->name);
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)
584
"hci%u PIN Code reply failed with status 0x%02x (%s)",
585
id, status, mgmt_errstr(status));
589
printf("hci%u PIN Reply successful\n", id);
592
static int mgmt_pin_reply(int mgmt_sk, uint16_t index, bdaddr_t *bdaddr,
593
const char *pin, size_t len)
595
struct mgmt_cp_pin_code_reply cp;
597
memset(&cp, 0, sizeof(cp));
598
bacpy(&cp.bdaddr, bdaddr);
600
memcpy(cp.pin_code, pin, len);
602
return mgmt_send_cmd(mgmt_sk, MGMT_OP_PIN_CODE_REPLY, index,
603
&cp, sizeof(cp), pin_rsp, NULL);
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)
611
"hci%u PIN Neg reply failed with status 0x%02x (%s)",
612
id, status, mgmt_errstr(status));
616
printf("hci%u PIN Negative Reply successful\n", id);
619
static int mgmt_pin_neg_reply(int mgmt_sk, uint16_t index, bdaddr_t *bdaddr)
621
struct mgmt_cp_pin_code_neg_reply cp;
623
memset(&cp, 0, sizeof(cp));
624
bacpy(&cp.bdaddr, bdaddr);
626
return mgmt_send_cmd(mgmt_sk, MGMT_OP_PIN_CODE_NEG_REPLY, index,
627
&cp, sizeof(cp), pin_neg_rsp, NULL);
630
static int mgmt_request_pin(int mgmt_sk, uint16_t index,
631
struct mgmt_ev_pin_code_request *ev,
637
if (len != sizeof(*ev)) {
639
"Invalid pin_code request length (%u bytes)\n", len);
645
ba2str(&ev->bdaddr, addr);
646
printf("hci%u %s request PIN\n", index, addr);
649
printf("PIN Request (press enter to reject) >> ");
652
memset(pin, 0, sizeof(pin));
654
if (fgets(pin, sizeof(pin), stdin) == NULL || pin[0] == '\n')
655
return mgmt_pin_neg_reply(mgmt_sk, index, &ev->bdaddr);
657
pin_len = strlen(pin);
658
if (pin[pin_len - 1] == '\n') {
659
pin[pin_len - 1] = '\0';
663
return mgmt_pin_reply(mgmt_sk, index, &ev->bdaddr, pin, pin_len);
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)
671
"hci%u User Confirm reply failed. status 0x%02x (%s)",
672
id, status, mgmt_errstr(status));
676
printf("hci%u User Confirm Reply successful\n", id);
679
static int mgmt_confirm_reply(int mgmt_sk, uint16_t index, bdaddr_t *bdaddr)
681
struct mgmt_cp_user_confirm_reply cp;
683
memset(&cp, 0, sizeof(cp));
684
bacpy(&cp.bdaddr, bdaddr);
686
return mgmt_send_cmd(mgmt_sk, MGMT_OP_USER_CONFIRM_REPLY, index,
687
&cp, sizeof(cp), confirm_rsp, NULL);
690
static void confirm_neg_rsp(int mgmt_sk, uint16_t op, uint16_t id,
691
uint8_t status, void *rsp, uint16_t len,
696
"hci%u Confirm Neg reply failed. status 0x%02x (%s)",
697
id, status, mgmt_errstr(status));
701
printf("hci%u User Confirm Negative Reply successful\n", id);
704
static int mgmt_confirm_neg_reply(int mgmt_sk, uint16_t index,
707
struct mgmt_cp_user_confirm_reply cp;
709
memset(&cp, 0, sizeof(cp));
710
bacpy(&cp.bdaddr, bdaddr);
712
return mgmt_send_cmd(mgmt_sk, MGMT_OP_USER_CONFIRM_NEG_REPLY, index,
713
&cp, sizeof(cp), confirm_neg_rsp, NULL);
717
static int mgmt_user_confirm(int mgmt_sk, uint16_t index,
718
struct mgmt_ev_user_confirm_request *ev,
726
if (len != sizeof(*ev)) {
728
"Invalid user_confirm request length (%u)\n", len);
732
ba2str(&ev->bdaddr, addr);
733
val = bt_get_le32(&ev->value);
736
printf("hci%u %s User Confirm %06u hint %u\n", index, addr,
737
val, ev->confirm_hint);
739
if (ev->confirm_hint)
740
printf("Accept pairing with %s (yes/no) >> ", addr);
742
printf("Confirm value %06u for %s (yes/no) >> ", val, addr);
746
memset(rsp, 0, sizeof(rsp));
748
if (fgets(rsp, sizeof(rsp), stdin) == NULL || rsp[0] == '\n')
749
return mgmt_confirm_neg_reply(mgmt_sk, index, &ev->bdaddr);
751
rsp_len = strlen(rsp);
752
if (rsp[rsp_len - 1] == '\n') {
753
rsp[rsp_len - 1] = '\0';
757
if (rsp[0] == 'y' || rsp[0] == 'Y')
758
return mgmt_confirm_reply(mgmt_sk, index, &ev->bdaddr);
760
return mgmt_confirm_neg_reply(mgmt_sk, index, &ev->bdaddr);
763
static int mgmt_handle_event(int mgmt_sk, uint16_t ev, uint16_t index,
764
void *data, uint16_t len)
767
printf("event: %s\n", mgmt_evstr(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);
806
printf("Unhandled event 0x%04x (%s)\n", ev, mgmt_evstr(ev));
811
static int mgmt_process_data(int mgmt_sk)
814
struct mgmt_hdr *hdr = (void *) buf;
815
uint16_t len, ev, index;
818
ret = read(mgmt_sk, buf, sizeof(buf));
820
fprintf(stderr, "read: %s\n", strerror(errno));
824
if (ret < MGMT_HDR_SIZE) {
825
fprintf(stderr, "Too small mgmt packet (%zd bytes)\n", ret);
829
ev = bt_get_le16(&hdr->opcode);
830
index = bt_get_le16(&hdr->index);
831
len = bt_get_le16(&hdr->len);
834
printf("event 0x%04x len 0x%04x index 0x%04x\n", ev, len, index);
836
if (ret != MGMT_HDR_SIZE + len) {
837
fprintf(stderr, "Packet length mismatch. ret %zd len %u",
842
mgmt_handle_event(mgmt_sk, ev, index, buf + MGMT_HDR_SIZE, len);
847
static void cmd_monitor(int mgmt_sk, uint16_t index, int argc, char **argv)
849
printf("Monitoring mgmt events...\n");
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)
856
struct mgmt_rp_read_info *rp = rsp;
861
"Reading hci%u info failed with status 0x%02x (%s)\n",
862
id, status, mgmt_errstr(status));
866
if (len < sizeof(*rp)) {
867
fprintf(stderr, "Too small info reply (%u bytes)\n", len);
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]);
877
printf("\tsupported settings: ");
878
print_settings(bt_get_le32(&rp->supported_settings));
880
printf("\n\tcurrent settings: ");
881
print_settings(bt_get_le32(&rp->current_settings));
883
printf("\n\tname %s\n", rp->name);
884
printf("\tshort name %s\n", rp->short_name);
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)
893
struct mgmt_rp_read_index_list *rp = rsp;
899
"Reading index list failed with status 0x%02x (%s)\n",
900
status, mgmt_errstr(status));
904
if (len < sizeof(*rp)) {
905
fprintf(stderr, "Too small index list reply (%u bytes)\n",
910
count = bt_get_le16(&rp->num_controllers);
912
if (len < sizeof(*rp) + count * sizeof(uint16_t)) {
914
"Index count (%u) doesn't match reply length (%u)\n",
920
printf("Index list with %u item%s\n",
921
count, count > 1 ? "s" : "");
926
if (monitor && count > 0)
929
for (i = 0; i < count; i++) {
932
index = bt_get_le16(&rp->index[i]);
935
printf("hci%u ", index);
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");
944
if (monitor && count > 0)
948
static void cmd_info(int mgmt_sk, uint16_t index, int argc, char **argv)
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");
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");
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)
975
"%s for hci%u failed with status 0x%02x (%s)\n",
976
mgmt_opstr(op), id, status, mgmt_errstr(status));
980
if (len < sizeof(*rp)) {
981
fprintf(stderr, "Too small %s response (%u bytes)\n",
982
mgmt_opstr(op), len);
986
printf("hci%u %s complete, settings: ", id, mgmt_opstr(op));
987
print_settings(bt_get_le32(rp));
993
static void cmd_setting(int mgmt_sk, uint16_t index, uint16_t op,
994
int argc, char **argv)
999
printf("Specify \"on\" or \"off\"\n");
1003
if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
1005
else if (strcasecmp(argv[1], "off") == 0)
1008
val = atoi(argv[1]);
1010
if (index == MGMT_INDEX_NONE)
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));
1020
static void cmd_power(int mgmt_sk, uint16_t index, int argc, char **argv)
1022
cmd_setting(mgmt_sk, index, MGMT_OP_SET_POWERED, argc, argv);
1025
static void cmd_discov(int mgmt_sk, uint16_t index, int argc, char **argv)
1027
struct mgmt_cp_set_discoverable cp;
1030
printf("Usage: btmgmt %s <yes/no> [timeout]\n", argv[0]);
1034
memset(&cp, 0, sizeof(cp));
1036
if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
1038
else if (strcasecmp(argv[1], "off") == 0)
1041
cp.val = atoi(argv[1]);
1044
cp.timeout = htobs(atoi(argv[2]));
1046
if (index == MGMT_INDEX_NONE)
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");
1056
static void cmd_connectable(int mgmt_sk, uint16_t index, int argc, char **argv)
1058
cmd_setting(mgmt_sk, index, MGMT_OP_SET_CONNECTABLE, argc, argv);
1061
static void cmd_pairable(int mgmt_sk, uint16_t index, int argc, char **argv)
1063
cmd_setting(mgmt_sk, index, MGMT_OP_SET_PAIRABLE, argc, argv);
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)
1071
"Setting hci%u class failed with status 0x%02x (%s)",
1072
id, status, mgmt_errstr(status));
1076
printf("hci%u class changed\n", id);
1080
static void cmd_class(int mgmt_sk, uint16_t index, int argc, char **argv)
1085
printf("Usage: btmgmt %s <major> <minor>\n", argv[0]);
1089
class[0] = atoi(argv[1]);
1090
class[1] = atoi(argv[2]);
1092
if (index == MGMT_INDEX_NONE)
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");
1102
static void disconnect_rsp(int mgmt_sk, uint16_t op, uint16_t id,
1103
uint8_t status, void *rsp, uint16_t len,
1106
struct mgmt_rp_disconnect *rp = rsp;
1110
fprintf(stderr, "Disconnect failed with status 0x%02x (%s)\n",
1111
status, mgmt_errstr(status));
1115
if (len != sizeof(*rp)) {
1116
fprintf(stderr, "Invalid disconnect response length (%u)\n",
1121
ba2str(&rp->bdaddr, addr);
1123
if (rp->status == 0) {
1124
printf("%s disconnected\n", addr);
1128
"Disconnecting %s failed with status 0x%02x (%s)\n",
1129
addr, rp->status, mgmt_errstr(rp->status));
1134
static void cmd_disconnect(int mgmt_sk, uint16_t index, int argc, char **argv)
1136
struct mgmt_cp_disconnect cp;
1139
printf("Usage: btmgmt %s <address>\n", argv[0]);
1143
str2ba(argv[1], &cp.bdaddr);
1145
if (index == MGMT_INDEX_NONE)
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");
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)
1158
struct mgmt_rp_get_connections *rp = rsp;
1161
if (len < sizeof(*rp)) {
1162
fprintf(stderr, "Too small (%u bytes) get_connections rsp\n",
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);
1174
for (i = 0; i < count; i++) {
1177
ba2str(&rp->addr[i].bdaddr, addr);
1179
printf("%s type %s\n", addr, typestr(rp->addr[i].type));
1185
static void cmd_con(int mgmt_sk, uint16_t index, int argc, char **argv)
1187
if (index == MGMT_INDEX_NONE)
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");
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)
1202
"Unable to start discovery. status 0x%02x (%s)\n",
1203
status, mgmt_errstr(status));
1207
printf("Discovery started\n");
1211
static void cmd_find(int mgmt_sk, uint16_t index, int argc, char **argv)
1213
struct mgmt_cp_start_discovery cp;
1216
if (index == MGMT_INDEX_NONE)
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);
1224
memset(&cp, 0, sizeof(cp));
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");
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)
1238
fprintf(stderr, "Unable to set local name. status 0x%02x (%s)",
1239
status, mgmt_errstr(status));
1246
static void cmd_name(int mgmt_sk, uint16_t index, int argc, char **argv)
1248
struct mgmt_cp_set_local_name cp;
1251
printf("Usage: btmgmt %s <name>\n", argv[0]);
1255
if (index == MGMT_INDEX_NONE)
1258
memset(&cp, 0, sizeof(cp));
1259
strncpy((char *) cp.name, argv[1], HCI_MAX_NAME_LENGTH);
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");
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)
1271
struct mgmt_rp_pair_device *rp = rsp;
1275
fprintf(stderr, "Pairing failed with status 0x%02x (%s)\n",
1276
status, mgmt_errstr(status));
1280
if (len != sizeof(*rp)) {
1281
fprintf(stderr, "Unexpected pair_rsp len %u\n", len);
1285
ba2str(&rp->addr.bdaddr, addr);
1287
if (rp->status != 0) {
1289
"Pairing with %s (%s) failed. status 0x%02x (%s)\n",
1290
addr, typestr(rp->addr.type), rp->status,
1291
mgmt_errstr(rp->status));
1295
printf("Paired with %s\n", addr);
1300
static void pair_usage(void)
1302
printf("Usage: btmgmt pair [-c cap] [-t type] <remote address>\n");
1305
static struct option pair_options[] = {
1306
{ "help", 0, 0, 'h' },
1307
{ "capability", 1, 0, 'c' },
1308
{ "type", 1, 0, 't' },
1312
static void cmd_pair(int mgmt_sk, uint16_t index, int argc, char **argv)
1314
struct mgmt_cp_pair_device cp;
1316
uint8_t type = MGMT_ADDR_BREDR;
1319
while ((opt = getopt_long(argc, argv, "+c:t:h", pair_options,
1323
cap = strtol(optarg, NULL, 0);
1326
type = strtol(optarg, NULL, 0);
1344
if (index == MGMT_INDEX_NONE)
1347
memset(&cp, 0, sizeof(cp));
1348
str2ba(argv[0], &cp.addr.bdaddr);
1349
cp.addr.type = type;
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");
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)
1362
struct mgmt_rp_remove_keys *rp = rsp;
1366
fprintf(stderr, "Remove keys failed with status 0x%02x (%s)\n",
1367
status, mgmt_errstr(status));
1371
if (len != sizeof(*rp)) {
1372
fprintf(stderr, "Unexpected remove_keys_rsp len %u\n", len);
1376
ba2str(&rp->bdaddr, addr);
1378
if (rp->status != 0) {
1380
"Removing keys for %s failed. status 0x%02x (%s)\n",
1381
addr, rp->status, mgmt_errstr(rp->status));
1385
printf("Removed keys for %s\n", addr);
1390
static void cmd_remove(int mgmt_sk, uint16_t index, int argc, char **argv)
1392
struct mgmt_cp_remove_keys cp;
1395
printf("Usage: btmgmt %s <remote address>\n", argv[0]);
1399
if (index == MGMT_INDEX_NONE)
1402
memset(&cp, 0, sizeof(cp));
1403
str2ba(argv[1], &cp.bdaddr);
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");
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)
1417
fprintf(stderr, "Load keys failed with status 0x%02x (%s)\n",
1418
status, mgmt_errstr(status));
1422
printf("Keys successfully loaded\n");
1427
static void cmd_keys(int mgmt_sk, uint16_t index, int argc, char **argv)
1429
struct mgmt_cp_load_link_keys cp;
1431
if (index == MGMT_INDEX_NONE)
1434
memset(&cp, 0, sizeof(cp));
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");
1445
void (*func)(int mgmt_sk, uint16_t index, int argc, char **argv);
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" },
1465
static void usage(void)
1469
printf("btmgmt ver %s\n", VERSION);
1471
"\tbtmgmt [options] <command> [command parameters]\n");
1474
"\t--index <id>\tSpecify adapter index\n"
1475
"\t--verbose\tEnable extra logging\n"
1476
"\t--help\tDisplay help\n");
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);
1483
"For more information on the usage of each command use:\n"
1484
"\tbtmgmt <command> --help\n" );
1487
static struct option main_options[] = {
1488
{ "index", 1, 0, 'i' },
1489
{ "verbose", 0, 0, 'v' },
1490
{ "help", 0, 0, 'h' },
1494
int main(int argc, char *argv[])
1496
int opt, i, mgmt_sk;
1497
uint16_t index = MGMT_INDEX_NONE;
1498
struct pollfd pollfd;
1500
while ((opt = getopt_long(argc, argv, "+hvi:",
1501
main_options, NULL)) != -1) {
1504
if (strlen(optarg) > 3 &&
1505
strncasecmp(optarg, "hci", 3) == 0)
1506
index = atoi(&optarg[4]);
1508
index = atoi(optarg);
1529
mgmt_sk = mgmt_open();
1531
fprintf(stderr, "Unable to open mgmt socket\n");
1535
for (i = 0; command[i].cmd; i++) {
1536
if (strcmp(command[i].cmd, argv[0]) != 0)
1539
command[i].func(mgmt_sk, index, argc, argv);
1543
if (command[i].cmd == NULL) {
1544
fprintf(stderr, "Unknown command: %s\n", argv[0]);
1549
pollfd.fd = mgmt_sk;
1550
pollfd.events = POLLIN;
1553
while (poll(&pollfd, 1, -1) >= 0) {
1554
if (pollfd.revents & (POLLHUP | POLLERR | POLLNVAL))
1557
if (pollfd.revents & POLLIN)
1558
mgmt_process_data(mgmt_sk);