diff options
Diffstat (limited to 'net/bluetooth/hci_core.c')
-rw-r--r-- | net/bluetooth/hci_core.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 9713a2917ddc..e3a49db9cfcb 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -594,6 +594,99 @@ done: | |||
594 | return err; | 594 | return err; |
595 | } | 595 | } |
596 | 596 | ||
597 | static u8 create_ad(struct hci_dev *hdev, u8 *ptr) | ||
598 | { | ||
599 | u8 ad_len = 0, flags = 0; | ||
600 | size_t name_len; | ||
601 | |||
602 | if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) | ||
603 | flags |= LE_AD_GENERAL; | ||
604 | |||
605 | if (!lmp_bredr_capable(hdev)) | ||
606 | flags |= LE_AD_NO_BREDR; | ||
607 | |||
608 | if (lmp_le_br_capable(hdev)) | ||
609 | flags |= LE_AD_SIM_LE_BREDR_CTRL; | ||
610 | |||
611 | if (lmp_host_le_br_capable(hdev)) | ||
612 | flags |= LE_AD_SIM_LE_BREDR_HOST; | ||
613 | |||
614 | if (flags) { | ||
615 | BT_DBG("adv flags 0x%02x", flags); | ||
616 | |||
617 | ptr[0] = 2; | ||
618 | ptr[1] = EIR_FLAGS; | ||
619 | ptr[2] = flags; | ||
620 | |||
621 | ad_len += 3; | ||
622 | ptr += 3; | ||
623 | } | ||
624 | |||
625 | if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) { | ||
626 | ptr[0] = 2; | ||
627 | ptr[1] = EIR_TX_POWER; | ||
628 | ptr[2] = (u8) hdev->adv_tx_power; | ||
629 | |||
630 | ad_len += 3; | ||
631 | ptr += 3; | ||
632 | } | ||
633 | |||
634 | name_len = strlen(hdev->dev_name); | ||
635 | if (name_len > 0) { | ||
636 | size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2; | ||
637 | |||
638 | if (name_len > max_len) { | ||
639 | name_len = max_len; | ||
640 | ptr[1] = EIR_NAME_SHORT; | ||
641 | } else | ||
642 | ptr[1] = EIR_NAME_COMPLETE; | ||
643 | |||
644 | ptr[0] = name_len + 1; | ||
645 | |||
646 | memcpy(ptr + 2, hdev->dev_name, name_len); | ||
647 | |||
648 | ad_len += (name_len + 2); | ||
649 | ptr += (name_len + 2); | ||
650 | } | ||
651 | |||
652 | return ad_len; | ||
653 | } | ||
654 | |||
655 | int hci_update_ad(struct hci_dev *hdev) | ||
656 | { | ||
657 | struct hci_cp_le_set_adv_data cp; | ||
658 | u8 len; | ||
659 | int err; | ||
660 | |||
661 | hci_dev_lock(hdev); | ||
662 | |||
663 | if (!lmp_le_capable(hdev)) { | ||
664 | err = -EINVAL; | ||
665 | goto unlock; | ||
666 | } | ||
667 | |||
668 | memset(&cp, 0, sizeof(cp)); | ||
669 | |||
670 | len = create_ad(hdev, cp.data); | ||
671 | |||
672 | if (hdev->adv_data_len == len && | ||
673 | memcmp(cp.data, hdev->adv_data, len) == 0) { | ||
674 | err = 0; | ||
675 | goto unlock; | ||
676 | } | ||
677 | |||
678 | memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); | ||
679 | hdev->adv_data_len = len; | ||
680 | |||
681 | cp.length = len; | ||
682 | err = hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); | ||
683 | |||
684 | unlock: | ||
685 | hci_dev_unlock(hdev); | ||
686 | |||
687 | return err; | ||
688 | } | ||
689 | |||
597 | /* ---- HCI ioctl helpers ---- */ | 690 | /* ---- HCI ioctl helpers ---- */ |
598 | 691 | ||
599 | int hci_dev_open(__u16 dev) | 692 | int hci_dev_open(__u16 dev) |
@@ -651,6 +744,7 @@ int hci_dev_open(__u16 dev) | |||
651 | hci_dev_hold(hdev); | 744 | hci_dev_hold(hdev); |
652 | set_bit(HCI_UP, &hdev->flags); | 745 | set_bit(HCI_UP, &hdev->flags); |
653 | hci_notify(hdev, HCI_DEV_UP); | 746 | hci_notify(hdev, HCI_DEV_UP); |
747 | hci_update_ad(hdev); | ||
654 | if (!test_bit(HCI_SETUP, &hdev->dev_flags) && | 748 | if (!test_bit(HCI_SETUP, &hdev->dev_flags) && |
655 | mgmt_valid_hdev(hdev)) { | 749 | mgmt_valid_hdev(hdev)) { |
656 | hci_dev_lock(hdev); | 750 | hci_dev_lock(hdev); |