mgmtops.c revision 14655825c95fd065afc41bfc1c810987bfb1a2c6
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 "adapter.h" 45#include "manager.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 uint8_t dev_class[3]; 59 uint16_t manufacturer; 60 uint8_t hci_ver; 61 uint16_t hci_rev; 62 gboolean enabled; 63 gboolean connectable; 64 gboolean discoverable; 65 gboolean pairable; 66 uint8_t sec_mode; 67} *controllers = NULL; 68 69static int mgmt_sock = -1; 70static guint mgmt_watch = 0; 71 72static uint8_t mgmt_version = 0; 73static uint16_t mgmt_revision = 0; 74 75static void read_version_complete(int sk, void *buf, size_t len) 76{ 77 struct mgmt_hdr hdr; 78 struct mgmt_rp_read_version *rp = buf; 79 80 if (len < sizeof(*rp)) { 81 error("Too small read version complete event"); 82 return; 83 } 84 85 mgmt_revision = btohs(bt_get_unaligned(&rp->revision)); 86 mgmt_version = rp->version; 87 88 DBG("version %u revision %u", mgmt_version, mgmt_revision); 89 90 memset(&hdr, 0, sizeof(hdr)); 91 hdr.opcode = MGMT_OP_READ_INDEX_LIST; 92 if (write(sk, &hdr, sizeof(hdr)) < 0) 93 error("Unable to read controller index list: %s (%d)", 94 strerror(errno), errno); 95} 96 97static void add_controller(uint16_t index) 98{ 99 if (index > max_index) { 100 size_t size = sizeof(struct controller_info) * (index + 1); 101 max_index = index; 102 controllers = g_realloc(controllers, size); 103 } 104 105 memset(&controllers[index], 0, sizeof(struct controller_info)); 106 107 controllers[index].valid = TRUE; 108 109 DBG("Added controller %u", index); 110} 111 112static void read_info(int sk, uint16_t index) 113{ 114 char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_read_info)]; 115 struct mgmt_hdr *hdr = (void *) buf; 116 struct mgmt_cp_read_info *cp = (void *) &buf[sizeof(*hdr)]; 117 118 memset(buf, 0, sizeof(buf)); 119 hdr->opcode = MGMT_OP_READ_INFO; 120 hdr->len = htobs(sizeof(*cp)); 121 122 cp->index = htobs(index); 123 124 if (write(sk, buf, sizeof(buf)) < 0) 125 error("Unable to send read_info command: %s (%d)", 126 strerror(errno), errno); 127} 128 129static void mgmt_index_added(int sk, void *buf, size_t len) 130{ 131 struct mgmt_ev_index_added *ev = buf; 132 uint16_t index; 133 134 if (len < sizeof(*ev)) { 135 error("Too small index added event"); 136 return; 137 } 138 139 index = btohs(bt_get_unaligned(&ev->index)); 140 141 add_controller(index); 142 read_info(sk, index); 143} 144 145static void remove_controller(uint16_t index) 146{ 147 if (index > max_index) 148 return; 149 150 if (!controllers[index].valid) 151 return; 152 153 btd_manager_unregister_adapter(index); 154 155 memset(&controllers[index], 0, sizeof(struct controller_info)); 156 157 DBG("Removed controller %u", index); 158} 159 160static void mgmt_index_removed(int sk, void *buf, size_t len) 161{ 162 struct mgmt_ev_index_removed *ev = buf; 163 uint16_t index; 164 165 if (len < sizeof(*ev)) { 166 error("Too small index removed event"); 167 return; 168 } 169 170 index = btohs(bt_get_unaligned(&ev->index)); 171 172 remove_controller(index); 173} 174 175static int mgmt_set_connectable(int index, gboolean connectable) 176{ 177 char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_set_connectable)]; 178 struct mgmt_hdr *hdr = (void *) buf; 179 struct mgmt_cp_set_connectable *cp = (void *) &buf[sizeof(*hdr)]; 180 181 DBG("index %d connectable %d", index, connectable); 182 183 memset(buf, 0, sizeof(buf)); 184 hdr->opcode = MGMT_OP_SET_CONNECTABLE; 185 hdr->len = htobs(sizeof(*cp)); 186 187 cp->index = htobs(index); 188 cp->connectable = connectable; 189 190 if (write(mgmt_sock, buf, sizeof(buf)) < 0) 191 return -errno; 192 193 return 0; 194} 195 196static int mgmt_set_discoverable(int index, gboolean discoverable) 197{ 198 char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_set_discoverable)]; 199 struct mgmt_hdr *hdr = (void *) buf; 200 struct mgmt_cp_set_discoverable *cp = (void *) &buf[sizeof(*hdr)]; 201 202 DBG("index %d discoverable %d", index, discoverable); 203 204 memset(buf, 0, sizeof(buf)); 205 hdr->opcode = MGMT_OP_SET_DISCOVERABLE; 206 hdr->len = htobs(sizeof(*cp)); 207 208 cp->index = htobs(index); 209 cp->discoverable = discoverable; 210 211 if (write(mgmt_sock, buf, sizeof(buf)) < 0) 212 return -errno; 213 214 return 0; 215} 216 217static int mgmt_set_pairable(int index, gboolean pairable) 218{ 219 DBG("index %d pairable %d", index, pairable); 220 return -ENOSYS; 221} 222 223static int mgmt_update_mode(int index, uint8_t powered) 224{ 225 struct controller_info *info; 226 struct btd_adapter *adapter; 227 gboolean pairable, discoverable; 228 uint8_t on_mode; 229 230 if (index > max_index) { 231 error("Unexpected index %u", index); 232 return -ENODEV; 233 } 234 235 info = &controllers[index]; 236 237 info->enabled = powered; 238 239 adapter = manager_find_adapter(&info->bdaddr); 240 if (adapter == NULL) { 241 DBG("Adapter not found"); 242 return -ENODEV; 243 } 244 245 if (!powered) { 246 info->connectable = FALSE; 247 info->pairable = FALSE; 248 info->discoverable = FALSE; 249 250 btd_adapter_stop(adapter); 251 return 0; 252 } 253 254 btd_adapter_start(adapter); 255 256 btd_adapter_get_mode(adapter, NULL, &on_mode, &pairable); 257 258 discoverable = (on_mode == MODE_DISCOVERABLE); 259 260 if (on_mode == MODE_DISCOVERABLE && !info->discoverable) 261 mgmt_set_discoverable(index, TRUE); 262 else if (on_mode == MODE_CONNECTABLE && !info->connectable) 263 mgmt_set_connectable(index, TRUE); 264 else { 265 uint8_t mode = 0; 266 267 if (info->connectable) 268 mode |= SCAN_PAGE; 269 if (info->discoverable) 270 mode |= SCAN_INQUIRY; 271 272 adapter_mode_changed(adapter, mode); 273 } 274 275 mgmt_set_pairable(index, pairable); 276 277 return 0; 278} 279 280static void mgmt_powered(int sk, void *buf, size_t len) 281{ 282 struct mgmt_ev_powered *ev = buf; 283 uint16_t index; 284 285 if (len < sizeof(*ev)) { 286 error("Too small powered event"); 287 return; 288 } 289 290 index = btohs(bt_get_unaligned(&ev->index)); 291 292 DBG("Controller %u powered %u", index, ev->powered); 293 294 mgmt_update_mode(index, ev->powered); 295} 296 297static void mgmt_discoverable(int sk, void *buf, size_t len) 298{ 299 struct mgmt_ev_discoverable *ev = buf; 300 struct controller_info *info; 301 struct btd_adapter *adapter; 302 uint16_t index; 303 304 if (len < sizeof(*ev)) { 305 error("Too small discoverable event"); 306 return; 307 } 308 309 index = btohs(bt_get_unaligned(&ev->index)); 310 311 DBG("Controller %u discoverable %u", index, ev->discoverable); 312 313 if (index > max_index) { 314 error("Unexpected index %u in discoverable event", index); 315 return; 316 } 317 318 info = &controllers[index]; 319 320 info->discoverable = ev->discoverable ? TRUE : FALSE; 321 322 adapter = manager_find_adapter(&info->bdaddr); 323 if (adapter) 324 adapter_mode_changed(adapter, ev->discoverable ? 0x03 : 0x02); 325} 326 327static void mgmt_connectable(int sk, void *buf, size_t len) 328{ 329 struct mgmt_ev_connectable *ev = buf; 330 struct controller_info *info; 331 struct btd_adapter *adapter; 332 uint16_t index; 333 uint8_t mode; 334 335 if (len < sizeof(*ev)) { 336 error("Too small connectable event"); 337 return; 338 } 339 340 index = btohs(bt_get_unaligned(&ev->index)); 341 342 DBG("Controller %u connectable %u", index, ev->connectable); 343 344 if (index > max_index) { 345 error("Unexpected index %u in connectable event", index); 346 return; 347 } 348 349 info = &controllers[index]; 350 351 info->connectable = ev->connectable ? TRUE : FALSE; 352 353 adapter = manager_find_adapter(&info->bdaddr); 354 if (!adapter) 355 return; 356 357 if (info->discoverable) 358 mode = SCAN_INQUIRY; 359 else 360 mode = 0; 361 362 if (info->connectable) 363 mode |= SCAN_PAGE; 364 365 adapter_mode_changed(adapter, mode); 366} 367 368static void read_index_list_complete(int sk, void *buf, size_t len) 369{ 370 struct mgmt_rp_read_index_list *rp = buf; 371 uint16_t num; 372 int i; 373 374 if (len < sizeof(*rp)) { 375 error("Too small read index list complete event"); 376 return; 377 } 378 379 num = btohs(bt_get_unaligned(&rp->num_controllers)); 380 381 if (num * sizeof(uint16_t) + sizeof(*rp) != len) { 382 error("Incorrect packet size for index list event"); 383 return; 384 } 385 386 for (i = 0; i < num; i++) { 387 uint16_t index; 388 389 index = btohs(bt_get_unaligned(&rp->index[i])); 390 391 add_controller(index); 392 read_info(sk, index); 393 } 394} 395 396static int mgmt_set_powered(int index, gboolean powered) 397{ 398 char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_set_powered)]; 399 struct mgmt_hdr *hdr = (void *) buf; 400 struct mgmt_cp_set_powered *cp = (void *) &buf[sizeof(*hdr)]; 401 402 DBG("index %d powered %d", index, powered); 403 404 memset(buf, 0, sizeof(buf)); 405 hdr->opcode = MGMT_OP_SET_POWERED; 406 hdr->len = htobs(sizeof(*cp)); 407 408 cp->index = htobs(index); 409 cp->powered = powered; 410 411 if (write(mgmt_sock, buf, sizeof(buf)) < 0) 412 return -errno; 413 414 return 0; 415} 416 417static void read_info_complete(int sk, void *buf, size_t len) 418{ 419 struct mgmt_rp_read_info *rp = buf; 420 struct controller_info *info; 421 struct btd_adapter *adapter; 422 uint8_t mode; 423 uint16_t index; 424 char addr[18]; 425 426 if (len < sizeof(*rp)) { 427 error("Too small read info complete event"); 428 return; 429 } 430 431 index = btohs(bt_get_unaligned(&rp->index)); 432 if (index > max_index) { 433 error("Unexpected index %u in read info complete", index); 434 return; 435 } 436 437 info = &controllers[index]; 438 info->type = rp->type; 439 info->enabled = rp->powered; 440 info->connectable = rp->connectable; 441 info->discoverable = rp->discoverable; 442 info->pairable = rp->pairable; 443 info->sec_mode = rp->sec_mode; 444 bacpy(&info->bdaddr, &rp->bdaddr); 445 memcpy(info->dev_class, rp->dev_class, 3); 446 memcpy(info->features, rp->features, 8); 447 info->manufacturer = btohs(bt_get_unaligned(&rp->manufacturer)); 448 info->hci_ver = rp->hci_ver; 449 info->hci_rev = btohs(bt_get_unaligned(&rp->hci_rev)); 450 451 ba2str(&info->bdaddr, addr); 452 DBG("hci%u type %u addr %s", index, info->type, addr); 453 DBG("hci%u class 0x%02x%02x%02x", index, 454 info->dev_class[2], info->dev_class[1], info->dev_class[0]); 455 DBG("hci%u manufacturer %d HCI ver %d:%d", index, info->manufacturer, 456 info->hci_ver, info->hci_rev); 457 DBG("hci%u enabled %u discoverable %u pairable %u sec_mode %u", index, 458 info->enabled, info->discoverable, 459 info->pairable, info->sec_mode); 460 461 adapter = btd_manager_register_adapter(index); 462 if (adapter == NULL) { 463 error("mgmtops: unable to register adapter"); 464 return; 465 } 466 467 btd_adapter_get_mode(adapter, &mode, NULL, NULL); 468 if (mode == MODE_OFF) { 469 mgmt_set_powered(index, FALSE); 470 return; 471 } 472 473 if (info->enabled) 474 mgmt_update_mode(index, TRUE); 475 else 476 mgmt_set_powered(index, TRUE); 477 478 btd_adapter_unref(adapter); 479} 480 481static void set_powered_complete(int sk, void *buf, size_t len) 482{ 483 struct mgmt_rp_set_powered *rp = buf; 484 uint16_t index; 485 486 if (len < sizeof(*rp)) { 487 error("Too small set powered complete event"); 488 return; 489 } 490 491 index = btohs(bt_get_unaligned(&rp->index)); 492 493 DBG("hci%d powered %u", index, rp->powered); 494 495 mgmt_update_mode(index, rp->powered); 496} 497 498static void set_discoverable_complete(int sk, void *buf, size_t len) 499{ 500 struct mgmt_rp_set_discoverable *rp = buf; 501 struct controller_info *info; 502 struct btd_adapter *adapter; 503 uint16_t index; 504 505 if (len < sizeof(*rp)) { 506 error("Too small set discoverable complete event"); 507 return; 508 } 509 510 index = btohs(bt_get_unaligned(&rp->index)); 511 512 DBG("hci%d discoverable %u", index, rp->discoverable); 513 514 if (index > max_index) { 515 error("Unexpected index %u in discoverable complete", index); 516 return; 517 } 518 519 info = &controllers[index]; 520 521 info->discoverable = rp->discoverable ? TRUE : FALSE; 522 523 adapter = manager_find_adapter(&info->bdaddr); 524 if (adapter) 525 adapter_mode_changed(adapter, rp->discoverable ? 0x03 : 0x02); 526} 527 528static void set_connectable_complete(int sk, void *buf, size_t len) 529{ 530 struct mgmt_rp_set_connectable *rp = buf; 531 struct controller_info *info; 532 struct btd_adapter *adapter; 533 uint16_t index; 534 535 if (len < sizeof(*rp)) { 536 error("Too small set connectable complete event"); 537 return; 538 } 539 540 index = btohs(bt_get_unaligned(&rp->index)); 541 542 DBG("hci%d connectable %u", index, rp->connectable); 543 544 if (index > max_index) { 545 error("Unexpected index %u in connectable complete", index); 546 return; 547 } 548 549 info = &controllers[index]; 550 551 info->connectable = rp->connectable ? TRUE : FALSE; 552 553 adapter = manager_find_adapter(&info->bdaddr); 554 if (adapter) 555 adapter_mode_changed(adapter, rp->connectable ? SCAN_PAGE : 0); 556} 557 558static void mgmt_cmd_complete(int sk, void *buf, size_t len) 559{ 560 struct mgmt_ev_cmd_complete *ev = buf; 561 uint16_t opcode; 562 563 DBG(""); 564 565 if (len < sizeof(*ev)) { 566 error("Too small management command complete event packet"); 567 return; 568 } 569 570 opcode = btohs(bt_get_unaligned(&ev->opcode)); 571 572 switch (opcode) { 573 case MGMT_OP_READ_VERSION: 574 read_version_complete(sk, ev->data, len - sizeof(*ev)); 575 break; 576 case MGMT_OP_READ_INDEX_LIST: 577 read_index_list_complete(sk, ev->data, len - sizeof(*ev)); 578 break; 579 case MGMT_OP_READ_INFO: 580 read_info_complete(sk, ev->data, len - sizeof(*ev)); 581 break; 582 case MGMT_OP_SET_POWERED: 583 set_powered_complete(sk, ev->data, len - sizeof(*ev)); 584 break; 585 case MGMT_OP_SET_DISCOVERABLE: 586 set_discoverable_complete(sk, ev->data, len - sizeof(*ev)); 587 break; 588 case MGMT_OP_SET_CONNECTABLE: 589 set_connectable_complete(sk, ev->data, len - sizeof(*ev)); 590 break; 591 default: 592 error("Unknown command complete for opcode %u", opcode); 593 break; 594 } 595} 596 597static void mgmt_cmd_status(int sk, void *buf, size_t len) 598{ 599 struct mgmt_ev_cmd_status *ev = buf; 600 uint16_t opcode; 601 602 if (len < sizeof(*ev)) { 603 error("Too small management command status event packet"); 604 return; 605 } 606 607 opcode = btohs(bt_get_unaligned(&ev->opcode)); 608 609 DBG("status %u opcode %u", ev->status, opcode); 610} 611 612static void mgmt_controller_error(int sk, void *buf, size_t len) 613{ 614 struct mgmt_ev_controller_error *ev = buf; 615 uint16_t index; 616 617 if (len < sizeof(*ev)) { 618 error("Too small management controller error event packet"); 619 return; 620 } 621 622 index = btohs(bt_get_unaligned(&ev->index)); 623 624 DBG("index %u error_code %u", index, ev->error_code); 625} 626 627static gboolean mgmt_event(GIOChannel *io, GIOCondition cond, gpointer user_data) 628{ 629 char buf[MGMT_BUF_SIZE]; 630 struct mgmt_hdr *hdr = (void *) buf; 631 int sk; 632 ssize_t ret; 633 uint16_t len, opcode; 634 635 DBG("cond %d", cond); 636 637 if (cond & G_IO_NVAL) 638 return FALSE; 639 640 sk = g_io_channel_unix_get_fd(io); 641 642 if (cond & (G_IO_ERR | G_IO_HUP)) { 643 error("Error on management socket"); 644 return FALSE; 645 } 646 647 ret = read(sk, buf, sizeof(buf)); 648 if (ret < 0) { 649 error("Unable to read from management socket: %s (%d)", 650 strerror(errno), errno); 651 return TRUE; 652 } 653 654 DBG("Received %zd bytes from management socket", ret); 655 656 if (ret < MGMT_HDR_SIZE) { 657 error("Too small Management packet"); 658 return TRUE; 659 } 660 661 opcode = btohs(bt_get_unaligned(&hdr->opcode)); 662 len = btohs(bt_get_unaligned(&hdr->len)); 663 664 if (ret != MGMT_HDR_SIZE + len) { 665 error("Packet length mismatch. ret %zd len %u", ret, len); 666 return TRUE; 667 } 668 669 switch (opcode) { 670 case MGMT_EV_CMD_COMPLETE: 671 mgmt_cmd_complete(sk, buf + MGMT_HDR_SIZE, len); 672 break; 673 case MGMT_EV_CMD_STATUS: 674 mgmt_cmd_status(sk, buf + MGMT_HDR_SIZE, len); 675 break; 676 case MGMT_EV_CONTROLLER_ERROR: 677 mgmt_controller_error(sk, buf + MGMT_HDR_SIZE, len); 678 break; 679 case MGMT_EV_INDEX_ADDED: 680 mgmt_index_added(sk, buf + MGMT_HDR_SIZE, len); 681 break; 682 case MGMT_EV_INDEX_REMOVED: 683 mgmt_index_removed(sk, buf + MGMT_HDR_SIZE, len); 684 break; 685 case MGMT_EV_POWERED: 686 mgmt_powered(sk, buf + MGMT_HDR_SIZE, len); 687 break; 688 case MGMT_EV_DISCOVERABLE: 689 mgmt_discoverable(sk, buf + MGMT_HDR_SIZE, len); 690 break; 691 case MGMT_EV_CONNECTABLE: 692 mgmt_connectable(sk, buf + MGMT_HDR_SIZE, len); 693 break; 694 default: 695 error("Unknown Management opcode %u", opcode); 696 break; 697 } 698 699 return TRUE; 700} 701 702static int mgmt_setup(void) 703{ 704 struct mgmt_hdr hdr; 705 struct sockaddr_hci addr; 706 GIOChannel *io; 707 GIOCondition condition; 708 int dd, err; 709 710 dd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 711 if (dd < 0) 712 return -errno; 713 714 memset(&addr, 0, sizeof(addr)); 715 addr.hci_family = AF_BLUETOOTH; 716 addr.hci_dev = HCI_DEV_NONE; 717 addr.hci_channel = HCI_CHANNEL_CONTROL; 718 719 if (bind(dd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 720 err = -errno; 721 goto fail; 722 } 723 724 memset(&hdr, 0, sizeof(hdr)); 725 hdr.opcode = MGMT_OP_READ_VERSION; 726 if (write(dd, &hdr, sizeof(hdr)) < 0) { 727 err = -errno; 728 goto fail; 729 } 730 731 io = g_io_channel_unix_new(dd); 732 condition = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL; 733 mgmt_watch = g_io_add_watch(io, condition, mgmt_event, NULL); 734 g_io_channel_unref(io); 735 736 mgmt_sock = dd; 737 738 info("Bluetooth Management interface initialized"); 739 740 return 0; 741 742fail: 743 close(dd); 744 return err; 745} 746 747static void mgmt_cleanup(void) 748{ 749 g_free(controllers); 750 controllers = NULL; 751 max_index = -1; 752 753 if (mgmt_sock >= 0) { 754 close(mgmt_sock); 755 mgmt_sock = -1; 756 } 757 758 if (mgmt_watch > 0) { 759 g_source_remove(mgmt_watch); 760 mgmt_watch = 0; 761 } 762} 763 764static int mgmt_set_dev_class(int index, uint8_t major, uint8_t minor) 765{ 766 DBG("index %d major %u minor %u", index, major, minor); 767 return -ENOSYS; 768} 769 770static int mgmt_set_limited_discoverable(int index, gboolean limited) 771{ 772 DBG("index %d limited %d", index, limited); 773 return -ENOSYS; 774} 775 776static int mgmt_start_inquiry(int index, uint8_t length, gboolean periodic) 777{ 778 DBG("index %d length %u periodic %d", index, length, periodic); 779 return -ENOSYS; 780} 781 782static int mgmt_stop_inquiry(int index) 783{ 784 DBG("index %d", index); 785 return -ENOSYS; 786} 787 788static int mgmt_start_scanning(int index) 789{ 790 DBG("index %d", index); 791 return -ENOSYS; 792} 793 794static int mgmt_stop_scanning(int index) 795{ 796 DBG("index %d", index); 797 return -ENOSYS; 798} 799 800static int mgmt_resolve_name(int index, bdaddr_t *bdaddr) 801{ 802 char addr[18]; 803 804 ba2str(bdaddr, addr); 805 DBG("index %d addr %s", index, addr); 806 807 return -ENOSYS; 808} 809 810static int mgmt_set_name(int index, const char *name) 811{ 812 DBG("index %d, name %s", index, name); 813 return -ENOSYS; 814} 815 816static int mgmt_cancel_resolve_name(int index, bdaddr_t *bdaddr) 817{ 818 char addr[18]; 819 820 ba2str(bdaddr, addr); 821 DBG("index %d addr %s", index, addr); 822 823 return -ENOSYS; 824} 825 826static int mgmt_fast_connectable(int index, gboolean enable) 827{ 828 DBG("index %d enable %d", index, enable); 829 return -ENOSYS; 830} 831 832static int mgmt_read_clock(int index, bdaddr_t *bdaddr, int which, int timeout, 833 uint32_t *clock, uint16_t *accuracy) 834{ 835 char addr[18]; 836 837 ba2str(bdaddr, addr); 838 DBG("index %d addr %s which %d timeout %d", index, addr, which, 839 timeout); 840 841 return -ENOSYS; 842} 843 844static int mgmt_read_bdaddr(int index, bdaddr_t *bdaddr) 845{ 846 char addr[18]; 847 struct controller_info *info = &controllers[index]; 848 849 ba2str(&info->bdaddr, addr); 850 DBG("index %d addr %s", index, addr); 851 852 if (!info->valid) 853 return -ENODEV; 854 855 bacpy(bdaddr, &info->bdaddr); 856 857 return 0; 858} 859 860static int mgmt_block_device(int index, bdaddr_t *bdaddr) 861{ 862 char addr[18]; 863 864 ba2str(bdaddr, addr); 865 DBG("index %d addr %s", index, addr); 866 867 return -ENOSYS; 868} 869 870static int mgmt_unblock_device(int index, bdaddr_t *bdaddr) 871{ 872 char addr[18]; 873 874 ba2str(bdaddr, addr); 875 DBG("index %d addr %s", index, addr); 876 877 return -ENOSYS; 878} 879 880static int mgmt_get_conn_list(int index, GSList **conns) 881{ 882 DBG("index %d", index); 883 return -ENOSYS; 884} 885 886static int mgmt_read_local_version(int index, struct hci_version *ver) 887{ 888 struct controller_info *info = &controllers[index]; 889 890 DBG("index %d", index); 891 892 if (!info->valid) 893 return -ENODEV; 894 895 memset(ver, 0, sizeof(*ver)); 896 ver->manufacturer = info->manufacturer; 897 ver->hci_ver = info->hci_ver; 898 ver->hci_rev = info->hci_rev; 899 900 return 0; 901} 902 903static int mgmt_read_local_features(int index, uint8_t *features) 904{ 905 struct controller_info *info = &controllers[index]; 906 907 DBG("index %d", index); 908 909 if (!info->valid) 910 return -ENODEV; 911 912 memcpy(features, info->features, 8); 913 914 return 0; 915} 916 917static int mgmt_disconnect(int index, uint16_t handle) 918{ 919 DBG("index %d handle %u", index, handle); 920 return -ENOSYS; 921} 922 923static int mgmt_remove_bonding(int index, bdaddr_t *bdaddr) 924{ 925 char addr[18]; 926 927 ba2str(bdaddr, addr); 928 DBG("index %d addr %s", index, addr); 929 930 return -ENOSYS; 931} 932 933static int mgmt_request_authentication(int index, uint16_t handle) 934{ 935 DBG("index %d handle %u", index, handle); 936 return -ENOSYS; 937} 938 939static int mgmt_pincode_reply(int index, bdaddr_t *bdaddr, const char *pin) 940{ 941 char addr[18]; 942 943 ba2str(bdaddr, addr); 944 DBG("index %d addr %s pin %s", index, addr, pin); 945 946 return -ENOSYS; 947} 948 949static int mgmt_confirm_reply(int index, bdaddr_t *bdaddr, gboolean success) 950{ 951 char addr[18]; 952 953 ba2str(bdaddr, addr); 954 DBG("index %d addr %s success %d", index, addr, success); 955 956 return -ENOSYS; 957} 958 959static int mgmt_passkey_reply(int index, bdaddr_t *bdaddr, uint32_t passkey) 960{ 961 char addr[18]; 962 963 ba2str(bdaddr, addr); 964 DBG("index %d addr %s passkey %06u", index, addr, passkey); 965 966 return -ENOSYS; 967} 968 969static int mgmt_get_auth_info(int index, bdaddr_t *bdaddr, uint8_t *auth) 970{ 971 char addr[18]; 972 973 ba2str(bdaddr, addr); 974 DBG("index %d addr %s", index, addr); 975 976 return -ENOSYS; 977} 978 979static int mgmt_read_scan_enable(int index) 980{ 981 DBG("index %d", index); 982 return -ENOSYS; 983} 984 985static int mgmt_enable_le(int index) 986{ 987 DBG("index %d", index); 988 return -ENOSYS; 989} 990 991static int mgmt_encrypt_link(int index, bdaddr_t *dst, bt_hci_result_t cb, 992 gpointer user_data) 993{ 994 char addr[18]; 995 996 ba2str(dst, addr); 997 DBG("index %d addr %s", index, addr); 998 999 return -ENOSYS; 1000} 1001 1002static int mgmt_set_did(int index, uint16_t vendor, uint16_t product, 1003 uint16_t version) 1004{ 1005 DBG("index %d vendor %u product %u version %u", 1006 index, vendor, product, version); 1007 return -ENOSYS; 1008} 1009 1010static int mgmt_services_updated(int index) 1011{ 1012 DBG("index %d", index); 1013 return -ENOSYS; 1014} 1015 1016static int mgmt_disable_cod_cache(int index) 1017{ 1018 DBG("index %d", index); 1019 return -ENOSYS; 1020} 1021 1022static int mgmt_restore_powered(int index) 1023{ 1024 DBG("index %d", index); 1025 return -ENOSYS; 1026} 1027 1028static int mgmt_load_keys(int index, GSList *keys, gboolean debug_keys) 1029{ 1030 DBG("index %d keys %d debug_keys %d", index, g_slist_length(keys), 1031 debug_keys); 1032 return -ENOSYS; 1033} 1034 1035static struct btd_adapter_ops mgmt_ops = { 1036 .setup = mgmt_setup, 1037 .cleanup = mgmt_cleanup, 1038 .set_powered = mgmt_set_powered, 1039 .set_discoverable = mgmt_set_discoverable, 1040 .set_pairable = mgmt_set_pairable, 1041 .set_limited_discoverable = mgmt_set_limited_discoverable, 1042 .start_inquiry = mgmt_start_inquiry, 1043 .stop_inquiry = mgmt_stop_inquiry, 1044 .start_scanning = mgmt_start_scanning, 1045 .stop_scanning = mgmt_stop_scanning, 1046 .resolve_name = mgmt_resolve_name, 1047 .cancel_resolve_name = mgmt_cancel_resolve_name, 1048 .set_name = mgmt_set_name, 1049 .set_dev_class = mgmt_set_dev_class, 1050 .set_fast_connectable = mgmt_fast_connectable, 1051 .read_clock = mgmt_read_clock, 1052 .read_bdaddr = mgmt_read_bdaddr, 1053 .block_device = mgmt_block_device, 1054 .unblock_device = mgmt_unblock_device, 1055 .get_conn_list = mgmt_get_conn_list, 1056 .read_local_version = mgmt_read_local_version, 1057 .read_local_features = mgmt_read_local_features, 1058 .disconnect = mgmt_disconnect, 1059 .remove_bonding = mgmt_remove_bonding, 1060 .request_authentication = mgmt_request_authentication, 1061 .pincode_reply = mgmt_pincode_reply, 1062 .confirm_reply = mgmt_confirm_reply, 1063 .passkey_reply = mgmt_passkey_reply, 1064 .get_auth_info = mgmt_get_auth_info, 1065 .read_scan_enable = mgmt_read_scan_enable, 1066 .enable_le = mgmt_enable_le, 1067 .encrypt_link = mgmt_encrypt_link, 1068 .set_did = mgmt_set_did, 1069 .services_updated = mgmt_services_updated, 1070 .disable_cod_cache = mgmt_disable_cod_cache, 1071 .restore_powered = mgmt_restore_powered, 1072 .load_keys = mgmt_load_keys, 1073}; 1074 1075static int mgmt_init(void) 1076{ 1077 return btd_register_adapter_ops(&mgmt_ops, TRUE); 1078} 1079 1080static void mgmt_exit(void) 1081{ 1082 btd_adapter_cleanup_ops(&mgmt_ops); 1083} 1084 1085BLUETOOTH_PLUGIN_DEFINE(mgmtops, VERSION, 1086 BLUETOOTH_PLUGIN_PRIORITY_LOW, mgmt_init, mgmt_exit) 1087