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