mgmtops.c revision b18b51e97bddc67c8b4ff10a3f97241ac480596a
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/sdp.h> 41#include <bluetooth/sdp_lib.h> 42#include <bluetooth/mgmt.h> 43 44#include "plugin.h" 45#include "log.h" 46#include "adapter.h" 47#include "manager.h" 48#include "device.h" 49#include "event.h" 50 51#define MGMT_BUF_SIZE 1024 52 53static int max_index = -1; 54static struct controller_info { 55 gboolean valid; 56 gboolean notified; 57 uint8_t type; 58 bdaddr_t bdaddr; 59 uint8_t features[8]; 60 uint8_t dev_class[3]; 61 uint16_t manufacturer; 62 uint8_t hci_ver; 63 uint16_t hci_rev; 64 gboolean enabled; 65 gboolean connectable; 66 gboolean discoverable; 67 gboolean pairable; 68 uint8_t sec_mode; 69 GSList *connections; 70} *controllers = NULL; 71 72static int mgmt_sock = -1; 73static guint mgmt_watch = 0; 74 75static uint8_t mgmt_version = 0; 76static uint16_t mgmt_revision = 0; 77 78static void read_version_complete(int sk, void *buf, size_t len) 79{ 80 struct mgmt_hdr hdr; 81 struct mgmt_rp_read_version *rp = buf; 82 83 if (len < sizeof(*rp)) { 84 error("Too small read version complete event"); 85 return; 86 } 87 88 mgmt_revision = btohs(bt_get_unaligned(&rp->revision)); 89 mgmt_version = rp->version; 90 91 DBG("version %u revision %u", mgmt_version, mgmt_revision); 92 93 memset(&hdr, 0, sizeof(hdr)); 94 hdr.opcode = htobs(MGMT_OP_READ_INDEX_LIST); 95 if (write(sk, &hdr, sizeof(hdr)) < 0) 96 error("Unable to read controller index list: %s (%d)", 97 strerror(errno), errno); 98} 99 100static void add_controller(uint16_t index) 101{ 102 if (index > max_index) { 103 size_t size = sizeof(struct controller_info) * (index + 1); 104 max_index = index; 105 controllers = g_realloc(controllers, size); 106 } 107 108 memset(&controllers[index], 0, sizeof(struct controller_info)); 109 110 controllers[index].valid = TRUE; 111 112 DBG("Added controller %u", index); 113} 114 115static void read_info(int sk, uint16_t index) 116{ 117 char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_read_info)]; 118 struct mgmt_hdr *hdr = (void *) buf; 119 struct mgmt_cp_read_info *cp = (void *) &buf[sizeof(*hdr)]; 120 121 memset(buf, 0, sizeof(buf)); 122 hdr->opcode = htobs(MGMT_OP_READ_INFO); 123 hdr->len = htobs(sizeof(*cp)); 124 125 cp->index = htobs(index); 126 127 if (write(sk, buf, sizeof(buf)) < 0) 128 error("Unable to send read_info command: %s (%d)", 129 strerror(errno), errno); 130} 131 132static void get_connections(int sk, uint16_t index) 133{ 134 char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_get_connections)]; 135 struct mgmt_hdr *hdr = (void *) buf; 136 struct mgmt_cp_get_connections *cp = (void *) &buf[sizeof(*hdr)]; 137 138 memset(buf, 0, sizeof(buf)); 139 hdr->opcode = htobs(MGMT_OP_GET_CONNECTIONS); 140 hdr->len = htobs(sizeof(*cp)); 141 142 cp->index = htobs(index); 143 144 if (write(sk, buf, sizeof(buf)) < 0) 145 error("Unable to send get_connections command: %s (%d)", 146 strerror(errno), errno); 147} 148 149static void mgmt_index_added(int sk, void *buf, size_t len) 150{ 151 struct mgmt_ev_index_added *ev = buf; 152 uint16_t index; 153 154 if (len < sizeof(*ev)) { 155 error("Too small index added event"); 156 return; 157 } 158 159 index = btohs(bt_get_unaligned(&ev->index)); 160 161 add_controller(index); 162 read_info(sk, index); 163} 164 165static void remove_controller(uint16_t index) 166{ 167 if (index > max_index) 168 return; 169 170 if (!controllers[index].valid) 171 return; 172 173 btd_manager_unregister_adapter(index); 174 175 memset(&controllers[index], 0, sizeof(struct controller_info)); 176 177 DBG("Removed controller %u", index); 178} 179 180static void mgmt_index_removed(int sk, void *buf, size_t len) 181{ 182 struct mgmt_ev_index_removed *ev = buf; 183 uint16_t index; 184 185 if (len < sizeof(*ev)) { 186 error("Too small index removed event"); 187 return; 188 } 189 190 index = btohs(bt_get_unaligned(&ev->index)); 191 192 remove_controller(index); 193} 194 195static int mgmt_set_mode(int index, uint16_t opcode, uint8_t val) 196{ 197 char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_mode)]; 198 struct mgmt_hdr *hdr = (void *) buf; 199 struct mgmt_mode *cp = (void *) &buf[sizeof(*hdr)]; 200 201 memset(buf, 0, sizeof(buf)); 202 hdr->opcode = htobs(opcode); 203 hdr->len = htobs(sizeof(*cp)); 204 205 cp->index = htobs(index); 206 cp->val = val; 207 208 if (write(mgmt_sock, buf, sizeof(buf)) < 0) 209 return -errno; 210 211 return 0; 212} 213 214static int mgmt_set_connectable(int index, gboolean connectable) 215{ 216 DBG("index %d connectable %d", index, connectable); 217 return mgmt_set_mode(index, MGMT_OP_SET_CONNECTABLE, connectable); 218} 219 220static int mgmt_set_discoverable(int index, gboolean discoverable) 221{ 222 DBG("index %d discoverable %d", index, discoverable); 223 return mgmt_set_mode(index, MGMT_OP_SET_DISCOVERABLE, discoverable); 224} 225 226static int mgmt_set_pairable(int index, gboolean pairable) 227{ 228 DBG("index %d pairable %d", index, pairable); 229 return mgmt_set_mode(index, MGMT_OP_SET_PAIRABLE, pairable); 230} 231 232static int mgmt_update_powered(int index, uint8_t powered) 233{ 234 struct controller_info *info; 235 struct btd_adapter *adapter; 236 gboolean pairable, discoverable; 237 uint8_t on_mode; 238 239 if (index > max_index) { 240 error("Unexpected index %u", index); 241 return -ENODEV; 242 } 243 244 info = &controllers[index]; 245 246 info->enabled = powered; 247 248 adapter = manager_find_adapter(&info->bdaddr); 249 if (adapter == NULL) { 250 DBG("Adapter not found"); 251 return -ENODEV; 252 } 253 254 if (!powered) { 255 info->connectable = FALSE; 256 info->pairable = FALSE; 257 info->discoverable = FALSE; 258 259 btd_adapter_stop(adapter); 260 return 0; 261 } 262 263 btd_adapter_start(adapter); 264 265 btd_adapter_get_mode(adapter, NULL, &on_mode, &pairable); 266 267 discoverable = (on_mode == MODE_DISCOVERABLE); 268 269 if (on_mode == MODE_DISCOVERABLE && !info->discoverable) 270 mgmt_set_discoverable(index, TRUE); 271 else if (on_mode == MODE_CONNECTABLE && !info->connectable) 272 mgmt_set_connectable(index, TRUE); 273 else { 274 uint8_t mode = 0; 275 276 if (info->connectable) 277 mode |= SCAN_PAGE; 278 if (info->discoverable) 279 mode |= SCAN_INQUIRY; 280 281 adapter_mode_changed(adapter, mode); 282 } 283 284 if (info->pairable != pairable) 285 mgmt_set_pairable(index, pairable); 286 287 return 0; 288} 289 290static void mgmt_powered(int sk, void *buf, size_t len) 291{ 292 struct mgmt_mode *ev = buf; 293 uint16_t index; 294 295 if (len < sizeof(*ev)) { 296 error("Too small powered event"); 297 return; 298 } 299 300 index = btohs(bt_get_unaligned(&ev->index)); 301 302 DBG("Controller %u powered %u", index, ev->val); 303 304 mgmt_update_powered(index, ev->val); 305} 306 307static void mgmt_discoverable(int sk, void *buf, size_t len) 308{ 309 struct mgmt_mode *ev = buf; 310 struct controller_info *info; 311 struct btd_adapter *adapter; 312 uint16_t index; 313 uint8_t mode; 314 315 if (len < sizeof(*ev)) { 316 error("Too small discoverable event"); 317 return; 318 } 319 320 index = btohs(bt_get_unaligned(&ev->index)); 321 322 DBG("Controller %u discoverable %u", index, ev->val); 323 324 if (index > max_index) { 325 error("Unexpected index %u in discoverable event", index); 326 return; 327 } 328 329 info = &controllers[index]; 330 331 info->discoverable = ev->val ? TRUE : FALSE; 332 333 adapter = manager_find_adapter(&info->bdaddr); 334 if (!adapter) 335 return; 336 337 if (info->connectable) 338 mode = SCAN_PAGE; 339 else 340 mode = 0; 341 342 if (info->discoverable) 343 mode |= SCAN_INQUIRY; 344 345 adapter_mode_changed(adapter, mode); 346} 347 348static void mgmt_connectable(int sk, void *buf, size_t len) 349{ 350 struct mgmt_mode *ev = buf; 351 struct controller_info *info; 352 struct btd_adapter *adapter; 353 uint16_t index; 354 uint8_t mode; 355 356 if (len < sizeof(*ev)) { 357 error("Too small connectable event"); 358 return; 359 } 360 361 index = btohs(bt_get_unaligned(&ev->index)); 362 363 DBG("Controller %u connectable %u", index, ev->val); 364 365 if (index > max_index) { 366 error("Unexpected index %u in connectable event", index); 367 return; 368 } 369 370 info = &controllers[index]; 371 372 info->connectable = ev->val ? TRUE : FALSE; 373 374 adapter = manager_find_adapter(&info->bdaddr); 375 if (!adapter) 376 return; 377 378 if (info->discoverable) 379 mode = SCAN_INQUIRY; 380 else 381 mode = 0; 382 383 if (info->connectable) 384 mode |= SCAN_PAGE; 385 386 adapter_mode_changed(adapter, mode); 387} 388 389static void mgmt_pairable(int sk, void *buf, size_t len) 390{ 391 struct mgmt_mode *ev = buf; 392 struct controller_info *info; 393 struct btd_adapter *adapter; 394 uint16_t index; 395 396 if (len < sizeof(*ev)) { 397 error("Too small pairable event"); 398 return; 399 } 400 401 index = btohs(bt_get_unaligned(&ev->index)); 402 403 DBG("Controller %u pairable %u", index, ev->val); 404 405 if (index > max_index) { 406 error("Unexpected index %u in pairable event", index); 407 return; 408 } 409 410 info = &controllers[index]; 411 412 info->pairable = ev->val ? TRUE : FALSE; 413 414 adapter = manager_find_adapter(&info->bdaddr); 415 if (!adapter) 416 return; 417 418 btd_adapter_pairable_changed(adapter, info->pairable); 419} 420 421static void mgmt_new_key(int sk, void *buf, size_t len) 422{ 423 struct mgmt_ev_new_key *ev = buf; 424 struct controller_info *info; 425 uint16_t index; 426 427 if (len != sizeof(*ev)) { 428 error("new_key event size mismatch (%zu != %zu)", 429 len, sizeof(*ev)); 430 return; 431 } 432 433 index = btohs(bt_get_unaligned(&ev->index)); 434 435 DBG("Controller %u new key of type %u pin_len %u", index, 436 ev->key.type, ev->key.pin_len); 437 438 if (index > max_index) { 439 error("Unexpected index %u in new_key event", index); 440 return; 441 } 442 443 if (ev->key.pin_len > 16) { 444 error("Invalid PIN length (%u) in new_key event", 445 ev->key.pin_len); 446 return; 447 } 448 449 info = &controllers[index]; 450 451 btd_event_link_key_notify(&info->bdaddr, &ev->key.bdaddr, 452 ev->key.val, ev->key.type, 453 ev->key.pin_len); 454} 455 456static void mgmt_device_connected(int sk, void *buf, size_t len) 457{ 458 struct mgmt_ev_device_connected *ev = buf; 459 struct controller_info *info; 460 uint16_t index; 461 char addr[18]; 462 463 if (len < sizeof(*ev)) { 464 error("Too small device_connected event"); 465 return; 466 } 467 468 index = btohs(bt_get_unaligned(&ev->index)); 469 ba2str(&ev->bdaddr, addr); 470 471 DBG("hci%u device %s connected", index, addr); 472 473 if (index > max_index) { 474 error("Unexpected index %u in device_connected event", index); 475 return; 476 } 477 478 info = &controllers[index]; 479 480 btd_event_conn_complete(&info->bdaddr, &ev->bdaddr); 481} 482 483static void mgmt_device_disconnected(int sk, void *buf, size_t len) 484{ 485 struct mgmt_ev_device_disconnected *ev = buf; 486 struct controller_info *info; 487 uint16_t index; 488 char addr[18]; 489 490 if (len < sizeof(*ev)) { 491 error("Too small device_disconnected event"); 492 return; 493 } 494 495 index = btohs(bt_get_unaligned(&ev->index)); 496 ba2str(&ev->bdaddr, addr); 497 498 DBG("hci%u device %s disconnected", index, addr); 499 500 if (index > max_index) { 501 error("Unexpected index %u in device_disconnected event", index); 502 return; 503 } 504 505 info = &controllers[index]; 506 507 btd_event_disconn_complete(&info->bdaddr, &ev->bdaddr); 508} 509 510static void mgmt_connect_failed(int sk, void *buf, size_t len) 511{ 512 struct mgmt_ev_connect_failed *ev = buf; 513 struct controller_info *info; 514 uint16_t index; 515 char addr[18]; 516 517 if (len < sizeof(*ev)) { 518 error("Too small connect_failed event"); 519 return; 520 } 521 522 index = btohs(bt_get_unaligned(&ev->index)); 523 ba2str(&ev->bdaddr, addr); 524 525 DBG("hci%u %s status %u", index, addr, ev->status); 526 527 if (index > max_index) { 528 error("Unexpected index %u in connect_failed event", index); 529 return; 530 } 531 532 info = &controllers[index]; 533 534 btd_event_conn_failed(&info->bdaddr, &ev->bdaddr, ev->status); 535} 536 537static int mgmt_pincode_reply(int index, bdaddr_t *bdaddr, const char *pin) 538{ 539 char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_pin_code_reply)]; 540 struct mgmt_hdr *hdr = (void *) buf; 541 size_t buf_len; 542 char addr[18]; 543 544 ba2str(bdaddr, addr); 545 DBG("index %d addr %s pin %s", index, addr, pin ? pin : "<none>"); 546 547 memset(buf, 0, sizeof(buf)); 548 549 if (pin == NULL) { 550 struct mgmt_cp_pin_code_neg_reply *cp; 551 552 hdr->opcode = htobs(MGMT_OP_PIN_CODE_NEG_REPLY); 553 hdr->len = htobs(sizeof(*cp)); 554 555 cp = (void *) &buf[sizeof(*hdr)]; 556 cp->index = htobs(index); 557 bacpy(&cp->bdaddr, bdaddr); 558 559 buf_len = sizeof(*hdr) + sizeof(*cp); 560 } else { 561 struct mgmt_cp_pin_code_reply *cp; 562 size_t pin_len; 563 564 pin_len = strlen(pin); 565 if (pin_len > 16) 566 return -EINVAL; 567 568 hdr->opcode = htobs(MGMT_OP_PIN_CODE_REPLY); 569 hdr->len = htobs(sizeof(*cp)); 570 571 cp = (void *) &buf[sizeof(*hdr)]; 572 cp->index = htobs(index); 573 bacpy(&cp->bdaddr, bdaddr); 574 cp->pin_len = pin_len; 575 memcpy(cp->pin_code, pin, pin_len); 576 577 buf_len = sizeof(*hdr) + sizeof(*cp); 578 } 579 580 if (write(mgmt_sock, buf, buf_len) < 0) 581 return -errno; 582 583 return 0; 584} 585 586static void mgmt_pin_code_request(int sk, void *buf, size_t len) 587{ 588 struct mgmt_ev_pin_code_request *ev = buf; 589 struct controller_info *info; 590 uint16_t index; 591 char addr[18]; 592 int err; 593 594 if (len < sizeof(*ev)) { 595 error("Too small pin_code_request event"); 596 return; 597 } 598 599 index = btohs(bt_get_unaligned(&ev->index)); 600 ba2str(&ev->bdaddr, addr); 601 602 DBG("hci%u %s", index, addr); 603 604 if (index > max_index) { 605 error("Unexpected index %u in pin_code_request event", index); 606 return; 607 } 608 609 info = &controllers[index]; 610 611 err = btd_event_request_pin(&info->bdaddr, &ev->bdaddr); 612 if (err < 0) { 613 error("btd_event_request_pin: %s", strerror(-err)); 614 mgmt_pincode_reply(index, &ev->bdaddr, NULL); 615 } 616} 617 618static void uuid_to_uuid128(uuid_t *uuid128, const uuid_t *uuid) 619{ 620 if (uuid->type == SDP_UUID16) 621 sdp_uuid16_to_uuid128(uuid128, uuid); 622 else if (uuid->type == SDP_UUID32) 623 sdp_uuid32_to_uuid128(uuid128, uuid); 624 else 625 memcpy(uuid128, uuid, sizeof(*uuid)); 626} 627 628static int mgmt_add_uuid(int index, uuid_t *uuid, uint8_t svc_hint) 629{ 630 char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_add_uuid)]; 631 struct mgmt_hdr *hdr = (void *) buf; 632 struct mgmt_cp_add_uuid *cp = (void *) &buf[sizeof(*hdr)]; 633 uuid_t uuid128; 634 635 DBG("index %d", index); 636 637 uuid_to_uuid128(&uuid128, uuid); 638 639 memset(buf, 0, sizeof(buf)); 640 hdr->opcode = htobs(MGMT_OP_ADD_UUID); 641 hdr->len = htobs(sizeof(*cp)); 642 643 cp->index = htobs(index); 644 memcpy(cp->uuid, uuid128.value.uuid128.data, 16); 645 cp->svc_hint = svc_hint; 646 647 if (write(mgmt_sock, buf, sizeof(buf)) < 0) 648 return -errno; 649 650 return 0; 651} 652 653static int mgmt_remove_uuid(int index, uuid_t *uuid) 654{ 655 char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_remove_uuid)]; 656 struct mgmt_hdr *hdr = (void *) buf; 657 struct mgmt_cp_remove_uuid *cp = (void *) &buf[sizeof(*hdr)]; 658 uuid_t uuid128; 659 660 DBG("index %d", index); 661 662 uuid_to_uuid128(&uuid128, uuid); 663 664 memset(buf, 0, sizeof(buf)); 665 hdr->opcode = htobs(MGMT_OP_REMOVE_UUID); 666 hdr->len = htobs(sizeof(*cp)); 667 668 cp->index = htobs(index); 669 memcpy(cp->uuid, uuid128.value.uuid128.data, 16); 670 671 if (write(mgmt_sock, buf, sizeof(buf)) < 0) 672 return -errno; 673 674 return 0; 675} 676 677static int clear_uuids(int index) 678{ 679 uuid_t uuid_any; 680 681 memset(&uuid_any, 0, sizeof(uuid_any)); 682 uuid_any.type = SDP_UUID128; 683 684 return mgmt_remove_uuid(index, &uuid_any); 685} 686 687static void read_index_list_complete(int sk, void *buf, size_t len) 688{ 689 struct mgmt_rp_read_index_list *rp = buf; 690 uint16_t num; 691 int i; 692 693 if (len < sizeof(*rp)) { 694 error("Too small read index list complete event"); 695 return; 696 } 697 698 num = btohs(bt_get_unaligned(&rp->num_controllers)); 699 700 if (num * sizeof(uint16_t) + sizeof(*rp) != len) { 701 error("Incorrect packet size for index list event"); 702 return; 703 } 704 705 for (i = 0; i < num; i++) { 706 uint16_t index; 707 708 index = btohs(bt_get_unaligned(&rp->index[i])); 709 710 add_controller(index); 711 get_connections(sk, index); 712 clear_uuids(index); 713 } 714} 715 716static int mgmt_set_powered(int index, gboolean powered) 717{ 718 DBG("index %d powered %d", index, powered); 719 return mgmt_set_mode(index, MGMT_OP_SET_POWERED, powered); 720} 721 722static void read_info_complete(int sk, void *buf, size_t len) 723{ 724 struct mgmt_rp_read_info *rp = buf; 725 struct controller_info *info; 726 struct btd_adapter *adapter; 727 uint8_t mode; 728 uint16_t index; 729 char addr[18]; 730 731 if (len < sizeof(*rp)) { 732 error("Too small read info complete event"); 733 return; 734 } 735 736 index = btohs(bt_get_unaligned(&rp->index)); 737 if (index > max_index) { 738 error("Unexpected index %u in read info complete", index); 739 return; 740 } 741 742 mgmt_set_mode(index, MGMT_OP_SET_SERVICE_CACHE, 1); 743 744 info = &controllers[index]; 745 info->type = rp->type; 746 info->enabled = rp->powered; 747 info->connectable = rp->connectable; 748 info->discoverable = rp->discoverable; 749 info->pairable = rp->pairable; 750 info->sec_mode = rp->sec_mode; 751 bacpy(&info->bdaddr, &rp->bdaddr); 752 memcpy(info->dev_class, rp->dev_class, 3); 753 memcpy(info->features, rp->features, 8); 754 info->manufacturer = btohs(bt_get_unaligned(&rp->manufacturer)); 755 info->hci_ver = rp->hci_ver; 756 info->hci_rev = btohs(bt_get_unaligned(&rp->hci_rev)); 757 758 ba2str(&info->bdaddr, addr); 759 DBG("hci%u type %u addr %s", index, info->type, addr); 760 DBG("hci%u class 0x%02x%02x%02x", index, 761 info->dev_class[2], info->dev_class[1], info->dev_class[0]); 762 DBG("hci%u manufacturer %d HCI ver %d:%d", index, info->manufacturer, 763 info->hci_ver, info->hci_rev); 764 DBG("hci%u enabled %u discoverable %u pairable %u sec_mode %u", index, 765 info->enabled, info->discoverable, 766 info->pairable, info->sec_mode); 767 768 adapter = btd_manager_register_adapter(index); 769 if (adapter == NULL) { 770 error("mgmtops: unable to register adapter"); 771 return; 772 } 773 774 btd_adapter_get_mode(adapter, &mode, NULL, NULL); 775 if (mode == MODE_OFF) { 776 mgmt_set_powered(index, FALSE); 777 return; 778 } 779 780 if (info->enabled) 781 mgmt_update_powered(index, TRUE); 782 else 783 mgmt_set_powered(index, TRUE); 784 785 btd_adapter_unref(adapter); 786} 787 788static void set_powered_complete(int sk, void *buf, size_t len) 789{ 790 struct mgmt_mode *rp = buf; 791 uint16_t index; 792 793 if (len < sizeof(*rp)) { 794 error("Too small set powered complete event"); 795 return; 796 } 797 798 index = btohs(bt_get_unaligned(&rp->index)); 799 800 DBG("hci%d powered %u", index, rp->val); 801 802 mgmt_update_powered(index, rp->val); 803} 804 805static void set_discoverable_complete(int sk, void *buf, size_t len) 806{ 807 struct mgmt_mode *rp = buf; 808 struct controller_info *info; 809 struct btd_adapter *adapter; 810 uint16_t index; 811 uint8_t mode; 812 813 if (len < sizeof(*rp)) { 814 error("Too small set discoverable complete event"); 815 return; 816 } 817 818 index = btohs(bt_get_unaligned(&rp->index)); 819 820 DBG("hci%d discoverable %u", index, rp->val); 821 822 if (index > max_index) { 823 error("Unexpected index %u in discoverable complete", index); 824 return; 825 } 826 827 info = &controllers[index]; 828 829 info->discoverable = rp->val ? TRUE : FALSE; 830 831 adapter = manager_find_adapter(&info->bdaddr); 832 if (!adapter) 833 return; 834 835 /* set_discoverable will always also change page scanning */ 836 mode = SCAN_PAGE; 837 838 if (info->discoverable) 839 mode |= SCAN_INQUIRY; 840 841 adapter_mode_changed(adapter, mode); 842} 843 844static void set_connectable_complete(int sk, void *buf, size_t len) 845{ 846 struct mgmt_mode *rp = buf; 847 struct controller_info *info; 848 struct btd_adapter *adapter; 849 uint16_t index; 850 851 if (len < sizeof(*rp)) { 852 error("Too small set connectable complete event"); 853 return; 854 } 855 856 index = btohs(bt_get_unaligned(&rp->index)); 857 858 DBG("hci%d connectable %u", index, rp->val); 859 860 if (index > max_index) { 861 error("Unexpected index %u in connectable complete", index); 862 return; 863 } 864 865 info = &controllers[index]; 866 867 info->connectable = rp->val ? TRUE : FALSE; 868 869 adapter = manager_find_adapter(&info->bdaddr); 870 if (adapter) 871 adapter_mode_changed(adapter, rp->val ? SCAN_PAGE : 0); 872} 873 874static void set_pairable_complete(int sk, void *buf, size_t len) 875{ 876 struct mgmt_mode *rp = buf; 877 struct controller_info *info; 878 struct btd_adapter *adapter; 879 uint16_t index; 880 881 if (len < sizeof(*rp)) { 882 error("Too small set pairable complete event"); 883 return; 884 } 885 886 index = btohs(bt_get_unaligned(&rp->index)); 887 888 DBG("hci%d pairable %u", index, rp->val); 889 890 if (index > max_index) { 891 error("Unexpected index %u in pairable complete", index); 892 return; 893 } 894 895 info = &controllers[index]; 896 897 info->pairable = rp->val ? TRUE : FALSE; 898 899 adapter = manager_find_adapter(&info->bdaddr); 900 if (!adapter) 901 return; 902 903 btd_adapter_pairable_changed(adapter, info->pairable); 904} 905 906static void disconnect_complete(int sk, void *buf, size_t len) 907{ 908 struct mgmt_rp_disconnect *rp = buf; 909 struct controller_info *info; 910 uint16_t index; 911 char addr[18]; 912 913 if (len < sizeof(*rp)) { 914 error("Too small disconnect complete event"); 915 return; 916 } 917 918 index = btohs(bt_get_unaligned(&rp->index)); 919 920 ba2str(&rp->bdaddr, addr); 921 922 DBG("hci%d %s disconnected", index, addr); 923 924 if (index > max_index) { 925 error("Unexpected index %u in disconnect complete", index); 926 return; 927 } 928 929 info = &controllers[index]; 930 931 btd_event_disconn_complete(&info->bdaddr, &rp->bdaddr); 932} 933 934static void get_connections_complete(int sk, void *buf, size_t len) 935{ 936 struct mgmt_rp_get_connections *rp = buf; 937 struct controller_info *info; 938 uint16_t index; 939 int i; 940 941 if (len < sizeof(*rp)) { 942 error("Too small get_connections complete event"); 943 return; 944 } 945 946 if (len < (sizeof(*rp) + (rp->conn_count * sizeof(bdaddr_t)))) { 947 error("Too small get_connections complete event"); 948 return; 949 } 950 951 index = btohs(bt_get_unaligned(&rp->index)); 952 953 if (index > max_index) { 954 error("Unexpected index %u in get_connections complete", 955 index); 956 return; 957 } 958 959 info = &controllers[index]; 960 961 for (i = 0; i < rp->conn_count; i++) { 962 bdaddr_t *bdaddr = g_memdup(&rp->conn[i], sizeof(bdaddr_t)); 963 info->connections = g_slist_append(info->connections, bdaddr); 964 } 965 966 read_info(sk, index); 967} 968 969static void mgmt_cmd_complete(int sk, void *buf, size_t len) 970{ 971 struct mgmt_ev_cmd_complete *ev = buf; 972 uint16_t opcode; 973 974 DBG(""); 975 976 if (len < sizeof(*ev)) { 977 error("Too small management command complete event packet"); 978 return; 979 } 980 981 opcode = btohs(bt_get_unaligned(&ev->opcode)); 982 983 switch (opcode) { 984 case MGMT_OP_READ_VERSION: 985 read_version_complete(sk, ev->data, len - sizeof(*ev)); 986 break; 987 case MGMT_OP_READ_INDEX_LIST: 988 read_index_list_complete(sk, ev->data, len - sizeof(*ev)); 989 break; 990 case MGMT_OP_READ_INFO: 991 read_info_complete(sk, ev->data, len - sizeof(*ev)); 992 break; 993 case MGMT_OP_SET_POWERED: 994 set_powered_complete(sk, ev->data, len - sizeof(*ev)); 995 break; 996 case MGMT_OP_SET_DISCOVERABLE: 997 set_discoverable_complete(sk, ev->data, len - sizeof(*ev)); 998 break; 999 case MGMT_OP_SET_CONNECTABLE: 1000 set_connectable_complete(sk, ev->data, len - sizeof(*ev)); 1001 break; 1002 case MGMT_OP_SET_PAIRABLE: 1003 set_pairable_complete(sk, ev->data, len - sizeof(*ev)); 1004 break; 1005 case MGMT_OP_ADD_UUID: 1006 DBG("add_uuid complete"); 1007 break; 1008 case MGMT_OP_REMOVE_UUID: 1009 DBG("remove_uuid complete"); 1010 break; 1011 case MGMT_OP_SET_DEV_CLASS: 1012 DBG("set_dev_class complete"); 1013 break; 1014 case MGMT_OP_SET_SERVICE_CACHE: 1015 DBG("set_service_cache complete"); 1016 break; 1017 case MGMT_OP_LOAD_KEYS: 1018 DBG("load_keys complete"); 1019 break; 1020 case MGMT_OP_REMOVE_KEY: 1021 DBG("remove_key complete"); 1022 break; 1023 case MGMT_OP_DISCONNECT: 1024 DBG("disconnect complete"); 1025 disconnect_complete(sk, ev->data, len - sizeof(*ev)); 1026 break; 1027 case MGMT_OP_GET_CONNECTIONS: 1028 get_connections_complete(sk, ev->data, len - sizeof(*ev)); 1029 break; 1030 case MGMT_OP_PIN_CODE_REPLY: 1031 DBG("pin_code_reply complete"); 1032 break; 1033 case MGMT_OP_PIN_CODE_NEG_REPLY: 1034 DBG("pin_code_neg_reply complete"); 1035 break; 1036 case MGMT_OP_SET_IO_CAPABILITY: 1037 DBG("set_io_capability complete"); 1038 break; 1039 default: 1040 error("Unknown command complete for opcode %u", opcode); 1041 break; 1042 } 1043} 1044 1045static void mgmt_cmd_status(int sk, void *buf, size_t len) 1046{ 1047 struct mgmt_ev_cmd_status *ev = buf; 1048 uint16_t opcode; 1049 1050 if (len < sizeof(*ev)) { 1051 error("Too small management command status event packet"); 1052 return; 1053 } 1054 1055 opcode = btohs(bt_get_unaligned(&ev->opcode)); 1056 1057 DBG("status %u opcode %u", ev->status, opcode); 1058} 1059 1060static void mgmt_controller_error(int sk, void *buf, size_t len) 1061{ 1062 struct mgmt_ev_controller_error *ev = buf; 1063 uint16_t index; 1064 1065 if (len < sizeof(*ev)) { 1066 error("Too small management controller error event packet"); 1067 return; 1068 } 1069 1070 index = btohs(bt_get_unaligned(&ev->index)); 1071 1072 DBG("index %u error_code %u", index, ev->error_code); 1073} 1074 1075static gboolean mgmt_event(GIOChannel *io, GIOCondition cond, gpointer user_data) 1076{ 1077 char buf[MGMT_BUF_SIZE]; 1078 struct mgmt_hdr *hdr = (void *) buf; 1079 int sk; 1080 ssize_t ret; 1081 uint16_t len, opcode; 1082 1083 DBG("cond %d", cond); 1084 1085 if (cond & G_IO_NVAL) 1086 return FALSE; 1087 1088 sk = g_io_channel_unix_get_fd(io); 1089 1090 if (cond & (G_IO_ERR | G_IO_HUP)) { 1091 error("Error on management socket"); 1092 return FALSE; 1093 } 1094 1095 ret = read(sk, buf, sizeof(buf)); 1096 if (ret < 0) { 1097 error("Unable to read from management socket: %s (%d)", 1098 strerror(errno), errno); 1099 return TRUE; 1100 } 1101 1102 DBG("Received %zd bytes from management socket", ret); 1103 1104 if (ret < MGMT_HDR_SIZE) { 1105 error("Too small Management packet"); 1106 return TRUE; 1107 } 1108 1109 opcode = btohs(bt_get_unaligned(&hdr->opcode)); 1110 len = btohs(bt_get_unaligned(&hdr->len)); 1111 1112 if (ret != MGMT_HDR_SIZE + len) { 1113 error("Packet length mismatch. ret %zd len %u", ret, len); 1114 return TRUE; 1115 } 1116 1117 switch (opcode) { 1118 case MGMT_EV_CMD_COMPLETE: 1119 mgmt_cmd_complete(sk, buf + MGMT_HDR_SIZE, len); 1120 break; 1121 case MGMT_EV_CMD_STATUS: 1122 mgmt_cmd_status(sk, buf + MGMT_HDR_SIZE, len); 1123 break; 1124 case MGMT_EV_CONTROLLER_ERROR: 1125 mgmt_controller_error(sk, buf + MGMT_HDR_SIZE, len); 1126 break; 1127 case MGMT_EV_INDEX_ADDED: 1128 mgmt_index_added(sk, buf + MGMT_HDR_SIZE, len); 1129 break; 1130 case MGMT_EV_INDEX_REMOVED: 1131 mgmt_index_removed(sk, buf + MGMT_HDR_SIZE, len); 1132 break; 1133 case MGMT_EV_POWERED: 1134 mgmt_powered(sk, buf + MGMT_HDR_SIZE, len); 1135 break; 1136 case MGMT_EV_DISCOVERABLE: 1137 mgmt_discoverable(sk, buf + MGMT_HDR_SIZE, len); 1138 break; 1139 case MGMT_EV_CONNECTABLE: 1140 mgmt_connectable(sk, buf + MGMT_HDR_SIZE, len); 1141 break; 1142 case MGMT_EV_PAIRABLE: 1143 mgmt_pairable(sk, buf + MGMT_HDR_SIZE, len); 1144 break; 1145 case MGMT_EV_NEW_KEY: 1146 mgmt_new_key(sk, buf + MGMT_HDR_SIZE, len); 1147 break; 1148 case MGMT_EV_DEVICE_CONNECTED: 1149 mgmt_device_connected(sk, buf + MGMT_HDR_SIZE, len); 1150 break; 1151 case MGMT_EV_DEVICE_DISCONNECTED: 1152 mgmt_device_disconnected(sk, buf + MGMT_HDR_SIZE, len); 1153 break; 1154 case MGMT_EV_CONNECT_FAILED: 1155 mgmt_connect_failed(sk, buf + MGMT_HDR_SIZE, len); 1156 break; 1157 case MGMT_EV_PIN_CODE_REQUEST: 1158 mgmt_pin_code_request(sk, buf + MGMT_HDR_SIZE, len); 1159 break; 1160 default: 1161 error("Unknown Management opcode %u", opcode); 1162 break; 1163 } 1164 1165 return TRUE; 1166} 1167 1168static int mgmt_setup(void) 1169{ 1170 struct mgmt_hdr hdr; 1171 struct sockaddr_hci addr; 1172 GIOChannel *io; 1173 GIOCondition condition; 1174 int dd, err; 1175 1176 dd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 1177 if (dd < 0) 1178 return -errno; 1179 1180 memset(&addr, 0, sizeof(addr)); 1181 addr.hci_family = AF_BLUETOOTH; 1182 addr.hci_dev = HCI_DEV_NONE; 1183 addr.hci_channel = HCI_CHANNEL_CONTROL; 1184 1185 if (bind(dd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1186 err = -errno; 1187 goto fail; 1188 } 1189 1190 memset(&hdr, 0, sizeof(hdr)); 1191 hdr.opcode = htobs(MGMT_OP_READ_VERSION); 1192 if (write(dd, &hdr, sizeof(hdr)) < 0) { 1193 err = -errno; 1194 goto fail; 1195 } 1196 1197 io = g_io_channel_unix_new(dd); 1198 condition = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL; 1199 mgmt_watch = g_io_add_watch(io, condition, mgmt_event, NULL); 1200 g_io_channel_unref(io); 1201 1202 mgmt_sock = dd; 1203 1204 info("Bluetooth Management interface initialized"); 1205 1206 return 0; 1207 1208fail: 1209 close(dd); 1210 return err; 1211} 1212 1213static void mgmt_cleanup(void) 1214{ 1215 g_free(controllers); 1216 controllers = NULL; 1217 max_index = -1; 1218 1219 if (mgmt_sock >= 0) { 1220 close(mgmt_sock); 1221 mgmt_sock = -1; 1222 } 1223 1224 if (mgmt_watch > 0) { 1225 g_source_remove(mgmt_watch); 1226 mgmt_watch = 0; 1227 } 1228} 1229 1230static int mgmt_set_dev_class(int index, uint8_t major, uint8_t minor) 1231{ 1232 char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_set_dev_class)]; 1233 struct mgmt_hdr *hdr = (void *) buf; 1234 struct mgmt_cp_set_dev_class *cp = (void *) &buf[sizeof(*hdr)]; 1235 1236 DBG("index %d major %u minor %u", index, major, minor); 1237 1238 memset(buf, 0, sizeof(buf)); 1239 hdr->opcode = htobs(MGMT_OP_SET_DEV_CLASS); 1240 hdr->len = htobs(sizeof(*cp)); 1241 1242 cp->index = htobs(index); 1243 cp->major = major; 1244 cp->minor = minor; 1245 1246 if (write(mgmt_sock, buf, sizeof(buf)) < 0) 1247 return -errno; 1248 1249 return 0; 1250} 1251 1252static int mgmt_set_limited_discoverable(int index, gboolean limited) 1253{ 1254 DBG("index %d limited %d", index, limited); 1255 return -ENOSYS; 1256} 1257 1258static int mgmt_start_inquiry(int index, uint8_t length, gboolean periodic) 1259{ 1260 DBG("index %d length %u periodic %d", index, length, periodic); 1261 return -ENOSYS; 1262} 1263 1264static int mgmt_stop_inquiry(int index) 1265{ 1266 DBG("index %d", index); 1267 return -ENOSYS; 1268} 1269 1270static int mgmt_start_scanning(int index) 1271{ 1272 DBG("index %d", index); 1273 return -ENOSYS; 1274} 1275 1276static int mgmt_stop_scanning(int index) 1277{ 1278 DBG("index %d", index); 1279 return -ENOSYS; 1280} 1281 1282static int mgmt_resolve_name(int index, bdaddr_t *bdaddr) 1283{ 1284 char addr[18]; 1285 1286 ba2str(bdaddr, addr); 1287 DBG("index %d addr %s", index, addr); 1288 1289 return -ENOSYS; 1290} 1291 1292static int mgmt_set_name(int index, const char *name) 1293{ 1294 DBG("index %d, name %s", index, name); 1295 return -ENOSYS; 1296} 1297 1298static int mgmt_cancel_resolve_name(int index, bdaddr_t *bdaddr) 1299{ 1300 char addr[18]; 1301 1302 ba2str(bdaddr, addr); 1303 DBG("index %d addr %s", index, addr); 1304 1305 return -ENOSYS; 1306} 1307 1308static int mgmt_fast_connectable(int index, gboolean enable) 1309{ 1310 DBG("index %d enable %d", index, enable); 1311 return -ENOSYS; 1312} 1313 1314static int mgmt_read_clock(int index, bdaddr_t *bdaddr, int which, int timeout, 1315 uint32_t *clock, uint16_t *accuracy) 1316{ 1317 char addr[18]; 1318 1319 ba2str(bdaddr, addr); 1320 DBG("index %d addr %s which %d timeout %d", index, addr, which, 1321 timeout); 1322 1323 return -ENOSYS; 1324} 1325 1326static int mgmt_read_bdaddr(int index, bdaddr_t *bdaddr) 1327{ 1328 char addr[18]; 1329 struct controller_info *info = &controllers[index]; 1330 1331 ba2str(&info->bdaddr, addr); 1332 DBG("index %d addr %s", index, addr); 1333 1334 if (!info->valid) 1335 return -ENODEV; 1336 1337 bacpy(bdaddr, &info->bdaddr); 1338 1339 return 0; 1340} 1341 1342static int mgmt_block_device(int index, bdaddr_t *bdaddr) 1343{ 1344 char addr[18]; 1345 1346 ba2str(bdaddr, addr); 1347 DBG("index %d addr %s", index, addr); 1348 1349 return -ENOSYS; 1350} 1351 1352static int mgmt_unblock_device(int index, bdaddr_t *bdaddr) 1353{ 1354 char addr[18]; 1355 1356 ba2str(bdaddr, addr); 1357 DBG("index %d addr %s", index, addr); 1358 1359 return -ENOSYS; 1360} 1361 1362static int mgmt_get_conn_list(int index, GSList **conns) 1363{ 1364 struct controller_info *info = &controllers[index]; 1365 1366 DBG("index %d", index); 1367 1368 *conns = info->connections; 1369 info->connections = NULL; 1370 1371 return 0; 1372} 1373 1374static int mgmt_read_local_version(int index, struct hci_version *ver) 1375{ 1376 struct controller_info *info = &controllers[index]; 1377 1378 DBG("index %d", index); 1379 1380 if (!info->valid) 1381 return -ENODEV; 1382 1383 memset(ver, 0, sizeof(*ver)); 1384 ver->manufacturer = info->manufacturer; 1385 ver->hci_ver = info->hci_ver; 1386 ver->hci_rev = info->hci_rev; 1387 1388 return 0; 1389} 1390 1391static int mgmt_read_local_features(int index, uint8_t *features) 1392{ 1393 struct controller_info *info = &controllers[index]; 1394 1395 DBG("index %d", index); 1396 1397 if (!info->valid) 1398 return -ENODEV; 1399 1400 memcpy(features, info->features, 8); 1401 1402 return 0; 1403} 1404 1405static int mgmt_disconnect(int index, bdaddr_t *bdaddr) 1406{ 1407 char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_disconnect)]; 1408 struct mgmt_hdr *hdr = (void *) buf; 1409 struct mgmt_cp_disconnect *cp = (void *) &buf[sizeof(*hdr)]; 1410 char addr[18]; 1411 1412 ba2str(bdaddr, addr); 1413 DBG("index %d %s", index, addr); 1414 1415 memset(buf, 0, sizeof(buf)); 1416 hdr->opcode = htobs(MGMT_OP_DISCONNECT); 1417 hdr->len = htobs(sizeof(*cp)); 1418 1419 cp->index = htobs(index); 1420 bacpy(&cp->bdaddr, bdaddr); 1421 1422 if (write(mgmt_sock, buf, sizeof(buf)) < 0) 1423 error("write: %s (%d)", strerror(errno), errno); 1424 1425 return 0; 1426} 1427 1428static int mgmt_remove_bonding(int index, bdaddr_t *bdaddr) 1429{ 1430 char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_remove_key)]; 1431 struct mgmt_hdr *hdr = (void *) buf; 1432 struct mgmt_cp_remove_key *cp = (void *) &buf[sizeof(*hdr)]; 1433 char addr[18]; 1434 1435 ba2str(bdaddr, addr); 1436 DBG("index %d addr %s", index, addr); 1437 1438 memset(buf, 0, sizeof(buf)); 1439 hdr->opcode = htobs(MGMT_OP_REMOVE_KEY); 1440 hdr->len = htobs(sizeof(*cp)); 1441 1442 cp->index = htobs(index); 1443 bacpy(&cp->bdaddr, bdaddr); 1444 cp->disconnect = 1; 1445 1446 if (write(mgmt_sock, buf, sizeof(buf)) < 0) 1447 return -errno; 1448 1449 return 0; 1450} 1451 1452static int mgmt_request_authentication(int index, bdaddr_t *bdaddr) 1453{ 1454 char addr[18]; 1455 1456 ba2str(bdaddr, addr); 1457 DBG("index %d %s", index, addr); 1458 1459 return -ENOSYS; 1460} 1461 1462static int mgmt_confirm_reply(int index, bdaddr_t *bdaddr, gboolean success) 1463{ 1464 char addr[18]; 1465 1466 ba2str(bdaddr, addr); 1467 DBG("index %d addr %s success %d", index, addr, success); 1468 1469 return -ENOSYS; 1470} 1471 1472static int mgmt_passkey_reply(int index, bdaddr_t *bdaddr, uint32_t passkey) 1473{ 1474 char addr[18]; 1475 1476 ba2str(bdaddr, addr); 1477 DBG("index %d addr %s passkey %06u", index, addr, passkey); 1478 1479 return -ENOSYS; 1480} 1481 1482static int mgmt_read_scan_enable(int index) 1483{ 1484 DBG("index %d", index); 1485 return -ENOSYS; 1486} 1487 1488static int mgmt_enable_le(int index) 1489{ 1490 DBG("index %d", index); 1491 return -ENOSYS; 1492} 1493 1494static int mgmt_encrypt_link(int index, bdaddr_t *dst, bt_hci_result_t cb, 1495 gpointer user_data) 1496{ 1497 char addr[18]; 1498 1499 ba2str(dst, addr); 1500 DBG("index %d addr %s", index, addr); 1501 1502 return -ENOSYS; 1503} 1504 1505static int mgmt_set_did(int index, uint16_t vendor, uint16_t product, 1506 uint16_t version) 1507{ 1508 DBG("index %d vendor %u product %u version %u", 1509 index, vendor, product, version); 1510 return -ENOSYS; 1511} 1512 1513static int mgmt_disable_cod_cache(int index) 1514{ 1515 DBG("index %d", index); 1516 return mgmt_set_mode(index, MGMT_OP_SET_SERVICE_CACHE, 0); 1517} 1518 1519static int mgmt_restore_powered(int index) 1520{ 1521 DBG("index %d", index); 1522 return -ENOSYS; 1523} 1524 1525static int mgmt_load_keys(int index, GSList *keys, gboolean debug_keys) 1526{ 1527 char *buf; 1528 struct mgmt_hdr *hdr; 1529 struct mgmt_cp_load_keys *cp; 1530 struct mgmt_key_info *key; 1531 size_t key_count, cp_size; 1532 GSList *l; 1533 int err; 1534 1535 key_count = g_slist_length(keys); 1536 1537 DBG("index %d keys %zu debug_keys %d", index, key_count, debug_keys); 1538 1539 cp_size = sizeof(*cp) + (key_count * sizeof(*key)); 1540 1541 buf = g_try_malloc0(sizeof(*hdr) + cp_size); 1542 if (buf == NULL) 1543 return -ENOMEM; 1544 1545 memset(buf, 0, sizeof(buf)); 1546 1547 hdr = (void *) buf; 1548 hdr->opcode = htobs(MGMT_OP_LOAD_KEYS); 1549 hdr->len = htobs(cp_size); 1550 1551 cp = (void *) (buf + sizeof(*hdr)); 1552 cp->index = htobs(index); 1553 cp->debug_keys = debug_keys; 1554 cp->key_count = htobs(key_count); 1555 1556 for (l = keys, key = cp->keys; l != NULL; l = g_slist_next(l), key++) { 1557 struct link_key_info *info = l->data; 1558 1559 bacpy(&key->bdaddr, &info->bdaddr); 1560 key->type = info->type; 1561 memcpy(key->val, info->key, 16); 1562 key->pin_len = info->pin_len; 1563 } 1564 1565 if (write(mgmt_sock, buf, sizeof(*hdr) + cp_size) < 0) 1566 err = -errno; 1567 else 1568 err = 0; 1569 1570 g_free(buf); 1571 1572 return err; 1573} 1574 1575static int mgmt_set_io_capability(int index, uint8_t io_capability) 1576{ 1577 char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_set_io_capability)]; 1578 struct mgmt_hdr *hdr = (void *) buf; 1579 struct mgmt_cp_set_io_capability *cp = (void *) &buf[sizeof(*hdr)]; 1580 1581 DBG("hci%d io_capability 0x%02x", index, io_capability); 1582 1583 memset(buf, 0, sizeof(buf)); 1584 hdr->opcode = htobs(MGMT_OP_SET_IO_CAPABILITY); 1585 hdr->len = htobs(sizeof(*cp)); 1586 1587 cp->index = htobs(index); 1588 cp->io_capability = io_capability; 1589 1590 if (write(mgmt_sock, buf, sizeof(buf)) < 0) 1591 return -errno; 1592 1593 return 0; 1594} 1595 1596static int mgmt_create_bonding(int index, bdaddr_t *bdaddr, uint8_t io_cap) 1597{ 1598 char addr[18]; 1599 1600 ba2str(bdaddr, addr); 1601 DBG("hci%d bdaddr %s io_cap 0x%02x", index, addr, io_cap); 1602 1603 return -ENOSYS; 1604} 1605 1606static int mgmt_cancel_bonding(int index, bdaddr_t *bdaddr) 1607{ 1608 char addr[18]; 1609 1610 ba2str(bdaddr, addr); 1611 DBG("hci%d bdaddr %s", index, addr); 1612 1613 return -ENOSYS; 1614} 1615 1616static struct btd_adapter_ops mgmt_ops = { 1617 .setup = mgmt_setup, 1618 .cleanup = mgmt_cleanup, 1619 .set_powered = mgmt_set_powered, 1620 .set_discoverable = mgmt_set_discoverable, 1621 .set_pairable = mgmt_set_pairable, 1622 .set_limited_discoverable = mgmt_set_limited_discoverable, 1623 .start_inquiry = mgmt_start_inquiry, 1624 .stop_inquiry = mgmt_stop_inquiry, 1625 .start_scanning = mgmt_start_scanning, 1626 .stop_scanning = mgmt_stop_scanning, 1627 .resolve_name = mgmt_resolve_name, 1628 .cancel_resolve_name = mgmt_cancel_resolve_name, 1629 .set_name = mgmt_set_name, 1630 .set_dev_class = mgmt_set_dev_class, 1631 .set_fast_connectable = mgmt_fast_connectable, 1632 .read_clock = mgmt_read_clock, 1633 .read_bdaddr = mgmt_read_bdaddr, 1634 .block_device = mgmt_block_device, 1635 .unblock_device = mgmt_unblock_device, 1636 .get_conn_list = mgmt_get_conn_list, 1637 .read_local_version = mgmt_read_local_version, 1638 .read_local_features = mgmt_read_local_features, 1639 .disconnect = mgmt_disconnect, 1640 .remove_bonding = mgmt_remove_bonding, 1641 .request_authentication = mgmt_request_authentication, 1642 .pincode_reply = mgmt_pincode_reply, 1643 .confirm_reply = mgmt_confirm_reply, 1644 .passkey_reply = mgmt_passkey_reply, 1645 .read_scan_enable = mgmt_read_scan_enable, 1646 .enable_le = mgmt_enable_le, 1647 .encrypt_link = mgmt_encrypt_link, 1648 .set_did = mgmt_set_did, 1649 .add_uuid = mgmt_add_uuid, 1650 .remove_uuid = mgmt_remove_uuid, 1651 .disable_cod_cache = mgmt_disable_cod_cache, 1652 .restore_powered = mgmt_restore_powered, 1653 .load_keys = mgmt_load_keys, 1654 .set_io_capability = mgmt_set_io_capability, 1655 .create_bonding = mgmt_create_bonding, 1656 .cancel_bonding = mgmt_cancel_bonding, 1657}; 1658 1659static int mgmt_init(void) 1660{ 1661 return btd_register_adapter_ops(&mgmt_ops, TRUE); 1662} 1663 1664static void mgmt_exit(void) 1665{ 1666 btd_adapter_cleanup_ops(&mgmt_ops); 1667} 1668 1669BLUETOOTH_PLUGIN_DEFINE(mgmtops, VERSION, 1670 BLUETOOTH_PLUGIN_PRIORITY_LOW, mgmt_init, mgmt_exit) 1671