diff options
-rw-r--r-- | include/net/bluetooth/hci.h | 15 | ||||
-rw-r--r-- | include/net/bluetooth/hci_core.h | 4 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 94 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 11 |
4 files changed, 123 insertions, 1 deletions
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 344fea0a7244..7306078e547c 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
@@ -338,6 +338,13 @@ enum { | |||
338 | #define EIR_SSP_RAND_R 0x0F /* Simple Pairing Randomizer R */ | 338 | #define EIR_SSP_RAND_R 0x0F /* Simple Pairing Randomizer R */ |
339 | #define EIR_DEVICE_ID 0x10 /* device ID */ | 339 | #define EIR_DEVICE_ID 0x10 /* device ID */ |
340 | 340 | ||
341 | /* Low Energy Advertising Flags */ | ||
342 | #define LE_AD_LIMITED 0x01 /* Limited Discoverable */ | ||
343 | #define LE_AD_GENERAL 0x02 /* General Discoverable */ | ||
344 | #define LE_AD_NO_BREDR 0x04 /* BR/EDR not supported */ | ||
345 | #define LE_AD_SIM_LE_BREDR_CTRL 0x08 /* Simultaneous LE & BR/EDR Controller */ | ||
346 | #define LE_AD_SIM_LE_BREDR_HOST 0x10 /* Simultaneous LE & BR/EDR Host */ | ||
347 | |||
341 | /* ----- HCI Commands ---- */ | 348 | /* ----- HCI Commands ---- */ |
342 | #define HCI_OP_NOP 0x0000 | 349 | #define HCI_OP_NOP 0x0000 |
343 | 350 | ||
@@ -942,6 +949,14 @@ struct hci_rp_le_read_adv_tx_power { | |||
942 | __s8 tx_power; | 949 | __s8 tx_power; |
943 | } __packed; | 950 | } __packed; |
944 | 951 | ||
952 | #define HCI_MAX_AD_LENGTH 31 | ||
953 | |||
954 | #define HCI_OP_LE_SET_ADV_DATA 0x2008 | ||
955 | struct hci_cp_le_set_adv_data { | ||
956 | __u8 length; | ||
957 | __u8 data[HCI_MAX_AD_LENGTH]; | ||
958 | } __packed; | ||
959 | |||
945 | #define HCI_OP_LE_SET_SCAN_PARAM 0x200b | 960 | #define HCI_OP_LE_SET_SCAN_PARAM 0x200b |
946 | struct hci_cp_le_set_scan_param { | 961 | struct hci_cp_le_set_scan_param { |
947 | __u8 type; | 962 | __u8 type; |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index ce6dbeb6dfb6..ef5b85dac3f7 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -279,6 +279,8 @@ struct hci_dev { | |||
279 | struct le_scan_params le_scan_params; | 279 | struct le_scan_params le_scan_params; |
280 | 280 | ||
281 | __s8 adv_tx_power; | 281 | __s8 adv_tx_power; |
282 | __u8 adv_data[HCI_MAX_AD_LENGTH]; | ||
283 | __u8 adv_data_len; | ||
282 | 284 | ||
283 | int (*open)(struct hci_dev *hdev); | 285 | int (*open)(struct hci_dev *hdev); |
284 | int (*close)(struct hci_dev *hdev); | 286 | int (*close)(struct hci_dev *hdev); |
@@ -734,6 +736,8 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, | |||
734 | u8 *randomizer); | 736 | u8 *randomizer); |
735 | int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); | 737 | int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); |
736 | 738 | ||
739 | int hci_update_ad(struct hci_dev *hdev); | ||
740 | |||
737 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); | 741 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); |
738 | 742 | ||
739 | int hci_recv_frame(struct sk_buff *skb); | 743 | int hci_recv_frame(struct sk_buff *skb); |
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); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 09c65712e8cc..7caea1af557b 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -204,6 +204,9 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) | |||
204 | hdev->discovery.state = DISCOVERY_STOPPED; | 204 | hdev->discovery.state = DISCOVERY_STOPPED; |
205 | hdev->inq_tx_power = HCI_TX_POWER_INVALID; | 205 | hdev->inq_tx_power = HCI_TX_POWER_INVALID; |
206 | hdev->adv_tx_power = HCI_TX_POWER_INVALID; | 206 | hdev->adv_tx_power = HCI_TX_POWER_INVALID; |
207 | |||
208 | memset(hdev->adv_data, 0, sizeof(hdev->adv_data)); | ||
209 | hdev->adv_data_len = 0; | ||
207 | } | 210 | } |
208 | 211 | ||
209 | static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) | 212 | static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -226,6 +229,9 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) | |||
226 | 229 | ||
227 | hci_dev_unlock(hdev); | 230 | hci_dev_unlock(hdev); |
228 | 231 | ||
232 | if (!status && !test_bit(HCI_INIT, &hdev->flags)) | ||
233 | hci_update_ad(hdev); | ||
234 | |||
229 | hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status); | 235 | hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status); |
230 | } | 236 | } |
231 | 237 | ||
@@ -1091,8 +1097,11 @@ static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, | |||
1091 | 1097 | ||
1092 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 1098 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
1093 | 1099 | ||
1094 | if (!rp->status) | 1100 | if (!rp->status) { |
1095 | hdev->adv_tx_power = rp->tx_power; | 1101 | hdev->adv_tx_power = rp->tx_power; |
1102 | if (!test_bit(HCI_INIT, &hdev->flags)) | ||
1103 | hci_update_ad(hdev); | ||
1104 | } | ||
1096 | 1105 | ||
1097 | hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status); | 1106 | hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status); |
1098 | } | 1107 | } |