3
* BlueZ - Bluetooth protocol stack for Linux
5
* Copyright (C) 2010 Nokia Corporation
6
* Copyright (C) 2010 Marcel Holtmann <marcel@holtmann.org>
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32
#include <sys/types.h>
33
#include <sys/ioctl.h>
38
#include <bluetooth/bluetooth.h>
39
#include <bluetooth/hci.h>
40
#include <bluetooth/mgmt.h>
49
#define MGMT_BUF_SIZE 1024
51
static int max_index = -1;
52
static struct controller_info {
58
uint16_t manufacturer;
63
} *controllers = NULL;
65
static int mgmt_sock = -1;
66
static guint mgmt_watch = 0;
68
static uint8_t mgmt_version = 0;
69
static uint16_t mgmt_revision = 0;
71
static void read_version_complete(int sk, void *buf, size_t len)
74
struct mgmt_rp_read_version *rp = buf;
76
if (len < sizeof(*rp)) {
77
error("Too small read version complete event");
81
mgmt_revision = btohs(bt_get_unaligned(&rp->revision));
82
mgmt_version = rp->version;
84
DBG("version %u revision %u", mgmt_version, mgmt_revision);
86
memset(&hdr, 0, sizeof(hdr));
87
hdr.opcode = MGMT_OP_READ_INDEX_LIST;
88
if (write(sk, &hdr, sizeof(hdr)) < 0)
89
error("Unable to read controller index list: %s (%d)",
90
strerror(errno), errno);
93
static void add_controller(uint16_t index)
95
if (index > max_index) {
96
size_t size = sizeof(struct controller_info) * (index + 1);
98
controllers = g_realloc(controllers, size);
101
memset(&controllers[index], 0, sizeof(struct controller_info));
103
controllers[index].valid = TRUE;
105
DBG("Added controller %u", index);
108
static void read_info(int sk, uint16_t index)
110
char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_read_info)];
111
struct mgmt_hdr *hdr = (void *) buf;
112
struct mgmt_cp_read_info *cp = (void *) &buf[sizeof(*hdr)];
114
memset(buf, 0, sizeof(buf));
115
hdr->opcode = MGMT_OP_READ_INFO;
116
hdr->len = htobs(sizeof(*cp));
118
cp->index = htobs(index);
120
if (write(sk, buf, sizeof(buf)) < 0)
121
error("Unable to send read_info command: %s (%d)",
122
strerror(errno), errno);
125
static void mgmt_index_added(int sk, void *buf, size_t len)
127
struct mgmt_ev_index_added *ev = buf;
130
if (len < sizeof(*ev)) {
131
error("Too small index added event");
135
index = btohs(bt_get_unaligned(&ev->index));
137
add_controller(index);
138
read_info(sk, index);
141
static void remove_controller(uint16_t index)
143
if (index > max_index)
146
if (!controllers[index].valid)
149
manager_unregister_adapter(index);
151
memset(&controllers[index], 0, sizeof(struct controller_info));
153
DBG("Removed controller %u", index);
156
static void mgmt_index_removed(int sk, void *buf, size_t len)
158
struct mgmt_ev_index_removed *ev = buf;
161
if (len < sizeof(*ev)) {
162
error("Too small index removed event");
166
index = btohs(bt_get_unaligned(&ev->index));
168
remove_controller(index);
171
static void read_mode(int sk, uint16_t index)
173
char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_read_mode)];
174
struct mgmt_hdr *hdr = (void *) buf;
175
struct mgmt_cp_read_mode *cp = (void *) &buf[sizeof(*hdr)];
177
memset(buf, 0, sizeof(buf));
178
hdr->opcode = MGMT_OP_READ_MODE;
179
hdr->len = htobs(sizeof(*cp));
181
cp->index = htobs(index);
183
if (write(sk, buf, sizeof(buf)) < 0)
184
error("Unable to send read_mode command: %s (%d)",
185
strerror(errno), errno);
188
static void read_index_list_complete(int sk, void *buf, size_t len)
190
struct mgmt_rp_read_index_list *rp = buf;
194
if (len < sizeof(*rp)) {
195
error("Too small read index list complete event");
199
num = btohs(bt_get_unaligned(&rp->num_controllers));
201
if (num * sizeof(uint16_t) + sizeof(*rp) != len) {
202
error("Incorrect packet size for index list event");
206
for (i = 0; i < num; i++) {
209
index = btohs(bt_get_unaligned(&rp->index[i]));
211
add_controller(index);
212
read_info(sk, index);
216
static void read_info_complete(int sk, void *buf, size_t len)
218
struct mgmt_rp_read_info *rp = buf;
219
struct controller_info *info;
223
if (len < sizeof(*rp)) {
224
error("Too small read info complete event");
228
if (rp->status != 0) {
229
error("Reading controller info failed: %s (%u)",
230
strerror(rp->status), rp->status);
234
index = btohs(bt_get_unaligned(&rp->index));
235
if (index > max_index) {
236
error("Unexpected index %u in read info complete", index);
240
info = &controllers[index];
241
info->type = rp->type;
242
bacpy(&info->bdaddr, &rp->bdaddr);
243
memcpy(info->features, rp->features, 8);
244
info->manufacturer = btohs(bt_get_unaligned(&rp->manufacturer));
245
info->hci_ver = rp->hci_ver;
246
info->hci_rev = btohs(bt_get_unaligned(&rp->hci_rev));
248
ba2str(&info->bdaddr, addr);
249
DBG("hci%u addr %s type %u manufacturer %d hci ver %d:%d",
250
index, addr, info->type, info->manufacturer,
251
info->hci_ver, info->hci_rev);
253
read_mode(sk, index);
256
static void read_mode_complete(int sk, void *buf, size_t len)
258
struct mgmt_rp_read_mode *rp = buf;
259
struct controller_info *info;
262
if (len < sizeof(*rp)) {
263
error("Too small read mode complete event (%zu != %zu)",
268
if (rp->status != 0) {
269
error("Reading controller mode failed: %s (%u)",
270
strerror(rp->status), rp->status);
274
index = btohs(bt_get_unaligned(&rp->index));
275
if (index > max_index) {
276
error("Unexpected index %u in read mode complete", index);
280
info = &controllers[index];
281
info->enabled = rp->enabled ? TRUE : FALSE;
282
info->mode = rp->mode;
284
DBG("hci%u enabled %u mode %u", index, info->enabled, info->mode);
286
manager_register_adapter(index, info->enabled);
289
manager_start_adapter(index);
292
static void mgmt_cmd_complete(int sk, void *buf, size_t len)
294
struct mgmt_ev_cmd_complete *ev = buf;
299
if (len < sizeof(*ev)) {
300
error("Too small management command complete event packet");
304
opcode = btohs(bt_get_unaligned(&ev->opcode));
307
case MGMT_OP_READ_VERSION:
308
read_version_complete(sk, ev->data, len - sizeof(*ev));
310
case MGMT_OP_READ_INDEX_LIST:
311
read_index_list_complete(sk, ev->data, len - sizeof(*ev));
313
case MGMT_OP_READ_INFO:
314
read_info_complete(sk, ev->data, len - sizeof(*ev));
316
case MGMT_OP_READ_MODE:
317
read_mode_complete(sk, ev->data, len - sizeof(*ev));
320
error("Unknown command complete for opcode %u", opcode);
325
static void mgmt_cmd_status(int sk, void *buf, size_t len)
327
struct mgmt_ev_cmd_status *ev = buf;
330
if (len < sizeof(*ev)) {
331
error("Too small management command status event packet");
335
opcode = btohs(bt_get_unaligned(&ev->opcode));
337
DBG("status %u opcode %u", ev->status, opcode);
340
static void mgmt_controller_error(int sk, void *buf, size_t len)
342
struct mgmt_ev_controller_error *ev = buf;
345
if (len < sizeof(*ev)) {
346
error("Too small management controller error event packet");
350
index = btohs(bt_get_unaligned(&ev->index));
352
DBG("index %u error_code %u", index, ev->error_code);
355
static gboolean mgmt_event(GIOChannel *io, GIOCondition cond, gpointer user_data)
357
char buf[MGMT_BUF_SIZE];
358
struct mgmt_hdr *hdr = (void *) buf;
361
uint16_t len, opcode;
363
DBG("cond %d", cond);
365
if (cond & G_IO_NVAL)
368
sk = g_io_channel_unix_get_fd(io);
370
if (cond & (G_IO_ERR | G_IO_HUP)) {
371
error("Error on management socket");
375
ret = read(sk, buf, sizeof(buf));
377
error("Unable to read from management socket: %s (%d)",
378
strerror(errno), errno);
382
DBG("Received %zd bytes from management socket", ret);
384
if (ret < MGMT_HDR_SIZE) {
385
error("Too small Management packet");
389
opcode = btohs(bt_get_unaligned(&hdr->opcode));
390
len = btohs(bt_get_unaligned(&hdr->len));
392
if (ret != MGMT_HDR_SIZE + len) {
393
error("Packet length mismatch. ret %zd len %u", ret, len);
398
case MGMT_EV_CMD_COMPLETE:
399
mgmt_cmd_complete(sk, buf + MGMT_HDR_SIZE, len);
401
case MGMT_EV_CMD_STATUS:
402
mgmt_cmd_status(sk, buf + MGMT_HDR_SIZE, len);
404
case MGMT_EV_CONTROLLER_ERROR:
405
mgmt_controller_error(sk, buf + MGMT_HDR_SIZE, len);
407
case MGMT_EV_INDEX_ADDED:
408
mgmt_index_added(sk, buf + MGMT_HDR_SIZE, len);
410
case MGMT_EV_INDEX_REMOVED:
411
mgmt_index_removed(sk, buf + MGMT_HDR_SIZE, len);
414
error("Unknown Management opcode %u", opcode);
421
static int mgmt_setup(void)
424
struct sockaddr_hci addr;
426
GIOCondition condition;
429
dd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
433
memset(&addr, 0, sizeof(addr));
434
addr.hci_family = AF_BLUETOOTH;
435
addr.hci_dev = HCI_DEV_NONE;
436
addr.hci_channel = HCI_CHANNEL_CONTROL;
438
if (bind(dd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
443
memset(&hdr, 0, sizeof(hdr));
444
hdr.opcode = MGMT_OP_READ_VERSION;
445
if (write(dd, &hdr, sizeof(hdr)) < 0) {
450
io = g_io_channel_unix_new(dd);
451
condition = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
452
mgmt_watch = g_io_add_watch(io, condition, mgmt_event, NULL);
453
g_io_channel_unref(io);
457
info("Bluetooth Management interface initialized");
466
static void mgmt_cleanup(void)
472
if (mgmt_sock >= 0) {
477
if (mgmt_watch > 0) {
478
g_source_remove(mgmt_watch);
483
static int mgmt_start(int index)
485
DBG("index %d", index);
489
static int mgmt_stop(int index)
491
DBG("index %d", index);
495
static int mgmt_powered(int index, gboolean powered)
497
DBG("index %d powered %d", index, powered);
501
static int mgmt_connectable(int index)
503
DBG("index %d", index);
507
static int mgmt_discoverable(int index)
509
DBG("index %d", index);
513
static int mgmt_set_class(int index, uint32_t class)
515
DBG("index %d class %u", index, class);
519
static int mgmt_set_limited_discoverable(int index, uint32_t class,
522
DBG("index %d class %u, limited %d", index, class, limited);
526
static int mgmt_start_inquiry(int index, uint8_t length, gboolean periodic)
528
DBG("index %d length %u periodic %d", index, length, periodic);
532
static int mgmt_stop_inquiry(int index)
534
DBG("index %d", index);
538
static int mgmt_start_scanning(int index)
540
DBG("index %d", index);
544
static int mgmt_stop_scanning(int index)
546
DBG("index %d", index);
550
static int mgmt_resolve_name(int index, bdaddr_t *bdaddr)
554
ba2str(bdaddr, addr);
555
DBG("index %d addr %s", index, addr);
560
static int mgmt_set_name(int index, const char *name)
562
DBG("index %d, name %s", index, name);
566
static int mgmt_cancel_resolve_name(int index, bdaddr_t *bdaddr)
570
ba2str(bdaddr, addr);
571
DBG("index %d addr %s", index, addr);
576
static int mgmt_fast_connectable(int index, gboolean enable)
578
DBG("index %d enable %d", index, enable);
582
static int mgmt_read_clock(int index, int handle, int which, int timeout,
583
uint32_t *clock, uint16_t *accuracy)
585
DBG("index %d handle %d which %d timeout %d", index, handle,
590
static int mgmt_conn_handle(int index, const bdaddr_t *bdaddr, int *handle)
594
ba2str(bdaddr, addr);
595
DBG("index %d addr %s", index, addr);
600
static int mgmt_write_eir_data(int index, uint8_t *data)
602
DBG("index %d", index);
606
static int mgmt_read_bdaddr(int index, bdaddr_t *bdaddr)
609
struct controller_info *info = &controllers[index];
611
ba2str(&info->bdaddr, addr);
612
DBG("index %d addr %s", index, addr);
617
bacpy(bdaddr, &info->bdaddr);
622
static int mgmt_block_device(int index, bdaddr_t *bdaddr)
626
ba2str(bdaddr, addr);
627
DBG("index %d addr %s", index, addr);
632
static int mgmt_unblock_device(int index, bdaddr_t *bdaddr)
636
ba2str(bdaddr, addr);
637
DBG("index %d addr %s", index, addr);
642
static int mgmt_get_conn_list(int index, GSList **conns)
644
DBG("index %d", index);
648
static int mgmt_read_local_version(int index, struct hci_version *ver)
650
struct controller_info *info = &controllers[index];
652
DBG("index %d", index);
657
memset(ver, 0, sizeof(*ver));
658
ver->manufacturer = info->manufacturer;
659
ver->hci_ver = info->hci_ver;
660
ver->hci_rev = info->hci_rev;
665
static int mgmt_read_local_features(int index, uint8_t *features)
667
struct controller_info *info = &controllers[index];
669
DBG("index %d", index);
674
memcpy(features, info->features, 8);
679
static int mgmt_read_local_ext_features(int index)
681
DBG("index %d", index);
685
static int mgmt_read_link_policy(int index)
687
DBG("index %d", index);
691
static int mgmt_disconnect(int index, uint16_t handle)
693
DBG("index %d handle %u", index, handle);
697
static int mgmt_remove_bonding(int index, bdaddr_t *bdaddr)
701
ba2str(bdaddr, addr);
702
DBG("index %d addr %s", index, addr);
707
static int mgmt_request_authentication(int index, uint16_t handle)
709
DBG("index %d handle %u", index, handle);
713
static int mgmt_pincode_reply(int index, bdaddr_t *bdaddr, const char *pin)
717
ba2str(bdaddr, addr);
718
DBG("index %d addr %s pin %s", index, addr, pin);
723
static int mgmt_confirm_reply(int index, bdaddr_t *bdaddr, gboolean success)
727
ba2str(bdaddr, addr);
728
DBG("index %d addr %s success %d", index, addr, success);
733
static int mgmt_passkey_reply(int index, bdaddr_t *bdaddr, uint32_t passkey)
737
ba2str(bdaddr, addr);
738
DBG("index %d addr %s passkey %06u", index, addr, passkey);
743
static int mgmt_get_auth_info(int index, bdaddr_t *bdaddr, uint8_t *auth)
747
ba2str(bdaddr, addr);
748
DBG("index %d addr %s", index, addr);
753
static int mgmt_read_scan_enable(int index)
755
DBG("index %d", index);
759
static int mgmt_write_le_host(int index, uint8_t le, uint8_t simul)
761
DBG("index %d le %u simul %u", index, le, simul);
765
static int mgmt_get_remote_version(int index, uint16_t handle,
768
DBG("index %d handle %u delayed %d", index, handle, delayed);
772
static int mgmt_encrypt_link(int index, bdaddr_t *dst, bt_hci_result_t cb,
778
DBG("index %d addr %s", index, addr);
783
static struct btd_adapter_ops mgmt_ops = {
785
.cleanup = mgmt_cleanup,
788
.set_powered = mgmt_powered,
789
.set_connectable = mgmt_connectable,
790
.set_discoverable = mgmt_discoverable,
791
.set_limited_discoverable = mgmt_set_limited_discoverable,
792
.start_inquiry = mgmt_start_inquiry,
793
.stop_inquiry = mgmt_stop_inquiry,
794
.start_scanning = mgmt_start_scanning,
795
.stop_scanning = mgmt_stop_scanning,
796
.resolve_name = mgmt_resolve_name,
797
.cancel_resolve_name = mgmt_cancel_resolve_name,
798
.set_name = mgmt_set_name,
799
.set_class = mgmt_set_class,
800
.set_fast_connectable = mgmt_fast_connectable,
801
.read_clock = mgmt_read_clock,
802
.get_conn_handle = mgmt_conn_handle,
803
.write_eir_data = mgmt_write_eir_data,
804
.read_bdaddr = mgmt_read_bdaddr,
805
.block_device = mgmt_block_device,
806
.unblock_device = mgmt_unblock_device,
807
.get_conn_list = mgmt_get_conn_list,
808
.read_local_version = mgmt_read_local_version,
809
.read_local_features = mgmt_read_local_features,
810
.read_local_ext_features = mgmt_read_local_ext_features,
811
.read_link_policy = mgmt_read_link_policy,
812
.disconnect = mgmt_disconnect,
813
.remove_bonding = mgmt_remove_bonding,
814
.request_authentication = mgmt_request_authentication,
815
.pincode_reply = mgmt_pincode_reply,
816
.confirm_reply = mgmt_confirm_reply,
817
.passkey_reply = mgmt_passkey_reply,
818
.get_auth_info = mgmt_get_auth_info,
819
.read_scan_enable = mgmt_read_scan_enable,
820
.write_le_host = mgmt_write_le_host,
821
.get_remote_version = mgmt_get_remote_version,
822
.encrypt_link = mgmt_encrypt_link,
825
static int mgmt_init(void)
827
return btd_register_adapter_ops(&mgmt_ops, TRUE);
830
static void mgmt_exit(void)
832
btd_adapter_cleanup_ops(&mgmt_ops);
835
BLUETOOTH_PLUGIN_DEFINE(mgmtops, VERSION,
836
BLUETOOTH_PLUGIN_PRIORITY_LOW, mgmt_init, mgmt_exit)