hciops.c revision b5c556ef59a9a8318b239453c3d4a8aad951689f
1/* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 * 21 */ 22 23#ifdef HAVE_CONFIG_H 24#include <config.h> 25#endif 26 27#include <stdio.h> 28#include <errno.h> 29#include <unistd.h> 30#include <stdlib.h> 31#include <sys/types.h> 32#include <sys/ioctl.h> 33#include <sys/wait.h> 34 35#include <bluetooth/bluetooth.h> 36#include <bluetooth/hci.h> 37#include <bluetooth/hci_lib.h> 38 39#include <glib.h> 40 41#include "hcid.h" 42#include "sdpd.h" 43#include "adapter.h" 44#include "plugin.h" 45#include "log.h" 46#include "manager.h" 47 48static int child_pipe[2] = { -1, -1 }; 49 50static guint child_io_id = 0; 51static guint ctl_io_id = 0; 52 53static gboolean child_exit(GIOChannel *io, GIOCondition cond, void *user_data) 54{ 55 int status, fd = g_io_channel_unix_get_fd(io); 56 pid_t child_pid; 57 58 if (read(fd, &child_pid, sizeof(child_pid)) != sizeof(child_pid)) { 59 error("child_exit: unable to read child pid from pipe"); 60 return TRUE; 61 } 62 63 if (waitpid(child_pid, &status, 0) != child_pid) 64 error("waitpid(%d) failed", child_pid); 65 else 66 DBG("child %d exited", child_pid); 67 68 return TRUE; 69} 70 71static void at_child_exit(void) 72{ 73 pid_t pid = getpid(); 74 75 if (write(child_pipe[1], &pid, sizeof(pid)) != sizeof(pid)) 76 error("unable to write to child pipe"); 77} 78 79static void device_devup_setup(int index) 80{ 81 struct hci_dev_info di; 82 uint16_t policy; 83 int dd; 84 85 if (hci_devinfo(index, &di) < 0) 86 return; 87 88 if (ignore_device(&di)) 89 return; 90 91 dd = hci_open_dev(index); 92 if (dd < 0) { 93 error("Can't open device hci%d: %s (%d)", index, 94 strerror(errno), errno); 95 return; 96 } 97 98 /* Set page timeout */ 99 if ((main_opts.flags & (1 << HCID_SET_PAGETO))) { 100 write_page_timeout_cp cp; 101 102 cp.timeout = htobs(main_opts.pageto); 103 hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_PAGE_TIMEOUT, 104 WRITE_PAGE_TIMEOUT_CP_SIZE, &cp); 105 } 106 107 /* Set default link policy */ 108 policy = htobs(main_opts.link_policy); 109 hci_send_cmd(dd, OGF_LINK_POLICY, OCF_WRITE_DEFAULT_LINK_POLICY, 110 2, &policy); 111 112 hci_close_dev(dd); 113 114 start_security_manager(index); 115 116 /* Return value 1 means ioctl(DEVDOWN) was performed */ 117 if (manager_start_adapter(index) == 1) 118 stop_security_manager(index); 119} 120 121static void init_device(int index) 122{ 123 struct hci_dev_req dr; 124 struct hci_dev_info di; 125 pid_t pid; 126 int dd; 127 128 /* Do initialization in the separate process */ 129 pid = fork(); 130 switch (pid) { 131 case 0: 132 atexit(at_child_exit); 133 break; 134 case -1: 135 error("Fork failed. Can't init device hci%d: %s (%d)", 136 index, strerror(errno), errno); 137 default: 138 DBG("child %d forked", pid); 139 return; 140 } 141 142 dd = hci_open_dev(index); 143 if (dd < 0) { 144 error("Can't open device hci%d: %s (%d)", 145 index, strerror(errno), errno); 146 exit(1); 147 } 148 149 memset(&dr, 0, sizeof(dr)); 150 dr.dev_id = index; 151 152 /* Set link mode */ 153 dr.dev_opt = main_opts.link_mode; 154 if (ioctl(dd, HCISETLINKMODE, (unsigned long) &dr) < 0) 155 error("Can't set link mode on hci%d: %s (%d)", 156 index, strerror(errno), errno); 157 158 /* Set link policy for BR/EDR HCI devices */ 159 if (hci_devinfo(index, &di) < 0) 160 goto fail; 161 162 if (!ignore_device(&di)) { 163 dr.dev_opt = main_opts.link_policy; 164 if (ioctl(dd, HCISETLINKPOL, (unsigned long) &dr) < 0 && 165 errno != ENETDOWN) { 166 error("Can't set link policy on hci%d: %s (%d)", 167 index, strerror(errno), errno); 168 } 169 } 170 171 /* Start HCI device */ 172 if (ioctl(dd, HCIDEVUP, index) < 0 && errno != EALREADY) { 173 error("Can't init device hci%d: %s (%d)", 174 index, strerror(errno), errno); 175 goto fail; 176 } 177 178 hci_close_dev(dd); 179 exit(0); 180 181fail: 182 hci_close_dev(dd); 183 exit(1); 184} 185 186static void device_devreg_setup(int index) 187{ 188 struct hci_dev_info di; 189 gboolean devup; 190 191 init_device(index); 192 193 memset(&di, 0, sizeof(di)); 194 195 if (hci_devinfo(index, &di) < 0) 196 return; 197 198 devup = hci_test_bit(HCI_UP, &di.flags); 199 200 if (!ignore_device(&di)) 201 manager_register_adapter(index, devup); 202} 203 204static void device_event(int event, int index) 205{ 206 switch (event) { 207 case HCI_DEV_REG: 208 info("HCI dev %d registered", index); 209 device_devreg_setup(index); 210 break; 211 212 case HCI_DEV_UNREG: 213 info("HCI dev %d unregistered", index); 214 manager_unregister_adapter(index); 215 break; 216 217 case HCI_DEV_UP: 218 info("HCI dev %d up", index); 219 device_devup_setup(index); 220 break; 221 222 case HCI_DEV_DOWN: 223 info("HCI dev %d down", index); 224 manager_stop_adapter(index); 225 stop_security_manager(index); 226 break; 227 } 228} 229 230static int init_known_adapters(int ctl) 231{ 232 struct hci_dev_list_req *dl; 233 struct hci_dev_req *dr; 234 int i, err; 235 size_t req_size; 236 237 req_size = HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t); 238 239 dl = g_try_malloc0(req_size); 240 if (!dl) { 241 error("Can't allocate devlist buffer"); 242 return -ENOMEM; 243 } 244 245 dl->dev_num = HCI_MAX_DEV; 246 dr = dl->dev_req; 247 248 if (ioctl(ctl, HCIGETDEVLIST, dl) < 0) { 249 err = -errno; 250 error("Can't get device list: %s (%d)", strerror(-err), -err); 251 g_free(dl); 252 return err; 253 } 254 255 for (i = 0; i < dl->dev_num; i++, dr++) { 256 device_event(HCI_DEV_REG, dr->dev_id); 257 258 if (hci_test_bit(HCI_UP, &dr->dev_opt)) 259 device_event(HCI_DEV_UP, dr->dev_id); 260 } 261 262 g_free(dl); 263 return 0; 264} 265 266static gboolean io_stack_event(GIOChannel *chan, GIOCondition cond, 267 gpointer data) 268{ 269 unsigned char buf[HCI_MAX_FRAME_SIZE], *ptr; 270 evt_stack_internal *si; 271 evt_si_device *sd; 272 hci_event_hdr *eh; 273 int type; 274 size_t len; 275 GIOError err; 276 277 ptr = buf; 278 279 err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len); 280 if (err) { 281 if (err == G_IO_ERROR_AGAIN) 282 return TRUE; 283 284 error("Read from control socket failed: %s (%d)", 285 strerror(errno), errno); 286 return FALSE; 287 } 288 289 type = *ptr++; 290 291 if (type != HCI_EVENT_PKT) 292 return TRUE; 293 294 eh = (hci_event_hdr *) ptr; 295 if (eh->evt != EVT_STACK_INTERNAL) 296 return TRUE; 297 298 ptr += HCI_EVENT_HDR_SIZE; 299 300 si = (evt_stack_internal *) ptr; 301 switch (si->type) { 302 case EVT_SI_DEVICE: 303 sd = (void *) &si->data; 304 device_event(sd->event, sd->dev_id); 305 break; 306 } 307 308 return TRUE; 309} 310 311static int hciops_setup(void) 312{ 313 struct sockaddr_hci addr; 314 struct hci_filter flt; 315 GIOChannel *ctl_io, *child_io; 316 int sock, err; 317 318 if (child_pipe[0] != -1) 319 return -EALREADY; 320 321 if (pipe(child_pipe) < 0) { 322 err = -errno; 323 error("pipe(): %s (%d)", strerror(-err), -err); 324 return err; 325 } 326 327 child_io = g_io_channel_unix_new(child_pipe[0]); 328 g_io_channel_set_close_on_unref(child_io, TRUE); 329 child_io_id = g_io_add_watch(child_io, 330 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, 331 child_exit, NULL); 332 g_io_channel_unref(child_io); 333 334 /* Create and bind HCI socket */ 335 sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 336 if (sock < 0) { 337 err = -errno; 338 error("Can't open HCI socket: %s (%d)", strerror(-err), 339 -err); 340 return err; 341 } 342 343 /* Set filter */ 344 hci_filter_clear(&flt); 345 hci_filter_set_ptype(HCI_EVENT_PKT, &flt); 346 hci_filter_set_event(EVT_STACK_INTERNAL, &flt); 347 if (setsockopt(sock, SOL_HCI, HCI_FILTER, &flt, 348 sizeof(flt)) < 0) { 349 err = -errno; 350 error("Can't set filter: %s (%d)", strerror(-err), -err); 351 return err; 352 } 353 354 memset(&addr, 0, sizeof(addr)); 355 addr.hci_family = AF_BLUETOOTH; 356 addr.hci_dev = HCI_DEV_NONE; 357 if (bind(sock, (struct sockaddr *) &addr, 358 sizeof(addr)) < 0) { 359 err = -errno; 360 error("Can't bind HCI socket: %s (%d)", 361 strerror(-err), -err); 362 return err; 363 } 364 365 ctl_io = g_io_channel_unix_new(sock); 366 g_io_channel_set_close_on_unref(ctl_io, TRUE); 367 368 ctl_io_id = g_io_add_watch(ctl_io, G_IO_IN, io_stack_event, NULL); 369 370 g_io_channel_unref(ctl_io); 371 372 /* Initialize already connected devices */ 373 return init_known_adapters(sock); 374} 375 376static void hciops_cleanup(void) 377{ 378 if (child_io_id) { 379 g_source_remove(child_io_id); 380 child_io_id = 0; 381 } 382 383 if (ctl_io_id) { 384 g_source_remove(ctl_io_id); 385 ctl_io_id = 0; 386 } 387 388 if (child_pipe[0] >= 0) { 389 close(child_pipe[0]); 390 child_pipe[0] = -1; 391 } 392 393 if (child_pipe[1] >= 0) { 394 close(child_pipe[1]); 395 child_pipe[1] = -1; 396 } 397} 398 399static int hciops_start(int index) 400{ 401 int dd; 402 int err = 0; 403 404 dd = hci_open_dev(index); 405 if (dd < 0) 406 return -EIO; 407 408 if (ioctl(dd, HCIDEVUP, index) == 0) 409 goto done; /* on success */ 410 411 if (errno != EALREADY) { 412 err = -errno; 413 error("Can't init device hci%d: %s (%d)", 414 index, strerror(-err), -err); 415 } 416 417done: 418 hci_close_dev(dd); 419 return err; 420} 421 422static int hciops_stop(int index) 423{ 424 int dd; 425 int err = 0; 426 427 dd = hci_open_dev(index); 428 if (dd < 0) 429 return -EIO; 430 431 if (ioctl(dd, HCIDEVDOWN, index) == 0) 432 goto done; /* on success */ 433 434 if (errno != EALREADY) { 435 err = -errno; 436 error("Can't stop device hci%d: %s (%d)", 437 index, strerror(-err), -err); 438 } 439 440done: 441 hci_close_dev(dd); 442 return err; 443} 444 445static int hciops_powered(int index, gboolean powered) 446{ 447 int dd, err; 448 uint8_t mode = SCAN_DISABLED; 449 450 if (powered) 451 return hciops_start(index); 452 453 dd = hci_open_dev(index); 454 if (dd < 0) 455 return -EIO; 456 457 err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 458 1, &mode); 459 if (err < 0) { 460 err = -errno; 461 hci_close_dev(dd); 462 return err; 463 } 464 465 hci_close_dev(dd); 466 467 return hciops_stop(index); 468} 469 470static int hciops_connectable(int index) 471{ 472 int dd, err; 473 uint8_t mode = SCAN_PAGE; 474 475 dd = hci_open_dev(index); 476 if (dd < 0) 477 return -EIO; 478 479 err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 480 1, &mode); 481 if (err < 0) 482 err = -errno; 483 484 hci_close_dev(dd); 485 486 return err; 487} 488 489static int hciops_discoverable(int index) 490{ 491 int dd, err; 492 uint8_t mode = (SCAN_PAGE | SCAN_INQUIRY); 493 494 dd = hci_open_dev(index); 495 if (dd < 0) 496 return -EIO; 497 498 err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 499 1, &mode); 500 if (err < 0) 501 err = -errno; 502 503 hci_close_dev(dd); 504 505 return err; 506} 507 508static int hciops_set_class(int index, uint32_t class) 509{ 510 int dd, err; 511 write_class_of_dev_cp cp; 512 513 dd = hci_open_dev(index); 514 if (dd < 0) 515 return -EIO; 516 517 memcpy(cp.dev_class, &class, 3); 518 519 err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV, 520 WRITE_CLASS_OF_DEV_CP_SIZE, &cp); 521 522 if (err < 0) 523 err = -errno; 524 525 hci_close_dev(dd); 526 527 return err; 528} 529 530static int hciops_set_limited_discoverable(int index, uint32_t class, 531 gboolean limited) 532{ 533 int dd, err; 534 int num = (limited ? 2 : 1); 535 uint8_t lap[] = { 0x33, 0x8b, 0x9e, 0x00, 0x8b, 0x9e }; 536 write_current_iac_lap_cp cp; 537 538 /* 539 * 1: giac 540 * 2: giac + liac 541 */ 542 dd = hci_open_dev(index); 543 if (dd < 0) 544 return -EIO; 545 546 memset(&cp, 0, sizeof(cp)); 547 cp.num_current_iac = num; 548 memcpy(&cp.lap, lap, num * 3); 549 550 err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_CURRENT_IAC_LAP, 551 (num * 3 + 1), &cp); 552 if (err < 0) { 553 err = -errno; 554 goto fail; 555 } 556 557 err = hciops_set_class(index, class); 558 559fail: 560 hci_close_dev(dd); 561 return err; 562} 563 564static int hciops_start_discovery(int index, gboolean periodic) 565{ 566 uint8_t lap[3] = { 0x33, 0x8b, 0x9e }; 567 int dd, err; 568 569 dd = hci_open_dev(index); 570 if (dd < 0) 571 return -EIO; 572 573 if (periodic) { 574 periodic_inquiry_cp cp; 575 576 memset(&cp, 0, sizeof(cp)); 577 memcpy(&cp.lap, lap, 3); 578 cp.max_period = htobs(24); 579 cp.min_period = htobs(16); 580 cp.length = 0x08; 581 cp.num_rsp = 0x00; 582 583 err = hci_send_cmd(dd, OGF_LINK_CTL, OCF_PERIODIC_INQUIRY, 584 PERIODIC_INQUIRY_CP_SIZE, &cp); 585 } else { 586 inquiry_cp inq_cp; 587 588 memset(&inq_cp, 0, sizeof(inq_cp)); 589 memcpy(&inq_cp.lap, lap, 3); 590 inq_cp.length = 0x08; 591 inq_cp.num_rsp = 0x00; 592 593 err = hci_send_cmd(dd, OGF_LINK_CTL, OCF_INQUIRY, 594 INQUIRY_CP_SIZE, &inq_cp); 595 } 596 597 if (err < 0) 598 err = -errno; 599 600 hci_close_dev(dd); 601 602 return err; 603} 604 605static int hciops_stop_discovery(int index) 606{ 607 struct hci_dev_info di; 608 int dd, err; 609 610 if (hci_devinfo(index, &di) < 0) 611 return -errno; 612 613 dd = hci_open_dev(index); 614 if (dd < 0) 615 return -EIO; 616 617 if (hci_test_bit(HCI_INQUIRY, &di.flags)) 618 err = hci_send_cmd(dd, OGF_LINK_CTL, OCF_INQUIRY_CANCEL, 0, 0); 619 else 620 err = hci_send_cmd(dd, OGF_LINK_CTL, OCF_EXIT_PERIODIC_INQUIRY, 621 0, 0); 622 if (err < 0) 623 err = -errno; 624 625 hci_close_dev(dd); 626 627 return err; 628} 629 630static int hciops_resolve_name(int index, bdaddr_t *bdaddr) 631{ 632 remote_name_req_cp cp; 633 int dd, err; 634 635 dd = hci_open_dev(index); 636 if (dd < 0) 637 return -EIO; 638 639 memset(&cp, 0, sizeof(cp)); 640 bacpy(&cp.bdaddr, bdaddr); 641 cp.pscan_rep_mode = 0x02; 642 643 err = hci_send_cmd(dd, OGF_LINK_CTL, OCF_REMOTE_NAME_REQ, 644 REMOTE_NAME_REQ_CP_SIZE, &cp); 645 if (err < 0) 646 err = -errno; 647 648 hci_close_dev(dd); 649 650 return err; 651} 652 653static int hciops_set_name(int index, const char *name) 654{ 655 change_local_name_cp cp; 656 int dd, err; 657 658 dd = hci_open_dev(index); 659 if (dd < 0) 660 return -EIO; 661 662 memset(&cp, 0, sizeof(cp)); 663 strncpy((char *) cp.name, name, sizeof(cp.name)); 664 665 err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME, 666 CHANGE_LOCAL_NAME_CP_SIZE, &cp); 667 if (err < 0) 668 err = -errno; 669 670 hci_close_dev(dd); 671 672 return err; 673} 674 675static int hciops_read_name(int index) 676{ 677 int dd, err; 678 679 dd = hci_open_dev(index); 680 if (dd < 0) 681 return -EIO; 682 683 err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_READ_LOCAL_NAME, 0, 0); 684 if (err < 0) 685 err = -errno; 686 687 hci_close_dev(dd); 688 689 return err; 690} 691 692static int hciops_cancel_resolve_name(int index, bdaddr_t *bdaddr) 693{ 694 remote_name_req_cancel_cp cp; 695 int dd, err; 696 697 dd = hci_open_dev(index); 698 if (dd < 0) 699 return -EIO; 700 701 memset(&cp, 0, sizeof(cp)); 702 bacpy(&cp.bdaddr, bdaddr); 703 704 err = hci_send_cmd(dd, OGF_LINK_CTL, OCF_REMOTE_NAME_REQ_CANCEL, 705 REMOTE_NAME_REQ_CANCEL_CP_SIZE, &cp); 706 if (err < 0) 707 err = -errno; 708 709 hci_close_dev(dd); 710 711 return err; 712} 713 714static int hciops_fast_connectable(int index, gboolean enable) 715{ 716 int dd, err = 0; 717 write_page_activity_cp cp; 718 uint8_t type; 719 720 if (enable) { 721 type = PAGE_SCAN_TYPE_INTERLACED; 722 cp.interval = 0x0024; /* 22.5 msec page scan interval */ 723 } else { 724 type = PAGE_SCAN_TYPE_STANDARD; /* default */ 725 cp.interval = 0x0800; /* default 1.28 sec page scan */ 726 } 727 728 cp.window = 0x0012; /* default 11.25 msec page scan window */ 729 730 dd = hci_open_dev(index); 731 if (dd < 0) 732 return -EIO; 733 734 if (hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_PAGE_ACTIVITY, 735 WRITE_PAGE_ACTIVITY_CP_SIZE, &cp) < 0) 736 err = -errno; 737 else if (hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_PAGE_SCAN_TYPE, 738 1, &type) < 0) 739 err = -errno; 740 741 hci_close_dev(dd); 742 743 return err; 744} 745 746static int hciops_read_clock(int index, int handle, int which, int timeout, 747 uint32_t *clock, uint16_t *accuracy) 748{ 749 int dd, err = 0; 750 751 dd = hci_open_dev(index); 752 if (dd < 0) 753 return -EIO; 754 755 if (hci_read_clock(dd, handle, which, clock, accuracy, timeout) < 0) 756 err = -errno; 757 758 hci_close_dev(dd); 759 760 return err; 761} 762 763static int hciops_conn_handle(int index, const bdaddr_t *bdaddr, int *handle) 764{ 765 struct hci_conn_info_req *cr; 766 int dd, err = 0; 767 768 dd = hci_open_dev(index); 769 if (dd < 0) 770 return -EIO; 771 772 cr = g_malloc0(sizeof(*cr) + sizeof(struct hci_conn_info)); 773 bacpy(&cr->bdaddr, bdaddr); 774 cr->type = ACL_LINK; 775 776 if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { 777 err = -errno; 778 goto fail; 779 } 780 781 *handle = htobs(cr->conn_info->handle); 782 783fail: 784 hci_close_dev(dd); 785 g_free(cr); 786 return err; 787} 788 789static int hciops_write_eir_data(int index, uint8_t *data) 790{ 791 uint8_t fec = 0; 792 int ret, dd; 793 794 dd = hci_open_dev(index); 795 if (dd < 0) 796 return -errno; 797 798 if (hci_write_ext_inquiry_response(dd, fec, data, HCI_REQ_TIMEOUT) < 0) 799 ret = -errno; 800 else 801 ret = 0; 802 803 hci_close_dev(dd); 804 805 return ret; 806} 807 808static int hciops_read_bdaddr(int index, bdaddr_t *bdaddr) 809{ 810 int dd, err; 811 812 dd = hci_open_dev(index); 813 if (dd < 0) 814 return -errno; 815 816 if (hci_read_bd_addr(dd, bdaddr, HCI_REQ_TIMEOUT) < 0) 817 err = -errno; 818 else 819 err = 0; 820 821 hci_close_dev(dd); 822 823 return err; 824} 825 826static struct btd_adapter_ops hci_ops = { 827 .setup = hciops_setup, 828 .cleanup = hciops_cleanup, 829 .start = hciops_start, 830 .stop = hciops_stop, 831 .set_powered = hciops_powered, 832 .set_connectable = hciops_connectable, 833 .set_discoverable = hciops_discoverable, 834 .set_limited_discoverable = hciops_set_limited_discoverable, 835 .start_discovery = hciops_start_discovery, 836 .stop_discovery = hciops_stop_discovery, 837 .resolve_name = hciops_resolve_name, 838 .cancel_resolve_name = hciops_cancel_resolve_name, 839 .set_name = hciops_set_name, 840 .read_name = hciops_read_name, 841 .set_class = hciops_set_class, 842 .set_fast_connectable = hciops_fast_connectable, 843 .read_clock = hciops_read_clock, 844 .get_conn_handle = hciops_conn_handle, 845 .write_eir_data = hciops_write_eir_data, 846 .read_bdaddr = hciops_read_bdaddr, 847}; 848 849static int hciops_init(void) 850{ 851 return btd_register_adapter_ops(&hci_ops); 852} 853static void hciops_exit(void) 854{ 855 btd_adapter_cleanup_ops(&hci_ops); 856} 857 858BLUETOOTH_PLUGIN_DEFINE(hciops, VERSION, 859 BLUETOOTH_PLUGIN_PRIORITY_LOW, hciops_init, hciops_exit) 860